Skip to content

# context

## `xsdata.formats.dataclass.context`

### `XmlContext`

The models context class.

The context is responsible to provide binding metadata for models and their fields.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`element_name_generator` | `Callable` | Default element name generator | `return_input`
`attribute_name_generator` | `Callable` | Default attribute name generator | `return_input`
`class_type` | `str` | Default class type `dataclasses` | `'dataclasses'`
`models_package` | `str | None` | Restrict auto locate to a specific package | `None`

Attributes:

Name | Type | Description
--- | --- | ---
`cache` | `dict[type, XmlMeta]` | Internal cache for binding metadata instances
`xsi_cache` | `dict[str, list[type]]` | Internal cache for xsi types to class locations
`sys_modules` |  | The number of loaded sys modules

Source code in `xsdata/formats/dataclass/context.py`

     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

    class XmlContext:
        """The models context class.

        The context is responsible to provide binding metadata
        for models and their fields.

        Args:
            element_name_generator: Default element name generator
            attribute_name_generator: Default attribute name generator
            class_type: Default class type `dataclasses`
            models_package: Restrict auto locate to a specific package

        Attributes:
            cache: Internal cache for binding metadata instances
            xsi_cache: Internal cache for xsi types to class locations
            sys_modules: The number of loaded sys modules
        """

        __slots__ = (
            "attribute_name_generator",
            "cache",
            "class_type",
            "element_name_generator",
            "models_package",
            "sys_modules",
            "xsi_cache",
        )

        def __init__(
            self,
            element_name_generator: Callable = return_input,
            attribute_name_generator: Callable = return_input,
            class_type: str = "dataclasses",
            models_package: str | None = None,
        ):
            """Initialize the context."""
            self.element_name_generator = element_name_generator
            self.attribute_name_generator = attribute_name_generator
            self.class_type = class_types.get_type(class_type)

            self.cache: dict[type, XmlMeta] = {}
            self.xsi_cache: dict[str, list[type]] = defaultdict(list)
            self.models_package = models_package
            self.sys_modules = 0

        def reset(self) -> None:
            """Reset all internal caches."""
            self.cache.clear()
            self.xsi_cache.clear()
            self.sys_modules = 0

        def get_builder(
            self,
            globalns: dict[str, Callable] | None = None,
        ) -> XmlMetaBuilder:
            """Return a new xml meta builder instance."""
            return XmlMetaBuilder(
                class_type=self.class_type,
                element_name_generator=self.element_name_generator,
                attribute_name_generator=self.attribute_name_generator,
                globalns=globalns,
            )

        def fetch(
            self,
            clazz: type,
            parent_ns: str | None = None,
            xsi_type: str | None = None,
        ) -> XmlMeta:
            """Build the model metadata for the given class.

            Args:
                clazz: The requested dataclass type
                parent_ns: The inherited parent namespace
                xsi_type: if present it means that the given clazz is
                    derived and the lookup procedure needs to check and match a
                    dataclass model to the qualified name instead.

            Returns:
                A xml meta instance
            """
            meta = self.build(clazz, parent_ns)
            subclass = None
            if xsi_type and meta.target_qname != xsi_type:
                subclass = self.find_subclass(clazz, xsi_type)

            return self.build(subclass, parent_ns) if subclass else meta

        def build_xsi_cache(self) -> None:
            """Index all imported data classes by their xsi:type qualified name."""
            if len(sys.modules) == self.sys_modules:
                return

            self.xsi_cache.clear()
            builder = self.get_builder()
            for clazz in self.get_subclasses(object):
                if self.is_binding_model(clazz):
                    meta = builder.build_class_meta(clazz)

                    if meta.target_qname:
                        self.xsi_cache[meta.target_qname].append(clazz)

            self.sys_modules = len(sys.modules)

        def is_binding_model(self, clazz: type[T]) -> bool:
            """Return whether the clazz is a binding model.

            If the models package is not empty also validate
            the class is located within that package.

            Args:
                clazz: The class type to inspect

            Returns:
                The bool result.
            """
            if not self.class_type.is_model(clazz):
                return False

            return not self.models_package or (
                hasattr(clazz, "__module__")
                and isinstance(clazz.__module__, str)
                and clazz.__module__.startswith(self.models_package)
                and clazz.__module__ in sys.modules
            )

        def find_types(self, qname: str) -> list[type[T]]:
            """Find all classes that match the given xsi:type qname.

            - Ignores native schema types, xs:string, xs:float, xs:int, ...
            - Rebuild cache if new modules were imported since last run

            Args:
                qname: A namespace qualified name

            Returns:
                A list of the matched classes.
            """
            if not DataType.from_qname(qname):
                self.build_xsi_cache()
                if qname in self.xsi_cache:
                    return self.xsi_cache[qname]

            return []

        def find_type(self, qname: str) -> type[T] | None:
            """Return the last imported class that matches the given xsi:type qname.

            Args:
                qname: A namespace qualified name

            Returns:
                A class type or None if no matches.
            """
            types: list[type] = self.find_types(qname)
            return types[-1] if types else None

        def find_type_by_fields(self, field_names: set[str]) -> type[T] | None:
            """Find a data class that matches best the given list of field names.

            Args:
                field_names: A set of field names

            Returns:
                The best matching class or None if no matches. The class must
                have all the fields. If more than one classes have all the given
                fields, return the one with the least extra fields.
            """

            def get_field_diff(clazz: type) -> int:
                meta = self.cache[clazz]
                local_names = {var.local_name for var in meta.get_all_vars()}
                return len(local_names - field_names)

            self.build_xsi_cache()
            choices = [
                (clazz, get_field_diff(clazz))
                for types in self.xsi_cache.values()
                for clazz in types
                if self.local_names_match(field_names, clazz)
            ]

            choices.sort(key=lambda x: (x[1], x[0].__name__))
            return choices[0][0] if choices else None

        def find_subclass(self, clazz: type, qname: str) -> type | None:
            """Find a subclass for the given clazz and xsi:type qname.

            Compare all classes that match the given xsi:type qname and return the
            first one that is either a subclass or shares the same parent class as
            the original class.

            Args:
                clazz: The input clazz type
                qname: The xsi:type to lookup from cache

            Returns:
                The matching class type or None if no matches.
            """
            types: list[type] = self.find_types(qname)
            for tp in types:
                # Why would a xml node with have a xsi:type that points
                # to parent class is beyond me, but it happens, let's protect
                # against that scenario <node xsi:type="nodeAbstract" />
                if issubclass(clazz, tp):
                    continue

                for tp_mro in tp.__mro__:
                    if tp_mro is not object and tp_mro in clazz.__mro__:
                        return tp

            return None

        def build(
            self,
            clazz: type,
            parent_ns: str | None = None,
            globalns: dict[str, Callable] | None = None,
        ) -> XmlMeta:
            """Fetch or build the binding metadata for the given class.

            Args:
                clazz: A class type
                parent_ns: The inherited parent namespace
                globalns: Override the global python namespace

            Returns:
                The class binding metadata instance.
            """
            if clazz not in self.cache:
                builder = self.get_builder(globalns)
                self.cache[clazz] = builder.build(clazz, parent_ns)
            return self.cache[clazz]

        def build_recursive(self, clazz: type, parent_ns: str | None = None) -> None:
            """Build the binding metadata for the given class and all of its dependencies.

            This method is used in benchmarks!

            Args:
                clazz: The class type
                parent_ns: The inherited parent namespace
            """
            if clazz not in self.cache:
                meta = self.build(clazz, parent_ns)
                for var in meta.get_all_vars():
                    types = var.element_types if var.elements else var.types
                    for tp in types:
                        if self.class_type.is_model(tp):
                            self.build_recursive(tp, meta.namespace)

        def local_names_match(self, names: set[str], clazz: type) -> bool:
            """Check if the given field names match the given class type.

            Silently ignore, typing errors. These classes are from third
            party libraries most of them time.

            Args:
                names: A set of field names
                clazz: The class type to inspect

            Returns:
                Whether the class contains all the field names.
            """
            try:
                meta = self.build(clazz)
                local_names = {var.local_name for var in meta.get_all_vars()}
                return not names.difference(local_names)
            except (XmlContextError, NameError, TypeError):
                # The dataclass includes unsupported typing annotations
                # Let's remove it from xsi_cache
                builder = self.get_builder()
                target_qname = builder.build_class_meta(clazz).target_qname
                if target_qname and target_qname in self.xsi_cache:
                    self.xsi_cache[target_qname].remove(clazz)

                return False

        @classmethod
        def is_derived(cls, obj: Any, clazz: type) -> bool:
            """Return whether the obj is a subclass or a parent of the given class type."""
            if obj is None:
                return False

            if isinstance(obj, clazz):
                return True

            return any(x is not object and isinstance(obj, x) for x in clazz.__bases__)

        @classmethod
        def get_subclasses(cls, clazz: type) -> Iterator[type]:
            """Return an iterator of the given class subclasses."""
            with suppress(TypeError, AttributeError):
                for subclass in clazz.__subclasses__():
                    yield from cls.get_subclasses(subclass)
                    yield subclass

