Skip to content

# process_attributes_types

## `xsdata.codegen.handlers.process_attributes_types`

### `ProcessAttributeTypes`

Bases: `RelativeHandlerInterface`

Minimize class attrs complexity by filtering and flattening types.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`container` | `ContainerInterface` | The container instance | required

Attributes:

Name | Type | Description
--- | --- | ---
`dependencies` | `dict` | Class qname dependencies mapping

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339

    class ProcessAttributeTypes(RelativeHandlerInterface):
        """Minimize class attrs complexity by filtering and flattening types.

        Args:
            container: The container instance

        Attributes:
            dependencies: Class qname dependencies mapping
        """

        __slots__ = "dependencies"

        def __init__(self, container: ContainerInterface):
            """Initialize the class."""
            super().__init__(container)
            self.dependencies: dict = {}

        def process(self, target: Class) -> None:
            """Process the given class attrs and their types.

            Cascades class restrictions to class attrs.

            Args:
                target: The target class instance
            """
            for attr in target.attrs.copy():
                self.process_types(target, attr)
                self.cascade_properties(target, attr)

        def process_types(self, target: Class, attr: Attr) -> None:
            """Process every attr type and filter out duplicates.

            Args:
                target: The target class instance
                attr: The attr instance
            """
            if self.container.config.output.ignore_patterns:
                attr.restrictions.pattern = None

            for attr_type in attr.types.copy():
                self.process_type(target, attr, attr_type)

            attr.types = ClassUtils.filter_types(attr.types)

        @classmethod
        def cascade_properties(cls, target: Class, attr: Attr):
            """Cascade class properties to the attr if it's a text node.

            Properties:
                - Default value
                - Fixed flag
                - Nillable flag

            Args:
                target: The target class instance
                attr: The attr instance
            """
            if attr.xml_type is None:
                if target.default is not None and attr.default is None:
                    attr.default = target.default
                    attr.fixed = target.fixed

                if target.nillable:
                    attr.restrictions.nillable = True

        def process_type(self, target: Class, attr: Attr, attr_type: AttrType) -> None:
            """Process attr type.

            Cases:
                - Attr type is a native xsd type
                - Attr type is a forward reference (inner class)
                - Attr type is a complex user defined type

            Args:
                target: The target class instance
                attr: The attr instance
                attr_type: The attr type instance
            """
            if attr_type.native:
                self.process_native_type(attr, attr_type)
            elif attr_type.forward:
                self.process_inner_type(target, attr, attr_type)
            else:
                self.process_dependency_type(target, attr, attr_type)

        @classmethod
        def process_native_type(cls, attr: Attr, attr_type: AttrType):
            """Process native xsd types.

            Cascade the datatype restrictions to the attr and also
            resets the type to a simple xsd:string if there is a pattern
            restriction.

            Args:
                attr: The attr instance
                attr_type: The attr type instance
            """
            datatype = attr_type.datatype

            assert datatype is not None

            cls.update_restrictions(attr, datatype)

            if attr.restrictions.pattern:
                cls.reset_attribute_type(attr_type)

        def find_dependency(
            self, target: Class, attr_type: AttrType, tag: str
        ) -> Class | None:
            """Find the source type from the attr type and tag.

            Avoid conflicts by selecting any matching type by qname and preferably:
                1. Match the attr type reference, if it's already set
                2. Match element again complexType with no self reference
                3. Match the candidate object tag
                4. Match non element and complexType
                5. Anything

            Args:
                target: The target class instance
                attr_type: The attr type instance
                tag: The xml tag name, e.g. Element, Attribute, ComplexType

            Returns:
                The source class or None if no match is found
            """
            conditions: tuple[Callable[[Class], bool], ...]

            if attr_type.reference:
                conditions = (lambda obj: obj.ref == attr_type.reference,)
            else:
                conditions = (
                    lambda obj: (
                        tag == Tag.ELEMENT
                        and obj.tag == Tag.COMPLEX_TYPE
                        and obj is not target
                    ),
                    lambda obj: obj.tag == tag,
                    lambda obj: not obj.is_complex_type,
                    lambda x: True,
                )

            for condition in conditions:
                result = self.container.find(attr_type.qname, condition=condition)
                if result:
                    return result

            return None

        def process_inner_type(
            self, target: Class, attr: Attr, attr_type: AttrType
        ) -> None:
            """Process an attr type that depends on a simple inner type.

            Skip If the source class is not simple type, or it's a circular reference.

            Args:
                target: The target class instance
                attr: The attr instance
                attr_type: The attr type instance
            """
            if attr_type.circular:
                attr_type.reference = target.ref
                return

            inner = self.container.find_inner(target, attr_type.qname)

            # If the inner class behaves as a simple type flatten it.
            if (
                len(inner.attrs) == 1
                and not inner.attrs[0].xml_type
                and not inner.extensions
            ):
                self.copy_attribute_properties(inner, target, attr, attr_type)
                target.inner.remove(inner)
            else:
                attr_type.reference = inner.ref

        def process_dependency_type(
            self, target: Class, attr: Attr, attr_type: AttrType
        ) -> None:
            """Process an attr type that depends on any global type.

            Strategies:
                1. Reset absent types with a warning
                3. Copy format restriction from an enumeration
                2. Copy attribute properties from a simple type
                4. Set circular flag for the rest

            Args:
                target: The target class instance
                attr: The attr instance
                attr_type: The attr type instance
            """
            source = self.find_dependency(target, attr_type, attr.tag)
            if not source:
                logger.warning("Reset absent type: %s", attr_type.name)
                self.reset_attribute_type(attr_type)
            elif source.is_enumeration:
                attr.restrictions.min_length = None
                attr.restrictions.max_length = None
                attr.restrictions.format = collections.first(
                    x.restrictions.format for x in source.attrs if x.restrictions.format
                )
                attr_type.reference = id(source)
            elif not source.is_complex_type:
                self.copy_attribute_properties(source, target, attr, attr_type)
            elif source.is_element and source.abstract:
                # Substitution groups with abstract elements are used like
                # placeholders and shouldn't be added as standalone fields.
                ClassUtils.remove_attribute(target, attr)
            else:
                if source.nillable:
                    attr.restrictions.nillable = True

                attr_type.reference = id(source)
                self.detect_lazy_namespace(source, target, attr)

        @classmethod
        def copy_attribute_properties(
            cls,
            source: Class,
            target: Class,
            attr: Attr,
            attr_type: AttrType,
        ):
            """Replace the attr type with the types of the first attr in the source class.

            Ignore enumerations and gracefully handle dump types with no
            attrs.

            Args:
                source: The source class instance
                target: The target class instance
                attr: The attr instance
                attr_type: The attr type instance

            Raises:
                AnalyzerValueError: if the source class has more than one attributes
            """
            if not source.attrs:
                logger.warning("Reset absent simple type: %s", attr_type.name)
                cls.reset_attribute_type(attr_type)
                return

            source_attr = source.attrs[0]
            index = attr.types.index(attr_type)
            attr.types.pop(index)

            for source_attr_type in source_attr.types:
                clone_type = source_attr_type.clone()
                attr.types.insert(index, clone_type)
                index += 1

                ClassUtils.copy_inner_class(source, target, clone_type)

            restrictions = source_attr.restrictions.clone()
            restrictions.merge(attr.restrictions)

            # Maintain occurrences no matter what!
            restrictions.min_occurs = attr.restrictions.min_occurs
            restrictions.max_occurs = attr.restrictions.max_occurs

            if source.nillable:
                restrictions.nillable = True

            attr.restrictions = restrictions
            attr.help = attr.help or source_attr.help
            attr.fixed = attr.fixed or source_attr.fixed
            attr.default = attr.default or source_attr.default

        @classmethod
        def reset_attribute_type(cls, attr_type: AttrType):
            """Reset the attribute type to string.

            The method will also unset the circular/forward flags, as native
            types only depend on python builtin types.

            Args:
                attr_type: The attr type instance to reset
            """
            attr_type.qname = str(DataType.STRING)
            attr_type.native = True
            attr_type.circular = False
            attr_type.forward = False

        @classmethod
        def update_restrictions(cls, attr: Attr, datatype: DataType):
            """Helper method to copy the native datatype restriction to the attr.

            Sets:
                - The format restriction, e.g. hexBinary, base64Binary
                - The tokens flag for xs:NMTOKENS and xs:IDREFS

            Args:
                attr: The attr to update
                datatype: The datatype to extract the restrictions.
            """
            attr.restrictions.format = datatype.format

            if datatype in (DataType.NMTOKENS, DataType.IDREFS):
                attr.restrictions.tokens = True

        @classmethod
        def detect_lazy_namespace(cls, source: Class, target: Class, attr: Attr):
            """Set the attr namespace if the current is marked as lazy.

            Cases:
                WSDL message part type can be an element, complex or
                simple type, we can't do the detection during the initial
                mapping to class objects.

            Args:
                source: The source class instance
                target: The target class instance
                attr: The target class attr instance
            """
            if attr.namespace == "##lazy":
                logger.warning(
                    "Overriding field type namespace %s:%s (%s)",
                    target.name,
                    attr.name,
                    source.namespace,
                )

                if not source.namespace:
                    attr.namespace = "" if target.namespace else None
                else:
                    attr.namespace = source.namespace

