@autorest/python 6.12.4 → 6.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/autorest/codegen/models/__init__.py +2 -2
- package/autorest/codegen/models/base_builder.py +19 -6
- package/autorest/codegen/models/code_model.py +1 -21
- package/autorest/codegen/models/operation.py +3 -2
- package/autorest/codegen/models/property.py +14 -7
- package/autorest/codegen/models/request_builder.py +1 -1
- package/autorest/codegen/serializers/model_serializer.py +31 -2
- package/autorest/codegen/templates/model_base.py.jinja2 +31 -20
- package/autorest/codegen/templates/model_dpg.py.jinja2 +1 -1
- package/autorest/codegen/templates/packaging_templates/setup.py.jinja2 +3 -0
- package/autorest/codegen/templates/serialization.py.jinja2 +11 -18
- package/autorest/m4reformatter/__init__.py +4 -0
- package/package.json +1 -1
|
@@ -133,9 +133,9 @@ TYPE_TO_OBJECT = {
|
|
|
133
133
|
"binary": BinaryType,
|
|
134
134
|
"any": AnyType,
|
|
135
135
|
"datetime": DatetimeType,
|
|
136
|
-
"
|
|
136
|
+
"plainTime": TimeType,
|
|
137
137
|
"duration": DurationType,
|
|
138
|
-
"
|
|
138
|
+
"plainDate": DateType,
|
|
139
139
|
"bytes": ByteArraySchema,
|
|
140
140
|
"boolean": BooleanType,
|
|
141
141
|
"combined": CombinedType,
|
|
@@ -4,7 +4,17 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import (
|
|
8
|
+
List,
|
|
9
|
+
Dict,
|
|
10
|
+
Any,
|
|
11
|
+
Generic,
|
|
12
|
+
TypeVar,
|
|
13
|
+
Optional,
|
|
14
|
+
Union,
|
|
15
|
+
TYPE_CHECKING,
|
|
16
|
+
cast,
|
|
17
|
+
)
|
|
8
18
|
from abc import abstractmethod
|
|
9
19
|
|
|
10
20
|
from .base import BaseModel
|
|
@@ -28,11 +38,16 @@ if TYPE_CHECKING:
|
|
|
28
38
|
from .operation import Operation
|
|
29
39
|
from .request_builder import RequestBuilder
|
|
30
40
|
|
|
41
|
+
|
|
42
|
+
OverloadListType = TypeVar(
|
|
43
|
+
"OverloadListType", bound=Union[List["Operation"], List["RequestBuilder"]]
|
|
44
|
+
)
|
|
45
|
+
|
|
31
46
|
_LOGGER = logging.getLogger(__name__)
|
|
32
47
|
|
|
33
48
|
|
|
34
49
|
class BaseBuilder(
|
|
35
|
-
Generic[ParameterListType], BaseModel
|
|
50
|
+
Generic[ParameterListType, OverloadListType], BaseModel
|
|
36
51
|
): # pylint: disable=too-many-instance-attributes
|
|
37
52
|
"""Base class for Operations and Request Builders"""
|
|
38
53
|
|
|
@@ -44,16 +59,14 @@ class BaseBuilder(
|
|
|
44
59
|
name: str,
|
|
45
60
|
parameters: ParameterListType,
|
|
46
61
|
*,
|
|
47
|
-
overloads=None,
|
|
62
|
+
overloads: Optional[OverloadListType] = None,
|
|
48
63
|
) -> None:
|
|
49
64
|
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
50
65
|
self.client = client
|
|
51
66
|
self.name = name
|
|
52
67
|
self._description: str = yaml_data.get("description", "")
|
|
53
68
|
self.parameters = parameters
|
|
54
|
-
self.overloads
|
|
55
|
-
overloads or []
|
|
56
|
-
)
|
|
69
|
+
self.overloads = overloads or cast(OverloadListType, [])
|
|
57
70
|
self._summary: str = yaml_data.get("summary", "")
|
|
58
71
|
self.want_tracing: bool = yaml_data.get("wantTracing", True)
|
|
59
72
|
self.group_name: str = yaml_data[
|
|
@@ -11,7 +11,6 @@ from .model_type import ModelType
|
|
|
11
11
|
from .combined_type import CombinedType
|
|
12
12
|
from .client import Client
|
|
13
13
|
from .request_builder import RequestBuilder, OverloadedRequestBuilder
|
|
14
|
-
from .constant_type import ConstantType
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def _is_legacy(options) -> bool:
|
|
@@ -279,25 +278,6 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
279
278
|
|
|
280
279
|
@property
|
|
281
280
|
def need_typing_extensions(self) -> bool:
|
|
282
|
-
if self.options["models_mode"]
|
|
283
|
-
isinstance(p.type, ConstantType)
|
|
284
|
-
and (p.optional or self.options["models_mode"] == "dpg")
|
|
285
|
-
for model in self.model_types
|
|
286
|
-
for p in model.properties
|
|
287
|
-
):
|
|
288
|
-
return True
|
|
289
|
-
if any(
|
|
290
|
-
isinstance(parameter.type, ConstantType)
|
|
291
|
-
for client in self.clients
|
|
292
|
-
for og in client.operation_groups
|
|
293
|
-
for op in og.operations
|
|
294
|
-
for parameter in op.parameters.method
|
|
295
|
-
):
|
|
296
|
-
return True
|
|
297
|
-
if any(
|
|
298
|
-
isinstance(parameter.type, ConstantType)
|
|
299
|
-
for client in self.clients
|
|
300
|
-
for parameter in client.config.parameters.kwargs_to_pop
|
|
301
|
-
):
|
|
281
|
+
if self.options["models_mode"] == "dpg":
|
|
302
282
|
return True
|
|
303
283
|
return False
|
|
@@ -14,6 +14,7 @@ from typing import (
|
|
|
14
14
|
Generic,
|
|
15
15
|
TypeVar,
|
|
16
16
|
cast,
|
|
17
|
+
Sequence,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
from .request_builder_parameter import RequestBuilderParameter
|
|
@@ -54,7 +55,7 @@ def is_internal(target: Optional[BaseType]) -> bool:
|
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
class OperationBase( # pylint: disable=too-many-public-methods
|
|
57
|
-
Generic[ResponseType], BaseBuilder[ParameterList]
|
|
58
|
+
Generic[ResponseType], BaseBuilder[ParameterList, List["Operation"]]
|
|
58
59
|
):
|
|
59
60
|
def __init__(
|
|
60
61
|
self,
|
|
@@ -490,7 +491,7 @@ class OperationBase( # pylint: disable=too-many-public-methods
|
|
|
490
491
|
) from exc
|
|
491
492
|
|
|
492
493
|
@property
|
|
493
|
-
def success_status_codes(self) ->
|
|
494
|
+
def success_status_codes(self) -> Sequence[Union[str, int]]:
|
|
494
495
|
"""The list of all successfull status code."""
|
|
495
496
|
return sorted(
|
|
496
497
|
[code for response in self.responses for code in response.status_codes]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any, Dict, Optional, TYPE_CHECKING, List
|
|
6
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING, List, cast
|
|
7
7
|
|
|
8
8
|
from .base import BaseModel
|
|
9
9
|
from .constant_type import ConstantType
|
|
@@ -96,6 +96,17 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
96
96
|
def is_enum_discriminator(self) -> bool:
|
|
97
97
|
return self.is_discriminator and self.type.type == "enum"
|
|
98
98
|
|
|
99
|
+
@property
|
|
100
|
+
def is_base_discriminator(self) -> bool:
|
|
101
|
+
"""If this discriminator is on the base model for polymorphic inheritance"""
|
|
102
|
+
if self.is_enum_discriminator:
|
|
103
|
+
return self.is_polymorphic and self.client_default_value is None
|
|
104
|
+
return (
|
|
105
|
+
self.is_discriminator
|
|
106
|
+
and self.is_polymorphic
|
|
107
|
+
and cast(ConstantType, self.type).value is None
|
|
108
|
+
)
|
|
109
|
+
|
|
99
110
|
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
100
111
|
types_type_annotation = self.type.type_annotation(
|
|
101
112
|
is_operation_file=is_operation_file
|
|
@@ -103,17 +114,13 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
103
114
|
if self.is_multipart_file_input:
|
|
104
115
|
# we only support FileType or list of FileType
|
|
105
116
|
types_type_annotation = types_type_annotation.replace("bytes", "FileType")
|
|
106
|
-
if self.
|
|
107
|
-
|
|
108
|
-
return "Literal[None]"
|
|
117
|
+
if self.is_base_discriminator:
|
|
118
|
+
return "str"
|
|
109
119
|
if self.optional and self.client_default_value is None:
|
|
110
120
|
return f"Optional[{types_type_annotation}]"
|
|
111
121
|
return types_type_annotation
|
|
112
122
|
|
|
113
123
|
def get_declaration(self, value: Any = None) -> Any:
|
|
114
|
-
if self.is_enum_discriminator:
|
|
115
|
-
# here we are the enum discriminator property on the base model
|
|
116
|
-
return None
|
|
117
124
|
return self.type.get_declaration(value)
|
|
118
125
|
|
|
119
126
|
def get_json_template_representation(
|
|
@@ -197,6 +197,9 @@ class MsrestModelSerializer(_ModelSerializer):
|
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
class DpgModelSerializer(_ModelSerializer):
|
|
200
|
+
def super_call(self, model: ModelType):
|
|
201
|
+
return f"super().__init__({self.properties_to_pass_to_super(model)})"
|
|
202
|
+
|
|
200
203
|
def imports(self) -> FileImport:
|
|
201
204
|
file_import = FileImport(self.code_model)
|
|
202
205
|
file_import.add_submodule_import(
|
|
@@ -238,6 +241,7 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
238
241
|
if not any(
|
|
239
242
|
p.client_name == pp.client_name
|
|
240
243
|
and p.type_annotation() == pp.type_annotation()
|
|
244
|
+
and not p.is_base_discriminator
|
|
241
245
|
for pp in parent_properties
|
|
242
246
|
)
|
|
243
247
|
]
|
|
@@ -277,7 +281,7 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
277
281
|
def initialize_properties(self, model: ModelType) -> List[str]:
|
|
278
282
|
init_args = []
|
|
279
283
|
for prop in self.get_properties_to_declare(model):
|
|
280
|
-
if prop.constant
|
|
284
|
+
if prop.constant and not prop.is_base_discriminator:
|
|
281
285
|
init_args.append(
|
|
282
286
|
f"self.{prop.client_name}: {prop.type_annotation()} = "
|
|
283
287
|
f"{prop.get_declaration()}"
|
|
@@ -289,5 +293,30 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
289
293
|
return [
|
|
290
294
|
p
|
|
291
295
|
for p in model.properties
|
|
292
|
-
if
|
|
296
|
+
if p.is_base_discriminator
|
|
297
|
+
or not p.is_discriminator
|
|
298
|
+
and not p.constant
|
|
299
|
+
and p.visibility != ["read"]
|
|
293
300
|
]
|
|
301
|
+
|
|
302
|
+
@staticmethod
|
|
303
|
+
def properties_to_pass_to_super(model: ModelType) -> str:
|
|
304
|
+
properties_to_pass_to_super = ["*args"]
|
|
305
|
+
for parent in model.parents:
|
|
306
|
+
for prop in model.properties:
|
|
307
|
+
if (
|
|
308
|
+
prop.client_name
|
|
309
|
+
in [
|
|
310
|
+
prop.client_name
|
|
311
|
+
for prop in parent.properties
|
|
312
|
+
if prop.is_base_discriminator
|
|
313
|
+
]
|
|
314
|
+
and prop.is_discriminator
|
|
315
|
+
and not prop.constant
|
|
316
|
+
and not prop.readonly
|
|
317
|
+
):
|
|
318
|
+
properties_to_pass_to_super.append(
|
|
319
|
+
f"{prop.client_name}={prop.get_declaration()}"
|
|
320
|
+
)
|
|
321
|
+
properties_to_pass_to_super.append("**kwargs")
|
|
322
|
+
return ", ".join(properties_to_pass_to_super)
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
# license information.
|
|
6
6
|
# --------------------------------------------------------------------------
|
|
7
7
|
# pylint: disable=protected-access, arguments-differ, signature-differs, broad-except
|
|
8
|
-
# pyright: reportGeneralTypeIssues=false
|
|
9
8
|
|
|
10
9
|
import calendar
|
|
11
10
|
import decimal
|
|
@@ -19,6 +18,7 @@ import typing
|
|
|
19
18
|
import email.utils
|
|
20
19
|
from datetime import datetime, date, time, timedelta, timezone
|
|
21
20
|
from json import JSONEncoder
|
|
21
|
+
from typing_extensions import Self
|
|
22
22
|
import isodate
|
|
23
23
|
from {{ code_model.core_library }}.exceptions import DeserializationError
|
|
24
24
|
from {{ code_model.core_library }}{{ ".utils" if code_model.options["unbranded"] else "" }} import CaseInsensitiveEnumMeta
|
|
@@ -35,6 +35,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
35
35
|
__all__ = ["SdkJSONEncoder", "Model", "rest_field", "rest_discriminator"]
|
|
36
36
|
|
|
37
37
|
TZ_UTC = timezone.utc
|
|
38
|
+
_T = typing.TypeVar("_T")
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
def _timedelta_as_isostr(td: timedelta) -> str:
|
|
@@ -242,7 +243,7 @@ def _deserialize_date(attr: typing.Union[str, date]) -> date:
|
|
|
242
243
|
# This must NOT use defaultmonth/defaultday. Using None ensure this raises an exception.
|
|
243
244
|
if isinstance(attr, date):
|
|
244
245
|
return attr
|
|
245
|
-
return isodate.parse_date(attr, defaultmonth=None, defaultday=None)
|
|
246
|
+
return isodate.parse_date(attr, defaultmonth=None, defaultday=None) # type: ignore
|
|
246
247
|
|
|
247
248
|
|
|
248
249
|
def _deserialize_time(attr: typing.Union[str, time]) -> time:
|
|
@@ -383,8 +384,12 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=uns
|
|
|
383
384
|
except KeyError:
|
|
384
385
|
return default
|
|
385
386
|
|
|
386
|
-
@typing.overload
|
|
387
|
-
def pop(self, key: str) -> typing.Any:
|
|
387
|
+
@typing.overload
|
|
388
|
+
def pop(self, key: str) -> typing.Any:
|
|
389
|
+
...
|
|
390
|
+
|
|
391
|
+
@typing.overload
|
|
392
|
+
def pop(self, key: str, default: _T) -> _T:
|
|
388
393
|
...
|
|
389
394
|
|
|
390
395
|
@typing.overload
|
|
@@ -405,8 +410,8 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=uns
|
|
|
405
410
|
def update(self, *args: typing.Any, **kwargs: typing.Any) -> None:
|
|
406
411
|
self._data.update(*args, **kwargs)
|
|
407
412
|
|
|
408
|
-
@typing.overload
|
|
409
|
-
def setdefault(self, key: str) ->
|
|
413
|
+
@typing.overload
|
|
414
|
+
def setdefault(self, key: str, default: None = None) -> None:
|
|
410
415
|
...
|
|
411
416
|
|
|
412
417
|
@typing.overload
|
|
@@ -512,7 +517,7 @@ class Model(_MyMutableMapping):
|
|
|
512
517
|
def copy(self) -> "Model":
|
|
513
518
|
return Model(self.__dict__)
|
|
514
519
|
|
|
515
|
-
def __new__(cls, *args: typing.Any, **kwargs: typing.Any) ->
|
|
520
|
+
def __new__(cls, *args: typing.Any, **kwargs: typing.Any) -> Self: # pylint: disable=unused-argument
|
|
516
521
|
# we know the last three classes in mro are going to be 'Model', 'dict', and 'object'
|
|
517
522
|
mros = cls.__mro__[:-3][::-1] # ignore model, dict, and object parents, and reverse the mro order
|
|
518
523
|
attr_to_rest_field: typing.Dict[str, _RestField] = { # map attribute name to rest_field property
|
|
@@ -554,7 +559,7 @@ class Model(_MyMutableMapping):
|
|
|
554
559
|
exist_discriminators.append(discriminator)
|
|
555
560
|
mapped_cls = cls.__mapping__.get(
|
|
556
561
|
data.get(discriminator), cls
|
|
557
|
-
) # pylint: disable=no-member
|
|
562
|
+
) # pyright: ignore # pylint: disable=no-member
|
|
558
563
|
if mapped_cls == cls:
|
|
559
564
|
return cls(data)
|
|
560
565
|
return mapped_cls._deserialize(data, exist_discriminators) # pylint: disable=protected-access
|
|
@@ -571,7 +576,7 @@ class Model(_MyMutableMapping):
|
|
|
571
576
|
if exclude_readonly:
|
|
572
577
|
readonly_props = [p._rest_name for p in self._attr_to_rest_field.values() if _is_readonly(p)]
|
|
573
578
|
for k, v in self.items():
|
|
574
|
-
if exclude_readonly and k in readonly_props: # pyright: ignore
|
|
579
|
+
if exclude_readonly and k in readonly_props: # pyright: ignore
|
|
575
580
|
continue
|
|
576
581
|
is_multipart_file_input = False
|
|
577
582
|
try:
|
|
@@ -630,22 +635,22 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
|
|
|
630
635
|
return obj
|
|
631
636
|
return _deserialize(model_deserializer, obj)
|
|
632
637
|
|
|
633
|
-
return functools.partial(_deserialize_model, annotation)
|
|
638
|
+
return functools.partial(_deserialize_model, annotation) # pyright: ignore
|
|
634
639
|
except Exception:
|
|
635
640
|
pass
|
|
636
641
|
|
|
637
642
|
# is it a literal?
|
|
638
643
|
try:
|
|
639
|
-
if annotation.__origin__ is typing.Literal:
|
|
644
|
+
if annotation.__origin__ is typing.Literal: # pyright: ignore
|
|
640
645
|
return None
|
|
641
646
|
except AttributeError:
|
|
642
647
|
pass
|
|
643
648
|
|
|
644
649
|
# is it optional?
|
|
645
650
|
try:
|
|
646
|
-
if any(a for a in annotation.__args__ if a == type(None)):
|
|
651
|
+
if any(a for a in annotation.__args__ if a == type(None)): # pyright: ignore
|
|
647
652
|
if_obj_deserializer = _get_deserialize_callable_from_annotation(
|
|
648
|
-
next(a for a in annotation.__args__ if a != type(None)), module, rf
|
|
653
|
+
next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore
|
|
649
654
|
)
|
|
650
655
|
|
|
651
656
|
def _deserialize_with_optional(if_obj_deserializer: typing.Optional[typing.Callable], obj):
|
|
@@ -658,7 +663,9 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
|
|
|
658
663
|
pass
|
|
659
664
|
|
|
660
665
|
if getattr(annotation, "__origin__", None) is typing.Union:
|
|
661
|
-
deserializers = [
|
|
666
|
+
deserializers = [
|
|
667
|
+
_get_deserialize_callable_from_annotation(arg, module, rf) for arg in annotation.__args__ # pyright: ignore
|
|
668
|
+
]
|
|
662
669
|
|
|
663
670
|
def _deserialize_with_union(deserializers, obj):
|
|
664
671
|
for deserializer in deserializers:
|
|
@@ -671,8 +678,10 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
|
|
|
671
678
|
return functools.partial(_deserialize_with_union, deserializers)
|
|
672
679
|
|
|
673
680
|
try:
|
|
674
|
-
if annotation._name == "Dict":
|
|
675
|
-
value_deserializer = _get_deserialize_callable_from_annotation(
|
|
681
|
+
if annotation._name == "Dict": # pyright: ignore
|
|
682
|
+
value_deserializer = _get_deserialize_callable_from_annotation(
|
|
683
|
+
annotation.__args__[1], module, rf # pyright: ignore
|
|
684
|
+
)
|
|
676
685
|
|
|
677
686
|
def _deserialize_dict(
|
|
678
687
|
value_deserializer: typing.Optional[typing.Callable],
|
|
@@ -692,8 +701,8 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
|
|
|
692
701
|
except (AttributeError, IndexError):
|
|
693
702
|
pass
|
|
694
703
|
try:
|
|
695
|
-
if annotation._name in ["List", "Set", "Tuple", "Sequence"]:
|
|
696
|
-
if len(annotation.__args__) > 1:
|
|
704
|
+
if annotation._name in ["List", "Set", "Tuple", "Sequence"]: # pyright: ignore
|
|
705
|
+
if len(annotation.__args__) > 1: # pyright: ignore
|
|
697
706
|
|
|
698
707
|
def _deserialize_multiple_sequence(
|
|
699
708
|
entry_deserializers: typing.List[typing.Optional[typing.Callable]],
|
|
@@ -707,10 +716,12 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915,
|
|
|
707
716
|
)
|
|
708
717
|
|
|
709
718
|
entry_deserializers = [
|
|
710
|
-
_get_deserialize_callable_from_annotation(dt, module, rf) for dt in annotation.__args__
|
|
719
|
+
_get_deserialize_callable_from_annotation(dt, module, rf) for dt in annotation.__args__ # pyright: ignore
|
|
711
720
|
]
|
|
712
721
|
return functools.partial(_deserialize_multiple_sequence, entry_deserializers)
|
|
713
|
-
deserializer = _get_deserialize_callable_from_annotation(
|
|
722
|
+
deserializer = _get_deserialize_callable_from_annotation(
|
|
723
|
+
annotation.__args__[0], module, rf # pyright: ignore
|
|
724
|
+
)
|
|
714
725
|
|
|
715
726
|
def _deserialize_sequence(
|
|
716
727
|
deserializer: typing.Optional[typing.Callable],
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
{% set initialize_properties = serializer.initialize_properties(model) %}
|
|
61
61
|
{% if not model.internal and serializer.init_line(model) or initialize_properties %}
|
|
62
62
|
def __init__(self, *args: Any, **kwargs: Any) -> None:{{ '# pylint: disable=useless-super-delegation' if not initialize_properties else '' }}
|
|
63
|
-
|
|
63
|
+
{{ serializer.super_call(model) }}
|
|
64
64
|
{% for initialize_property in initialize_properties %}
|
|
65
65
|
{{ initialize_property }}
|
|
66
66
|
{% endfor %}
|
|
@@ -170,13 +170,6 @@ class RawDeserializer:
|
|
|
170
170
|
return None
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
try:
|
|
174
|
-
basestring # type: ignore
|
|
175
|
-
unicode_str = unicode # type: ignore
|
|
176
|
-
except NameError:
|
|
177
|
-
basestring = str
|
|
178
|
-
unicode_str = str
|
|
179
|
-
|
|
180
173
|
_LOGGER = logging.getLogger(__name__)
|
|
181
174
|
|
|
182
175
|
try:
|
|
@@ -547,7 +540,7 @@ class Serializer(object):
|
|
|
547
540
|
"multiple": lambda x, y: x % y != 0,
|
|
548
541
|
}
|
|
549
542
|
|
|
550
|
-
def __init__(self, classes: Optional[Mapping[str,
|
|
543
|
+
def __init__(self, classes: Optional[Mapping[str, type]]=None):
|
|
551
544
|
self.serialize_type = {
|
|
552
545
|
"iso-8601": Serializer.serialize_iso,
|
|
553
546
|
"rfc-1123": Serializer.serialize_rfc,
|
|
@@ -563,7 +556,7 @@ class Serializer(object):
|
|
|
563
556
|
"[]": self.serialize_iter,
|
|
564
557
|
"{}": self.serialize_dict,
|
|
565
558
|
}
|
|
566
|
-
self.dependencies: Dict[str,
|
|
559
|
+
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
|
|
567
560
|
self.key_transformer = full_restapi_key_transformer
|
|
568
561
|
self.client_side_validation = True
|
|
569
562
|
|
|
@@ -651,7 +644,7 @@ class Serializer(object):
|
|
|
651
644
|
else: # That's a basic type
|
|
652
645
|
# Integrate namespace if necessary
|
|
653
646
|
local_node = _create_xml_node(xml_name, xml_prefix, xml_ns)
|
|
654
|
-
local_node.text =
|
|
647
|
+
local_node.text = str(new_attr)
|
|
655
648
|
serialized.append(local_node) # type: ignore
|
|
656
649
|
else: # JSON
|
|
657
650
|
for k in reversed(keys): # type: ignore
|
|
@@ -1000,7 +993,7 @@ class Serializer(object):
|
|
|
1000
993
|
return self.serialize_basic(attr, self.basic_types[obj_type], **kwargs)
|
|
1001
994
|
if obj_type is _long_type:
|
|
1002
995
|
return self.serialize_long(attr)
|
|
1003
|
-
if obj_type is
|
|
996
|
+
if obj_type is str:
|
|
1004
997
|
return self.serialize_unicode(attr)
|
|
1005
998
|
if obj_type is datetime.datetime:
|
|
1006
999
|
return self.serialize_iso(attr)
|
|
@@ -1376,7 +1369,7 @@ class Deserializer(object):
|
|
|
1376
1369
|
|
|
1377
1370
|
valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}" r"\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
|
|
1378
1371
|
|
|
1379
|
-
def __init__(self, classes: Optional[Mapping[str,
|
|
1372
|
+
def __init__(self, classes: Optional[Mapping[str, type]]=None):
|
|
1380
1373
|
self.deserialize_type = {
|
|
1381
1374
|
"iso-8601": Deserializer.deserialize_iso,
|
|
1382
1375
|
"rfc-1123": Deserializer.deserialize_rfc,
|
|
@@ -1396,7 +1389,7 @@ class Deserializer(object):
|
|
|
1396
1389
|
"duration": (isodate.Duration, datetime.timedelta),
|
|
1397
1390
|
"iso-8601": (datetime.datetime),
|
|
1398
1391
|
}
|
|
1399
|
-
self.dependencies: Dict[str,
|
|
1392
|
+
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
|
|
1400
1393
|
self.key_extractors = [rest_key_extractor, xml_key_extractor]
|
|
1401
1394
|
# Additional properties only works if the "rest_key_extractor" is used to
|
|
1402
1395
|
# extract the keys. Making it to work whatever the key extractor is too much
|
|
@@ -1449,7 +1442,7 @@ class Deserializer(object):
|
|
|
1449
1442
|
|
|
1450
1443
|
response, class_name = self._classify_target(target_obj, data)
|
|
1451
1444
|
|
|
1452
|
-
if isinstance(response,
|
|
1445
|
+
if isinstance(response, str):
|
|
1453
1446
|
return self.deserialize_data(data, response)
|
|
1454
1447
|
elif isinstance(response, type) and issubclass(response, Enum):
|
|
1455
1448
|
return self.deserialize_enum(data, response)
|
|
@@ -1520,7 +1513,7 @@ class Deserializer(object):
|
|
|
1520
1513
|
if target is None:
|
|
1521
1514
|
return None, None
|
|
1522
1515
|
|
|
1523
|
-
if isinstance(target,
|
|
1516
|
+
if isinstance(target, str):
|
|
1524
1517
|
try:
|
|
1525
1518
|
target = self.dependencies[target]
|
|
1526
1519
|
except KeyError:
|
|
@@ -1583,7 +1576,7 @@ class Deserializer(object):
|
|
|
1583
1576
|
if hasattr(raw_data, "_content_consumed"):
|
|
1584
1577
|
return RawDeserializer.deserialize_from_http_generics(raw_data.text, raw_data.headers)
|
|
1585
1578
|
|
|
1586
|
-
if isinstance(raw_data, (
|
|
1579
|
+
if isinstance(raw_data, (str, bytes)) or hasattr(raw_data, "read"):
|
|
1587
1580
|
return RawDeserializer.deserialize_from_text(raw_data, content_type) # type: ignore
|
|
1588
1581
|
return raw_data
|
|
1589
1582
|
|
|
@@ -1705,7 +1698,7 @@ class Deserializer(object):
|
|
|
1705
1698
|
if isinstance(attr, ET.Element):
|
|
1706
1699
|
# Do no recurse on XML, just return the tree as-is
|
|
1707
1700
|
return attr
|
|
1708
|
-
if isinstance(attr,
|
|
1701
|
+
if isinstance(attr, str):
|
|
1709
1702
|
return self.deserialize_basic(attr, "str")
|
|
1710
1703
|
obj_type = type(attr)
|
|
1711
1704
|
if obj_type in self.basic_types:
|
|
@@ -1762,7 +1755,7 @@ class Deserializer(object):
|
|
|
1762
1755
|
if data_type == "bool":
|
|
1763
1756
|
if attr in [True, False, 1, 0]:
|
|
1764
1757
|
return bool(attr)
|
|
1765
|
-
elif isinstance(attr,
|
|
1758
|
+
elif isinstance(attr, str):
|
|
1766
1759
|
if attr.lower() in ["true", "1"]:
|
|
1767
1760
|
return True
|
|
1768
1761
|
elif attr.lower() in ["false", "0"]:
|
|
@@ -240,6 +240,10 @@ def update_primitive( # pylint: disable=too-many-return-statements
|
|
|
240
240
|
base = _update_type_base("bytes", yaml_data)
|
|
241
241
|
base["encode"] = yaml_data["format"]
|
|
242
242
|
return base
|
|
243
|
+
if type_group == "date":
|
|
244
|
+
return _update_type_base("plainDate", yaml_data)
|
|
245
|
+
if type_group == "time":
|
|
246
|
+
return _update_type_base("plainTime", yaml_data)
|
|
243
247
|
return _update_type_base(type_group, yaml_data)
|
|
244
248
|
|
|
245
249
|
|