#### `__init__(element_name_generator=return_input, attribute_name_generator=return_input, class_type='dataclasses', models_package=None)`

Initialize the context.

Source code in `xsdata/formats/dataclass/context.py`

    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59

    def __init__(
        self,
        element_name_generator: Callable = return_input,
        attribute_name_generator: Callable = return_input,
        class_type: str = "dataclasses",
        models_package: str | None = None,
    ):
        """Initialize the context."""
        self.element_name_generator = element_name_generator
        self.attribute_name_generator = attribute_name_generator
        self.class_type = class_types.get_type(class_type)

        self.cache: dict[type, XmlMeta] = {}
        self.xsi_cache: dict[str, list[type]] = defaultdict(list)
        self.models_package = models_package
        self.sys_modules = 0

#### `reset()`

Reset all internal caches.

Source code in `xsdata/formats/dataclass/context.py`

    61
    62
    63
    64
    65

    def reset(self) -> None:
        """Reset all internal caches."""
        self.cache.clear()
        self.xsi_cache.clear()
        self.sys_modules = 0

#### `get_builder(globalns=None)`

Return a new xml meta builder instance.

Source code in `xsdata/formats/dataclass/context.py`

    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77

    def get_builder(
        self,
        globalns: dict[str, Callable] | None = None,
    ) -> XmlMetaBuilder:
        """Return a new xml meta builder instance."""
        return XmlMetaBuilder(
            class_type=self.class_type,
            element_name_generator=self.element_name_generator,
            attribute_name_generator=self.attribute_name_generator,
            globalns=globalns,
        )