#### `__init__(container)`

Initialize the class.

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    23
    24
    25
    26

    def __init__(self, container: ContainerInterface):
        """Initialize the class."""
        super().__init__(container)
        self.dependencies: dict = {}

#### `process(target)`

Process the given class attrs and their types.

Cascades class restrictions to class attrs.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    def process(self, target: Class) -> None:
        """Process the given class attrs and their types.

        Cascades class restrictions to class attrs.

        Args:
            target: The target class instance
        """
        for attr in target.attrs.copy():
            self.process_types(target, attr)
            self.cascade_properties(target, attr)

#### `process_types(target, attr)`

Process every attr type and filter out duplicates.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53

    def process_types(self, target: Class, attr: Attr) -> None:
        """Process every attr type and filter out duplicates.

        Args:
            target: The target class instance
            attr: The attr instance
        """
        if self.container.config.output.ignore_patterns:
            attr.restrictions.pattern = None

        for attr_type in attr.types.copy():
            self.process_type(target, attr, attr_type)

        attr.types = ClassUtils.filter_types(attr.types)

#### `cascade_properties(target, attr)` `classmethod`

Cascade class properties to the attr if it's a text node.

Properties

- Default value
- Fixed flag
- Nillable flag

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74

    @classmethod
    def cascade_properties(cls, target: Class, attr: Attr):
        """Cascade class properties to the attr if it's a text node.

        Properties:
            - Default value
            - Fixed flag
            - Nillable flag

        Args:
            target: The target class instance
            attr: The attr instance
        """
        if attr.xml_type is None:
            if target.default is not None and attr.default is None:
                attr.default = target.default
                attr.fixed = target.fixed

            if target.nillable:
                attr.restrictions.nillable = True

