Skip to content

# typing

## `xsdata.formats.dataclass.typing`

### `Result`

Bases: `NamedTuple`

Analyze Result Object.

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

    54
    55
    56
    57
    58
    59
    60

    class Result(NamedTuple):
        """Analyze Result Object."""

        types: tuple[type[Any], ...]
        factory: Callable | None = None
        tokens_factory: Callable | None = None
        optional: bool = False

### `evaluate(tp, globalns, localns=None)`

Analyze/Validate the typing annotation.

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

    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    def evaluate(tp: Any, globalns: Any, localns: Any = None) -> Any:
        """Analyze/Validate the typing annotation."""
        result = _eval_type(tp, globalns, localns)

        # Ugly hack for the Type["str"]
        # Let's switch to ForwardRef("str")
        if get_origin(result) is type:
            args = get_args(result)
            if len(args) != 1:
                raise TypeError

            return args[0]

        return result

### `analyze_token_args(origin, args)`

Analyze token arguments.

Ensure it only has one argument, filter out ellipsis.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`origin` | `Any` | The annotation origin | required
`args` | `tuple[Any, ...]` | The annotation arguments | required

Returns:

Type | Description
--- | ---
`tuple[Any]` | A tuple that contains only one arg

Raises:

Type | Description
--- | ---
`TypeError` | If the origin is not list or tuple, and it has more than one argument

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

    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85

    def analyze_token_args(origin: Any, args: tuple[Any, ...]) -> tuple[Any]:
        """Analyze token arguments.

        Ensure it only has one argument, filter out ellipsis.

        Args:
            origin: The annotation origin
            args: The annotation arguments

        Returns:
            A tuple that contains only one arg

        Raises:
            TypeError: If the origin is not list or tuple,
                and it has more than one argument

        """
        if origin in ITERABLE_TYPES:
            args = filter_ellipsis(args)
            if len(args) == 1:
                return args

        raise TypeError

### `analyze_optional_origin(origin, args, types)`

Analyze optional type annotations.

Remove the NoneType, adjust and return the origin, args and types.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`origin` | `Any` | The annotation origin | required
`args` | `tuple[Any, ...]` | The annotation arguments | required
`types` | `tuple[Any, ...]` | The annotation types | required

Returns:

Type | Description
--- | ---
`tuple[Any, ...]` | The old or new origin args and types.

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

     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108

    def analyze_optional_origin(
        origin: Any, args: tuple[Any, ...], types: tuple[Any, ...]
    ) -> tuple[Any, ...]:
        """Analyze optional type annotations.

        Remove the NoneType, adjust and return the origin, args and types.

        Args:
            origin: The annotation origin
            args: The annotation arguments
            types: The annotation types

        Returns:
            The old or new origin args and types.
        """
        if origin in UNION_TYPES:
            new_args = filter_none_type(args)
            if len(new_args) == 1:
                return get_origin(new_args[0]), get_args(new_args[0]), new_args

        return origin, args, types

### `filter_none_type(args)`

Filter out none types from args.

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

    111
    112
    113

    def filter_none_type(args: tuple[Any, ...]) -> tuple[Any, ...]:
        """Filter out none types from args."""
        return tuple(arg for arg in args if arg is not NONE_TYPE)

### `filter_ellipsis(args)`

Filter out ellipsis from args.

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

    116
    117
    118

    def filter_ellipsis(args: tuple[Any, ...]) -> tuple[Any]:
        """Filter out ellipsis from args."""
        return tuple(arg for arg in args if arg is not Ellipsis)

### `evaluate_text(annotation, tokens=False)`

Run exactly the same validations with attribute.

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

    121
    122
    123

    def evaluate_text(annotation: Any, tokens: bool = False) -> Result:
        """Run exactly the same validations with attribute."""
        return evaluate_attribute(annotation, tokens)

### `evaluate_attribute(annotation, tokens=False)`