#### `fetch(clazz, parent_ns=None, xsi_type=None)`

Build the model metadata for the given class.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`clazz` | `type` | The requested dataclass type | required
`parent_ns` | `str | None` | The inherited parent namespace | `None`
`xsi_type` | `str | None` | if present it means that the given clazz is derived and the lookup procedure needs to check and match a dataclass model to the qualified name instead. | `None`

Returns:

Type | Description
--- | ---
`XmlMeta` | A xml meta instance

Source code in `xsdata/formats/dataclass/context.py`

     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102

    def fetch(
        self,
        clazz: type,
        parent_ns: str | None = None,
        xsi_type: str | None = None,
    ) -> XmlMeta:
        """Build the model metadata for the given class.

        Args:
            clazz: The requested dataclass type
            parent_ns: The inherited parent namespace
            xsi_type: if present it means that the given clazz is
                derived and the lookup procedure needs to check and match a
                dataclass model to the qualified name instead.

        Returns:
            A xml meta instance
        """
        meta = self.build(clazz, parent_ns)
        subclass = None
        if xsi_type and meta.target_qname != xsi_type:
            subclass = self.find_subclass(clazz, xsi_type)

        return self.build(subclass, parent_ns) if subclass else meta

#### `build_xsi_cache()`

Index all imported data classes by their xsi:type qualified name.

Source code in `xsdata/formats/dataclass/context.py`

    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118

    def build_xsi_cache(self) -> None:
        """Index all imported data classes by their xsi:type qualified name."""
        if len(sys.modules) == self.sys_modules:
            return

        self.xsi_cache.clear()
        builder = self.get_builder()
        for clazz in self.get_subclasses(object):
            if self.is_binding_model(clazz):
                meta = builder.build_class_meta(clazz)

                if meta.target_qname:
                    self.xsi_cache[meta.target_qname].append(clazz)

        self.sys_modules = len(sys.modules)

#### `is_binding_model(clazz)`

Return whether the clazz is a binding model.

If the models package is not empty also validate the class is located within that package.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`clazz` | `type[T]` | The class type to inspect | required

Returns:

Type | Description
--- | ---
`bool` | The bool result.