#### `process_type(target, attr, attr_type)`

Process attr type.

Cases

- Attr type is a native xsd type
- Attr type is a forward reference (inner class)
- Attr type is a complex user defined type

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required
`attr_type` | `AttrType` | The attr type instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94

    def process_type(self, target: Class, attr: Attr, attr_type: AttrType) -> None:
        """Process attr type.

        Cases:
            - Attr type is a native xsd type
            - Attr type is a forward reference (inner class)
            - Attr type is a complex user defined type

        Args:
            target: The target class instance
            attr: The attr instance
            attr_type: The attr type instance
        """
        if attr_type.native:
            self.process_native_type(attr, attr_type)
        elif attr_type.forward:
            self.process_inner_type(target, attr, attr_type)
        else:
            self.process_dependency_type(target, attr, attr_type)

#### `process_native_type(attr, attr_type)` `classmethod`

Process native xsd types.

Cascade the datatype restrictions to the attr and also resets the type to a simple xsd:string if there is a pattern restriction.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`attr` | `Attr` | The attr instance | required
`attr_type` | `AttrType` | The attr type instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115

    @classmethod
    def process_native_type(cls, attr: Attr, attr_type: AttrType):
        """Process native xsd types.

        Cascade the datatype restrictions to the attr and also
        resets the type to a simple xsd:string if there is a pattern
        restriction.

        Args:
            attr: The attr instance
            attr_type: The attr type instance
        """
        datatype = attr_type.datatype

        assert datatype is not None

        cls.update_restrictions(attr, datatype)

        if attr.restrictions.pattern:
            cls.reset_attribute_type(attr_type)

#### `find_dependency(target, attr_type, tag)`

Find the source type from the attr type and tag.

Avoid conflicts by selecting any matching type by qname and preferably