Validate annotations for an XML attribute.

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

    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

    def evaluate_attribute(annotation: Any, tokens: bool = False) -> Result:
        """Validate annotations for an XML attribute."""
        types = (annotation,)
        origin = get_origin(annotation)
        args = get_args(annotation)
        tokens_factory = None

        if origin in UNION_TYPES:
            optional = NONE_TYPE in args
        else:
            optional = False

        if tokens:
            origin, args, types = analyze_optional_origin(origin, args, types)

            args = analyze_token_args(origin, args)
            tokens_factory = origin
            if tokens_factory in LIST_CONTAINERS:
                tokens_factory = list

            origin = get_origin(args[0])

            if origin in UNION_TYPES:
                args = get_args(args[0])
            elif origin:
                raise TypeError

        if origin in UNION_TYPES:
            types = filter_none_type(args)
        elif origin is None:
            types = args or (annotation,)
        else:
            raise TypeError

        if any(get_origin(tp) for tp in types):
            raise TypeError

        return Result(types=types, tokens_factory=tokens_factory, optional=optional)

### `evaluate_attributes(annotation, **_)`

Validate annotations for XML wildcard attributes.

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

    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181

    def evaluate_attributes(annotation: Any, **_: Any) -> Result:
        """Validate annotations for XML wildcard attributes."""
        if annotation is dict:
            args = ()
        else:
            origin = get_origin(annotation)
            args = get_args(annotation)

            if origin is not dict and origin is not Mapping:
                raise TypeError

        if args and not all(arg is str for arg in args):
            raise TypeError

        # Attributes always have optional=False (nothing else is supported)
        return Result(types=(str,), factory=dict, optional=False)

### `evaluate_element(annotation, tokens=False)`

Validate annotations for an XML element.

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

    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

    def evaluate_element(annotation: Any, tokens: bool = False) -> Result:
        """Validate annotations for an XML element."""
        # Only the derived element value field is allowed a typevar
        if isinstance(annotation, TypeVar) and annotation.__bound__ is object:
            annotation = object

        types = (annotation,)
        origin = get_origin(annotation)
        args = get_args(annotation)
        tokens_factory = factory = None

        # Compute optional status from original annotation before any processing
        if origin in UNION_TYPES:
            optional = NONE_TYPE in args
        else:
            optional = False

        origin, args, types = analyze_optional_origin(origin, args, types)

        if tokens:
            args = analyze_token_args(origin, args)

            tokens_factory = origin
            origin = get_origin(args[0])
            types = args
            args = get_args(args[0])

        if origin in ITERABLE_TYPES:
            args = tuple(arg for arg in args if arg is not Ellipsis)
            if len(args) != 1:
                raise TypeError

            if tokens_factory:
                factory = tokens_factory
                tokens_factory = origin
            else:
                factory = origin

            types = args
            origin = get_origin(args[0])
            args = get_args(args[0])

        if origin in UNION_TYPES:
            types = filter_none_type(args)
        elif origin:
            raise TypeError

        if factory in LIST_CONTAINERS:
            factory = list

        if tokens_factory in LIST_CONTAINERS:
            tokens_factory = list

        return Result(
            types=types,
            factory=factory,
            tokens_factory=tokens_factory,
            optional=optional,
        )

### `evaluate_elements(annotation, **_)`

Validate annotations for an XML compound field.

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

    245
    246
    247
    248
    249
    250
    251
    252

    def evaluate_elements(annotation: Any, **_: Any) -> Result:
        """Validate annotations for an XML compound field."""
        result = evaluate_element(annotation, tokens=False)

        for tp in result.types:
            evaluate_element(tp, tokens=False)

        return Result(types=(object,), factory=result.factory, optional=result.optional)

### `evaluate_wildcard(annotation, **_)`

Validate annotations for an XML wildcard.

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

    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

    def evaluate_wildcard(annotation: Any, **_: Any) -> Result:
        """Validate annotations for an XML wildcard."""
        origin = get_origin(annotation)
        factory = None

        # Compute optional status from original annotation
        if origin in UNION_TYPES:
            args = get_args(annotation)
            optional = NONE_TYPE in args
        else:
            optional = False

        if origin in UNION_TYPES:
            types = filter_none_type(args)
        elif origin in ITERABLE_TYPES:
            factory = list if origin in LIST_CONTAINERS else origin
            types = filter_ellipsis(get_args(annotation))
        elif origin is None:
            types = (annotation,)
        else:
            raise TypeError

        if len(types) != 1 or object not in types:
            raise TypeError

        return Result(types=types, factory=factory, optional=optional)