Source code in `xsdata/formats/dataclass/context.py`

    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140

    def is_binding_model(self, clazz: type[T]) -> bool:
        """Return whether the clazz is a binding model.

        If the models package is not empty also validate
        the class is located within that package.

        Args:
            clazz: The class type to inspect

        Returns:
            The bool result.
        """
        if not self.class_type.is_model(clazz):
            return False

        return not self.models_package or (
            hasattr(clazz, "__module__")
            and isinstance(clazz.__module__, str)
            and clazz.__module__.startswith(self.models_package)
            and clazz.__module__ in sys.modules
        )

#### `find_types(qname)`

Find all classes that match the given xsi:type qname.

- Ignores native schema types, xs:string, xs:float, xs:int, ...
- Rebuild cache if new modules were imported since last run

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`qname` | `str` | A namespace qualified name | required

Returns:

Type | Description
--- | ---
`list[type[T]]` | A list of the matched classes.

Source code in `xsdata/formats/dataclass/context.py`

    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159

    def find_types(self, qname: str) -> list[type[T]]:
        """Find all classes that match the given xsi:type qname.

        - Ignores native schema types, xs:string, xs:float, xs:int, ...
        - Rebuild cache if new modules were imported since last run

        Args:
            qname: A namespace qualified name

        Returns:
            A list of the matched classes.
        """
        if not DataType.from_qname(qname):
            self.build_xsi_cache()
            if qname in self.xsi_cache:
                return self.xsi_cache[qname]

        return []

#### `find_type(qname)`

Return the last imported class that matches the given xsi:type qname.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`qname` | `str` | A namespace qualified name | required

Returns:

Type | Description
--- | ---
`type[T] | None` | A class type or None if no matches.

Source code in `xsdata/formats/dataclass/context.py`

    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171

    def find_type(self, qname: str) -> type[T] | None:
        """Return the last imported class that matches the given xsi:type qname.

        Args:
            qname: A namespace qualified name

        Returns:
            A class type or None if no matches.
        """
        types: list[type] = self.find_types(qname)
        return types[-1] if types else None

#### `find_type_by_fields(field_names)`

Find a data class that matches best the given list of field names.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`field_names` | `set[str]` | A set of field names | required

Returns:

Type | Description
--- | ---
`type[T] | None` | The best matching class or None if no matches. The class must
`type[T] | None` | have all the fields. If more than one classes have all the given
`type[T] | None` | fields, return the one with the least extra fields.

Source code in `xsdata/formats/dataclass/context.py`

    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

    def find_type_by_fields(self, field_names: set[str]) -> type[T] | None:
        """Find a data class that matches best the given list of field names.

        Args:
            field_names: A set of field names

        Returns:
            The best matching class or None if no matches. The class must
            have all the fields. If more than one classes have all the given
            fields, return the one with the least extra fields.
        """

        def get_field_diff(clazz: type) -> int:
            meta = self.cache[clazz]
            local_names = {var.local_name for var in meta.get_all_vars()}
            return len(local_names - field_names)

        self.build_xsi_cache()
        choices = [
            (clazz, get_field_diff(clazz))
            for types in self.xsi_cache.values()
            for clazz in types
            if self.local_names_match(field_names, clazz)
        ]

        choices.sort(key=lambda x: (x[1], x[0].__name__))
        return choices[0][0] if choices else None

#### `find_subclass(clazz, qname)`

Find a subclass for the given clazz and xsi:type qname.

Compare all classes that match the given xsi:type qname and return the first one that is either a subclass or shares the same parent class as the original class.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`clazz` | `type` | The input clazz type | required
`qname` | `str` | The xsi:type to lookup from cache | required

Returns:

Type | Description
--- | ---
`type | None` | The matching class type or None if no matches.

Source code in `xsdata/formats/dataclass/context.py`

    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 find_subclass(self, clazz: type, qname: str) -> type | None:
        """Find a subclass for the given clazz and xsi:type qname.

        Compare all classes that match the given xsi:type qname and return the
        first one that is either a subclass or shares the same parent class as
        the original class.

        Args:
            clazz: The input clazz type
            qname: The xsi:type to lookup from cache

        Returns:
            The matching class type or None if no matches.
        """
        types: list[type] = self.find_types(qname)
        for tp in types:
            # Why would a xml node with have a xsi:type that points
            # to parent class is beyond me, but it happens, let's protect
            # against that scenario <node xsi:type="nodeAbstract" />
            if issubclass(clazz, tp):
                continue

            for tp_mro in tp.__mro__:
                if tp_mro is not object and tp_mro in clazz.__mro__:
                    return tp

        return None

