azure-quantum 2.5.0.dev2__py3-none-any.whl → 3.0.0__py3-none-any.whl
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.
- azure/quantum/_client/__init__.py +11 -5
- azure/quantum/_client/_client.py +40 -49
- azure/quantum/_client/_configuration.py +34 -41
- azure/quantum/_client/_model_base.py +1159 -0
- azure/quantum/_client/_serialization.py +285 -172
- azure/quantum/_client/_version.py +1 -1
- azure/quantum/_client/models/__init__.py +41 -30
- azure/quantum/_client/models/_enums.py +34 -4
- azure/quantum/_client/models/_models.py +435 -764
- azure/quantum/_client/operations/__init__.py +16 -10
- azure/quantum/_client/operations/_operations.py +1191 -769
- azure/quantum/target/microsoft/elements/dft/target.py +4 -1
- azure/quantum/version.py +1 -1
- azure/quantum/workspace.py +371 -38
- {azure_quantum-2.5.0.dev2.dist-info → azure_quantum-3.0.0.dist-info}/METADATA +1 -1
- {azure_quantum-2.5.0.dev2.dist-info → azure_quantum-3.0.0.dist-info}/RECORD +18 -18
- azure/quantum/_client/_vendor.py +0 -20
- {azure_quantum-2.5.0.dev2.dist-info → azure_quantum-3.0.0.dist-info}/WHEEL +0 -0
- {azure_quantum-2.5.0.dev2.dist-info → azure_quantum-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint: disable=too-many-lines
|
|
1
2
|
# --------------------------------------------------------------------------
|
|
2
3
|
#
|
|
3
4
|
# Copyright (c) Microsoft 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
|
|
|
@@ -144,6 +145,8 @@ class RawDeserializer:
|
|
|
144
145
|
# context otherwise.
|
|
145
146
|
_LOGGER.critical("Wasn't XML not JSON, failing")
|
|
146
147
|
raise DeserializationError("XML is invalid") from err
|
|
148
|
+
elif content_type.startswith("text/"):
|
|
149
|
+
return data_as_str
|
|
147
150
|
raise DeserializationError("Cannot deserialize content-type: {}".format(content_type))
|
|
148
151
|
|
|
149
152
|
@classmethod
|
|
@@ -153,6 +156,11 @@ class RawDeserializer:
|
|
|
153
156
|
Use bytes and headers to NOT use any requests/aiohttp or whatever
|
|
154
157
|
specific implementation.
|
|
155
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
|
|
156
164
|
"""
|
|
157
165
|
# Try to use content-type from headers if available
|
|
158
166
|
content_type = None
|
|
@@ -170,13 +178,6 @@ class RawDeserializer:
|
|
|
170
178
|
return None
|
|
171
179
|
|
|
172
180
|
|
|
173
|
-
try:
|
|
174
|
-
basestring # type: ignore
|
|
175
|
-
unicode_str = unicode # type: ignore
|
|
176
|
-
except NameError:
|
|
177
|
-
basestring = str
|
|
178
|
-
unicode_str = str
|
|
179
|
-
|
|
180
181
|
_LOGGER = logging.getLogger(__name__)
|
|
181
182
|
|
|
182
183
|
try:
|
|
@@ -189,15 +190,30 @@ class UTC(datetime.tzinfo):
|
|
|
189
190
|
"""Time Zone info for handling UTC"""
|
|
190
191
|
|
|
191
192
|
def utcoffset(self, dt):
|
|
192
|
-
"""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
|
+
"""
|
|
193
199
|
return datetime.timedelta(0)
|
|
194
200
|
|
|
195
201
|
def tzname(self, dt):
|
|
196
|
-
"""Timestamp representation.
|
|
202
|
+
"""Timestamp representation.
|
|
203
|
+
|
|
204
|
+
:param datetime.datetime dt: The datetime
|
|
205
|
+
:returns: The timestamp representation
|
|
206
|
+
:rtype: str
|
|
207
|
+
"""
|
|
197
208
|
return "Z"
|
|
198
209
|
|
|
199
210
|
def dst(self, dt):
|
|
200
|
-
"""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
|
+
"""
|
|
201
217
|
return datetime.timedelta(hours=1)
|
|
202
218
|
|
|
203
219
|
|
|
@@ -211,7 +227,7 @@ except ImportError: # Python 2.7
|
|
|
211
227
|
:param datetime.timedelta offset: offset in timedelta format
|
|
212
228
|
"""
|
|
213
229
|
|
|
214
|
-
def __init__(self, offset):
|
|
230
|
+
def __init__(self, offset) -> None:
|
|
215
231
|
self.__offset = offset
|
|
216
232
|
|
|
217
233
|
def utcoffset(self, dt):
|
|
@@ -240,24 +256,26 @@ except ImportError:
|
|
|
240
256
|
_FLATTEN = re.compile(r"(?<!\\)\.")
|
|
241
257
|
|
|
242
258
|
|
|
243
|
-
def attribute_transformer(key, attr_desc, value):
|
|
259
|
+
def attribute_transformer(key, attr_desc, value): # pylint: disable=unused-argument
|
|
244
260
|
"""A key transformer that returns the Python attribute.
|
|
245
261
|
|
|
246
262
|
:param str key: The attribute name
|
|
247
263
|
:param dict attr_desc: The attribute metadata
|
|
248
264
|
:param object value: The value
|
|
249
265
|
:returns: A key using attribute name
|
|
266
|
+
:rtype: str
|
|
250
267
|
"""
|
|
251
268
|
return (key, value)
|
|
252
269
|
|
|
253
270
|
|
|
254
|
-
def full_restapi_key_transformer(key, attr_desc, value):
|
|
271
|
+
def full_restapi_key_transformer(key, attr_desc, value): # pylint: disable=unused-argument
|
|
255
272
|
"""A key transformer that returns the full RestAPI key path.
|
|
256
273
|
|
|
257
|
-
:param str
|
|
274
|
+
:param str key: The attribute name
|
|
258
275
|
:param dict attr_desc: The attribute metadata
|
|
259
276
|
:param object value: The value
|
|
260
277
|
:returns: A list of keys using RestAPI syntax.
|
|
278
|
+
:rtype: list
|
|
261
279
|
"""
|
|
262
280
|
keys = _FLATTEN.split(attr_desc["key"])
|
|
263
281
|
return ([_decode_attribute_map_key(k) for k in keys], value)
|
|
@@ -270,19 +288,26 @@ def last_restapi_key_transformer(key, attr_desc, value):
|
|
|
270
288
|
:param dict attr_desc: The attribute metadata
|
|
271
289
|
:param object value: The value
|
|
272
290
|
:returns: The last RestAPI key.
|
|
291
|
+
:rtype: str
|
|
273
292
|
"""
|
|
274
293
|
key, value = full_restapi_key_transformer(key, attr_desc, value)
|
|
275
294
|
return (key[-1], value)
|
|
276
295
|
|
|
277
296
|
|
|
278
297
|
def _create_xml_node(tag, prefix=None, ns=None):
|
|
279
|
-
"""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
|
+
"""
|
|
280
306
|
if prefix and ns:
|
|
281
307
|
ET.register_namespace(prefix, ns)
|
|
282
308
|
if ns:
|
|
283
309
|
return ET.Element("{" + ns + "}" + tag)
|
|
284
|
-
|
|
285
|
-
return ET.Element(tag)
|
|
310
|
+
return ET.Element(tag)
|
|
286
311
|
|
|
287
312
|
|
|
288
313
|
class Model(object):
|
|
@@ -296,7 +321,7 @@ class Model(object):
|
|
|
296
321
|
|
|
297
322
|
def __init__(self, **kwargs: Any) -> None:
|
|
298
323
|
self.additional_properties: Optional[Dict[str, Any]] = {}
|
|
299
|
-
for k in kwargs:
|
|
324
|
+
for k in kwargs: # pylint: disable=consider-using-dict-items
|
|
300
325
|
if k not in self._attribute_map:
|
|
301
326
|
_LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
|
|
302
327
|
elif k in self._validation and self._validation[k].get("readonly", False):
|
|
@@ -305,13 +330,23 @@ class Model(object):
|
|
|
305
330
|
setattr(self, k, kwargs[k])
|
|
306
331
|
|
|
307
332
|
def __eq__(self, other: Any) -> bool:
|
|
308
|
-
"""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
|
+
"""
|
|
309
339
|
if isinstance(other, self.__class__):
|
|
310
340
|
return self.__dict__ == other.__dict__
|
|
311
341
|
return False
|
|
312
342
|
|
|
313
343
|
def __ne__(self, other: Any) -> bool:
|
|
314
|
-
"""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
|
+
"""
|
|
315
350
|
return not self.__eq__(other)
|
|
316
351
|
|
|
317
352
|
def __str__(self) -> str:
|
|
@@ -331,7 +366,11 @@ class Model(object):
|
|
|
331
366
|
|
|
332
367
|
@classmethod
|
|
333
368
|
def _create_xml_node(cls):
|
|
334
|
-
"""Create XML node.
|
|
369
|
+
"""Create XML node.
|
|
370
|
+
|
|
371
|
+
:returns: The XML node
|
|
372
|
+
:rtype: xml.etree.ElementTree.Element
|
|
373
|
+
"""
|
|
335
374
|
try:
|
|
336
375
|
xml_map = cls._xml_map # type: ignore
|
|
337
376
|
except AttributeError:
|
|
@@ -351,7 +390,9 @@ class Model(object):
|
|
|
351
390
|
:rtype: dict
|
|
352
391
|
"""
|
|
353
392
|
serializer = Serializer(self._infer_class_models())
|
|
354
|
-
return serializer._serialize(
|
|
393
|
+
return serializer._serialize( # type: ignore # pylint: disable=protected-access
|
|
394
|
+
self, keep_readonly=keep_readonly, **kwargs
|
|
395
|
+
)
|
|
355
396
|
|
|
356
397
|
def as_dict(
|
|
357
398
|
self,
|
|
@@ -385,12 +426,15 @@ class Model(object):
|
|
|
385
426
|
|
|
386
427
|
If you want XML serialization, you can pass the kwargs is_xml=True.
|
|
387
428
|
|
|
429
|
+
:param bool keep_readonly: If you want to serialize the readonly attributes
|
|
388
430
|
:param function key_transformer: A key transformer function.
|
|
389
431
|
:returns: A dict JSON compatible object
|
|
390
432
|
:rtype: dict
|
|
391
433
|
"""
|
|
392
434
|
serializer = Serializer(self._infer_class_models())
|
|
393
|
-
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
|
+
)
|
|
394
438
|
|
|
395
439
|
@classmethod
|
|
396
440
|
def _infer_class_models(cls):
|
|
@@ -400,7 +444,7 @@ class Model(object):
|
|
|
400
444
|
client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
|
|
401
445
|
if cls.__name__ not in client_models:
|
|
402
446
|
raise ValueError("Not Autorest generated code")
|
|
403
|
-
except Exception:
|
|
447
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
404
448
|
# Assume it's not Autorest generated (tests?). Add ourselves as dependencies.
|
|
405
449
|
client_models = {cls.__name__: cls}
|
|
406
450
|
return client_models
|
|
@@ -413,6 +457,7 @@ class Model(object):
|
|
|
413
457
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
414
458
|
:returns: An instance of this model
|
|
415
459
|
:raises: DeserializationError if something went wrong
|
|
460
|
+
:rtype: ModelType
|
|
416
461
|
"""
|
|
417
462
|
deserializer = Deserializer(cls._infer_class_models())
|
|
418
463
|
return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
|
|
@@ -431,9 +476,11 @@ class Model(object):
|
|
|
431
476
|
and last_rest_key_case_insensitive_extractor)
|
|
432
477
|
|
|
433
478
|
:param dict data: A dict using RestAPI structure
|
|
479
|
+
:param function key_extractors: A key extractor function.
|
|
434
480
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
435
481
|
:returns: An instance of this model
|
|
436
482
|
:raises: DeserializationError if something went wrong
|
|
483
|
+
:rtype: ModelType
|
|
437
484
|
"""
|
|
438
485
|
deserializer = Deserializer(cls._infer_class_models())
|
|
439
486
|
deserializer.key_extractors = ( # type: ignore
|
|
@@ -453,21 +500,25 @@ class Model(object):
|
|
|
453
500
|
return {}
|
|
454
501
|
result = dict(cls._subtype_map[key])
|
|
455
502
|
for valuetype in cls._subtype_map[key].values():
|
|
456
|
-
result.update(objects[valuetype]._flatten_subtype(key, objects))
|
|
503
|
+
result.update(objects[valuetype]._flatten_subtype(key, objects)) # pylint: disable=protected-access
|
|
457
504
|
return result
|
|
458
505
|
|
|
459
506
|
@classmethod
|
|
460
507
|
def _classify(cls, response, objects):
|
|
461
508
|
"""Check the class _subtype_map for any child classes.
|
|
462
509
|
We want to ignore any inherited _subtype_maps.
|
|
463
|
-
|
|
510
|
+
|
|
511
|
+
:param dict response: The initial data
|
|
512
|
+
:param dict objects: The class objects
|
|
513
|
+
:returns: The class to be used
|
|
514
|
+
:rtype: class
|
|
464
515
|
"""
|
|
465
516
|
for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
|
|
466
517
|
subtype_value = None
|
|
467
518
|
|
|
468
519
|
if not isinstance(response, ET.Element):
|
|
469
520
|
rest_api_response_key = cls._get_rest_key_parts(subtype_key)[-1]
|
|
470
|
-
subtype_value = response.
|
|
521
|
+
subtype_value = response.get(rest_api_response_key, None) or response.get(subtype_key, None)
|
|
471
522
|
else:
|
|
472
523
|
subtype_value = xml_key_extractor(subtype_key, cls._attribute_map[subtype_key], response)
|
|
473
524
|
if subtype_value:
|
|
@@ -506,11 +557,13 @@ def _decode_attribute_map_key(key):
|
|
|
506
557
|
inside the received data.
|
|
507
558
|
|
|
508
559
|
:param str key: A key string from the generated code
|
|
560
|
+
:returns: The decoded key
|
|
561
|
+
:rtype: str
|
|
509
562
|
"""
|
|
510
563
|
return key.replace("\\.", ".")
|
|
511
564
|
|
|
512
565
|
|
|
513
|
-
class Serializer(object):
|
|
566
|
+
class Serializer(object): # pylint: disable=too-many-public-methods
|
|
514
567
|
"""Request object model serializer."""
|
|
515
568
|
|
|
516
569
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
|
@@ -545,7 +598,7 @@ class Serializer(object):
|
|
|
545
598
|
"multiple": lambda x, y: x % y != 0,
|
|
546
599
|
}
|
|
547
600
|
|
|
548
|
-
def __init__(self, classes: Optional[Mapping[str,
|
|
601
|
+
def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
|
|
549
602
|
self.serialize_type = {
|
|
550
603
|
"iso-8601": Serializer.serialize_iso,
|
|
551
604
|
"rfc-1123": Serializer.serialize_rfc,
|
|
@@ -561,17 +614,20 @@ class Serializer(object):
|
|
|
561
614
|
"[]": self.serialize_iter,
|
|
562
615
|
"{}": self.serialize_dict,
|
|
563
616
|
}
|
|
564
|
-
self.dependencies: Dict[str,
|
|
617
|
+
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
|
|
565
618
|
self.key_transformer = full_restapi_key_transformer
|
|
566
619
|
self.client_side_validation = True
|
|
567
620
|
|
|
568
|
-
def _serialize(
|
|
621
|
+
def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
|
|
622
|
+
self, target_obj, data_type=None, **kwargs
|
|
623
|
+
):
|
|
569
624
|
"""Serialize data into a string according to type.
|
|
570
625
|
|
|
571
|
-
:param target_obj: The data to be serialized.
|
|
626
|
+
:param object target_obj: The data to be serialized.
|
|
572
627
|
:param str data_type: The type to be serialized from.
|
|
573
628
|
:rtype: str, dict
|
|
574
629
|
:raises: SerializationError if serialization fails.
|
|
630
|
+
:returns: The serialized data.
|
|
575
631
|
"""
|
|
576
632
|
key_transformer = kwargs.get("key_transformer", self.key_transformer)
|
|
577
633
|
keep_readonly = kwargs.get("keep_readonly", False)
|
|
@@ -597,12 +653,14 @@ class Serializer(object):
|
|
|
597
653
|
|
|
598
654
|
serialized = {}
|
|
599
655
|
if is_xml_model_serialization:
|
|
600
|
-
serialized = target_obj._create_xml_node()
|
|
656
|
+
serialized = target_obj._create_xml_node() # pylint: disable=protected-access
|
|
601
657
|
try:
|
|
602
|
-
attributes = target_obj._attribute_map
|
|
658
|
+
attributes = target_obj._attribute_map # pylint: disable=protected-access
|
|
603
659
|
for attr, attr_desc in attributes.items():
|
|
604
660
|
attr_name = attr
|
|
605
|
-
if not keep_readonly and target_obj._validation.get(
|
|
661
|
+
if not keep_readonly and target_obj._validation.get( # pylint: disable=protected-access
|
|
662
|
+
attr_name, {}
|
|
663
|
+
).get("readonly", False):
|
|
606
664
|
continue
|
|
607
665
|
|
|
608
666
|
if attr_name == "additional_properties" and attr_desc["key"] == "":
|
|
@@ -638,7 +696,8 @@ class Serializer(object):
|
|
|
638
696
|
if isinstance(new_attr, list):
|
|
639
697
|
serialized.extend(new_attr) # type: ignore
|
|
640
698
|
elif isinstance(new_attr, ET.Element):
|
|
641
|
-
# If the down XML has no XML/Name,
|
|
699
|
+
# If the down XML has no XML/Name,
|
|
700
|
+
# we MUST replace the tag with the local tag. But keeping the namespaces.
|
|
642
701
|
if "name" not in getattr(orig_attr, "_xml_map", {}):
|
|
643
702
|
splitted_tag = new_attr.tag.split("}")
|
|
644
703
|
if len(splitted_tag) == 2: # Namespace
|
|
@@ -649,7 +708,7 @@ class Serializer(object):
|
|
|
649
708
|
else: # That's a basic type
|
|
650
709
|
# Integrate namespace if necessary
|
|
651
710
|
local_node = _create_xml_node(xml_name, xml_prefix, xml_ns)
|
|
652
|
-
local_node.text =
|
|
711
|
+
local_node.text = str(new_attr)
|
|
653
712
|
serialized.append(local_node) # type: ignore
|
|
654
713
|
else: # JSON
|
|
655
714
|
for k in reversed(keys): # type: ignore
|
|
@@ -669,17 +728,17 @@ class Serializer(object):
|
|
|
669
728
|
except (AttributeError, KeyError, TypeError) as err:
|
|
670
729
|
msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
|
|
671
730
|
raise SerializationError(msg) from err
|
|
672
|
-
|
|
673
|
-
return serialized
|
|
731
|
+
return serialized
|
|
674
732
|
|
|
675
733
|
def body(self, data, data_type, **kwargs):
|
|
676
734
|
"""Serialize data intended for a request body.
|
|
677
735
|
|
|
678
|
-
:param data: The data to be serialized.
|
|
736
|
+
:param object data: The data to be serialized.
|
|
679
737
|
:param str data_type: The type to be serialized from.
|
|
680
738
|
:rtype: dict
|
|
681
739
|
:raises: SerializationError if serialization fails.
|
|
682
740
|
:raises: ValueError if data is None
|
|
741
|
+
:returns: The serialized request body
|
|
683
742
|
"""
|
|
684
743
|
|
|
685
744
|
# Just in case this is a dict
|
|
@@ -708,7 +767,7 @@ class Serializer(object):
|
|
|
708
767
|
attribute_key_case_insensitive_extractor,
|
|
709
768
|
last_rest_key_case_insensitive_extractor,
|
|
710
769
|
]
|
|
711
|
-
data = deserializer._deserialize(data_type, data)
|
|
770
|
+
data = deserializer._deserialize(data_type, data) # pylint: disable=protected-access
|
|
712
771
|
except DeserializationError as err:
|
|
713
772
|
raise SerializationError("Unable to build a model: " + str(err)) from err
|
|
714
773
|
|
|
@@ -717,9 +776,11 @@ class Serializer(object):
|
|
|
717
776
|
def url(self, name, data, data_type, **kwargs):
|
|
718
777
|
"""Serialize data intended for a URL path.
|
|
719
778
|
|
|
720
|
-
:param
|
|
779
|
+
:param str name: The name of the URL path parameter.
|
|
780
|
+
:param object data: The data to be serialized.
|
|
721
781
|
:param str data_type: The type to be serialized from.
|
|
722
782
|
:rtype: str
|
|
783
|
+
:returns: The serialized URL path
|
|
723
784
|
:raises: TypeError if serialization fails.
|
|
724
785
|
:raises: ValueError if data is None
|
|
725
786
|
"""
|
|
@@ -733,21 +794,20 @@ class Serializer(object):
|
|
|
733
794
|
output = output.replace("{", quote("{")).replace("}", quote("}"))
|
|
734
795
|
else:
|
|
735
796
|
output = quote(str(output), safe="")
|
|
736
|
-
except SerializationError:
|
|
737
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
738
|
-
|
|
739
|
-
return output
|
|
797
|
+
except SerializationError as exc:
|
|
798
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
799
|
+
return output
|
|
740
800
|
|
|
741
801
|
def query(self, name, data, data_type, **kwargs):
|
|
742
802
|
"""Serialize data intended for a URL query.
|
|
743
803
|
|
|
744
|
-
:param
|
|
804
|
+
:param str name: The name of the query parameter.
|
|
805
|
+
:param object data: The data to be serialized.
|
|
745
806
|
:param str data_type: The type to be serialized from.
|
|
746
|
-
:keyword bool skip_quote: Whether to skip quote the serialized result.
|
|
747
|
-
Defaults to False.
|
|
748
807
|
:rtype: str, list
|
|
749
808
|
:raises: TypeError if serialization fails.
|
|
750
809
|
:raises: ValueError if data is None
|
|
810
|
+
:returns: The serialized query parameter
|
|
751
811
|
"""
|
|
752
812
|
try:
|
|
753
813
|
# Treat the list aside, since we don't want to encode the div separator
|
|
@@ -764,19 +824,20 @@ class Serializer(object):
|
|
|
764
824
|
output = str(output)
|
|
765
825
|
else:
|
|
766
826
|
output = quote(str(output), safe="")
|
|
767
|
-
except SerializationError:
|
|
768
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
769
|
-
|
|
770
|
-
return str(output)
|
|
827
|
+
except SerializationError as exc:
|
|
828
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
829
|
+
return str(output)
|
|
771
830
|
|
|
772
831
|
def header(self, name, data, data_type, **kwargs):
|
|
773
832
|
"""Serialize data intended for a request header.
|
|
774
833
|
|
|
775
|
-
:param
|
|
834
|
+
:param str name: The name of the header.
|
|
835
|
+
:param object data: The data to be serialized.
|
|
776
836
|
:param str data_type: The type to be serialized from.
|
|
777
837
|
:rtype: str
|
|
778
838
|
:raises: TypeError if serialization fails.
|
|
779
839
|
:raises: ValueError if data is None
|
|
840
|
+
:returns: The serialized header
|
|
780
841
|
"""
|
|
781
842
|
try:
|
|
782
843
|
if data_type in ["[str]"]:
|
|
@@ -785,21 +846,20 @@ class Serializer(object):
|
|
|
785
846
|
output = self.serialize_data(data, data_type, **kwargs)
|
|
786
847
|
if data_type == "bool":
|
|
787
848
|
output = json.dumps(output)
|
|
788
|
-
except SerializationError:
|
|
789
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
|
790
|
-
|
|
791
|
-
return str(output)
|
|
849
|
+
except SerializationError as exc:
|
|
850
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
|
851
|
+
return str(output)
|
|
792
852
|
|
|
793
853
|
def serialize_data(self, data, data_type, **kwargs):
|
|
794
854
|
"""Serialize generic data according to supplied data type.
|
|
795
855
|
|
|
796
|
-
:param data: The data to be serialized.
|
|
856
|
+
:param object data: The data to be serialized.
|
|
797
857
|
:param str data_type: The type to be serialized from.
|
|
798
|
-
:param bool required: Whether it's essential that the data not be
|
|
799
|
-
empty or None
|
|
800
858
|
:raises: AttributeError if required data is None.
|
|
801
859
|
:raises: ValueError if data is None
|
|
802
860
|
:raises: SerializationError if serialization fails.
|
|
861
|
+
:returns: The serialized data.
|
|
862
|
+
:rtype: str, int, float, bool, dict, list
|
|
803
863
|
"""
|
|
804
864
|
if data is None:
|
|
805
865
|
raise ValueError("No value for given attribute")
|
|
@@ -810,7 +870,7 @@ class Serializer(object):
|
|
|
810
870
|
if data_type in self.basic_types.values():
|
|
811
871
|
return self.serialize_basic(data, data_type, **kwargs)
|
|
812
872
|
|
|
813
|
-
|
|
873
|
+
if data_type in self.serialize_type:
|
|
814
874
|
return self.serialize_type[data_type](data, **kwargs)
|
|
815
875
|
|
|
816
876
|
# If dependencies is empty, try with current data class
|
|
@@ -826,11 +886,10 @@ class Serializer(object):
|
|
|
826
886
|
except (ValueError, TypeError) as err:
|
|
827
887
|
msg = "Unable to serialize value: {!r} as type: {!r}."
|
|
828
888
|
raise SerializationError(msg.format(data, data_type)) from err
|
|
829
|
-
|
|
830
|
-
return self._serialize(data, **kwargs)
|
|
889
|
+
return self._serialize(data, **kwargs)
|
|
831
890
|
|
|
832
891
|
@classmethod
|
|
833
|
-
def _get_custom_serializers(cls, data_type, **kwargs):
|
|
892
|
+
def _get_custom_serializers(cls, data_type, **kwargs): # pylint: disable=inconsistent-return-statements
|
|
834
893
|
custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type)
|
|
835
894
|
if custom_serializer:
|
|
836
895
|
return custom_serializer
|
|
@@ -846,23 +905,26 @@ class Serializer(object):
|
|
|
846
905
|
- basic_types_serializers dict[str, callable] : If set, use the callable as serializer
|
|
847
906
|
- is_xml bool : If set, use xml_basic_types_serializers
|
|
848
907
|
|
|
849
|
-
:param data: Object to be serialized.
|
|
908
|
+
:param obj data: Object to be serialized.
|
|
850
909
|
:param str data_type: Type of object in the iterable.
|
|
910
|
+
:rtype: str, int, float, bool
|
|
911
|
+
:return: serialized object
|
|
851
912
|
"""
|
|
852
913
|
custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
|
|
853
914
|
if custom_serializer:
|
|
854
915
|
return custom_serializer(data)
|
|
855
916
|
if data_type == "str":
|
|
856
917
|
return cls.serialize_unicode(data)
|
|
857
|
-
return eval(data_type)(data) # nosec
|
|
918
|
+
return eval(data_type)(data) # nosec # pylint: disable=eval-used
|
|
858
919
|
|
|
859
920
|
@classmethod
|
|
860
921
|
def serialize_unicode(cls, data):
|
|
861
922
|
"""Special handling for serializing unicode strings in Py2.
|
|
862
923
|
Encode to UTF-8 if unicode, otherwise handle as a str.
|
|
863
924
|
|
|
864
|
-
:param data: Object to be serialized.
|
|
925
|
+
:param str data: Object to be serialized.
|
|
865
926
|
:rtype: str
|
|
927
|
+
:return: serialized object
|
|
866
928
|
"""
|
|
867
929
|
try: # If I received an enum, return its value
|
|
868
930
|
return data.value
|
|
@@ -876,8 +938,7 @@ class Serializer(object):
|
|
|
876
938
|
return data
|
|
877
939
|
except NameError:
|
|
878
940
|
return str(data)
|
|
879
|
-
|
|
880
|
-
return str(data)
|
|
941
|
+
return str(data)
|
|
881
942
|
|
|
882
943
|
def serialize_iter(self, data, iter_type, div=None, **kwargs):
|
|
883
944
|
"""Serialize iterable.
|
|
@@ -887,15 +948,13 @@ class Serializer(object):
|
|
|
887
948
|
serialization_ctxt['type'] should be same as data_type.
|
|
888
949
|
- is_xml bool : If set, serialize as XML
|
|
889
950
|
|
|
890
|
-
:param list
|
|
951
|
+
:param list data: Object to be serialized.
|
|
891
952
|
:param str iter_type: Type of object in the iterable.
|
|
892
|
-
:param bool required: Whether the objects in the iterable must
|
|
893
|
-
not be None or empty.
|
|
894
953
|
:param str div: If set, this str will be used to combine the elements
|
|
895
954
|
in the iterable into a combined string. Default is 'None'.
|
|
896
|
-
:keyword bool do_quote: Whether to quote the serialized result of each iterable element.
|
|
897
955
|
Defaults to False.
|
|
898
956
|
:rtype: list, str
|
|
957
|
+
:return: serialized iterable
|
|
899
958
|
"""
|
|
900
959
|
if isinstance(data, str):
|
|
901
960
|
raise SerializationError("Refuse str type as a valid iter type.")
|
|
@@ -950,9 +1009,8 @@ class Serializer(object):
|
|
|
950
1009
|
|
|
951
1010
|
:param dict attr: Object to be serialized.
|
|
952
1011
|
:param str dict_type: Type of object in the dictionary.
|
|
953
|
-
:param bool required: Whether the objects in the dictionary must
|
|
954
|
-
not be None or empty.
|
|
955
1012
|
:rtype: dict
|
|
1013
|
+
:return: serialized dictionary
|
|
956
1014
|
"""
|
|
957
1015
|
serialization_ctxt = kwargs.get("serialization_ctxt", {})
|
|
958
1016
|
serialized = {}
|
|
@@ -976,7 +1034,7 @@ class Serializer(object):
|
|
|
976
1034
|
|
|
977
1035
|
return serialized
|
|
978
1036
|
|
|
979
|
-
def serialize_object(self, attr, **kwargs):
|
|
1037
|
+
def serialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
|
|
980
1038
|
"""Serialize a generic object.
|
|
981
1039
|
This will be handled as a dictionary. If object passed in is not
|
|
982
1040
|
a basic type (str, int, float, dict, list) it will simply be
|
|
@@ -984,6 +1042,7 @@ class Serializer(object):
|
|
|
984
1042
|
|
|
985
1043
|
:param dict attr: Object to be serialized.
|
|
986
1044
|
:rtype: dict or str
|
|
1045
|
+
:return: serialized object
|
|
987
1046
|
"""
|
|
988
1047
|
if attr is None:
|
|
989
1048
|
return None
|
|
@@ -994,7 +1053,7 @@ class Serializer(object):
|
|
|
994
1053
|
return self.serialize_basic(attr, self.basic_types[obj_type], **kwargs)
|
|
995
1054
|
if obj_type is _long_type:
|
|
996
1055
|
return self.serialize_long(attr)
|
|
997
|
-
if obj_type is
|
|
1056
|
+
if obj_type is str:
|
|
998
1057
|
return self.serialize_unicode(attr)
|
|
999
1058
|
if obj_type is datetime.datetime:
|
|
1000
1059
|
return self.serialize_iso(attr)
|
|
@@ -1008,7 +1067,7 @@ class Serializer(object):
|
|
|
1008
1067
|
return self.serialize_decimal(attr)
|
|
1009
1068
|
|
|
1010
1069
|
# If it's a model or I know this dependency, serialize as a Model
|
|
1011
|
-
|
|
1070
|
+
if obj_type in self.dependencies.values() or isinstance(attr, Model):
|
|
1012
1071
|
return self._serialize(attr)
|
|
1013
1072
|
|
|
1014
1073
|
if obj_type == dict:
|
|
@@ -1039,56 +1098,61 @@ class Serializer(object):
|
|
|
1039
1098
|
try:
|
|
1040
1099
|
enum_obj(result) # type: ignore
|
|
1041
1100
|
return result
|
|
1042
|
-
except ValueError:
|
|
1101
|
+
except ValueError as exc:
|
|
1043
1102
|
for enum_value in enum_obj: # type: ignore
|
|
1044
1103
|
if enum_value.value.lower() == str(attr).lower():
|
|
1045
1104
|
return enum_value.value
|
|
1046
1105
|
error = "{!r} is not valid value for enum {!r}"
|
|
1047
|
-
raise SerializationError(error.format(attr, enum_obj))
|
|
1106
|
+
raise SerializationError(error.format(attr, enum_obj)) from exc
|
|
1048
1107
|
|
|
1049
1108
|
@staticmethod
|
|
1050
|
-
def serialize_bytearray(attr, **kwargs):
|
|
1109
|
+
def serialize_bytearray(attr, **kwargs): # pylint: disable=unused-argument
|
|
1051
1110
|
"""Serialize bytearray into base-64 string.
|
|
1052
1111
|
|
|
1053
|
-
:param attr: Object to be serialized.
|
|
1112
|
+
:param str attr: Object to be serialized.
|
|
1054
1113
|
:rtype: str
|
|
1114
|
+
:return: serialized base64
|
|
1055
1115
|
"""
|
|
1056
1116
|
return b64encode(attr).decode()
|
|
1057
1117
|
|
|
1058
1118
|
@staticmethod
|
|
1059
|
-
def serialize_base64(attr, **kwargs):
|
|
1119
|
+
def serialize_base64(attr, **kwargs): # pylint: disable=unused-argument
|
|
1060
1120
|
"""Serialize str into base-64 string.
|
|
1061
1121
|
|
|
1062
|
-
:param attr: Object to be serialized.
|
|
1122
|
+
:param str attr: Object to be serialized.
|
|
1063
1123
|
:rtype: str
|
|
1124
|
+
:return: serialized base64
|
|
1064
1125
|
"""
|
|
1065
1126
|
encoded = b64encode(attr).decode("ascii")
|
|
1066
1127
|
return encoded.strip("=").replace("+", "-").replace("/", "_")
|
|
1067
1128
|
|
|
1068
1129
|
@staticmethod
|
|
1069
|
-
def serialize_decimal(attr, **kwargs):
|
|
1130
|
+
def serialize_decimal(attr, **kwargs): # pylint: disable=unused-argument
|
|
1070
1131
|
"""Serialize Decimal object to float.
|
|
1071
1132
|
|
|
1072
|
-
:param attr: Object to be serialized.
|
|
1133
|
+
:param decimal attr: Object to be serialized.
|
|
1073
1134
|
:rtype: float
|
|
1135
|
+
:return: serialized decimal
|
|
1074
1136
|
"""
|
|
1075
1137
|
return float(attr)
|
|
1076
1138
|
|
|
1077
1139
|
@staticmethod
|
|
1078
|
-
def serialize_long(attr, **kwargs):
|
|
1140
|
+
def serialize_long(attr, **kwargs): # pylint: disable=unused-argument
|
|
1079
1141
|
"""Serialize long (Py2) or int (Py3).
|
|
1080
1142
|
|
|
1081
|
-
:param attr: Object to be serialized.
|
|
1143
|
+
:param int attr: Object to be serialized.
|
|
1082
1144
|
:rtype: int/long
|
|
1145
|
+
:return: serialized long
|
|
1083
1146
|
"""
|
|
1084
1147
|
return _long_type(attr)
|
|
1085
1148
|
|
|
1086
1149
|
@staticmethod
|
|
1087
|
-
def serialize_date(attr, **kwargs):
|
|
1150
|
+
def serialize_date(attr, **kwargs): # pylint: disable=unused-argument
|
|
1088
1151
|
"""Serialize Date object into ISO-8601 formatted string.
|
|
1089
1152
|
|
|
1090
1153
|
:param Date attr: Object to be serialized.
|
|
1091
1154
|
:rtype: str
|
|
1155
|
+
:return: serialized date
|
|
1092
1156
|
"""
|
|
1093
1157
|
if isinstance(attr, str):
|
|
1094
1158
|
attr = isodate.parse_date(attr)
|
|
@@ -1096,11 +1160,12 @@ class Serializer(object):
|
|
|
1096
1160
|
return t
|
|
1097
1161
|
|
|
1098
1162
|
@staticmethod
|
|
1099
|
-
def serialize_time(attr, **kwargs):
|
|
1163
|
+
def serialize_time(attr, **kwargs): # pylint: disable=unused-argument
|
|
1100
1164
|
"""Serialize Time object into ISO-8601 formatted string.
|
|
1101
1165
|
|
|
1102
1166
|
:param datetime.time attr: Object to be serialized.
|
|
1103
1167
|
:rtype: str
|
|
1168
|
+
:return: serialized time
|
|
1104
1169
|
"""
|
|
1105
1170
|
if isinstance(attr, str):
|
|
1106
1171
|
attr = isodate.parse_time(attr)
|
|
@@ -1110,30 +1175,32 @@ class Serializer(object):
|
|
|
1110
1175
|
return t
|
|
1111
1176
|
|
|
1112
1177
|
@staticmethod
|
|
1113
|
-
def serialize_duration(attr, **kwargs):
|
|
1178
|
+
def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
|
|
1114
1179
|
"""Serialize TimeDelta object into ISO-8601 formatted string.
|
|
1115
1180
|
|
|
1116
1181
|
:param TimeDelta attr: Object to be serialized.
|
|
1117
1182
|
:rtype: str
|
|
1183
|
+
:return: serialized duration
|
|
1118
1184
|
"""
|
|
1119
1185
|
if isinstance(attr, str):
|
|
1120
1186
|
attr = isodate.parse_duration(attr)
|
|
1121
1187
|
return isodate.duration_isoformat(attr)
|
|
1122
1188
|
|
|
1123
1189
|
@staticmethod
|
|
1124
|
-
def serialize_rfc(attr, **kwargs):
|
|
1190
|
+
def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
|
|
1125
1191
|
"""Serialize Datetime object into RFC-1123 formatted string.
|
|
1126
1192
|
|
|
1127
1193
|
:param Datetime attr: Object to be serialized.
|
|
1128
1194
|
:rtype: str
|
|
1129
1195
|
:raises: TypeError if format invalid.
|
|
1196
|
+
:return: serialized rfc
|
|
1130
1197
|
"""
|
|
1131
1198
|
try:
|
|
1132
1199
|
if not attr.tzinfo:
|
|
1133
1200
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
|
1134
1201
|
utc = attr.utctimetuple()
|
|
1135
|
-
except AttributeError:
|
|
1136
|
-
raise TypeError("RFC1123 object must be valid Datetime object.")
|
|
1202
|
+
except AttributeError as exc:
|
|
1203
|
+
raise TypeError("RFC1123 object must be valid Datetime object.") from exc
|
|
1137
1204
|
|
|
1138
1205
|
return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
|
|
1139
1206
|
Serializer.days[utc.tm_wday],
|
|
@@ -1146,12 +1213,13 @@ class Serializer(object):
|
|
|
1146
1213
|
)
|
|
1147
1214
|
|
|
1148
1215
|
@staticmethod
|
|
1149
|
-
def serialize_iso(attr, **kwargs):
|
|
1216
|
+
def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument
|
|
1150
1217
|
"""Serialize Datetime object into ISO-8601 formatted string.
|
|
1151
1218
|
|
|
1152
1219
|
:param Datetime attr: Object to be serialized.
|
|
1153
1220
|
:rtype: str
|
|
1154
1221
|
:raises: SerializationError if format invalid.
|
|
1222
|
+
:return: serialized iso
|
|
1155
1223
|
"""
|
|
1156
1224
|
if isinstance(attr, str):
|
|
1157
1225
|
attr = isodate.parse_datetime(attr)
|
|
@@ -1177,13 +1245,14 @@ class Serializer(object):
|
|
|
1177
1245
|
raise TypeError(msg) from err
|
|
1178
1246
|
|
|
1179
1247
|
@staticmethod
|
|
1180
|
-
def serialize_unix(attr, **kwargs):
|
|
1248
|
+
def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument
|
|
1181
1249
|
"""Serialize Datetime object into IntTime format.
|
|
1182
1250
|
This is represented as seconds.
|
|
1183
1251
|
|
|
1184
1252
|
:param Datetime attr: Object to be serialized.
|
|
1185
1253
|
:rtype: int
|
|
1186
1254
|
:raises: SerializationError if format invalid
|
|
1255
|
+
:return: serialied unix
|
|
1187
1256
|
"""
|
|
1188
1257
|
if isinstance(attr, int):
|
|
1189
1258
|
return attr
|
|
@@ -1191,11 +1260,11 @@ class Serializer(object):
|
|
|
1191
1260
|
if not attr.tzinfo:
|
|
1192
1261
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
|
1193
1262
|
return int(calendar.timegm(attr.utctimetuple()))
|
|
1194
|
-
except AttributeError:
|
|
1195
|
-
raise TypeError("Unix time object must be valid Datetime object.")
|
|
1263
|
+
except AttributeError as exc:
|
|
1264
|
+
raise TypeError("Unix time object must be valid Datetime object.") from exc
|
|
1196
1265
|
|
|
1197
1266
|
|
|
1198
|
-
def rest_key_extractor(attr, attr_desc, data):
|
|
1267
|
+
def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1199
1268
|
key = attr_desc["key"]
|
|
1200
1269
|
working_data = data
|
|
1201
1270
|
|
|
@@ -1216,7 +1285,9 @@ def rest_key_extractor(attr, attr_desc, data):
|
|
|
1216
1285
|
return working_data.get(key)
|
|
1217
1286
|
|
|
1218
1287
|
|
|
1219
|
-
def rest_key_case_insensitive_extractor(
|
|
1288
|
+
def rest_key_case_insensitive_extractor( # pylint: disable=unused-argument, inconsistent-return-statements
|
|
1289
|
+
attr, attr_desc, data
|
|
1290
|
+
):
|
|
1220
1291
|
key = attr_desc["key"]
|
|
1221
1292
|
working_data = data
|
|
1222
1293
|
|
|
@@ -1237,17 +1308,29 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
|
|
|
1237
1308
|
return attribute_key_case_insensitive_extractor(key, None, working_data)
|
|
1238
1309
|
|
|
1239
1310
|
|
|
1240
|
-
def last_rest_key_extractor(attr, attr_desc, data):
|
|
1241
|
-
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1311
|
+
def last_rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1312
|
+
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1313
|
+
|
|
1314
|
+
:param str attr: The attribute to extract
|
|
1315
|
+
:param dict attr_desc: The attribute description
|
|
1316
|
+
:param dict data: The data to extract from
|
|
1317
|
+
:rtype: object
|
|
1318
|
+
:returns: The extracted attribute
|
|
1319
|
+
"""
|
|
1242
1320
|
key = attr_desc["key"]
|
|
1243
1321
|
dict_keys = _FLATTEN.split(key)
|
|
1244
1322
|
return attribute_key_extractor(dict_keys[-1], None, data)
|
|
1245
1323
|
|
|
1246
1324
|
|
|
1247
|
-
def last_rest_key_case_insensitive_extractor(attr, attr_desc, data):
|
|
1325
|
+
def last_rest_key_case_insensitive_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
1248
1326
|
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
|
1249
1327
|
|
|
1250
1328
|
This is the case insensitive version of "last_rest_key_extractor"
|
|
1329
|
+
:param str attr: The attribute to extract
|
|
1330
|
+
:param dict attr_desc: The attribute description
|
|
1331
|
+
:param dict data: The data to extract from
|
|
1332
|
+
:rtype: object
|
|
1333
|
+
:returns: The extracted attribute
|
|
1251
1334
|
"""
|
|
1252
1335
|
key = attr_desc["key"]
|
|
1253
1336
|
dict_keys = _FLATTEN.split(key)
|
|
@@ -1284,7 +1367,7 @@ def _extract_name_from_internal_type(internal_type):
|
|
|
1284
1367
|
return xml_name
|
|
1285
1368
|
|
|
1286
1369
|
|
|
1287
|
-
def xml_key_extractor(attr, attr_desc, data):
|
|
1370
|
+
def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument,too-many-return-statements
|
|
1288
1371
|
if isinstance(data, dict):
|
|
1289
1372
|
return None
|
|
1290
1373
|
|
|
@@ -1336,22 +1419,21 @@ def xml_key_extractor(attr, attr_desc, data):
|
|
|
1336
1419
|
if is_iter_type:
|
|
1337
1420
|
if is_wrapped:
|
|
1338
1421
|
return None # is_wrapped no node, we want None
|
|
1339
|
-
|
|
1340
|
-
return [] # not wrapped, assume empty list
|
|
1422
|
+
return [] # not wrapped, assume empty list
|
|
1341
1423
|
return None # Assume it's not there, maybe an optional node.
|
|
1342
1424
|
|
|
1343
1425
|
# If is_iter_type and not wrapped, return all found children
|
|
1344
1426
|
if is_iter_type:
|
|
1345
1427
|
if not is_wrapped:
|
|
1346
1428
|
return children
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
)
|
|
1429
|
+
# Iter and wrapped, should have found one node only (the wrap one)
|
|
1430
|
+
if len(children) != 1:
|
|
1431
|
+
raise DeserializationError(
|
|
1432
|
+
"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
|
|
1433
|
+
xml_name
|
|
1353
1434
|
)
|
|
1354
|
-
|
|
1435
|
+
)
|
|
1436
|
+
return list(children[0]) # Might be empty list and that's ok.
|
|
1355
1437
|
|
|
1356
1438
|
# Here it's not a itertype, we should have found one element only or empty
|
|
1357
1439
|
if len(children) > 1:
|
|
@@ -1368,9 +1450,9 @@ class Deserializer(object):
|
|
|
1368
1450
|
|
|
1369
1451
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
|
1370
1452
|
|
|
1371
|
-
valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}
|
|
1453
|
+
valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
|
|
1372
1454
|
|
|
1373
|
-
def __init__(self, classes: Optional[Mapping[str,
|
|
1455
|
+
def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
|
|
1374
1456
|
self.deserialize_type = {
|
|
1375
1457
|
"iso-8601": Deserializer.deserialize_iso,
|
|
1376
1458
|
"rfc-1123": Deserializer.deserialize_rfc,
|
|
@@ -1390,7 +1472,7 @@ class Deserializer(object):
|
|
|
1390
1472
|
"duration": (isodate.Duration, datetime.timedelta),
|
|
1391
1473
|
"iso-8601": (datetime.datetime),
|
|
1392
1474
|
}
|
|
1393
|
-
self.dependencies: Dict[str,
|
|
1475
|
+
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
|
|
1394
1476
|
self.key_extractors = [rest_key_extractor, xml_key_extractor]
|
|
1395
1477
|
# Additional properties only works if the "rest_key_extractor" is used to
|
|
1396
1478
|
# extract the keys. Making it to work whatever the key extractor is too much
|
|
@@ -1408,11 +1490,12 @@ class Deserializer(object):
|
|
|
1408
1490
|
:param str content_type: Swagger "produces" if available.
|
|
1409
1491
|
:raises: DeserializationError if deserialization fails.
|
|
1410
1492
|
:return: Deserialized object.
|
|
1493
|
+
:rtype: object
|
|
1411
1494
|
"""
|
|
1412
1495
|
data = self._unpack_content(response_data, content_type)
|
|
1413
1496
|
return self._deserialize(target_obj, data)
|
|
1414
1497
|
|
|
1415
|
-
def _deserialize(self, target_obj, data):
|
|
1498
|
+
def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return-statements
|
|
1416
1499
|
"""Call the deserializer on a model.
|
|
1417
1500
|
|
|
1418
1501
|
Data needs to be already deserialized as JSON or XML ElementTree
|
|
@@ -1421,12 +1504,13 @@ class Deserializer(object):
|
|
|
1421
1504
|
:param object data: Object to deserialize.
|
|
1422
1505
|
:raises: DeserializationError if deserialization fails.
|
|
1423
1506
|
:return: Deserialized object.
|
|
1507
|
+
:rtype: object
|
|
1424
1508
|
"""
|
|
1425
1509
|
# This is already a model, go recursive just in case
|
|
1426
1510
|
if hasattr(data, "_attribute_map"):
|
|
1427
1511
|
constants = [name for name, config in getattr(data, "_validation", {}).items() if config.get("constant")]
|
|
1428
1512
|
try:
|
|
1429
|
-
for attr, mapconfig in data._attribute_map.items():
|
|
1513
|
+
for attr, mapconfig in data._attribute_map.items(): # pylint: disable=protected-access
|
|
1430
1514
|
if attr in constants:
|
|
1431
1515
|
continue
|
|
1432
1516
|
value = getattr(data, attr)
|
|
@@ -1443,15 +1527,15 @@ class Deserializer(object):
|
|
|
1443
1527
|
|
|
1444
1528
|
response, class_name = self._classify_target(target_obj, data)
|
|
1445
1529
|
|
|
1446
|
-
if isinstance(response,
|
|
1530
|
+
if isinstance(response, str):
|
|
1447
1531
|
return self.deserialize_data(data, response)
|
|
1448
|
-
|
|
1532
|
+
if isinstance(response, type) and issubclass(response, Enum):
|
|
1449
1533
|
return self.deserialize_enum(data, response)
|
|
1450
1534
|
|
|
1451
|
-
if data is None:
|
|
1535
|
+
if data is None or data is CoreNull:
|
|
1452
1536
|
return data
|
|
1453
1537
|
try:
|
|
1454
|
-
attributes = response._attribute_map # type: ignore
|
|
1538
|
+
attributes = response._attribute_map # type: ignore # pylint: disable=protected-access
|
|
1455
1539
|
d_attrs = {}
|
|
1456
1540
|
for attr, attr_desc in attributes.items():
|
|
1457
1541
|
# Check empty string. If it's not empty, someone has a real "additionalProperties"...
|
|
@@ -1481,9 +1565,8 @@ class Deserializer(object):
|
|
|
1481
1565
|
except (AttributeError, TypeError, KeyError) as err:
|
|
1482
1566
|
msg = "Unable to deserialize to object: " + class_name # type: ignore
|
|
1483
1567
|
raise DeserializationError(msg) from err
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
return self._instantiate_model(response, d_attrs, additional_properties)
|
|
1568
|
+
additional_properties = self._build_additional_properties(attributes, data)
|
|
1569
|
+
return self._instantiate_model(response, d_attrs, additional_properties)
|
|
1487
1570
|
|
|
1488
1571
|
def _build_additional_properties(self, attribute_map, data):
|
|
1489
1572
|
if not self.additional_properties_detection:
|
|
@@ -1510,18 +1593,20 @@ class Deserializer(object):
|
|
|
1510
1593
|
|
|
1511
1594
|
:param str target: The target object type to deserialize to.
|
|
1512
1595
|
:param str/dict data: The response data to deserialize.
|
|
1596
|
+
:return: The classified target object and its class name.
|
|
1597
|
+
:rtype: tuple
|
|
1513
1598
|
"""
|
|
1514
1599
|
if target is None:
|
|
1515
1600
|
return None, None
|
|
1516
1601
|
|
|
1517
|
-
if isinstance(target,
|
|
1602
|
+
if isinstance(target, str):
|
|
1518
1603
|
try:
|
|
1519
1604
|
target = self.dependencies[target]
|
|
1520
1605
|
except KeyError:
|
|
1521
1606
|
return target, target
|
|
1522
1607
|
|
|
1523
1608
|
try:
|
|
1524
|
-
target = target._classify(data, self.dependencies)
|
|
1609
|
+
target = target._classify(data, self.dependencies) # type: ignore # pylint: disable=protected-access
|
|
1525
1610
|
except AttributeError:
|
|
1526
1611
|
pass # Target is not a Model, no classify
|
|
1527
1612
|
return target, target.__class__.__name__ # type: ignore
|
|
@@ -1536,10 +1621,12 @@ class Deserializer(object):
|
|
|
1536
1621
|
:param str target_obj: The target object type to deserialize to.
|
|
1537
1622
|
:param str/dict data: The response data to deserialize.
|
|
1538
1623
|
:param str content_type: Swagger "produces" if available.
|
|
1624
|
+
:return: Deserialized object.
|
|
1625
|
+
:rtype: object
|
|
1539
1626
|
"""
|
|
1540
1627
|
try:
|
|
1541
1628
|
return self(target_obj, data, content_type=content_type)
|
|
1542
|
-
except:
|
|
1629
|
+
except: # pylint: disable=bare-except
|
|
1543
1630
|
_LOGGER.debug(
|
|
1544
1631
|
"Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True
|
|
1545
1632
|
)
|
|
@@ -1557,10 +1644,12 @@ class Deserializer(object):
|
|
|
1557
1644
|
|
|
1558
1645
|
If raw_data is something else, bypass all logic and return it directly.
|
|
1559
1646
|
|
|
1560
|
-
:param raw_data: Data to be processed.
|
|
1561
|
-
:param content_type: How to parse if raw_data is a string/bytes.
|
|
1647
|
+
:param obj raw_data: Data to be processed.
|
|
1648
|
+
:param str content_type: How to parse if raw_data is a string/bytes.
|
|
1562
1649
|
:raises JSONDecodeError: If JSON is requested and parsing is impossible.
|
|
1563
1650
|
:raises UnicodeDecodeError: If bytes is not UTF8
|
|
1651
|
+
:rtype: object
|
|
1652
|
+
:return: Unpacked content.
|
|
1564
1653
|
"""
|
|
1565
1654
|
# Assume this is enough to detect a Pipeline Response without importing it
|
|
1566
1655
|
context = getattr(raw_data, "context", {})
|
|
@@ -1577,31 +1666,42 @@ class Deserializer(object):
|
|
|
1577
1666
|
if hasattr(raw_data, "_content_consumed"):
|
|
1578
1667
|
return RawDeserializer.deserialize_from_http_generics(raw_data.text, raw_data.headers)
|
|
1579
1668
|
|
|
1580
|
-
if isinstance(raw_data, (
|
|
1669
|
+
if isinstance(raw_data, (str, bytes)) or hasattr(raw_data, "read"):
|
|
1581
1670
|
return RawDeserializer.deserialize_from_text(raw_data, content_type) # type: ignore
|
|
1582
1671
|
return raw_data
|
|
1583
1672
|
|
|
1584
1673
|
def _instantiate_model(self, response, attrs, additional_properties=None):
|
|
1585
1674
|
"""Instantiate a response model passing in deserialized args.
|
|
1586
1675
|
|
|
1587
|
-
:param response: The response model class.
|
|
1588
|
-
:param
|
|
1676
|
+
:param Response response: The response model class.
|
|
1677
|
+
:param dict attrs: The deserialized response attributes.
|
|
1678
|
+
:param dict additional_properties: Additional properties to be set.
|
|
1679
|
+
:rtype: Response
|
|
1680
|
+
:return: The instantiated response model.
|
|
1589
1681
|
"""
|
|
1590
1682
|
if callable(response):
|
|
1591
1683
|
subtype = getattr(response, "_subtype_map", {})
|
|
1592
1684
|
try:
|
|
1593
|
-
readonly = [
|
|
1594
|
-
|
|
1685
|
+
readonly = [
|
|
1686
|
+
k
|
|
1687
|
+
for k, v in response._validation.items() # pylint: disable=protected-access # type: ignore
|
|
1688
|
+
if v.get("readonly")
|
|
1689
|
+
]
|
|
1690
|
+
const = [
|
|
1691
|
+
k
|
|
1692
|
+
for k, v in response._validation.items() # pylint: disable=protected-access # type: ignore
|
|
1693
|
+
if v.get("constant")
|
|
1694
|
+
]
|
|
1595
1695
|
kwargs = {k: v for k, v in attrs.items() if k not in subtype and k not in readonly + const}
|
|
1596
1696
|
response_obj = response(**kwargs)
|
|
1597
1697
|
for attr in readonly:
|
|
1598
1698
|
setattr(response_obj, attr, attrs.get(attr))
|
|
1599
1699
|
if additional_properties:
|
|
1600
|
-
response_obj.additional_properties = additional_properties
|
|
1700
|
+
response_obj.additional_properties = additional_properties # type: ignore
|
|
1601
1701
|
return response_obj
|
|
1602
1702
|
except TypeError as err:
|
|
1603
1703
|
msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
|
|
1604
|
-
raise DeserializationError(msg + str(err))
|
|
1704
|
+
raise DeserializationError(msg + str(err)) from err
|
|
1605
1705
|
else:
|
|
1606
1706
|
try:
|
|
1607
1707
|
for attr, value in attrs.items():
|
|
@@ -1610,15 +1710,16 @@ class Deserializer(object):
|
|
|
1610
1710
|
except Exception as exp:
|
|
1611
1711
|
msg = "Unable to populate response model. "
|
|
1612
1712
|
msg += "Type: {}, Error: {}".format(type(response), exp)
|
|
1613
|
-
raise DeserializationError(msg)
|
|
1713
|
+
raise DeserializationError(msg) from exp
|
|
1614
1714
|
|
|
1615
|
-
def deserialize_data(self, data, data_type):
|
|
1715
|
+
def deserialize_data(self, data, data_type): # pylint: disable=too-many-return-statements
|
|
1616
1716
|
"""Process data for deserialization according to data type.
|
|
1617
1717
|
|
|
1618
1718
|
:param str data: The response string to be deserialized.
|
|
1619
1719
|
:param str data_type: The type to deserialize to.
|
|
1620
1720
|
:raises: DeserializationError if deserialization fails.
|
|
1621
1721
|
:return: Deserialized object.
|
|
1722
|
+
:rtype: object
|
|
1622
1723
|
"""
|
|
1623
1724
|
if data is None:
|
|
1624
1725
|
return data
|
|
@@ -1632,7 +1733,11 @@ class Deserializer(object):
|
|
|
1632
1733
|
if isinstance(data, self.deserialize_expected_types.get(data_type, tuple())):
|
|
1633
1734
|
return data
|
|
1634
1735
|
|
|
1635
|
-
is_a_text_parsing_type = lambda x: x not in [
|
|
1736
|
+
is_a_text_parsing_type = lambda x: x not in [ # pylint: disable=unnecessary-lambda-assignment
|
|
1737
|
+
"object",
|
|
1738
|
+
"[]",
|
|
1739
|
+
r"{}",
|
|
1740
|
+
]
|
|
1636
1741
|
if isinstance(data, ET.Element) and is_a_text_parsing_type(data_type) and not data.text:
|
|
1637
1742
|
return None
|
|
1638
1743
|
data_val = self.deserialize_type[data_type](data)
|
|
@@ -1652,14 +1757,14 @@ class Deserializer(object):
|
|
|
1652
1757
|
msg = "Unable to deserialize response data."
|
|
1653
1758
|
msg += " Data: {}, {}".format(data, data_type)
|
|
1654
1759
|
raise DeserializationError(msg) from err
|
|
1655
|
-
|
|
1656
|
-
return self._deserialize(obj_type, data)
|
|
1760
|
+
return self._deserialize(obj_type, data)
|
|
1657
1761
|
|
|
1658
1762
|
def deserialize_iter(self, attr, iter_type):
|
|
1659
1763
|
"""Deserialize an iterable.
|
|
1660
1764
|
|
|
1661
1765
|
:param list attr: Iterable to be deserialized.
|
|
1662
1766
|
:param str iter_type: The type of object in the iterable.
|
|
1767
|
+
:return: Deserialized iterable.
|
|
1663
1768
|
:rtype: list
|
|
1664
1769
|
"""
|
|
1665
1770
|
if attr is None:
|
|
@@ -1676,6 +1781,7 @@ class Deserializer(object):
|
|
|
1676
1781
|
:param dict/list attr: Dictionary to be deserialized. Also accepts
|
|
1677
1782
|
a list of key, value pairs.
|
|
1678
1783
|
:param str dict_type: The object type of the items in the dictionary.
|
|
1784
|
+
:return: Deserialized dictionary.
|
|
1679
1785
|
:rtype: dict
|
|
1680
1786
|
"""
|
|
1681
1787
|
if isinstance(attr, list):
|
|
@@ -1686,11 +1792,12 @@ class Deserializer(object):
|
|
|
1686
1792
|
attr = {el.tag: el.text for el in attr}
|
|
1687
1793
|
return {k: self.deserialize_data(v, dict_type) for k, v in attr.items()}
|
|
1688
1794
|
|
|
1689
|
-
def deserialize_object(self, attr, **kwargs):
|
|
1795
|
+
def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
|
|
1690
1796
|
"""Deserialize a generic object.
|
|
1691
1797
|
This will be handled as a dictionary.
|
|
1692
1798
|
|
|
1693
1799
|
:param dict attr: Dictionary to be deserialized.
|
|
1800
|
+
:return: Deserialized object.
|
|
1694
1801
|
:rtype: dict
|
|
1695
1802
|
:raises: TypeError if non-builtin datatype encountered.
|
|
1696
1803
|
"""
|
|
@@ -1699,7 +1806,7 @@ class Deserializer(object):
|
|
|
1699
1806
|
if isinstance(attr, ET.Element):
|
|
1700
1807
|
# Do no recurse on XML, just return the tree as-is
|
|
1701
1808
|
return attr
|
|
1702
|
-
if isinstance(attr,
|
|
1809
|
+
if isinstance(attr, str):
|
|
1703
1810
|
return self.deserialize_basic(attr, "str")
|
|
1704
1811
|
obj_type = type(attr)
|
|
1705
1812
|
if obj_type in self.basic_types:
|
|
@@ -1725,11 +1832,10 @@ class Deserializer(object):
|
|
|
1725
1832
|
pass
|
|
1726
1833
|
return deserialized
|
|
1727
1834
|
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
raise TypeError(error + str(obj_type))
|
|
1835
|
+
error = "Cannot deserialize generic object with type: "
|
|
1836
|
+
raise TypeError(error + str(obj_type))
|
|
1731
1837
|
|
|
1732
|
-
def deserialize_basic(self, attr, data_type):
|
|
1838
|
+
def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return-statements
|
|
1733
1839
|
"""Deserialize basic builtin data type from string.
|
|
1734
1840
|
Will attempt to convert to str, int, float and bool.
|
|
1735
1841
|
This function will also accept '1', '0', 'true' and 'false' as
|
|
@@ -1737,6 +1843,7 @@ class Deserializer(object):
|
|
|
1737
1843
|
|
|
1738
1844
|
:param str attr: response string to be deserialized.
|
|
1739
1845
|
:param str data_type: deserialization data type.
|
|
1846
|
+
:return: Deserialized basic type.
|
|
1740
1847
|
:rtype: str, int, float or bool
|
|
1741
1848
|
:raises: TypeError if string format is not valid.
|
|
1742
1849
|
"""
|
|
@@ -1748,24 +1855,23 @@ class Deserializer(object):
|
|
|
1748
1855
|
if data_type == "str":
|
|
1749
1856
|
# None or '', node <a/> is empty string.
|
|
1750
1857
|
return ""
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
return None
|
|
1858
|
+
# None or '', node <a/> with a strong type is None.
|
|
1859
|
+
# Don't try to model "empty bool" or "empty int"
|
|
1860
|
+
return None
|
|
1755
1861
|
|
|
1756
1862
|
if data_type == "bool":
|
|
1757
1863
|
if attr in [True, False, 1, 0]:
|
|
1758
1864
|
return bool(attr)
|
|
1759
|
-
|
|
1865
|
+
if isinstance(attr, str):
|
|
1760
1866
|
if attr.lower() in ["true", "1"]:
|
|
1761
1867
|
return True
|
|
1762
|
-
|
|
1868
|
+
if attr.lower() in ["false", "0"]:
|
|
1763
1869
|
return False
|
|
1764
1870
|
raise TypeError("Invalid boolean value: {}".format(attr))
|
|
1765
1871
|
|
|
1766
1872
|
if data_type == "str":
|
|
1767
1873
|
return self.deserialize_unicode(attr)
|
|
1768
|
-
return eval(data_type)(attr) # nosec
|
|
1874
|
+
return eval(data_type)(attr) # nosec # pylint: disable=eval-used
|
|
1769
1875
|
|
|
1770
1876
|
@staticmethod
|
|
1771
1877
|
def deserialize_unicode(data):
|
|
@@ -1773,6 +1879,7 @@ class Deserializer(object):
|
|
|
1773
1879
|
as a string.
|
|
1774
1880
|
|
|
1775
1881
|
:param str data: response string to be deserialized.
|
|
1882
|
+
:return: Deserialized string.
|
|
1776
1883
|
:rtype: str or unicode
|
|
1777
1884
|
"""
|
|
1778
1885
|
# We might be here because we have an enum modeled as string,
|
|
@@ -1786,8 +1893,7 @@ class Deserializer(object):
|
|
|
1786
1893
|
return data
|
|
1787
1894
|
except NameError:
|
|
1788
1895
|
return str(data)
|
|
1789
|
-
|
|
1790
|
-
return str(data)
|
|
1896
|
+
return str(data)
|
|
1791
1897
|
|
|
1792
1898
|
@staticmethod
|
|
1793
1899
|
def deserialize_enum(data, enum_obj):
|
|
@@ -1799,6 +1905,7 @@ class Deserializer(object):
|
|
|
1799
1905
|
:param str data: Response string to be deserialized. If this value is
|
|
1800
1906
|
None or invalid it will be returned as-is.
|
|
1801
1907
|
:param Enum enum_obj: Enum object to deserialize to.
|
|
1908
|
+
:return: Deserialized enum object.
|
|
1802
1909
|
:rtype: Enum
|
|
1803
1910
|
"""
|
|
1804
1911
|
if isinstance(data, enum_obj) or data is None:
|
|
@@ -1809,9 +1916,9 @@ class Deserializer(object):
|
|
|
1809
1916
|
# Workaround. We might consider remove it in the future.
|
|
1810
1917
|
try:
|
|
1811
1918
|
return list(enum_obj.__members__.values())[data]
|
|
1812
|
-
except IndexError:
|
|
1919
|
+
except IndexError as exc:
|
|
1813
1920
|
error = "{!r} is not a valid index for enum {!r}"
|
|
1814
|
-
raise DeserializationError(error.format(data, enum_obj))
|
|
1921
|
+
raise DeserializationError(error.format(data, enum_obj)) from exc
|
|
1815
1922
|
try:
|
|
1816
1923
|
return enum_obj(str(data))
|
|
1817
1924
|
except ValueError:
|
|
@@ -1827,6 +1934,7 @@ class Deserializer(object):
|
|
|
1827
1934
|
"""Deserialize string into bytearray.
|
|
1828
1935
|
|
|
1829
1936
|
:param str attr: response string to be deserialized.
|
|
1937
|
+
:return: Deserialized bytearray
|
|
1830
1938
|
:rtype: bytearray
|
|
1831
1939
|
:raises: TypeError if string format invalid.
|
|
1832
1940
|
"""
|
|
@@ -1839,6 +1947,7 @@ class Deserializer(object):
|
|
|
1839
1947
|
"""Deserialize base64 encoded string into string.
|
|
1840
1948
|
|
|
1841
1949
|
:param str attr: response string to be deserialized.
|
|
1950
|
+
:return: Deserialized base64 string
|
|
1842
1951
|
:rtype: bytearray
|
|
1843
1952
|
:raises: TypeError if string format invalid.
|
|
1844
1953
|
"""
|
|
@@ -1854,8 +1963,9 @@ class Deserializer(object):
|
|
|
1854
1963
|
"""Deserialize string into Decimal object.
|
|
1855
1964
|
|
|
1856
1965
|
:param str attr: response string to be deserialized.
|
|
1857
|
-
:
|
|
1966
|
+
:return: Deserialized decimal
|
|
1858
1967
|
:raises: DeserializationError if string format invalid.
|
|
1968
|
+
:rtype: decimal
|
|
1859
1969
|
"""
|
|
1860
1970
|
if isinstance(attr, ET.Element):
|
|
1861
1971
|
attr = attr.text
|
|
@@ -1870,6 +1980,7 @@ class Deserializer(object):
|
|
|
1870
1980
|
"""Deserialize string into long (Py2) or int (Py3).
|
|
1871
1981
|
|
|
1872
1982
|
:param str attr: response string to be deserialized.
|
|
1983
|
+
:return: Deserialized int
|
|
1873
1984
|
:rtype: long or int
|
|
1874
1985
|
:raises: ValueError if string format invalid.
|
|
1875
1986
|
"""
|
|
@@ -1882,6 +1993,7 @@ class Deserializer(object):
|
|
|
1882
1993
|
"""Deserialize ISO-8601 formatted string into TimeDelta object.
|
|
1883
1994
|
|
|
1884
1995
|
:param str attr: response string to be deserialized.
|
|
1996
|
+
:return: Deserialized duration
|
|
1885
1997
|
:rtype: TimeDelta
|
|
1886
1998
|
:raises: DeserializationError if string format invalid.
|
|
1887
1999
|
"""
|
|
@@ -1892,14 +2004,14 @@ class Deserializer(object):
|
|
|
1892
2004
|
except (ValueError, OverflowError, AttributeError) as err:
|
|
1893
2005
|
msg = "Cannot deserialize duration object."
|
|
1894
2006
|
raise DeserializationError(msg) from err
|
|
1895
|
-
|
|
1896
|
-
return duration
|
|
2007
|
+
return duration
|
|
1897
2008
|
|
|
1898
2009
|
@staticmethod
|
|
1899
2010
|
def deserialize_date(attr):
|
|
1900
2011
|
"""Deserialize ISO-8601 formatted string into Date object.
|
|
1901
2012
|
|
|
1902
2013
|
:param str attr: response string to be deserialized.
|
|
2014
|
+
:return: Deserialized date
|
|
1903
2015
|
:rtype: Date
|
|
1904
2016
|
:raises: DeserializationError if string format invalid.
|
|
1905
2017
|
"""
|
|
@@ -1915,6 +2027,7 @@ class Deserializer(object):
|
|
|
1915
2027
|
"""Deserialize ISO-8601 formatted string into time object.
|
|
1916
2028
|
|
|
1917
2029
|
:param str attr: response string to be deserialized.
|
|
2030
|
+
:return: Deserialized time
|
|
1918
2031
|
:rtype: datetime.time
|
|
1919
2032
|
:raises: DeserializationError if string format invalid.
|
|
1920
2033
|
"""
|
|
@@ -1929,6 +2042,7 @@ class Deserializer(object):
|
|
|
1929
2042
|
"""Deserialize RFC-1123 formatted string into Datetime object.
|
|
1930
2043
|
|
|
1931
2044
|
:param str attr: response string to be deserialized.
|
|
2045
|
+
:return: Deserialized RFC datetime
|
|
1932
2046
|
:rtype: Datetime
|
|
1933
2047
|
:raises: DeserializationError if string format invalid.
|
|
1934
2048
|
"""
|
|
@@ -1944,14 +2058,14 @@ class Deserializer(object):
|
|
|
1944
2058
|
except ValueError as err:
|
|
1945
2059
|
msg = "Cannot deserialize to rfc datetime object."
|
|
1946
2060
|
raise DeserializationError(msg) from err
|
|
1947
|
-
|
|
1948
|
-
return date_obj
|
|
2061
|
+
return date_obj
|
|
1949
2062
|
|
|
1950
2063
|
@staticmethod
|
|
1951
2064
|
def deserialize_iso(attr):
|
|
1952
2065
|
"""Deserialize ISO-8601 formatted string into Datetime object.
|
|
1953
2066
|
|
|
1954
2067
|
:param str attr: response string to be deserialized.
|
|
2068
|
+
:return: Deserialized ISO datetime
|
|
1955
2069
|
:rtype: Datetime
|
|
1956
2070
|
:raises: DeserializationError if string format invalid.
|
|
1957
2071
|
"""
|
|
@@ -1981,8 +2095,7 @@ class Deserializer(object):
|
|
|
1981
2095
|
except (ValueError, OverflowError, AttributeError) as err:
|
|
1982
2096
|
msg = "Cannot deserialize datetime object."
|
|
1983
2097
|
raise DeserializationError(msg) from err
|
|
1984
|
-
|
|
1985
|
-
return date_obj
|
|
2098
|
+
return date_obj
|
|
1986
2099
|
|
|
1987
2100
|
@staticmethod
|
|
1988
2101
|
def deserialize_unix(attr):
|
|
@@ -1990,6 +2103,7 @@ class Deserializer(object):
|
|
|
1990
2103
|
This is represented as seconds.
|
|
1991
2104
|
|
|
1992
2105
|
:param int attr: Object to be serialized.
|
|
2106
|
+
:return: Deserialized datetime
|
|
1993
2107
|
:rtype: Datetime
|
|
1994
2108
|
:raises: DeserializationError if format invalid
|
|
1995
2109
|
"""
|
|
@@ -2001,5 +2115,4 @@ class Deserializer(object):
|
|
|
2001
2115
|
except ValueError as err:
|
|
2002
2116
|
msg = "Cannot deserialize to unix datetime object."
|
|
2003
2117
|
raise DeserializationError(msg) from err
|
|
2004
|
-
|
|
2005
|
-
return date_obj
|
|
2118
|
+
return date_obj
|