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