#### `build(clazz, parent_ns=None, globalns=None)`

Fetch or build the binding metadata for the given class.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`clazz` | `type` | A class type | required
`parent_ns` | `str | None` | The inherited parent namespace | `None`
`globalns` | `dict[str, Callable] | None` | Override the global python namespace | `None`

Returns:

Type | Description
--- | ---
`XmlMeta` | The class binding metadata instance.

Source code in `xsdata/formats/dataclass/context.py`

    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248

    def build(
        self,
        clazz: type,
        parent_ns: str | None = None,
        globalns: dict[str, Callable] | None = None,
    ) -> XmlMeta:
        """Fetch or build the binding metadata for the given class.

        Args:
            clazz: A class type
            parent_ns: The inherited parent namespace
            globalns: Override the global python namespace

        Returns:
            The class binding metadata instance.
        """
        if clazz not in self.cache:
            builder = self.get_builder(globalns)
            self.cache[clazz] = builder.build(clazz, parent_ns)
        return self.cache[clazz]

#### `build_recursive(clazz, parent_ns=None)`

Build the binding metadata for the given class and all of its dependencies.

This method is used in benchmarks!

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`clazz` | `type` | The class type | required
`parent_ns` | `str | None` | The inherited parent namespace | `None`

Source code in `xsdata/formats/dataclass/context.py`

    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265

    def build_recursive(self, clazz: type, parent_ns: str | None = None) -> None:
        """Build the binding metadata for the given class and all of its dependencies.

        This method is used in benchmarks!

        Args:
            clazz: The class type
            parent_ns: The inherited parent namespace
        """
        if clazz not in self.cache:
            meta = self.build(clazz, parent_ns)
            for var in meta.get_all_vars():
                types = var.element_types if var.elements else var.types
                for tp in types:
                    if self.class_type.is_model(tp):
                        self.build_recursive(tp, meta.namespace)

#### `local_names_match(names, clazz)`

Check if the given field names match the given class type.

Silently ignore, typing errors. These classes are from third party libraries most of them time.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`names` | `set[str]` | A set of field names | required
`clazz` | `type` | The class type to inspect | required

Returns:

Type | Description
--- | ---
`bool` | Whether the class contains all the field names.

Source code in `xsdata/formats/dataclass/context.py`

    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

    def local_names_match(self, names: set[str], clazz: type) -> bool:
        """Check if the given field names match the given class type.

        Silently ignore, typing errors. These classes are from third
        party libraries most of them time.

        Args:
            names: A set of field names
            clazz: The class type to inspect

        Returns:
            Whether the class contains all the field names.
        """
        try:
            meta = self.build(clazz)
            local_names = {var.local_name for var in meta.get_all_vars()}
            return not names.difference(local_names)
        except (XmlContextError, NameError, TypeError):
            # The dataclass includes unsupported typing annotations
            # Let's remove it from xsi_cache
            builder = self.get_builder()
            target_qname = builder.build_class_meta(clazz).target_qname
            if target_qname and target_qname in self.xsi_cache:
                self.xsi_cache[target_qname].remove(clazz)

            return False

#### `is_derived(obj, clazz)` `classmethod`

Return whether the obj is a subclass or a parent of the given class type.

Source code in `xsdata/formats/dataclass/context.py`

    294
    295
    296
    297
    298
    299
    300
    301
    302
    303

    @classmethod
    def is_derived(cls, obj: Any, clazz: type) -> bool:
        """Return whether the obj is a subclass or a parent of the given class type."""
        if obj is None:
            return False

        if isinstance(obj, clazz):
            return True

        return any(x is not object and isinstance(obj, x) for x in clazz.__bases__)

#### `get_subclasses(clazz)` `classmethod`

Return an iterator of the given class subclasses.

Source code in `xsdata/formats/dataclass/context.py`

    305
    306
    307
    308
    309
    310
    311

    @classmethod
    def get_subclasses(cls, clazz: type) -> Iterator[type]:
        """Return an iterator of the given class subclasses."""
        with suppress(TypeError, AttributeError):
            for subclass in clazz.__subclasses__():
                yield from cls.get_subclasses(subclass)
                yield subclass