@azure-tools/typespec-python 0.29.0 → 0.31.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/dist/scripts/eng/format.d.ts +2 -0
- package/dist/scripts/eng/format.d.ts.map +1 -0
- package/dist/scripts/eng/format.js +4 -0
- package/dist/scripts/eng/format.js.map +1 -0
- package/dist/scripts/eng/lint.d.ts +5 -0
- package/dist/scripts/eng/lint.d.ts.map +1 -0
- package/dist/scripts/eng/lint.js +66 -0
- package/dist/scripts/eng/lint.js.map +1 -0
- package/dist/scripts/{regenerate.d.ts.map → eng/regenerate.d.ts.map} +1 -1
- package/dist/scripts/{regenerate.js → eng/regenerate.js} +27 -29
- package/dist/scripts/eng/regenerate.js.map +1 -0
- package/dist/scripts/{run-tests.d.ts.map → eng/run-tests.d.ts.map} +1 -1
- package/dist/scripts/eng/run-tests.js +80 -0
- package/dist/scripts/eng/run-tests.js.map +1 -0
- package/dist/scripts/eng/utils.d.ts +3 -0
- package/dist/scripts/eng/utils.d.ts.map +1 -0
- package/dist/scripts/eng/utils.js +39 -0
- package/dist/scripts/eng/utils.js.map +1 -0
- package/dist/scripts/system-requirements.d.ts.map +1 -1
- package/dist/scripts/system-requirements.js.map +1 -1
- package/dist/src/code-model.d.ts.map +1 -1
- package/dist/src/code-model.js +4 -1
- package/dist/src/code-model.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +17 -4
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/external-process.d.ts +0 -1
- package/dist/src/external-process.d.ts.map +1 -1
- package/dist/src/http.js +14 -8
- package/dist/src/http.js.map +1 -1
- package/dist/src/lib.d.ts +1 -0
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +1 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +82 -9
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils.d.ts +2 -2
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +65 -10
- package/dist/src/utils.js.map +1 -1
- package/generator/pygen/black.py +2 -3
- package/generator/pygen/codegen/models/combined_type.py +1 -1
- package/generator/pygen/codegen/models/credential_types.py +7 -14
- package/generator/pygen/codegen/models/enum_type.py +1 -1
- package/generator/pygen/codegen/models/lro_operation.py +0 -1
- package/generator/pygen/codegen/models/lro_paging_operation.py +1 -1
- package/generator/pygen/codegen/models/model_type.py +5 -7
- package/generator/pygen/codegen/models/operation.py +13 -2
- package/generator/pygen/codegen/models/paging_operation.py +0 -1
- package/generator/pygen/codegen/models/parameter.py +5 -1
- package/generator/pygen/codegen/models/parameter_list.py +2 -5
- package/generator/pygen/codegen/models/primitive_types.py +11 -4
- package/generator/pygen/codegen/models/property.py +5 -1
- package/generator/pygen/codegen/serializers/__init__.py +1 -1
- package/generator/pygen/codegen/serializers/builder_serializer.py +22 -20
- package/generator/pygen/codegen/serializers/general_serializer.py +2 -1
- package/generator/pygen/codegen/serializers/model_serializer.py +3 -0
- package/generator/pygen/codegen/serializers/sample_serializer.py +1 -3
- package/generator/pygen/codegen/serializers/test_serializer.py +6 -0
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +319 -67
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +5 -0
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +271 -162
- package/generator/pygen/codegen/templates/test.py.jinja2 +2 -2
- package/generator/pygen/m2r.py +1 -1
- package/generator/pygen/postprocess/__init__.py +2 -2
- package/generator/pygen/postprocess/venvtools.py +1 -3
- package/generator/pygen/preprocess/__init__.py +1 -1
- package/generator/pygen/utils.py +10 -3
- package/generator/setup.py +1 -1
- package/package.json +13 -10
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
- package/scripts/eng/format.ts +5 -0
- package/scripts/eng/lint.ts +75 -0
- package/scripts/eng/mypy.ini +38 -0
- package/scripts/eng/pylintrc +58 -0
- package/scripts/eng/pyrightconfig.json +6 -0
- package/scripts/{regenerate.ts → eng/regenerate.ts} +40 -33
- package/scripts/eng/run-tests.ts +90 -0
- package/scripts/eng/utils.ts +38 -0
- package/scripts/run_tsp.py +7 -5
- package/dist/scripts/regenerate.js.map +0 -1
- package/dist/scripts/run-tests.js +0 -50
- package/dist/scripts/run-tests.js.map +0 -1
- package/scripts/run-tests.ts +0 -57
- /package/dist/scripts/{regenerate.d.ts → eng/regenerate.d.ts} +0 -0
- /package/dist/scripts/{run-tests.d.ts → eng/run-tests.d.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint: disable=too-many-lines
|
|
1
2
|
# --------------------------------------------------------------------------
|
|
2
3
|
#
|
|
3
4
|
# Copyright (c) {{ code_model.options["company_name"] }} Corporation. All rights reserved.
|
|
@@ -24,7 +25,6 @@
|
|
|
24
25
|
#
|
|
25
26
|
# --------------------------------------------------------------------------
|
|
26
27
|
|
|
27
|
-
# pylint: skip-file
|
|
28
28
|
# pyright: reportUnnecessaryTypeIgnoreComment=false
|
|
29
29
|
|
|
30
30
|
from base64 import b64decode, b64encode
|
|
@@ -52,7 +52,6 @@ from typing import (
|
|
|
52
52
|
MutableMapping,
|
|
53
53
|
Type,
|
|
54
54
|
List,
|
|
55
|
-
Mapping,
|
|
56
55
|
)
|
|
57
56
|
|
|
58
57
|
try:
|
|
@@ -91,6 +90,8 @@ class RawDeserializer:
|
|
|
91
90
|
:param data: Input, could be bytes or stream (will be decoded with UTF8) or text
|
|
92
91
|
:type data: str or bytes or IO
|
|
93
92
|
:param str content_type: The content type.
|
|
93
|
+
:return: The deserialized data.
|
|
94
|
+
:rtype: object
|
|
94
95
|
"""
|
|
95
96
|
if hasattr(data, "read"):
|
|
96
97
|
# Assume a stream
|
|
@@ -112,7 +113,7 @@ class RawDeserializer:
|
|
|
112
113
|
try:
|
|
113
114
|
return json.loads(data_as_str)
|
|
114
115
|
except ValueError as err:
|
|
115
|
-
raise DeserializationError("JSON is invalid: {}".format(err), err)
|
|
116
|
+
raise DeserializationError("JSON is invalid: {}".format(err), err) from err
|
|
116
117
|
elif "xml" in (content_type or []):
|
|
117
118
|
try:
|
|
118
119
|
|
|
@@ -155,6 +156,11 @@ class RawDeserializer:
|
|
|
155
156
|
Use bytes and headers to NOT use any requests/aiohttp or whatever
|
|
156
157
|
specific implementation.
|
|
157
158
|
Headers will tested for "content-type"
|
|
159
|
+
|
|
160
|
+
:param bytes body_bytes: The body of the response.
|
|
161
|
+
:param dict headers: The headers of the response.
|
|
162
|
+
:returns: The deserialized data.
|
|
163
|
+
:rtype: object
|
|
158
164
|
"""
|
|
159
165
|
# Try to use content-type from headers if available
|
|
160
166
|
content_type = None
|
|
@@ -184,15 +190,30 @@ class UTC(datetime.tzinfo):
|
|
|
184
190
|
"""Time Zone info for handling UTC"""
|
|
185
191
|
|
|
186
192
|
def utcoffset(self, dt):
|
|
187
|
-
"""UTF offset for UTC is 0.
|
|
193
|
+
"""UTF offset for UTC is 0.
|
|
194
|
+
|
|
195
|
+
:param datetime.datetime dt: The datetime
|
|
196
|
+
:returns: The offset
|
|
197
|
+
:rtype: datetime.timedelta
|
|
198
|
+
"""
|
|
188
199
|
return datetime.timedelta(0)
|
|
189
200
|
|
|
190
201
|
def tzname(self, dt):
|
|
191
|
-
"""Timestamp representation.
|
|
202
|
+
"""Timestamp representation.
|
|
203
|
+
|
|
204
|
+
:param datetime.datetime dt: The datetime
|
|
205
|
+
:returns: The timestamp representation
|
|
206
|
+
:rtype: str
|
|
207
|
+
"""
|
|
192
208
|
return "Z"
|
|
193
209
|
|
|
194
210
|
def dst(self, dt):
|
|
195
|
-
"""No daylight saving for UTC.
|
|
211
|
+
"""No daylight saving for UTC.
|
|
212
|
+
|
|
213
|
+
:param datetime.datetime dt: The datetime
|
|
214
|
+
:returns: The daylight saving time
|
|
215
|
+
:rtype: datetime.timedelta
|
|
216
|
+
"""
|
|
196
217
|
return datetime.timedelta(hours=1)
|
|
197
218
|
|
|
198
219
|
|
|
@@ -235,24 +256,26 @@ except ImportError:
|
|
|
235
256
|
_FLATTEN = re.compile(r"(?<!\\)\.")
|
|
236
257
|
|
|
237
258
|
|
|
238
|
-
def attribute_transformer(key, attr_desc, value):
|
|
259
|
+
def attribute_transformer(key, attr_desc, value): # pylint: disable=unused-argument
|
|
239
260
|
"""A key transformer that returns the Python attribute.
|
|
240
261
|
|
|
241
262
|
:param str key: The attribute name
|
|
242
263
|
:param dict attr_desc: The attribute metadata
|
|
243
264
|
:param object value: The value
|
|
244
265
|
:returns: A key using attribute name
|
|
266
|
+
:rtype: str
|
|
245
267
|
"""
|
|
246
268
|
return (key, value)
|
|
247
269
|
|
|
248
270
|
|
|
249
|
-
def full_restapi_key_transformer(key, attr_desc, value):
|
|
271
|
+
def full_restapi_key_transformer(key, attr_desc, value): # pylint: disable=unused-argument
|
|
250
272
|
"""A key transformer that returns the full RestAPI key path.
|
|
251
273
|
|
|
252
|
-
:param str
|
|
274
|
+
:param str key: The attribute name
|
|
253
275
|
:param dict attr_desc: The attribute metadata
|
|
254
276
|
:param object value: The value
|
|
255
277
|
:returns: A list of keys using RestAPI syntax.
|
|
278
|
+
:rtype: list
|
|
256
279
|
"""
|
|
257
280
|
keys = _FLATTEN.split(attr_desc["key"])
|
|
258
281
|
return ([_decode_attribute_map_key(k) for k in keys], value)
|
|
@@ -265,19 +288,26 @@ def last_restapi_key_transformer(key, attr_desc, value):
|
|
|
265
288
|
:param dict attr_desc: The attribute metadata
|
|
266
289
|
:param object value: The value
|
|
267
290
|
:returns: The last RestAPI key.
|
|
291
|
+
:rtype: str
|
|
268
292
|
"""
|
|
269
293
|
key, value = full_restapi_key_transformer(key, attr_desc, value)
|
|
270
294
|
return (key[-1], value)
|
|
271
295
|
|
|
272
296
|
|
|
273
297
|
def _create_xml_node(tag, prefix=None, ns=None):
|
|
274
|
-
"""Create a XML node.
|
|
298
|
+
"""Create a XML node.
|
|
299
|
+
|
|
300
|
+
:param str tag: The tag name
|
|
301
|
+
:param str prefix: The prefix
|
|
302
|
+
:param str ns: The namespace
|
|
303
|
+
:return: The XML node
|
|
304
|
+
:rtype: xml.etree.ElementTree.Element
|
|
305
|
+
"""
|
|
275
306
|
if prefix and ns:
|
|
276
307
|
ET.register_namespace(prefix, ns)
|
|
277
308
|
if ns:
|
|
278
309
|
return ET.Element("{" + ns + "}" + tag)
|
|
279
|
-
|
|
280
|
-
return ET.Element(tag)
|
|
310
|
+
return ET.Element(tag)
|
|
281
311
|
|
|
282
312
|
|
|
283
313
|
class Model(object):
|
|
@@ -291,7 +321,7 @@ class Model(object):
|
|
|
291
321
|
|
|
292
322
|
def __init__(self, **kwargs: Any) -> None:
|
|
293
323
|
self.additional_properties: Optional[Dict[str, Any]] = {}
|
|
294
|
-
for k in kwargs:
|
|
324
|
+
for k in kwargs: # pylint: disable=consider-using-dict-items
|
|
295
325
|
if k not in self._attribute_map:
|
|
296
326
|
_LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
|
|
297
327
|
elif k in self._validation and self._validation[k].get("readonly", False):
|
|
@@ -300,13 +330,23 @@ class Model(object):
|
|
|
300
330
|
setattr(self, k, kwargs[k])
|
|
301
331
|
|
|
302
332
|
def __eq__(self, other: Any) -> bool:
|
|
303
|
-
"""Compare objects by comparing all attributes.
|
|
333
|
+
"""Compare objects by comparing all attributes.
|
|
334
|
+
|
|
335
|
+
:param object other: The object to compare
|
|
336
|
+
:returns: True if objects are equal
|
|
337
|
+
:rtype: bool
|
|
338
|
+
"""
|
|
304
339
|
if isinstance(other, self.__class__):
|
|
305
340
|
return self.__dict__ == other.__dict__
|
|
306
341
|
return False
|
|
307
342
|
|
|
308
343
|
def __ne__(self, other: Any) -> bool:
|
|
309
|
-
"""Compare objects by comparing all attributes.
|
|
344
|
+
"""Compare objects by comparing all attributes.
|
|
345
|
+
|
|
346
|
+
:param object other: The object to compare
|
|
347
|
+
:returns: True if objects are not equal
|
|
348
|
+
:rtype: bool
|
|
349
|
+
"""
|
|
310
350
|
return not self.__eq__(other)
|
|
311
351
|
|
|
312
352
|
def __str__(self) -> str:
|
|
@@ -326,7 +366,11 @@ class Model(object):
|
|
|
326
366
|
|
|
327
367
|
@classmethod
|
|
328
368
|
def _create_xml_node(cls):
|
|
329
|
-
"""Create XML node.
|
|
369
|
+
"""Create XML node.
|
|
370
|
+
|
|
371
|
+
:returns: The XML node
|
|
372
|
+
:rtype: xml.etree.ElementTree.Element
|
|
373
|
+
"""
|
|
330
374
|
try:
|
|
331
375
|
xml_map = cls._xml_map # type: ignore
|
|
332
376
|
except AttributeError:
|
|
@@ -346,14 +390,14 @@ class Model(object):
|
|
|
346
390
|
:rtype: dict
|
|
347
391
|
"""
|
|
348
392
|
serializer = Serializer(self._infer_class_models())
|
|
349
|
-
return serializer._serialize(
|
|
393
|
+
return serializer._serialize( # type: ignore # pylint: disable=protected-access
|
|
394
|
+
self, keep_readonly=keep_readonly, **kwargs
|
|
395
|
+
)
|
|
350
396
|
|
|
351
397
|
def as_dict(
|
|
352
398
|
self,
|
|
353
399
|
keep_readonly: bool = True,
|
|
354
|
-
key_transformer: Callable[
|
|
355
|
-
[str, Dict[str, Any], Any], Any
|
|
356
|
-
] = attribute_transformer,
|
|
400
|
+
key_transformer: Callable[[str, Dict[str, Any], Any], Any] = attribute_transformer,
|
|
357
401
|
**kwargs: Any
|
|
358
402
|
) -> JSON:
|
|
359
403
|
"""Return a dict that can be serialized using json.dump.
|
|
@@ -382,12 +426,15 @@ class Model(object):
|
|
|
382
426
|
|
|
383
427
|
If you want XML serialization, you can pass the kwargs is_xml=True.
|
|
384
428
|
|
|
429
|
+
:param bool keep_readonly: If you want to serialize the readonly attributes
|
|
385
430
|
:param function key_transformer: A key transformer function.
|
|
386
431
|
:returns: A dict JSON compatible object
|
|
387
432
|
:rtype: dict
|
|
388
433
|
"""
|
|
389
434
|
serializer = Serializer(self._infer_class_models())
|
|
390
|
-
return serializer._serialize(
|
|
435
|
+
return serializer._serialize( # type: ignore # pylint: disable=protected-access
|
|
436
|
+
self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs
|
|
437
|
+
)
|
|
391
438
|
|
|
392
439
|
@classmethod
|
|
393
440
|
def _infer_class_models(cls):
|
|
@@ -397,7 +444,7 @@ class Model(object):
|
|
|
397
444
|
client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
|
|
398
445
|
if cls.__name__ not in client_models:
|
|
399
446
|
raise ValueError("Not Autorest generated code")
|
|
400
|
-
except Exception:
|
|
447
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
401
448
|
# Assume it's not Autorest generated (tests?). Add ourselves as dependencies.
|
|
402
449
|
client_models = {cls.__name__: cls}
|
|
403
450
|
return client_models
|
|
@@ -410,6 +457,7 @@ class Model(object):
|
|
|
410
457
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
411
458
|
:returns: An instance of this model
|
|
412
459
|
:raises: DeserializationError if something went wrong
|
|
460
|
+
:rtype: ModelType
|
|
413
461
|
"""
|
|
414
462
|
deserializer = Deserializer(cls._infer_class_models())
|
|
415
463
|
return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
|
|
@@ -428,9 +476,11 @@ class Model(object):
|
|
|
428
476
|
and last_rest_key_case_insensitive_extractor)
|
|
429
477
|
|
|
430
478
|
:param dict data: A dict using RestAPI structure
|
|
479
|
+
:param function key_extractors: A key extractor function.
|
|
431
480
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
432
481
|
:returns: An instance of this model
|
|
433
482
|
:raises: DeserializationError if something went wrong
|
|
483
|
+
:rtype: ModelType
|
|
434
484
|
"""
|
|
435
485
|
deserializer = Deserializer(cls._infer_class_models())
|
|
436
486
|
deserializer.key_extractors = ( # type: ignore
|
|
@@ -450,7 +500,7 @@ class Model(object):
|
|
|
450
500
|
return {}
|
|
451
501
|
result = dict(cls._subtype_map[key])
|
|
452
502
|
for valuetype in cls._subtype_map[key].values():
|
|
453
|
-
result.update(objects[valuetype]._flatten_subtype(key, objects))
|
|
503
|
+
result.update(objects[valuetype]._flatten_subtype(key, objects)) # pylint: disable=protected-access
|
|
454
504
|
return result
|
|
455
505
|
|
|
456
506
|
@classmethod
|
|
@@ -458,6 +508,11 @@ class Model(object):
|
|
|
458
508
|
"""Check the class _subtype_map for any child classes.
|
|
459
509
|
We want to ignore any inherited _subtype_maps.
|
|
460
510
|
Remove the polymorphic key from the initial data.
|
|
511
|
+
|
|
512
|
+
:param dict response: The initial data
|
|
513
|
+
:param dict objects: The class objects
|
|
514
|
+
:returns: The class to be used
|
|
515
|
+
:rtype: class
|
|
461
516
|
"""
|
|
462
517
|
for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
|
|
463
518
|
subtype_value = None
|
|
@@ -503,11 +558,13 @@ def _decode_attribute_map_key(key):
|
|
|
503
558
|
inside the received data.
|
|
504
559
|
|
|
505
560
|
:param str key: A key string from the generated code
|
|
561
|
+
:returns: The decoded key
|
|
562
|
+
:rtype: str
|
|
506
563
|
"""
|
|
507
564
|
return key.replace("\\.", ".")
|
|
508
565
|
|
|
509
566
|
|
|
510
|
-
class Serializer(object):
|
|
567
|
+
class Serializer(object): # pylint: disable=too-many-public-methods
|
|
511
568
|
"""Request object model serializer."""
|
|
512
569
|
|
|
513
570
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
|
@@ -542,7 +599,7 @@ class Serializer(object):
|
|
|
542
599
|
"multiple": lambda x, y: x % y != 0,
|
|
543
600
|
}
|
|
544
601
|
|
|
545
|
-
def __init__(self, classes: Optional[Mapping[str, type]]=None):
|
|
602
|
+
def __init__(self, classes: Optional[Mapping[str, type]] = None):
|
|
546
603
|
self.serialize_type = {
|
|
547
604
|
"iso-8601": Serializer.serialize_iso,
|
|
548
605
|
"rfc-1123": Serializer.serialize_rfc,
|
|
@@ -562,13 +619,16 @@ class Serializer(object):
|
|
|
562
619
|
self.key_transformer = full_restapi_key_transformer
|
|
563
620
|
self.client_side_validation = True
|
|
564
621
|
|
|
565
|
-
def _serialize(
|
|
622
|
+
def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
|
|
623
|
+
self, target_obj, data_type=None, **kwargs
|
|
624
|
+
):
|
|
566
625
|
"""Serialize data into a string according to type.
|
|
567
626
|
|
|
568
|
-
:param target_obj: The data to be serialized.
|
|
627
|
+
:param object target_obj: The data to be serialized.
|
|
569
628
|
:param str data_type: The type to be serialized from.
|
|
570
629
|
:rtype: str, dict
|
|
571
630
|
:raises: SerializationError if serialization fails.
|
|
631
|
+
:returns: The serialized data.
|
|
572
632
|
"""
|
|
573
633
|
key_transformer = kwargs.get("key_transformer", self.key_transformer)
|
|
574
634
|
keep_readonly = kwargs.get("keep_readonly", False)
|
|
@@ -594,12 +654,14 @@ class Serializer(object):
|
|
|
594
654
|
|
|
595
655
|
serialized = {}
|
|
596
656
|
if is_xml_model_serialization:
|
|
597
|
-
serialized = target_obj._create_xml_node()
|
|
657
|
+
serialized = target_obj._create_xml_node() # pylint: disable=protected-access
|
|
598
658
|
try:
|
|
599
|
-
attributes = target_obj._attribute_map
|
|
659
|
+
attributes = target_obj._attribute_map # pylint: disable=protected-access
|
|
600
660
|
for attr, attr_desc in attributes.items():
|
|
601
661
|
attr_name = attr
|
|
602
|
-
if not keep_readonly and target_obj._validation.get(
|
|
662
|
+
if not keep_readonly and target_obj._validation.get( # pylint: disable=protected-access
|
|
663
|
+
attr_name, {}
|
|
664
|
+
).get("readonly", False):
|
|
603
665
|
continue
|
|
604
666
|
|
|
605
667
|
if attr_name == "additional_properties" and attr_desc["key"] == "":
|
|
@@ -635,7 +697,8 @@ class Serializer(object):
|
|
|
635
697
|
if isinstance(new_attr, list):
|
|
636
698
|
serialized.extend(new_attr) # type: ignore
|
|
637
699
|
elif isinstance(new_attr, ET.Element):
|
|
638
|
-
# If the down XML has no XML/Name,
|
|
700
|
+
# If the down XML has no XML/Name,
|
|
701
|
+
# we MUST replace the tag with the local tag. But keeping the namespaces.
|
|
639
702
|
if "name" not in getattr(orig_attr, "_xml_map", {}):
|
|
640
703
|
splitted_tag = new_attr.tag.split("}")
|
|
641
704
|
if len(splitted_tag) == 2: # Namespace
|
|
@@ -666,17 +729,17 @@ class Serializer(object):
|
|
|
666
729
|
except (AttributeError, KeyError, TypeError) as err:
|
|
667
730
|
msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
|
|
668
731
|
raise SerializationError(msg) from err
|
|
669
|
-
|
|
670
|
-
return serialized
|
|
732
|
+
return serialized
|
|
671
733
|
|
|
672
734
|
def body(self, data, data_type, **kwargs):
|
|
673
735
|
"""Serialize data intended for a request body.
|
|
674
736
|
|
|
675
|
-
:param data: The data to be serialized.
|
|
737
|
+
:param object data: The data to be serialized.
|
|
676
738
|
:param str data_type: The type to be serialized from.
|
|
677
739
|
:rtype: dict
|
|
678
740
|
:raises: SerializationError if serialization fails.
|
|
679
741
|
:raises: ValueError if data is None
|
|
742
|
+
:returns: The serialized request body
|
|
680
743
|
"""
|
|
681
744
|
|
|
682
745
|
# Just in case this is a dict
|
|
@@ -705,7 +768,7 @@ class Serializer(object):
|
|
|
705
768
|
attribute_key_case_insensitive_extractor,
|
|
706
769
|
last_rest_key_case_insensitive_extractor,
|
|
707
770
|
]
|
|
708
|
-
data = deserializer._deserialize(data_type, data)
|
|
771
|
+
data = deserializer._deserialize(data_type, data) # pylint: disable=protected-access
|
|
709
772
|
except DeserializationError as err:
|
|
710
773
|
raise SerializationError("Unable to build a model: " + str(err)) from err
|
|
711
774
|
|
|
@@ -714,9 +777,11 @@ class Serializer(object):
|
|
|
714
777
|
def url(self, name, data, data_type, **kwargs):
|
|
715
778
|
"""Serialize data intended for a URL path.
|
|
716
779
|
|
|
717
|
-
:param
|
|
780
|
+
:param str name: The name of the URL path parameter.
|
|
781
|
+
:param object data: The data to be serialized.
|
|
718
782
|
:param str data_type: The type to be serialized from.
|
|
719
783
|
:rtype: str
|
|
784
|
+
:returns: The serialized URL path
|
|
720
785
|
:raises: TypeError if serialization fails.
|
|
721
786
|
:raises: ValueError if data is None
|
|
722
787
|
"""
|
|
@@ -730,27 +795,26 @@ class Serializer(object):
|
|
|
730
795
|
output = output.replace("{", quote("{")).replace("}", quote("}"))
|
|
731
796
|
else:
|
|
732
797
|
output = quote(str(output), safe="")
|
|
733
|
-
except SerializationError:
|
|
734
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
735
|
-
|
|
736
|
-
return output
|
|
798
|
+
except SerializationError as exc:
|
|
799
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
800
|
+
return output
|
|
737
801
|
|
|
738
802
|
def query(self, name, data, data_type, **kwargs):
|
|
739
803
|
"""Serialize data intended for a URL query.
|
|
740
804
|
|
|
741
|
-
:param
|
|
805
|
+
:param str name: The name of the query parameter.
|
|
806
|
+
:param object data: The data to be serialized.
|
|
742
807
|
:param str data_type: The type to be serialized from.
|
|
743
|
-
:keyword bool skip_quote: Whether to skip quote the serialized result.
|
|
744
|
-
Defaults to False.
|
|
745
808
|
:rtype: str, list
|
|
746
809
|
:raises: TypeError if serialization fails.
|
|
747
810
|
:raises: ValueError if data is None
|
|
811
|
+
:returns: The serialized query parameter
|
|
748
812
|
"""
|
|
749
813
|
try:
|
|
750
814
|
# Treat the list aside, since we don't want to encode the div separator
|
|
751
815
|
if data_type.startswith("["):
|
|
752
816
|
internal_data_type = data_type[1:-1]
|
|
753
|
-
do_quote = not kwargs.get(
|
|
817
|
+
do_quote = not kwargs.get("skip_quote", False)
|
|
754
818
|
return self.serialize_iter(data, internal_data_type, do_quote=do_quote, **kwargs)
|
|
755
819
|
|
|
756
820
|
# Not a list, regular serialization
|
|
@@ -761,19 +825,20 @@ class Serializer(object):
|
|
|
761
825
|
output = str(output)
|
|
762
826
|
else:
|
|
763
827
|
output = quote(str(output), safe="")
|
|
764
|
-
except SerializationError:
|
|
765
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
766
|
-
|
|
767
|
-
return str(output)
|
|
828
|
+
except SerializationError as exc:
|
|
829
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
830
|
+
return str(output)
|
|
768
831
|
|
|
769
832
|
def header(self, name, data, data_type, **kwargs):
|
|
770
833
|
"""Serialize data intended for a request header.
|
|
771
834
|
|
|
772
|
-
:param
|
|
835
|
+
:param str name: The name of the header.
|
|
836
|
+
:param object data: The data to be serialized.
|
|
773
837
|
:param str data_type: The type to be serialized from.
|
|
774
838
|
:rtype: str
|
|
775
839
|
:raises: TypeError if serialization fails.
|
|
776
840
|
:raises: ValueError if data is None
|
|
841
|
+
:returns: The serialized header
|
|
777
842
|
"""
|
|
778
843
|
try:
|
|
779
844
|
if data_type in ["[str]"]:
|
|
@@ -782,21 +847,20 @@ class Serializer(object):
|
|
|
782
847
|
output = self.serialize_data(data, data_type, **kwargs)
|
|
783
848
|
if data_type == "bool":
|
|
784
849
|
output = json.dumps(output)
|
|
785
|
-
except SerializationError:
|
|
786
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
787
|
-
|
|
788
|
-
return str(output)
|
|
850
|
+
except SerializationError as exc:
|
|
851
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
852
|
+
return str(output)
|
|
789
853
|
|
|
790
854
|
def serialize_data(self, data, data_type, **kwargs):
|
|
791
855
|
"""Serialize generic data according to supplied data type.
|
|
792
856
|
|
|
793
|
-
:param data: The data to be serialized.
|
|
857
|
+
:param object data: The data to be serialized.
|
|
794
858
|
:param str data_type: The type to be serialized from.
|
|
795
|
-
:param bool required: Whether it's essential that the data not be
|
|
796
|
-
empty or None
|
|
797
859
|
:raises: AttributeError if required data is None.
|
|
798
860
|
:raises: ValueError if data is None
|
|
799
861
|
:raises: SerializationError if serialization fails.
|
|
862
|
+
:returns: The serialized data.
|
|
863
|
+
:rtype: str, int, float, bool, dict, list
|
|
800
864
|
"""
|
|
801
865
|
if data is None:
|
|
802
866
|
raise ValueError("No value for given attribute")
|
|
@@ -807,7 +871,7 @@ class Serializer(object):
|
|
|
807
871
|
if data_type in self.basic_types.values():
|
|
808
872
|
return self.serialize_basic(data, data_type, **kwargs)
|
|
809
873
|
|
|
810
|
-
|
|
874
|
+
if data_type in self.serialize_type:
|
|
811
875
|
return self.serialize_type[data_type](data, **kwargs)
|
|
812
876
|
|
|
813
877
|
# If dependencies is empty, try with current data class
|
|
@@ -823,11 +887,10 @@ class Serializer(object):
|
|
|
823
887
|
except (ValueError, TypeError) as err:
|
|
824
888
|
msg = "Unable to serialize value: {!r} as type: {!r}."
|
|
825
889
|
raise SerializationError(msg.format(data, data_type)) from err
|
|
826
|
-
|
|
827
|
-
return self._serialize(data, **kwargs)
|
|
890
|
+
return self._serialize(data, **kwargs)
|
|
828
891
|
|
|
829
892
|
@classmethod
|
|
830
|
-
def _get_custom_serializers(cls, data_type, **kwargs):
|
|
893
|
+
def _get_custom_serializers(cls, data_type, **kwargs): # pylint: disable=inconsistent-return-statements
|
|
831
894
|
custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type)
|
|
832
895
|
if custom_serializer:
|
|
833
896
|
return custom_serializer
|
|
@@ -843,23 +906,26 @@ class Serializer(object):
|
|
|
843
906
|
- basic_types_serializers dict[str, callable] : If set, use the callable as serializer
|
|
844
907
|
- is_xml bool : If set, use xml_basic_types_serializers
|
|
845
908
|
|
|
846
|
-
:param data: Object to be serialized.
|
|
909
|
+
:param obj data: Object to be serialized.
|
|
847
910
|
:param str data_type: Type of object in the iterable.
|
|
911
|
+
:rtype: str, int, float, bool
|
|
912
|
+
:return: serialized object
|
|
848
913
|
"""
|
|
849
914
|
custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
|
|
850
915
|
if custom_serializer:
|
|
851
916
|
return custom_serializer(data)
|
|
852
917
|
if data_type == "str":
|
|
853
918
|
return cls.serialize_unicode(data)
|
|
854
|
-
return eval(data_type)(data) # nosec
|
|
919
|
+
return eval(data_type)(data) # nosec # pylint: disable=eval-used
|
|
855
920
|
|
|
856
921
|
@classmethod
|
|
857
922
|
def serialize_unicode(cls, data):
|
|
858
923
|
"""Special handling for serializing unicode strings in Py2.
|
|
859
924
|
Encode to UTF-8 if unicode, otherwise handle as a str.
|
|
860
925
|
|
|
861
|
-
:param data: Object to be serialized.
|
|
926
|
+
:param str data: Object to be serialized.
|
|
862
927
|
:rtype: str
|
|
928
|
+
:return: serialized object
|
|
863
929
|
"""
|
|
864
930
|
try: # If I received an enum, return its value
|
|
865
931
|
return data.value
|
|
@@ -873,8 +939,7 @@ class Serializer(object):
|
|
|
873
939
|
return data
|
|
874
940
|
except NameError:
|
|
875
941
|
return str(data)
|
|
876
|
-
|
|
877
|
-
return str(data)
|
|
942
|
+
return str(data)
|
|
878
943
|
|
|
879
944
|
def serialize_iter(self, data, iter_type, div=None, **kwargs):
|
|
880
945
|
"""Serialize iterable.
|
|
@@ -884,15 +949,13 @@ class Serializer(object):
|
|
|
884
949
|
serialization_ctxt['type'] should be same as data_type.
|
|
885
950
|
- is_xml bool : If set, serialize as XML
|
|
886
951
|
|
|
887
|
-
:param list
|
|
952
|
+
:param list data: Object to be serialized.
|
|
888
953
|
:param str iter_type: Type of object in the iterable.
|
|
889
|
-
:param bool required: Whether the objects in the iterable must
|
|
890
|
-
not be None or empty.
|
|
891
954
|
:param str div: If set, this str will be used to combine the elements
|
|
892
955
|
in the iterable into a combined string. Default is 'None'.
|
|
893
|
-
:keyword bool do_quote: Whether to quote the serialized result of each iterable element.
|
|
894
956
|
Defaults to False.
|
|
895
957
|
:rtype: list, str
|
|
958
|
+
:return: serialized iterable
|
|
896
959
|
"""
|
|
897
960
|
if isinstance(data, str):
|
|
898
961
|
raise SerializationError("Refuse str type as a valid iter type.")
|
|
@@ -909,12 +972,8 @@ class Serializer(object):
|
|
|
909
972
|
raise
|
|
910
973
|
serialized.append(None)
|
|
911
974
|
|
|
912
|
-
if kwargs.get(
|
|
913
|
-
serialized = [
|
|
914
|
-
'' if s is None else quote(str(s), safe='')
|
|
915
|
-
for s
|
|
916
|
-
in serialized
|
|
917
|
-
]
|
|
975
|
+
if kwargs.get("do_quote", False):
|
|
976
|
+
serialized = ["" if s is None else quote(str(s), safe="") for s in serialized]
|
|
918
977
|
|
|
919
978
|
if div:
|
|
920
979
|
serialized = ["" if s is None else str(s) for s in serialized]
|
|
@@ -951,9 +1010,8 @@ class Serializer(object):
|
|
|
951
1010
|
|
|
952
1011
|
:param dict attr: Object to be serialized.
|
|
953
1012
|
:param str dict_type: Type of object in the dictionary.
|
|
954
|
-
:param bool required: Whether the objects in the dictionary must
|
|
955
|
-
not be None or empty.
|
|
956
1013
|
:rtype: dict
|
|
1014
|
+
:return: serialized dictionary
|
|
957
1015
|
"""
|
|
958
1016
|
serialization_ctxt = kwargs.get("serialization_ctxt", {})
|
|
959
1017
|
serialized = {}
|
|
@@ -977,7 +1035,7 @@ class Serializer(object):
|
|
|
977
1035
|
|
|
978
1036
|
return serialized
|
|
979
1037
|
|
|
980
|
-
def serialize_object(self, attr, **kwargs):
|
|
1038
|
+
def serialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
|
|
981
1039
|
"""Serialize a generic object.
|
|
982
1040
|
This will be handled as a dictionary. If object passed in is not
|
|
983
1041
|
a basic type (str, int, float, dict, list) it will simply be
|
|
@@ -985,6 +1043,7 @@ class Serializer(object):
|
|
|
985
1043
|
|
|
986
1044
|
:param dict attr: Object to be serialized.
|
|
987
1045
|
:rtype: dict or str
|
|
1046
|
+
:return: serialized object
|
|
988
1047
|
"""
|
|
989
1048
|
if attr is None:
|
|
990
1049
|
return None
|
|
@@ -1009,7 +1068,7 @@ class Serializer(object):
|
|
|
1009
1068
|
return self.serialize_decimal(attr)
|
|
1010
1069
|
|
|
1011
1070
|
# If it's a model or I know this dependency, serialize as a Model
|
|
1012
|
-
|
|
1071
|
+
if obj_type in self.dependencies.values() or isinstance(attr, Model):
|
|
1013
1072
|
return self._serialize(attr)
|
|
1014
1073
|
|
|
1015
1074
|
if obj_type == dict:
|
|
@@ -1040,56 +1099,61 @@ class Serializer(object):
|
|
|
1040
1099
|
try:
|
|
1041
1100
|
enum_obj(result) # type: ignore
|
|
1042
1101
|
return result
|
|
1043
|
-
except ValueError:
|
|
1102
|
+
except ValueError as exc:
|
|
1044
1103
|
for enum_value in enum_obj: # type: ignore
|
|
1045
1104
|
if enum_value.value.lower() == str(attr).lower():
|
|
1046
1105
|
return enum_value.value
|
|
1047
1106
|
error = "{!r} is not valid value for enum {!r}"
|
|
1048
|
-
raise SerializationError(error.format(attr, enum_obj))
|
|
1107
|
+
raise SerializationError(error.format(attr, enum_obj)) from exc
|
|
1049
1108
|
|
|
1050
1109
|
@staticmethod
|
|
1051
|
-
def serialize_bytearray(attr, **kwargs):
|
|
1110
|
+
def serialize_bytearray(attr, **kwargs): # pylint: disable=unused-argument
|
|
1052
1111
|
"""Serialize bytearray into base-64 string.
|
|
1053
1112
|
|
|
1054
|
-
:param attr: Object to be serialized.
|
|
1113
|
+
:param str attr: Object to be serialized.
|
|
1055
1114
|
:rtype: str
|
|
1115
|
+
:return: serialized base64
|
|
1056
1116
|
"""
|
|
1057
1117
|
return b64encode(attr).decode()
|
|
1058
1118
|
|
|
1059
1119
|
@staticmethod
|
|
1060
|
-
def serialize_base64(attr, **kwargs):
|
|
1120
|
+
def serialize_base64(attr, **kwargs): # pylint: disable=unused-argument
|
|
1061
1121
|
"""Serialize str into base-64 string.
|
|
1062
1122
|
|
|
1063
|
-
:param attr: Object to be serialized.
|
|
1123
|
+
:param str attr: Object to be serialized.
|
|
1064
1124
|
:rtype: str
|
|
1125
|
+
:return: serialized base64
|
|
1065
1126
|
"""
|
|
1066
1127
|
encoded = b64encode(attr).decode("ascii")
|
|
1067
1128
|
return encoded.strip("=").replace("+", "-").replace("/", "_")
|
|
1068
1129
|
|
|
1069
1130
|
@staticmethod
|
|
1070
|
-
def serialize_decimal(attr, **kwargs):
|
|
1131
|
+
def serialize_decimal(attr, **kwargs): # pylint: disable=unused-argument
|
|
1071
1132
|
"""Serialize Decimal object to float.
|
|
1072
1133
|
|
|
1073
|
-
:param attr: Object to be serialized.
|
|
1134
|
+
:param decimal attr: Object to be serialized.
|
|
1074
1135
|
:rtype: float
|
|
1136
|
+
:return: serialized decimal
|
|
1075
1137
|
"""
|
|
1076
1138
|
return float(attr)
|
|
1077
1139
|
|
|
1078
1140
|
@staticmethod
|
|
1079
|
-
def serialize_long(attr, **kwargs):
|
|
1141
|
+
def serialize_long(attr, **kwargs): # pylint: disable=unused-argument
|
|
1080
1142
|
"""Serialize long (Py2) or int (Py3).
|
|
1081
1143
|
|
|
1082
|
-
:param attr: Object to be serialized.
|
|
1144
|
+
:param int attr: Object to be serialized.
|
|
1083
1145
|
:rtype: int/long
|
|
1146
|
+
:return: serialized long
|
|
1084
1147
|
"""
|
|
1085
1148
|
return _long_type(attr)
|
|
1086
1149
|
|
|
1087
1150
|
@staticmethod
|
|
1088
|
-
def serialize_date(attr, **kwargs):
|
|
1151
|
+
def serialize_date(attr, **kwargs): # pylint: disable=unused-argument
|
|
1089
1152
|
"""Serialize Date object into ISO-8601 formatted string.
|
|
1090
1153
|
|
|
1091
1154
|
:param Date attr: Object to be serialized.
|
|
1092
1155
|
:rtype: str
|
|
1156
|
+
:return: serialized date
|
|
1093
1157
|
"""
|
|
1094
1158
|
if isinstance(attr, str):
|
|
1095
1159
|
attr = isodate.parse_date(attr)
|
|
@@ -1097,11 +1161,12 @@ class Serializer(object):
|
|
|
1097
1161
|
return t
|
|
1098
1162
|
|
|
1099
1163
|
@staticmethod
|
|
1100
|
-
def serialize_time(attr, **kwargs):
|
|
1164
|
+
def serialize_time(attr, **kwargs): # pylint: disable=unused-argument
|
|
1101
1165
|
"""Serialize Time object into ISO-8601 formatted string.
|
|
1102
1166
|
|
|
1103
1167
|
:param datetime.time attr: Object to be serialized.
|
|
1104
1168
|
:rtype: str
|
|
1169
|
+
:return: serialized time
|
|
1105
1170
|
"""
|
|
1106
1171
|
if isinstance(attr, str):
|
|
1107
1172
|
attr = isodate.parse_time(attr)
|
|
@@ -1111,30 +1176,32 @@ class Serializer(object):
|
|
|
1111
1176
|
return t
|
|
1112
1177
|
|
|
1113
1178
|
@staticmethod
|
|
1114
|
-
def serialize_duration(attr, **kwargs):
|
|
1179
|
+
def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
|
|
1115
1180
|
"""Serialize TimeDelta object into ISO-8601 formatted string.
|
|
1116
1181
|
|
|
1117
1182
|
:param TimeDelta attr: Object to be serialized.
|
|
1118
1183
|
:rtype: str
|
|
1184
|
+
:return: serialized duration
|
|
1119
1185
|
"""
|
|
1120
1186
|
if isinstance(attr, str):
|
|
1121
1187
|
attr = isodate.parse_duration(attr)
|
|
1122
1188
|
return isodate.duration_isoformat(attr)
|
|
1123
1189
|
|
|
1124
1190
|
@staticmethod
|
|
1125
|
-
def serialize_rfc(attr, **kwargs):
|
|
1191
|
+
def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
|
|
1126
1192
|
"""Serialize Datetime object into RFC-1123 formatted string.
|
|
1127
1193
|
|
|
1128
1194
|
:param Datetime attr: Object to be serialized.
|
|
1129
1195
|
:rtype: str
|
|
1130
1196
|
:raises: TypeError if format invalid.
|
|
1197
|
+
:return: serialized rfc
|
|
1131
1198
|
"""
|
|
1132
1199
|
try:
|
|
1133
1200
|
if not attr.tzinfo:
|
|
1134
1201
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
|
1135
1202
|
utc = attr.utctimetuple()
|
|
1136
|
-
except AttributeError:
|
|
1137
|
-
raise TypeError("RFC1123 object must be valid Datetime object.")
|
|
1203
|
+
except AttributeError as exc:
|
|
1204
|
+
raise TypeError("RFC1123 object must be valid Datetime object.") from exc
|
|
1138
1205
|
|
|
1139
1206
|
return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
|
|
1140
1207
|
Serializer.days[utc.tm_wday],
|
|
@@ -1147,12 +1214,13 @@ class Serializer(object):
|
|
|
1147
1214
|
)
|
|
1148
1215
|
|
|
1149
1216
|
@staticmethod
|
|
1150
|
-
def serialize_iso(attr, **kwargs):
|
|
1217
|
+
def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument
|
|
1151
1218
|
"""Serialize Datetime object into ISO-8601 formatted string.
|
|
1152
1219
|
|
|
1153
1220
|
:param Datetime attr: Object to be serialized.
|
|
1154
1221
|
:rtype: str
|
|
1155
1222
|
:raises: SerializationError if format invalid.
|
|
1223
|
+
:return: serialized iso
|
|
1156
1224
|
"""
|
|
1157
1225
|
if isinstance(attr, str):
|
|
1158
1226
|
attr = isodate.parse_datetime(attr)
|
|
@@ -1178,13 +1246,14 @@ class Serializer(object):
|
|
|
1178
1246
|
raise TypeError(msg) from err
|
|
1179
1247
|
|
|
1180
1248
|
@staticmethod
|
|
1181
|
-
def serialize_unix(attr, **kwargs):
|
|
1249
|
+
def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument
|
|
1182
1250
|
"""Serialize Datetime object into IntTime format.
|
|
1183
1251
|
This is represented as seconds.
|
|
1184
1252
|
|
|
1185
1253
|
:param Datetime attr: Object to be serialized.
|
|
1186
1254
|
:rtype: int
|
|
1187
1255
|
:raises: SerializationError if format invalid
|
|
1256
|
+
:return: serialied unix
|
|
1188
1257
|
"""
|
|
1189
1258
|
if isinstance(attr, int):
|
|
1190
1259
|
return attr
|
|
@@ -1192,11 +1261,11 @@ class Serializer(object):
|
|
|
1192
1261
|
if not attr.tzinfo:
|
|
1193
1262
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
|
1194
1263
|
return int(calendar.timegm(attr.utctimetuple()))
|
|
1195
|
-
except AttributeError:
|
|
1196
|
-
raise TypeError("Unix time object must be valid Datetime object.")
|
|
1264
|
+
except AttributeError as exc:
|
|
1265
|
+
raise TypeError("Unix time object must be valid Datetime object.") from exc
|
|
1197
1266
|
|
|
1198
1267
|
|
|
1199
|
-
def rest_key_extractor(attr, attr_desc, data):
|
|
1268
|
+
def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1200
1269
|
key = attr_desc["key"]
|
|
1201
1270
|
working_data = data
|
|
1202
1271
|
|
|
@@ -1217,7 +1286,9 @@ def rest_key_extractor(attr, attr_desc, data):
|
|
|
1217
1286
|
return working_data.get(key)
|
|
1218
1287
|
|
|
1219
1288
|
|
|
1220
|
-
def rest_key_case_insensitive_extractor(
|
|
1289
|
+
def rest_key_case_insensitive_extractor( # pylint: disable=unused-argument, inconsistent-return-statements
|
|
1290
|
+
attr, attr_desc, data
|
|
1291
|
+
):
|
|
1221
1292
|
key = attr_desc["key"]
|
|
1222
1293
|
working_data = data
|
|
1223
1294
|
|
|
@@ -1238,17 +1309,29 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
|
|
|
1238
1309
|
return attribute_key_case_insensitive_extractor(key, None, working_data)
|
|
1239
1310
|
|
|
1240
1311
|
|
|
1241
|
-
def last_rest_key_extractor(attr, attr_desc, data):
|
|
1242
|
-
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1312
|
+
def last_rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1313
|
+
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1314
|
+
|
|
1315
|
+
:param str attr: The attribute to extract
|
|
1316
|
+
:param dict attr_desc: The attribute description
|
|
1317
|
+
:param dict data: The data to extract from
|
|
1318
|
+
:rtype: object
|
|
1319
|
+
:returns: The extracted attribute
|
|
1320
|
+
"""
|
|
1243
1321
|
key = attr_desc["key"]
|
|
1244
1322
|
dict_keys = _FLATTEN.split(key)
|
|
1245
1323
|
return attribute_key_extractor(dict_keys[-1], None, data)
|
|
1246
1324
|
|
|
1247
1325
|
|
|
1248
|
-
def last_rest_key_case_insensitive_extractor(attr, attr_desc, data):
|
|
1326
|
+
def last_rest_key_case_insensitive_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1249
1327
|
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1250
1328
|
|
|
1251
1329
|
This is the case insensitive version of "last_rest_key_extractor"
|
|
1330
|
+
:param str attr: The attribute to extract
|
|
1331
|
+
:param dict attr_desc: The attribute description
|
|
1332
|
+
:param dict data: The data to extract from
|
|
1333
|
+
:rtype: object
|
|
1334
|
+
:returns: The extracted attribute
|
|
1252
1335
|
"""
|
|
1253
1336
|
key = attr_desc["key"]
|
|
1254
1337
|
dict_keys = _FLATTEN.split(key)
|
|
@@ -1285,7 +1368,7 @@ def _extract_name_from_internal_type(internal_type):
|
|
|
1285
1368
|
return xml_name
|
|
1286
1369
|
|
|
1287
1370
|
|
|
1288
|
-
def xml_key_extractor(attr, attr_desc, data):
|
|
1371
|
+
def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument,too-many-return-statements
|
|
1289
1372
|
if isinstance(data, dict):
|
|
1290
1373
|
return None
|
|
1291
1374
|
|
|
@@ -1337,22 +1420,21 @@ def xml_key_extractor(attr, attr_desc, data):
|
|
|
1337
1420
|
if is_iter_type:
|
|
1338
1421
|
if is_wrapped:
|
|
1339
1422
|
return None # is_wrapped no node, we want None
|
|
1340
|
-
|
|
1341
|
-
return [] # not wrapped, assume empty list
|
|
1423
|
+
return [] # not wrapped, assume empty list
|
|
1342
1424
|
return None # Assume it's not there, maybe an optional node.
|
|
1343
1425
|
|
|
1344
1426
|
# If is_iter_type and not wrapped, return all found children
|
|
1345
1427
|
if is_iter_type:
|
|
1346
1428
|
if not is_wrapped:
|
|
1347
1429
|
return children
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
)
|
|
1430
|
+
# Iter and wrapped, should have found one node only (the wrap one)
|
|
1431
|
+
if len(children) != 1:
|
|
1432
|
+
raise DeserializationError(
|
|
1433
|
+
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( # pylint: disable=line-too-long
|
|
1434
|
+
xml_name
|
|
1354
1435
|
)
|
|
1355
|
-
|
|
1436
|
+
)
|
|
1437
|
+
return list(children[0]) # Might be empty list and that's ok.
|
|
1356
1438
|
|
|
1357
1439
|
# Here it's not a itertype, we should have found one element only or empty
|
|
1358
1440
|
if len(children) > 1:
|
|
@@ -1369,9 +1451,9 @@ class Deserializer(object):
|
|
|
1369
1451
|
|
|
1370
1452
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
|
1371
1453
|
|
|
1372
|
-
valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}
|
|
1454
|
+
valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
|
|
1373
1455
|
|
|
1374
|
-
def __init__(self, classes: Optional[Mapping[str, type]]=None):
|
|
1456
|
+
def __init__(self, classes: Optional[Mapping[str, type]] = None):
|
|
1375
1457
|
self.deserialize_type = {
|
|
1376
1458
|
"iso-8601": Deserializer.deserialize_iso,
|
|
1377
1459
|
"rfc-1123": Deserializer.deserialize_rfc,
|
|
@@ -1409,11 +1491,12 @@ class Deserializer(object):
|
|
|
1409
1491
|
:param str content_type: Swagger "produces" if available.
|
|
1410
1492
|
:raises: DeserializationError if deserialization fails.
|
|
1411
1493
|
:return: Deserialized object.
|
|
1494
|
+
:rtype: object
|
|
1412
1495
|
"""
|
|
1413
1496
|
data = self._unpack_content(response_data, content_type)
|
|
1414
1497
|
return self._deserialize(target_obj, data)
|
|
1415
1498
|
|
|
1416
|
-
def _deserialize(self, target_obj, data):
|
|
1499
|
+
def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return-statements
|
|
1417
1500
|
"""Call the deserializer on a model.
|
|
1418
1501
|
|
|
1419
1502
|
Data needs to be already deserialized as JSON or XML ElementTree
|
|
@@ -1422,12 +1505,13 @@ class Deserializer(object):
|
|
|
1422
1505
|
:param object data: Object to deserialize.
|
|
1423
1506
|
:raises: DeserializationError if deserialization fails.
|
|
1424
1507
|
:return: Deserialized object.
|
|
1508
|
+
:rtype: object
|
|
1425
1509
|
"""
|
|
1426
1510
|
# This is already a model, go recursive just in case
|
|
1427
1511
|
if hasattr(data, "_attribute_map"):
|
|
1428
1512
|
constants = [name for name, config in getattr(data, "_validation", {}).items() if config.get("constant")]
|
|
1429
1513
|
try:
|
|
1430
|
-
for attr, mapconfig in data._attribute_map.items():
|
|
1514
|
+
for attr, mapconfig in data._attribute_map.items(): # pylint: disable=protected-access
|
|
1431
1515
|
if attr in constants:
|
|
1432
1516
|
continue
|
|
1433
1517
|
value = getattr(data, attr)
|
|
@@ -1446,13 +1530,13 @@ class Deserializer(object):
|
|
|
1446
1530
|
|
|
1447
1531
|
if isinstance(response, str):
|
|
1448
1532
|
return self.deserialize_data(data, response)
|
|
1449
|
-
|
|
1533
|
+
if isinstance(response, type) and issubclass(response, Enum):
|
|
1450
1534
|
return self.deserialize_enum(data, response)
|
|
1451
1535
|
|
|
1452
1536
|
if data is None or data is CoreNull:
|
|
1453
1537
|
return data
|
|
1454
1538
|
try:
|
|
1455
|
-
attributes = response._attribute_map # type: ignore
|
|
1539
|
+
attributes = response._attribute_map # type: ignore # pylint: disable=protected-access
|
|
1456
1540
|
d_attrs = {}
|
|
1457
1541
|
for attr, attr_desc in attributes.items():
|
|
1458
1542
|
# Check empty string. If it's not empty, someone has a real "additionalProperties"...
|
|
@@ -1482,9 +1566,8 @@ class Deserializer(object):
|
|
|
1482
1566
|
except (AttributeError, TypeError, KeyError) as err:
|
|
1483
1567
|
msg = "Unable to deserialize to object: " + class_name # type: ignore
|
|
1484
1568
|
raise DeserializationError(msg) from err
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
return self._instantiate_model(response, d_attrs, additional_properties)
|
|
1569
|
+
additional_properties = self._build_additional_properties(attributes, data)
|
|
1570
|
+
return self._instantiate_model(response, d_attrs, additional_properties)
|
|
1488
1571
|
|
|
1489
1572
|
def _build_additional_properties(self, attribute_map, data):
|
|
1490
1573
|
if not self.additional_properties_detection:
|
|
@@ -1511,6 +1594,8 @@ class Deserializer(object):
|
|
|
1511
1594
|
|
|
1512
1595
|
:param str target: The target object type to deserialize to.
|
|
1513
1596
|
:param str/dict data: The response data to deserialize.
|
|
1597
|
+
:return: The classified target object and its class name.
|
|
1598
|
+
:rtype: tuple
|
|
1514
1599
|
"""
|
|
1515
1600
|
if target is None:
|
|
1516
1601
|
return None, None
|
|
@@ -1522,7 +1607,7 @@ class Deserializer(object):
|
|
|
1522
1607
|
return target, target
|
|
1523
1608
|
|
|
1524
1609
|
try:
|
|
1525
|
-
target = target._classify(data, self.dependencies) # type: ignore
|
|
1610
|
+
target = target._classify(data, self.dependencies) # type: ignore # pylint: disable=protected-access
|
|
1526
1611
|
except AttributeError:
|
|
1527
1612
|
pass # Target is not a Model, no classify
|
|
1528
1613
|
return target, target.__class__.__name__ # type: ignore
|
|
@@ -1537,10 +1622,12 @@ class Deserializer(object):
|
|
|
1537
1622
|
:param str target_obj: The target object type to deserialize to.
|
|
1538
1623
|
:param str/dict data: The response data to deserialize.
|
|
1539
1624
|
:param str content_type: Swagger "produces" if available.
|
|
1625
|
+
:return: Deserialized object.
|
|
1626
|
+
:rtype: object
|
|
1540
1627
|
"""
|
|
1541
1628
|
try:
|
|
1542
1629
|
return self(target_obj, data, content_type=content_type)
|
|
1543
|
-
except:
|
|
1630
|
+
except: # pylint: disable=bare-except
|
|
1544
1631
|
_LOGGER.debug(
|
|
1545
1632
|
"Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True
|
|
1546
1633
|
)
|
|
@@ -1558,10 +1645,12 @@ class Deserializer(object):
|
|
|
1558
1645
|
|
|
1559
1646
|
If raw_data is something else, bypass all logic and return it directly.
|
|
1560
1647
|
|
|
1561
|
-
:param raw_data: Data to be processed.
|
|
1562
|
-
:param content_type: How to parse if raw_data is a string/bytes.
|
|
1648
|
+
:param obj raw_data: Data to be processed.
|
|
1649
|
+
:param str content_type: How to parse if raw_data is a string/bytes.
|
|
1563
1650
|
:raises JSONDecodeError: If JSON is requested and parsing is impossible.
|
|
1564
1651
|
:raises UnicodeDecodeError: If bytes is not UTF8
|
|
1652
|
+
:rtype: object
|
|
1653
|
+
:return: Unpacked content.
|
|
1565
1654
|
"""
|
|
1566
1655
|
# Assume this is enough to detect a Pipeline Response without importing it
|
|
1567
1656
|
context = getattr(raw_data, "context", {})
|
|
@@ -1585,14 +1674,21 @@ class Deserializer(object):
|
|
|
1585
1674
|
def _instantiate_model(self, response, attrs, additional_properties=None):
|
|
1586
1675
|
"""Instantiate a response model passing in deserialized args.
|
|
1587
1676
|
|
|
1588
|
-
:param response: The response model class.
|
|
1589
|
-
:param
|
|
1677
|
+
:param Response response: The response model class.
|
|
1678
|
+
:param dict attrs: The deserialized response attributes.
|
|
1679
|
+
:param dict additional_properties: Additional properties to be set.
|
|
1680
|
+
:rtype: Response
|
|
1681
|
+
:return: The instantiated response model.
|
|
1590
1682
|
"""
|
|
1591
1683
|
if callable(response):
|
|
1592
1684
|
subtype = getattr(response, "_subtype_map", {})
|
|
1593
1685
|
try:
|
|
1594
|
-
readonly = [
|
|
1595
|
-
|
|
1686
|
+
readonly = [
|
|
1687
|
+
k for k, v in response._validation.items() if v.get("readonly") # pylint: disable=protected-access
|
|
1688
|
+
]
|
|
1689
|
+
const = [
|
|
1690
|
+
k for k, v in response._validation.items() if v.get("constant") # pylint: disable=protected-access
|
|
1691
|
+
]
|
|
1596
1692
|
kwargs = {k: v for k, v in attrs.items() if k not in subtype and k not in readonly + const}
|
|
1597
1693
|
response_obj = response(**kwargs)
|
|
1598
1694
|
for attr in readonly:
|
|
@@ -1602,7 +1698,7 @@ class Deserializer(object):
|
|
|
1602
1698
|
return response_obj
|
|
1603
1699
|
except TypeError as err:
|
|
1604
1700
|
msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
|
|
1605
|
-
raise DeserializationError(msg + str(err))
|
|
1701
|
+
raise DeserializationError(msg + str(err)) from err
|
|
1606
1702
|
else:
|
|
1607
1703
|
try:
|
|
1608
1704
|
for attr, value in attrs.items():
|
|
@@ -1611,15 +1707,16 @@ class Deserializer(object):
|
|
|
1611
1707
|
except Exception as exp:
|
|
1612
1708
|
msg = "Unable to populate response model. "
|
|
1613
1709
|
msg += "Type: {}, Error: {}".format(type(response), exp)
|
|
1614
|
-
raise DeserializationError(msg)
|
|
1710
|
+
raise DeserializationError(msg) from exp
|
|
1615
1711
|
|
|
1616
|
-
def deserialize_data(self, data, data_type):
|
|
1712
|
+
def deserialize_data(self, data, data_type): # pylint: disable=too-many-return-statements
|
|
1617
1713
|
"""Process data for deserialization according to data type.
|
|
1618
1714
|
|
|
1619
1715
|
:param str data: The response string to be deserialized.
|
|
1620
1716
|
:param str data_type: The type to deserialize to.
|
|
1621
1717
|
:raises: DeserializationError if deserialization fails.
|
|
1622
1718
|
:return: Deserialized object.
|
|
1719
|
+
:rtype: object
|
|
1623
1720
|
"""
|
|
1624
1721
|
if data is None:
|
|
1625
1722
|
return data
|
|
@@ -1633,7 +1730,11 @@ class Deserializer(object):
|
|
|
1633
1730
|
if isinstance(data, self.deserialize_expected_types.get(data_type, tuple())):
|
|
1634
1731
|
return data
|
|
1635
1732
|
|
|
1636
|
-
is_a_text_parsing_type = lambda x: x not in [
|
|
1733
|
+
is_a_text_parsing_type = lambda x: x not in [ # pylint: disable=unnecessary-lambda-assignment
|
|
1734
|
+
"object",
|
|
1735
|
+
"[]",
|
|
1736
|
+
r"{}",
|
|
1737
|
+
]
|
|
1637
1738
|
if isinstance(data, ET.Element) and is_a_text_parsing_type(data_type) and not data.text:
|
|
1638
1739
|
return None
|
|
1639
1740
|
data_val = self.deserialize_type[data_type](data)
|
|
@@ -1653,14 +1754,14 @@ class Deserializer(object):
|
|
|
1653
1754
|
msg = "Unable to deserialize response data."
|
|
1654
1755
|
msg += " Data: {}, {}".format(data, data_type)
|
|
1655
1756
|
raise DeserializationError(msg) from err
|
|
1656
|
-
|
|
1657
|
-
return self._deserialize(obj_type, data)
|
|
1757
|
+
return self._deserialize(obj_type, data)
|
|
1658
1758
|
|
|
1659
1759
|
def deserialize_iter(self, attr, iter_type):
|
|
1660
1760
|
"""Deserialize an iterable.
|
|
1661
1761
|
|
|
1662
1762
|
:param list attr: Iterable to be deserialized.
|
|
1663
1763
|
:param str iter_type: The type of object in the iterable.
|
|
1764
|
+
:return: Deserialized iterable.
|
|
1664
1765
|
:rtype: list
|
|
1665
1766
|
"""
|
|
1666
1767
|
if attr is None:
|
|
@@ -1677,6 +1778,7 @@ class Deserializer(object):
|
|
|
1677
1778
|
:param dict/list attr: Dictionary to be deserialized. Also accepts
|
|
1678
1779
|
a list of key, value pairs.
|
|
1679
1780
|
:param str dict_type: The object type of the items in the dictionary.
|
|
1781
|
+
:return: Deserialized dictionary.
|
|
1680
1782
|
:rtype: dict
|
|
1681
1783
|
"""
|
|
1682
1784
|
if isinstance(attr, list):
|
|
@@ -1687,11 +1789,12 @@ class Deserializer(object):
|
|
|
1687
1789
|
attr = {el.tag: el.text for el in attr}
|
|
1688
1790
|
return {k: self.deserialize_data(v, dict_type) for k, v in attr.items()}
|
|
1689
1791
|
|
|
1690
|
-
def deserialize_object(self, attr, **kwargs):
|
|
1792
|
+
def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
|
|
1691
1793
|
"""Deserialize a generic object.
|
|
1692
1794
|
This will be handled as a dictionary.
|
|
1693
1795
|
|
|
1694
1796
|
:param dict attr: Dictionary to be deserialized.
|
|
1797
|
+
:return: Deserialized object.
|
|
1695
1798
|
:rtype: dict
|
|
1696
1799
|
:raises: TypeError if non-builtin datatype encountered.
|
|
1697
1800
|
"""
|
|
@@ -1726,11 +1829,10 @@ class Deserializer(object):
|
|
|
1726
1829
|
pass
|
|
1727
1830
|
return deserialized
|
|
1728
1831
|
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
raise TypeError(error + str(obj_type))
|
|
1832
|
+
error = "Cannot deserialize generic object with type: "
|
|
1833
|
+
raise TypeError(error + str(obj_type))
|
|
1732
1834
|
|
|
1733
|
-
def deserialize_basic(self, attr, data_type):
|
|
1835
|
+
def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return-statements
|
|
1734
1836
|
"""Deserialize basic builtin data type from string.
|
|
1735
1837
|
Will attempt to convert to str, int, float and bool.
|
|
1736
1838
|
This function will also accept '1', '0', 'true' and 'false' as
|
|
@@ -1738,6 +1840,7 @@ class Deserializer(object):
|
|
|
1738
1840
|
|
|
1739
1841
|
:param str attr: response string to be deserialized.
|
|
1740
1842
|
:param str data_type: deserialization data type.
|
|
1843
|
+
:return: Deserialized basic type.
|
|
1741
1844
|
:rtype: str, int, float or bool
|
|
1742
1845
|
:raises: TypeError if string format is not valid.
|
|
1743
1846
|
"""
|
|
@@ -1749,24 +1852,23 @@ class Deserializer(object):
|
|
|
1749
1852
|
if data_type == "str":
|
|
1750
1853
|
# None or '', node <a/> is empty string.
|
|
1751
1854
|
return ""
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
return None
|
|
1855
|
+
# None or '', node <a/> with a strong type is None.
|
|
1856
|
+
# Don't try to model "empty bool" or "empty int"
|
|
1857
|
+
return None
|
|
1756
1858
|
|
|
1757
1859
|
if data_type == "bool":
|
|
1758
1860
|
if attr in [True, False, 1, 0]:
|
|
1759
1861
|
return bool(attr)
|
|
1760
|
-
|
|
1862
|
+
if isinstance(attr, str):
|
|
1761
1863
|
if attr.lower() in ["true", "1"]:
|
|
1762
1864
|
return True
|
|
1763
|
-
|
|
1865
|
+
if attr.lower() in ["false", "0"]:
|
|
1764
1866
|
return False
|
|
1765
1867
|
raise TypeError("Invalid boolean value: {}".format(attr))
|
|
1766
1868
|
|
|
1767
1869
|
if data_type == "str":
|
|
1768
1870
|
return self.deserialize_unicode(attr)
|
|
1769
|
-
return eval(data_type)(attr) # nosec
|
|
1871
|
+
return eval(data_type)(attr) # nosec # pylint: disable=eval-used
|
|
1770
1872
|
|
|
1771
1873
|
@staticmethod
|
|
1772
1874
|
def deserialize_unicode(data):
|
|
@@ -1774,6 +1876,7 @@ class Deserializer(object):
|
|
|
1774
1876
|
as a string.
|
|
1775
1877
|
|
|
1776
1878
|
:param str data: response string to be deserialized.
|
|
1879
|
+
:return: Deserialized string.
|
|
1777
1880
|
:rtype: str or unicode
|
|
1778
1881
|
"""
|
|
1779
1882
|
# We might be here because we have an enum modeled as string,
|
|
@@ -1787,8 +1890,7 @@ class Deserializer(object):
|
|
|
1787
1890
|
return data
|
|
1788
1891
|
except NameError:
|
|
1789
1892
|
return str(data)
|
|
1790
|
-
|
|
1791
|
-
return str(data)
|
|
1893
|
+
return str(data)
|
|
1792
1894
|
|
|
1793
1895
|
@staticmethod
|
|
1794
1896
|
def deserialize_enum(data, enum_obj):
|
|
@@ -1800,6 +1902,7 @@ class Deserializer(object):
|
|
|
1800
1902
|
:param str data: Response string to be deserialized. If this value is
|
|
1801
1903
|
None or invalid it will be returned as-is.
|
|
1802
1904
|
:param Enum enum_obj: Enum object to deserialize to.
|
|
1905
|
+
:return: Deserialized enum object.
|
|
1803
1906
|
:rtype: Enum
|
|
1804
1907
|
"""
|
|
1805
1908
|
if isinstance(data, enum_obj) or data is None:
|
|
@@ -1810,9 +1913,9 @@ class Deserializer(object):
|
|
|
1810
1913
|
# Workaround. We might consider remove it in the future.
|
|
1811
1914
|
try:
|
|
1812
1915
|
return list(enum_obj.__members__.values())[data]
|
|
1813
|
-
except IndexError:
|
|
1916
|
+
except IndexError as exc:
|
|
1814
1917
|
error = "{!r} is not a valid index for enum {!r}"
|
|
1815
|
-
raise DeserializationError(error.format(data, enum_obj))
|
|
1918
|
+
raise DeserializationError(error.format(data, enum_obj)) from exc
|
|
1816
1919
|
try:
|
|
1817
1920
|
return enum_obj(str(data))
|
|
1818
1921
|
except ValueError:
|
|
@@ -1828,6 +1931,7 @@ class Deserializer(object):
|
|
|
1828
1931
|
"""Deserialize string into bytearray.
|
|
1829
1932
|
|
|
1830
1933
|
:param str attr: response string to be deserialized.
|
|
1934
|
+
:return: Deserialized bytearray
|
|
1831
1935
|
:rtype: bytearray
|
|
1832
1936
|
:raises: TypeError if string format invalid.
|
|
1833
1937
|
"""
|
|
@@ -1840,6 +1944,7 @@ class Deserializer(object):
|
|
|
1840
1944
|
"""Deserialize base64 encoded string into string.
|
|
1841
1945
|
|
|
1842
1946
|
:param str attr: response string to be deserialized.
|
|
1947
|
+
:return: Deserialized base64 string
|
|
1843
1948
|
:rtype: bytearray
|
|
1844
1949
|
:raises: TypeError if string format invalid.
|
|
1845
1950
|
"""
|
|
@@ -1855,8 +1960,9 @@ class Deserializer(object):
|
|
|
1855
1960
|
"""Deserialize string into Decimal object.
|
|
1856
1961
|
|
|
1857
1962
|
:param str attr: response string to be deserialized.
|
|
1858
|
-
:
|
|
1963
|
+
:return: Deserialized decimal
|
|
1859
1964
|
:raises: DeserializationError if string format invalid.
|
|
1965
|
+
:rtype: decimal
|
|
1860
1966
|
"""
|
|
1861
1967
|
if isinstance(attr, ET.Element):
|
|
1862
1968
|
attr = attr.text
|
|
@@ -1871,6 +1977,7 @@ class Deserializer(object):
|
|
|
1871
1977
|
"""Deserialize string into long (Py2) or int (Py3).
|
|
1872
1978
|
|
|
1873
1979
|
:param str attr: response string to be deserialized.
|
|
1980
|
+
:return: Deserialized int
|
|
1874
1981
|
:rtype: long or int
|
|
1875
1982
|
:raises: ValueError if string format invalid.
|
|
1876
1983
|
"""
|
|
@@ -1883,6 +1990,7 @@ class Deserializer(object):
|
|
|
1883
1990
|
"""Deserialize ISO-8601 formatted string into TimeDelta object.
|
|
1884
1991
|
|
|
1885
1992
|
:param str attr: response string to be deserialized.
|
|
1993
|
+
:return: Deserialized duration
|
|
1886
1994
|
:rtype: TimeDelta
|
|
1887
1995
|
:raises: DeserializationError if string format invalid.
|
|
1888
1996
|
"""
|
|
@@ -1893,14 +2001,14 @@ class Deserializer(object):
|
|
|
1893
2001
|
except (ValueError, OverflowError, AttributeError) as err:
|
|
1894
2002
|
msg = "Cannot deserialize duration object."
|
|
1895
2003
|
raise DeserializationError(msg) from err
|
|
1896
|
-
|
|
1897
|
-
return duration
|
|
2004
|
+
return duration
|
|
1898
2005
|
|
|
1899
2006
|
@staticmethod
|
|
1900
2007
|
def deserialize_date(attr):
|
|
1901
2008
|
"""Deserialize ISO-8601 formatted string into Date object.
|
|
1902
2009
|
|
|
1903
2010
|
:param str attr: response string to be deserialized.
|
|
2011
|
+
:return: Deserialized date
|
|
1904
2012
|
:rtype: Date
|
|
1905
2013
|
:raises: DeserializationError if string format invalid.
|
|
1906
2014
|
"""
|
|
@@ -1916,6 +2024,7 @@ class Deserializer(object):
|
|
|
1916
2024
|
"""Deserialize ISO-8601 formatted string into time object.
|
|
1917
2025
|
|
|
1918
2026
|
:param str attr: response string to be deserialized.
|
|
2027
|
+
:return: Deserialized time
|
|
1919
2028
|
:rtype: datetime.time
|
|
1920
2029
|
:raises: DeserializationError if string format invalid.
|
|
1921
2030
|
"""
|
|
@@ -1930,6 +2039,7 @@ class Deserializer(object):
|
|
|
1930
2039
|
"""Deserialize RFC-1123 formatted string into Datetime object.
|
|
1931
2040
|
|
|
1932
2041
|
:param str attr: response string to be deserialized.
|
|
2042
|
+
:return: Deserialized RFC datetime
|
|
1933
2043
|
:rtype: Datetime
|
|
1934
2044
|
:raises: DeserializationError if string format invalid.
|
|
1935
2045
|
"""
|
|
@@ -1945,14 +2055,14 @@ class Deserializer(object):
|
|
|
1945
2055
|
except ValueError as err:
|
|
1946
2056
|
msg = "Cannot deserialize to rfc datetime object."
|
|
1947
2057
|
raise DeserializationError(msg) from err
|
|
1948
|
-
|
|
1949
|
-
return date_obj
|
|
2058
|
+
return date_obj
|
|
1950
2059
|
|
|
1951
2060
|
@staticmethod
|
|
1952
2061
|
def deserialize_iso(attr):
|
|
1953
2062
|
"""Deserialize ISO-8601 formatted string into Datetime object.
|
|
1954
2063
|
|
|
1955
2064
|
:param str attr: response string to be deserialized.
|
|
2065
|
+
:return: Deserialized ISO datetime
|
|
1956
2066
|
:rtype: Datetime
|
|
1957
2067
|
:raises: DeserializationError if string format invalid.
|
|
1958
2068
|
"""
|
|
@@ -1982,8 +2092,7 @@ class Deserializer(object):
|
|
|
1982
2092
|
except (ValueError, OverflowError, AttributeError) as err:
|
|
1983
2093
|
msg = "Cannot deserialize datetime object."
|
|
1984
2094
|
raise DeserializationError(msg) from err
|
|
1985
|
-
|
|
1986
|
-
return date_obj
|
|
2095
|
+
return date_obj
|
|
1987
2096
|
|
|
1988
2097
|
@staticmethod
|
|
1989
2098
|
def deserialize_unix(attr):
|
|
@@ -1991,6 +2100,7 @@ class Deserializer(object):
|
|
|
1991
2100
|
This is represented as seconds.
|
|
1992
2101
|
|
|
1993
2102
|
:param int attr: Object to be serialized.
|
|
2103
|
+
:return: Deserialized datetime
|
|
1994
2104
|
:rtype: Datetime
|
|
1995
2105
|
:raises: DeserializationError if format invalid
|
|
1996
2106
|
"""
|
|
@@ -2002,5 +2112,4 @@ class Deserializer(object):
|
|
|
2002
2112
|
except ValueError as err:
|
|
2003
2113
|
msg = "Cannot deserialize to unix datetime object."
|
|
2004
2114
|
raise DeserializationError(msg) from err
|
|
2005
|
-
|
|
2006
|
-
return date_obj
|
|
2115
|
+
return date_obj
|