1. Match the attr type reference, if it's already set
2. Match element again complexType with no self reference
3. Match the candidate object tag
4. Match non element and complexType
5. Anything

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr_type` | `AttrType` | The attr type instance | required
`tag` | `str` | The xml tag name, e.g. Element, Attribute, ComplexType | required

Returns:

Type | Description
--- | ---
`Class | None` | The source class or None if no match is found

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158

    def find_dependency(
        self, target: Class, attr_type: AttrType, tag: str
    ) -> Class | None:
        """Find the source type from the attr type and tag.

        Avoid conflicts by selecting any matching type by qname and preferably:
            1. Match the attr type reference, if it's already set
            2. Match element again complexType with no self reference
            3. Match the candidate object tag
            4. Match non element and complexType
            5. Anything

        Args:
            target: The target class instance
            attr_type: The attr type instance
            tag: The xml tag name, e.g. Element, Attribute, ComplexType

        Returns:
            The source class or None if no match is found
        """
        conditions: tuple[Callable[[Class], bool], ...]

        if attr_type.reference:
            conditions = (lambda obj: obj.ref == attr_type.reference,)
        else:
            conditions = (
                lambda obj: (
                    tag == Tag.ELEMENT
                    and obj.tag == Tag.COMPLEX_TYPE
                    and obj is not target
                ),
                lambda obj: obj.tag == tag,
                lambda obj: not obj.is_complex_type,
                lambda x: True,
            )

        for condition in conditions:
            result = self.container.find(attr_type.qname, condition=condition)
            if result:
                return result

        return None

#### `process_inner_type(target, attr, attr_type)`

Process an attr type that depends on a simple inner type.

Skip If the source class is not simple type, or it's a circular reference.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required
`attr_type` | `AttrType` | The attr type instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187

    def process_inner_type(
        self, target: Class, attr: Attr, attr_type: AttrType
    ) -> None:
        """Process an attr type that depends on a simple inner type.

        Skip If the source class is not simple type, or it's a circular reference.

        Args:
            target: The target class instance
            attr: The attr instance
            attr_type: The attr type instance
        """
        if attr_type.circular:
            attr_type.reference = target.ref
            return

        inner = self.container.find_inner(target, attr_type.qname)

        # If the inner class behaves as a simple type flatten it.
        if (
            len(inner.attrs) == 1
            and not inner.attrs[0].xml_type
            and not inner.extensions
        ):
            self.copy_attribute_properties(inner, target, attr, attr_type)
            target.inner.remove(inner)
        else:
            attr_type.reference = inner.ref

#### `process_dependency_type(target, attr, attr_type)`

Process an attr type that depends on any global type.

Strategies

1. Reset absent types with a warning
2. Copy format restriction from an enumeration
3. Copy attribute properties from a simple type
4. Set circular flag for the rest

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required
`attr_type` | `AttrType` | The attr type instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227

    def process_dependency_type(
        self, target: Class, attr: Attr, attr_type: AttrType
    ) -> None:
        """Process an attr type that depends on any global type.

        Strategies:
            1. Reset absent types with a warning
            3. Copy format restriction from an enumeration
            2. Copy attribute properties from a simple type
            4. Set circular flag for the rest

        Args:
            target: The target class instance
            attr: The attr instance
            attr_type: The attr type instance
        """
        source = self.find_dependency(target, attr_type, attr.tag)
        if not source:
            logger.warning("Reset absent type: %s", attr_type.name)
            self.reset_attribute_type(attr_type)
        elif source.is_enumeration:
            attr.restrictions.min_length = None
            attr.restrictions.max_length = None
            attr.restrictions.format = collections.first(
                x.restrictions.format for x in source.attrs if x.restrictions.format
            )
            attr_type.reference = id(source)
        elif not source.is_complex_type:
            self.copy_attribute_properties(source, target, attr, attr_type)
        elif source.is_element and source.abstract:
            # Substitution groups with abstract elements are used like
            # placeholders and shouldn't be added as standalone fields.
            ClassUtils.remove_attribute(target, attr)
        else:
            if source.nillable:
                attr.restrictions.nillable = True

            attr_type.reference = id(source)
            self.detect_lazy_namespace(source, target, attr)

#### `copy_attribute_properties(source, target, attr, attr_type)` `classmethod`

Replace the attr type with the types of the first attr in the source class.

Ignore enumerations and gracefully handle dump types with no attrs.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`source` | `Class` | The source class instance | required
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The attr instance | required
`attr_type` | `AttrType` | The attr type instance | required

Raises:

Type | Description
--- | ---
`AnalyzerValueError` | if the source class has more than one attributes

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280

    @classmethod
    def copy_attribute_properties(
        cls,
        source: Class,
        target: Class,
        attr: Attr,
        attr_type: AttrType,
    ):
        """Replace the attr type with the types of the first attr in the source class.

        Ignore enumerations and gracefully handle dump types with no
        attrs.

        Args:
            source: The source class instance
            target: The target class instance
            attr: The attr instance
            attr_type: The attr type instance

        Raises:
            AnalyzerValueError: if the source class has more than one attributes
        """
        if not source.attrs:
            logger.warning("Reset absent simple type: %s", attr_type.name)
            cls.reset_attribute_type(attr_type)
            return

        source_attr = source.attrs[0]
        index = attr.types.index(attr_type)
        attr.types.pop(index)

        for source_attr_type in source_attr.types:
            clone_type = source_attr_type.clone()
            attr.types.insert(index, clone_type)
            index += 1

            ClassUtils.copy_inner_class(source, target, clone_type)

        restrictions = source_attr.restrictions.clone()
        restrictions.merge(attr.restrictions)

        # Maintain occurrences no matter what!
        restrictions.min_occurs = attr.restrictions.min_occurs
        restrictions.max_occurs = attr.restrictions.max_occurs

        if source.nillable:
            restrictions.nillable = True

        attr.restrictions = restrictions
        attr.help = attr.help or source_attr.help
        attr.fixed = attr.fixed or source_attr.fixed
        attr.default = attr.default or source_attr.default

#### `reset_attribute_type(attr_type)` `classmethod`

Reset the attribute type to string.

The method will also unset the circular/forward flags, as native types only depend on python builtin types.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`attr_type` | `AttrType` | The attr type instance to reset | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295

    @classmethod
    def reset_attribute_type(cls, attr_type: AttrType):
        """Reset the attribute type to string.

        The method will also unset the circular/forward flags, as native
        types only depend on python builtin types.

        Args:
            attr_type: The attr type instance to reset
        """
        attr_type.qname = str(DataType.STRING)
        attr_type.native = True
        attr_type.circular = False
        attr_type.forward = False

#### `update_restrictions(attr, datatype)` `classmethod`

Helper method to copy the native datatype restriction to the attr.

Sets

- The format restriction, e.g. hexBinary, base64Binary
- The tokens flag for xs:NMTOKENS and xs:IDREFS

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`attr` | `Attr` | The attr to update | required
`datatype` | `DataType` | The datatype to extract the restrictions. | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312

    @classmethod
    def update_restrictions(cls, attr: Attr, datatype: DataType):
        """Helper method to copy the native datatype restriction to the attr.

        Sets:
            - The format restriction, e.g. hexBinary, base64Binary
            - The tokens flag for xs:NMTOKENS and xs:IDREFS

        Args:
            attr: The attr to update
            datatype: The datatype to extract the restrictions.
        """
        attr.restrictions.format = datatype.format

        if datatype in (DataType.NMTOKENS, DataType.IDREFS):
            attr.restrictions.tokens = True

#### `detect_lazy_namespace(source, target, attr)` `classmethod`

Set the attr namespace if the current is marked as lazy.

Cases

WSDL message part type can be an element, complex or simple type, we can't do the detection during the initial mapping to class objects.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`source` | `Class` | The source class instance | required
`target` | `Class` | The target class instance | required
`attr` | `Attr` | The target class attr instance | required

Source code in `xsdata/codegen/handlers/process_attributes_types.py`

    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339

    @classmethod
    def detect_lazy_namespace(cls, source: Class, target: Class, attr: Attr):
        """Set the attr namespace if the current is marked as lazy.

        Cases:
            WSDL message part type can be an element, complex or
            simple type, we can't do the detection during the initial
            mapping to class objects.

        Args:
            source: The source class instance
            target: The target class instance
            attr: The target class attr instance
        """
        if attr.namespace == "##lazy":
            logger.warning(
                "Overriding field type namespace %s:%s (%s)",
                target.name,
                attr.name,
                source.namespace,
            )

            if not source.namespace:
                attr.namespace = "" if target.namespace else None
            else:
                attr.namespace = source.namespace