diracx-client 0.0.1a17__py3-none-any.whl → 0.0.1a19__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.
- diracx/client/__init__.py +4 -18
- diracx/client/aio.py +1 -0
- diracx/client/extensions.py +90 -0
- diracx/client/{aio → generated}/__init__.py +2 -2
- diracx/client/{_client.py → generated/_client.py} +7 -6
- diracx/client/{_configuration.py → generated/_configuration.py} +1 -1
- diracx/client/generated/_patch.py +47 -0
- diracx/client/{_serialization.py → generated/_serialization.py} +301 -151
- diracx/client/{_vendor.py → generated/_vendor.py} +1 -1
- diracx/client/generated/aio/__init__.py +21 -0
- diracx/client/{aio → generated/aio}/_client.py +7 -6
- diracx/client/{aio → generated/aio}/_configuration.py +1 -1
- diracx/client/generated/aio/_patch.py +23 -0
- diracx/client/{aio → generated/aio}/_vendor.py +1 -1
- diracx/client/{aio → generated/aio}/operations/__init__.py +1 -1
- diracx/client/{aio → generated/aio}/operations/_operations.py +402 -385
- diracx/client/{models → generated/models}/__init__.py +3 -1
- diracx/client/{models → generated/models}/_enums.py +2 -2
- diracx/client/{models → generated/models}/_models.py +84 -43
- diracx/client/{operations → generated/operations}/__init__.py +1 -1
- diracx/client/{operations → generated/operations}/_operations.py +402 -385
- diracx/client/generated/py.typed +1 -0
- diracx/client/models.py +5 -0
- diracx/client/patches/__init__.py +19 -0
- diracx/client/patches/aio/__init__.py +18 -0
- diracx/client/{aio/_patch.py → patches/aio/utils.py} +10 -19
- diracx/client/{_patch.py → patches/utils.py} +98 -121
- {diracx_client-0.0.1a17.dist-info → diracx_client-0.0.1a19.dist-info}/METADATA +4 -4
- diracx_client-0.0.1a19.dist-info/RECORD +36 -0
- {diracx_client-0.0.1a17.dist-info → diracx_client-0.0.1a19.dist-info}/WHEEL +1 -1
- diracx_client-0.0.1a19.dist-info/entry_points.txt +3 -0
- diracx_client-0.0.1a17.dist-info/RECORD +0 -26
- /diracx/client/{aio → generated/aio}/operations/_patch.py +0 -0
- /diracx/client/{models → generated/models}/_patch.py +0 -0
- /diracx/client/{operations → generated/operations}/_patch.py +0 -0
- {diracx_client-0.0.1a17.dist-info → diracx_client-0.0.1a19.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:
|
@@ -93,6 +92,8 @@ class RawDeserializer:
|
|
93
92
|
:param data: Input, could be bytes or stream (will be decoded with UTF8) or text
|
94
93
|
:type data: str or bytes or IO
|
95
94
|
:param str content_type: The content type.
|
95
|
+
:return: The deserialized data.
|
96
|
+
:rtype: object
|
96
97
|
"""
|
97
98
|
if hasattr(data, "read"):
|
98
99
|
# Assume a stream
|
@@ -114,7 +115,9 @@ class RawDeserializer:
|
|
114
115
|
try:
|
115
116
|
return json.loads(data_as_str)
|
116
117
|
except ValueError as err:
|
117
|
-
raise DeserializationError(
|
118
|
+
raise DeserializationError(
|
119
|
+
"JSON is invalid: {}".format(err), err
|
120
|
+
) from err
|
118
121
|
elif "xml" in (content_type or []):
|
119
122
|
try:
|
120
123
|
|
@@ -146,6 +149,8 @@ class RawDeserializer:
|
|
146
149
|
# context otherwise.
|
147
150
|
_LOGGER.critical("Wasn't XML not JSON, failing")
|
148
151
|
raise DeserializationError("XML is invalid") from err
|
152
|
+
elif content_type.startswith("text/"):
|
153
|
+
return data_as_str
|
149
154
|
raise DeserializationError(
|
150
155
|
"Cannot deserialize content-type: {}".format(content_type)
|
151
156
|
)
|
@@ -159,6 +164,11 @@ class RawDeserializer:
|
|
159
164
|
Use bytes and headers to NOT use any requests/aiohttp or whatever
|
160
165
|
specific implementation.
|
161
166
|
Headers will tested for "content-type"
|
167
|
+
|
168
|
+
:param bytes body_bytes: The body of the response.
|
169
|
+
:param dict headers: The headers of the response.
|
170
|
+
:returns: The deserialized data.
|
171
|
+
:rtype: object
|
162
172
|
"""
|
163
173
|
# Try to use content-type from headers if available
|
164
174
|
content_type = None
|
@@ -188,15 +198,30 @@ class UTC(datetime.tzinfo):
|
|
188
198
|
"""Time Zone info for handling UTC"""
|
189
199
|
|
190
200
|
def utcoffset(self, dt):
|
191
|
-
"""UTF offset for UTC is 0.
|
201
|
+
"""UTF offset for UTC is 0.
|
202
|
+
|
203
|
+
:param datetime.datetime dt: The datetime
|
204
|
+
:returns: The offset
|
205
|
+
:rtype: datetime.timedelta
|
206
|
+
"""
|
192
207
|
return datetime.timedelta(0)
|
193
208
|
|
194
209
|
def tzname(self, dt):
|
195
|
-
"""Timestamp representation.
|
210
|
+
"""Timestamp representation.
|
211
|
+
|
212
|
+
:param datetime.datetime dt: The datetime
|
213
|
+
:returns: The timestamp representation
|
214
|
+
:rtype: str
|
215
|
+
"""
|
196
216
|
return "Z"
|
197
217
|
|
198
218
|
def dst(self, dt):
|
199
|
-
"""No daylight saving for UTC.
|
219
|
+
"""No daylight saving for UTC.
|
220
|
+
|
221
|
+
:param datetime.datetime dt: The datetime
|
222
|
+
:returns: The daylight saving time
|
223
|
+
:rtype: datetime.timedelta
|
224
|
+
"""
|
200
225
|
return datetime.timedelta(hours=1)
|
201
226
|
|
202
227
|
|
@@ -239,24 +264,28 @@ except ImportError:
|
|
239
264
|
_FLATTEN = re.compile(r"(?<!\\)\.")
|
240
265
|
|
241
266
|
|
242
|
-
def attribute_transformer(key, attr_desc, value):
|
267
|
+
def attribute_transformer(key, attr_desc, value): # pylint: disable=unused-argument
|
243
268
|
"""A key transformer that returns the Python attribute.
|
244
269
|
|
245
270
|
:param str key: The attribute name
|
246
271
|
:param dict attr_desc: The attribute metadata
|
247
272
|
:param object value: The value
|
248
273
|
:returns: A key using attribute name
|
274
|
+
:rtype: str
|
249
275
|
"""
|
250
276
|
return (key, value)
|
251
277
|
|
252
278
|
|
253
|
-
def full_restapi_key_transformer(
|
279
|
+
def full_restapi_key_transformer(
|
280
|
+
key, attr_desc, value
|
281
|
+
): # pylint: disable=unused-argument
|
254
282
|
"""A key transformer that returns the full RestAPI key path.
|
255
283
|
|
256
|
-
:param str
|
284
|
+
:param str key: The attribute name
|
257
285
|
:param dict attr_desc: The attribute metadata
|
258
286
|
:param object value: The value
|
259
287
|
:returns: A list of keys using RestAPI syntax.
|
288
|
+
:rtype: list
|
260
289
|
"""
|
261
290
|
keys = _FLATTEN.split(attr_desc["key"])
|
262
291
|
return ([_decode_attribute_map_key(k) for k in keys], value)
|
@@ -269,19 +298,26 @@ def last_restapi_key_transformer(key, attr_desc, value):
|
|
269
298
|
:param dict attr_desc: The attribute metadata
|
270
299
|
:param object value: The value
|
271
300
|
:returns: The last RestAPI key.
|
301
|
+
:rtype: str
|
272
302
|
"""
|
273
303
|
key, value = full_restapi_key_transformer(key, attr_desc, value)
|
274
304
|
return (key[-1], value)
|
275
305
|
|
276
306
|
|
277
307
|
def _create_xml_node(tag, prefix=None, ns=None):
|
278
|
-
"""Create a XML node.
|
308
|
+
"""Create a XML node.
|
309
|
+
|
310
|
+
:param str tag: The tag name
|
311
|
+
:param str prefix: The prefix
|
312
|
+
:param str ns: The namespace
|
313
|
+
:return: The XML node
|
314
|
+
:rtype: xml.etree.ElementTree.Element
|
315
|
+
"""
|
279
316
|
if prefix and ns:
|
280
317
|
ET.register_namespace(prefix, ns)
|
281
318
|
if ns:
|
282
319
|
return ET.Element("{" + ns + "}" + tag)
|
283
|
-
|
284
|
-
return ET.Element(tag)
|
320
|
+
return ET.Element(tag)
|
285
321
|
|
286
322
|
|
287
323
|
class Model(object):
|
@@ -295,7 +331,7 @@ class Model(object):
|
|
295
331
|
|
296
332
|
def __init__(self, **kwargs: Any) -> None:
|
297
333
|
self.additional_properties: Optional[Dict[str, Any]] = {}
|
298
|
-
for k in kwargs:
|
334
|
+
for k in kwargs: # pylint: disable=consider-using-dict-items
|
299
335
|
if k not in self._attribute_map:
|
300
336
|
_LOGGER.warning(
|
301
337
|
"%s is not a known attribute of class %s and will be ignored",
|
@@ -312,13 +348,23 @@ class Model(object):
|
|
312
348
|
setattr(self, k, kwargs[k])
|
313
349
|
|
314
350
|
def __eq__(self, other: Any) -> bool:
|
315
|
-
"""Compare objects by comparing all attributes.
|
351
|
+
"""Compare objects by comparing all attributes.
|
352
|
+
|
353
|
+
:param object other: The object to compare
|
354
|
+
:returns: True if objects are equal
|
355
|
+
:rtype: bool
|
356
|
+
"""
|
316
357
|
if isinstance(other, self.__class__):
|
317
358
|
return self.__dict__ == other.__dict__
|
318
359
|
return False
|
319
360
|
|
320
361
|
def __ne__(self, other: Any) -> bool:
|
321
|
-
"""Compare objects by comparing all attributes.
|
362
|
+
"""Compare objects by comparing all attributes.
|
363
|
+
|
364
|
+
:param object other: The object to compare
|
365
|
+
:returns: True if objects are not equal
|
366
|
+
:rtype: bool
|
367
|
+
"""
|
322
368
|
return not self.__eq__(other)
|
323
369
|
|
324
370
|
def __str__(self) -> str:
|
@@ -338,7 +384,11 @@ class Model(object):
|
|
338
384
|
|
339
385
|
@classmethod
|
340
386
|
def _create_xml_node(cls):
|
341
|
-
"""Create XML node.
|
387
|
+
"""Create XML node.
|
388
|
+
|
389
|
+
:returns: The XML node
|
390
|
+
:rtype: xml.etree.ElementTree.Element
|
391
|
+
"""
|
342
392
|
try:
|
343
393
|
xml_map = cls._xml_map # type: ignore
|
344
394
|
except AttributeError:
|
@@ -362,7 +412,9 @@ class Model(object):
|
|
362
412
|
:rtype: dict
|
363
413
|
"""
|
364
414
|
serializer = Serializer(self._infer_class_models())
|
365
|
-
return serializer._serialize(
|
415
|
+
return serializer._serialize( # type: ignore # pylint: disable=protected-access
|
416
|
+
self, keep_readonly=keep_readonly, **kwargs
|
417
|
+
)
|
366
418
|
|
367
419
|
def as_dict(
|
368
420
|
self,
|
@@ -398,12 +450,15 @@ class Model(object):
|
|
398
450
|
|
399
451
|
If you want XML serialization, you can pass the kwargs is_xml=True.
|
400
452
|
|
453
|
+
:param bool keep_readonly: If you want to serialize the readonly attributes
|
401
454
|
:param function key_transformer: A key transformer function.
|
402
455
|
:returns: A dict JSON compatible object
|
403
456
|
:rtype: dict
|
404
457
|
"""
|
405
458
|
serializer = Serializer(self._infer_class_models())
|
406
|
-
return serializer._serialize(
|
459
|
+
return serializer._serialize( # type: ignore # pylint: disable=protected-access
|
460
|
+
self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs
|
461
|
+
)
|
407
462
|
|
408
463
|
@classmethod
|
409
464
|
def _infer_class_models(cls):
|
@@ -415,7 +470,7 @@ class Model(object):
|
|
415
470
|
}
|
416
471
|
if cls.__name__ not in client_models:
|
417
472
|
raise ValueError("Not Autorest generated code")
|
418
|
-
except Exception:
|
473
|
+
except Exception: # pylint: disable=broad-exception-caught
|
419
474
|
# Assume it's not Autorest generated (tests?). Add ourselves as dependencies.
|
420
475
|
client_models = {cls.__name__: cls}
|
421
476
|
return client_models
|
@@ -430,6 +485,7 @@ class Model(object):
|
|
430
485
|
:param str content_type: JSON by default, set application/xml if XML.
|
431
486
|
:returns: An instance of this model
|
432
487
|
:raises: DeserializationError if something went wrong
|
488
|
+
:rtype: ModelType
|
433
489
|
"""
|
434
490
|
deserializer = Deserializer(cls._infer_class_models())
|
435
491
|
return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
|
@@ -448,9 +504,11 @@ class Model(object):
|
|
448
504
|
and last_rest_key_case_insensitive_extractor)
|
449
505
|
|
450
506
|
:param dict data: A dict using RestAPI structure
|
507
|
+
:param function key_extractors: A key extractor function.
|
451
508
|
:param str content_type: JSON by default, set application/xml if XML.
|
452
509
|
:returns: An instance of this model
|
453
510
|
:raises: DeserializationError if something went wrong
|
511
|
+
:rtype: ModelType
|
454
512
|
"""
|
455
513
|
deserializer = Deserializer(cls._infer_class_models())
|
456
514
|
deserializer.key_extractors = ( # type: ignore
|
@@ -470,7 +528,9 @@ class Model(object):
|
|
470
528
|
return {}
|
471
529
|
result = dict(cls._subtype_map[key])
|
472
530
|
for valuetype in cls._subtype_map[key].values():
|
473
|
-
result.update(
|
531
|
+
result.update(
|
532
|
+
objects[valuetype]._flatten_subtype(key, objects)
|
533
|
+
) # pylint: disable=protected-access
|
474
534
|
return result
|
475
535
|
|
476
536
|
@classmethod
|
@@ -478,6 +538,11 @@ class Model(object):
|
|
478
538
|
"""Check the class _subtype_map for any child classes.
|
479
539
|
We want to ignore any inherited _subtype_maps.
|
480
540
|
Remove the polymorphic key from the initial data.
|
541
|
+
|
542
|
+
:param dict response: The initial data
|
543
|
+
:param dict objects: The class objects
|
544
|
+
:returns: The class to be used
|
545
|
+
:rtype: class
|
481
546
|
"""
|
482
547
|
for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
|
483
548
|
subtype_value = None
|
@@ -531,11 +596,13 @@ def _decode_attribute_map_key(key):
|
|
531
596
|
inside the received data.
|
532
597
|
|
533
598
|
:param str key: A key string from the generated code
|
599
|
+
:returns: The decoded key
|
600
|
+
:rtype: str
|
534
601
|
"""
|
535
602
|
return key.replace("\\.", ".")
|
536
603
|
|
537
604
|
|
538
|
-
class Serializer(object):
|
605
|
+
class Serializer(object): # pylint: disable=too-many-public-methods
|
539
606
|
"""Request object model serializer."""
|
540
607
|
|
541
608
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
@@ -590,13 +657,16 @@ class Serializer(object):
|
|
590
657
|
self.key_transformer = full_restapi_key_transformer
|
591
658
|
self.client_side_validation = True
|
592
659
|
|
593
|
-
def _serialize(
|
660
|
+
def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
|
661
|
+
self, target_obj, data_type=None, **kwargs
|
662
|
+
):
|
594
663
|
"""Serialize data into a string according to type.
|
595
664
|
|
596
|
-
:param target_obj: The data to be serialized.
|
665
|
+
:param object target_obj: The data to be serialized.
|
597
666
|
:param str data_type: The type to be serialized from.
|
598
667
|
:rtype: str, dict
|
599
668
|
:raises: SerializationError if serialization fails.
|
669
|
+
:returns: The serialized data.
|
600
670
|
"""
|
601
671
|
key_transformer = kwargs.get("key_transformer", self.key_transformer)
|
602
672
|
keep_readonly = kwargs.get("keep_readonly", False)
|
@@ -624,13 +694,18 @@ class Serializer(object):
|
|
624
694
|
|
625
695
|
serialized = {}
|
626
696
|
if is_xml_model_serialization:
|
627
|
-
serialized =
|
697
|
+
serialized = (
|
698
|
+
target_obj._create_xml_node()
|
699
|
+
) # pylint: disable=protected-access
|
628
700
|
try:
|
629
|
-
attributes = target_obj._attribute_map
|
701
|
+
attributes = target_obj._attribute_map # pylint: disable=protected-access
|
630
702
|
for attr, attr_desc in attributes.items():
|
631
703
|
attr_name = attr
|
632
|
-
if
|
633
|
-
|
704
|
+
if (
|
705
|
+
not keep_readonly
|
706
|
+
and target_obj._validation.get( # pylint: disable=protected-access
|
707
|
+
attr_name, {}
|
708
|
+
).get("readonly", False)
|
634
709
|
):
|
635
710
|
continue
|
636
711
|
|
@@ -671,7 +746,8 @@ class Serializer(object):
|
|
671
746
|
if isinstance(new_attr, list):
|
672
747
|
serialized.extend(new_attr) # type: ignore
|
673
748
|
elif isinstance(new_attr, ET.Element):
|
674
|
-
# If the down XML has no XML/Name,
|
749
|
+
# If the down XML has no XML/Name,
|
750
|
+
# we MUST replace the tag with the local tag. But keeping the namespaces.
|
675
751
|
if "name" not in getattr(orig_attr, "_xml_map", {}):
|
676
752
|
splitted_tag = new_attr.tag.split("}")
|
677
753
|
if len(splitted_tag) == 2: # Namespace
|
@@ -704,17 +780,17 @@ class Serializer(object):
|
|
704
780
|
attr_name, class_name, str(target_obj)
|
705
781
|
)
|
706
782
|
raise SerializationError(msg) from err
|
707
|
-
|
708
|
-
return serialized
|
783
|
+
return serialized
|
709
784
|
|
710
785
|
def body(self, data, data_type, **kwargs):
|
711
786
|
"""Serialize data intended for a request body.
|
712
787
|
|
713
|
-
:param data: The data to be serialized.
|
788
|
+
:param object data: The data to be serialized.
|
714
789
|
:param str data_type: The type to be serialized from.
|
715
790
|
:rtype: dict
|
716
791
|
:raises: SerializationError if serialization fails.
|
717
792
|
:raises: ValueError if data is None
|
793
|
+
:returns: The serialized request body
|
718
794
|
"""
|
719
795
|
|
720
796
|
# Just in case this is a dict
|
@@ -745,7 +821,9 @@ class Serializer(object):
|
|
745
821
|
attribute_key_case_insensitive_extractor,
|
746
822
|
last_rest_key_case_insensitive_extractor,
|
747
823
|
]
|
748
|
-
data = deserializer._deserialize(
|
824
|
+
data = deserializer._deserialize(
|
825
|
+
data_type, data
|
826
|
+
) # pylint: disable=protected-access
|
749
827
|
except DeserializationError as err:
|
750
828
|
raise SerializationError(
|
751
829
|
"Unable to build a model: " + str(err)
|
@@ -756,9 +834,11 @@ class Serializer(object):
|
|
756
834
|
def url(self, name, data, data_type, **kwargs):
|
757
835
|
"""Serialize data intended for a URL path.
|
758
836
|
|
759
|
-
:param
|
837
|
+
:param str name: The name of the URL path parameter.
|
838
|
+
:param object data: The data to be serialized.
|
760
839
|
:param str data_type: The type to be serialized from.
|
761
840
|
:rtype: str
|
841
|
+
:returns: The serialized URL path
|
762
842
|
:raises: TypeError if serialization fails.
|
763
843
|
:raises: ValueError if data is None
|
764
844
|
"""
|
@@ -772,21 +852,20 @@ class Serializer(object):
|
|
772
852
|
output = output.replace("{", quote("{")).replace("}", quote("}"))
|
773
853
|
else:
|
774
854
|
output = quote(str(output), safe="")
|
775
|
-
except SerializationError:
|
776
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
777
|
-
|
778
|
-
return output
|
855
|
+
except SerializationError as exc:
|
856
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
857
|
+
return output
|
779
858
|
|
780
859
|
def query(self, name, data, data_type, **kwargs):
|
781
860
|
"""Serialize data intended for a URL query.
|
782
861
|
|
783
|
-
:param
|
862
|
+
:param str name: The name of the query parameter.
|
863
|
+
:param object data: The data to be serialized.
|
784
864
|
:param str data_type: The type to be serialized from.
|
785
|
-
:keyword bool skip_quote: Whether to skip quote the serialized result.
|
786
|
-
Defaults to False.
|
787
865
|
:rtype: str, list
|
788
866
|
:raises: TypeError if serialization fails.
|
789
867
|
:raises: ValueError if data is None
|
868
|
+
:returns: The serialized query parameter
|
790
869
|
"""
|
791
870
|
try:
|
792
871
|
# Treat the list aside, since we don't want to encode the div separator
|
@@ -805,19 +884,20 @@ class Serializer(object):
|
|
805
884
|
output = str(output)
|
806
885
|
else:
|
807
886
|
output = quote(str(output), safe="")
|
808
|
-
except SerializationError:
|
809
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
810
|
-
|
811
|
-
return str(output)
|
887
|
+
except SerializationError as exc:
|
888
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
889
|
+
return str(output)
|
812
890
|
|
813
891
|
def header(self, name, data, data_type, **kwargs):
|
814
892
|
"""Serialize data intended for a request header.
|
815
893
|
|
816
|
-
:param
|
894
|
+
:param str name: The name of the header.
|
895
|
+
:param object data: The data to be serialized.
|
817
896
|
:param str data_type: The type to be serialized from.
|
818
897
|
:rtype: str
|
819
898
|
:raises: TypeError if serialization fails.
|
820
899
|
:raises: ValueError if data is None
|
900
|
+
:returns: The serialized header
|
821
901
|
"""
|
822
902
|
try:
|
823
903
|
if data_type in ["[str]"]:
|
@@ -826,21 +906,20 @@ class Serializer(object):
|
|
826
906
|
output = self.serialize_data(data, data_type, **kwargs)
|
827
907
|
if data_type == "bool":
|
828
908
|
output = json.dumps(output)
|
829
|
-
except SerializationError:
|
830
|
-
raise TypeError("{} must be type {}.".format(name, data_type))
|
831
|
-
|
832
|
-
return str(output)
|
909
|
+
except SerializationError as exc:
|
910
|
+
raise TypeError("{} must be type {}.".format(name, data_type)) from exc
|
911
|
+
return str(output)
|
833
912
|
|
834
913
|
def serialize_data(self, data, data_type, **kwargs):
|
835
914
|
"""Serialize generic data according to supplied data type.
|
836
915
|
|
837
|
-
:param data: The data to be serialized.
|
916
|
+
:param object data: The data to be serialized.
|
838
917
|
:param str data_type: The type to be serialized from.
|
839
|
-
:param bool required: Whether it's essential that the data not be
|
840
|
-
empty or None
|
841
918
|
:raises: AttributeError if required data is None.
|
842
919
|
:raises: ValueError if data is None
|
843
920
|
:raises: SerializationError if serialization fails.
|
921
|
+
:returns: The serialized data.
|
922
|
+
:rtype: str, int, float, bool, dict, list
|
844
923
|
"""
|
845
924
|
if data is None:
|
846
925
|
raise ValueError("No value for given attribute")
|
@@ -851,7 +930,7 @@ class Serializer(object):
|
|
851
930
|
if data_type in self.basic_types.values():
|
852
931
|
return self.serialize_basic(data, data_type, **kwargs)
|
853
932
|
|
854
|
-
|
933
|
+
if data_type in self.serialize_type:
|
855
934
|
return self.serialize_type[data_type](data, **kwargs)
|
856
935
|
|
857
936
|
# If dependencies is empty, try with current data class
|
@@ -867,11 +946,12 @@ class Serializer(object):
|
|
867
946
|
except (ValueError, TypeError) as err:
|
868
947
|
msg = "Unable to serialize value: {!r} as type: {!r}."
|
869
948
|
raise SerializationError(msg.format(data, data_type)) from err
|
870
|
-
|
871
|
-
return self._serialize(data, **kwargs)
|
949
|
+
return self._serialize(data, **kwargs)
|
872
950
|
|
873
951
|
@classmethod
|
874
|
-
def _get_custom_serializers(
|
952
|
+
def _get_custom_serializers(
|
953
|
+
cls, data_type, **kwargs
|
954
|
+
): # pylint: disable=inconsistent-return-statements
|
875
955
|
custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type)
|
876
956
|
if custom_serializer:
|
877
957
|
return custom_serializer
|
@@ -887,23 +967,26 @@ class Serializer(object):
|
|
887
967
|
- basic_types_serializers dict[str, callable] : If set, use the callable as serializer
|
888
968
|
- is_xml bool : If set, use xml_basic_types_serializers
|
889
969
|
|
890
|
-
:param data: Object to be serialized.
|
970
|
+
:param obj data: Object to be serialized.
|
891
971
|
:param str data_type: Type of object in the iterable.
|
972
|
+
:rtype: str, int, float, bool
|
973
|
+
:return: serialized object
|
892
974
|
"""
|
893
975
|
custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
|
894
976
|
if custom_serializer:
|
895
977
|
return custom_serializer(data)
|
896
978
|
if data_type == "str":
|
897
979
|
return cls.serialize_unicode(data)
|
898
|
-
return eval(data_type)(data) # nosec
|
980
|
+
return eval(data_type)(data) # nosec # pylint: disable=eval-used
|
899
981
|
|
900
982
|
@classmethod
|
901
983
|
def serialize_unicode(cls, data):
|
902
984
|
"""Special handling for serializing unicode strings in Py2.
|
903
985
|
Encode to UTF-8 if unicode, otherwise handle as a str.
|
904
986
|
|
905
|
-
:param data: Object to be serialized.
|
987
|
+
:param str data: Object to be serialized.
|
906
988
|
:rtype: str
|
989
|
+
:return: serialized object
|
907
990
|
"""
|
908
991
|
try: # If I received an enum, return its value
|
909
992
|
return data.value
|
@@ -917,8 +1000,7 @@ class Serializer(object):
|
|
917
1000
|
return data
|
918
1001
|
except NameError:
|
919
1002
|
return str(data)
|
920
|
-
|
921
|
-
return str(data)
|
1003
|
+
return str(data)
|
922
1004
|
|
923
1005
|
def serialize_iter(self, data, iter_type, div=None, **kwargs):
|
924
1006
|
"""Serialize iterable.
|
@@ -928,15 +1010,13 @@ class Serializer(object):
|
|
928
1010
|
serialization_ctxt['type'] should be same as data_type.
|
929
1011
|
- is_xml bool : If set, serialize as XML
|
930
1012
|
|
931
|
-
:param list
|
1013
|
+
:param list data: Object to be serialized.
|
932
1014
|
:param str iter_type: Type of object in the iterable.
|
933
|
-
:param bool required: Whether the objects in the iterable must
|
934
|
-
not be None or empty.
|
935
1015
|
:param str div: If set, this str will be used to combine the elements
|
936
1016
|
in the iterable into a combined string. Default is 'None'.
|
937
|
-
:keyword bool do_quote: Whether to quote the serialized result of each iterable element.
|
938
1017
|
Defaults to False.
|
939
1018
|
:rtype: list, str
|
1019
|
+
:return: serialized iterable
|
940
1020
|
"""
|
941
1021
|
if isinstance(data, str):
|
942
1022
|
raise SerializationError("Refuse str type as a valid iter type.")
|
@@ -999,9 +1079,8 @@ class Serializer(object):
|
|
999
1079
|
|
1000
1080
|
:param dict attr: Object to be serialized.
|
1001
1081
|
:param str dict_type: Type of object in the dictionary.
|
1002
|
-
:param bool required: Whether the objects in the dictionary must
|
1003
|
-
not be None or empty.
|
1004
1082
|
:rtype: dict
|
1083
|
+
:return: serialized dictionary
|
1005
1084
|
"""
|
1006
1085
|
serialization_ctxt = kwargs.get("serialization_ctxt", {})
|
1007
1086
|
serialized = {}
|
@@ -1029,7 +1108,9 @@ class Serializer(object):
|
|
1029
1108
|
|
1030
1109
|
return serialized
|
1031
1110
|
|
1032
|
-
def serialize_object(
|
1111
|
+
def serialize_object(
|
1112
|
+
self, attr, **kwargs
|
1113
|
+
): # pylint: disable=too-many-return-statements
|
1033
1114
|
"""Serialize a generic object.
|
1034
1115
|
This will be handled as a dictionary. If object passed in is not
|
1035
1116
|
a basic type (str, int, float, dict, list) it will simply be
|
@@ -1037,6 +1118,7 @@ class Serializer(object):
|
|
1037
1118
|
|
1038
1119
|
:param dict attr: Object to be serialized.
|
1039
1120
|
:rtype: dict or str
|
1121
|
+
:return: serialized object
|
1040
1122
|
"""
|
1041
1123
|
if attr is None:
|
1042
1124
|
return None
|
@@ -1061,7 +1143,7 @@ class Serializer(object):
|
|
1061
1143
|
return self.serialize_decimal(attr)
|
1062
1144
|
|
1063
1145
|
# If it's a model or I know this dependency, serialize as a Model
|
1064
|
-
|
1146
|
+
if obj_type in self.dependencies.values() or isinstance(attr, Model):
|
1065
1147
|
return self._serialize(attr)
|
1066
1148
|
|
1067
1149
|
if obj_type == dict:
|
@@ -1094,56 +1176,61 @@ class Serializer(object):
|
|
1094
1176
|
try:
|
1095
1177
|
enum_obj(result) # type: ignore
|
1096
1178
|
return result
|
1097
|
-
except ValueError:
|
1179
|
+
except ValueError as exc:
|
1098
1180
|
for enum_value in enum_obj: # type: ignore
|
1099
1181
|
if enum_value.value.lower() == str(attr).lower():
|
1100
1182
|
return enum_value.value
|
1101
1183
|
error = "{!r} is not valid value for enum {!r}"
|
1102
|
-
raise SerializationError(error.format(attr, enum_obj))
|
1184
|
+
raise SerializationError(error.format(attr, enum_obj)) from exc
|
1103
1185
|
|
1104
1186
|
@staticmethod
|
1105
|
-
def serialize_bytearray(attr, **kwargs):
|
1187
|
+
def serialize_bytearray(attr, **kwargs): # pylint: disable=unused-argument
|
1106
1188
|
"""Serialize bytearray into base-64 string.
|
1107
1189
|
|
1108
|
-
:param attr: Object to be serialized.
|
1190
|
+
:param str attr: Object to be serialized.
|
1109
1191
|
:rtype: str
|
1192
|
+
:return: serialized base64
|
1110
1193
|
"""
|
1111
1194
|
return b64encode(attr).decode()
|
1112
1195
|
|
1113
1196
|
@staticmethod
|
1114
|
-
def serialize_base64(attr, **kwargs):
|
1197
|
+
def serialize_base64(attr, **kwargs): # pylint: disable=unused-argument
|
1115
1198
|
"""Serialize str into base-64 string.
|
1116
1199
|
|
1117
|
-
:param attr: Object to be serialized.
|
1200
|
+
:param str attr: Object to be serialized.
|
1118
1201
|
:rtype: str
|
1202
|
+
:return: serialized base64
|
1119
1203
|
"""
|
1120
1204
|
encoded = b64encode(attr).decode("ascii")
|
1121
1205
|
return encoded.strip("=").replace("+", "-").replace("/", "_")
|
1122
1206
|
|
1123
1207
|
@staticmethod
|
1124
|
-
def serialize_decimal(attr, **kwargs):
|
1208
|
+
def serialize_decimal(attr, **kwargs): # pylint: disable=unused-argument
|
1125
1209
|
"""Serialize Decimal object to float.
|
1126
1210
|
|
1127
|
-
:param attr: Object to be serialized.
|
1211
|
+
:param decimal attr: Object to be serialized.
|
1128
1212
|
:rtype: float
|
1213
|
+
:return: serialized decimal
|
1129
1214
|
"""
|
1130
1215
|
return float(attr)
|
1131
1216
|
|
1132
1217
|
@staticmethod
|
1133
|
-
def serialize_long(attr, **kwargs):
|
1218
|
+
def serialize_long(attr, **kwargs): # pylint: disable=unused-argument
|
1134
1219
|
"""Serialize long (Py2) or int (Py3).
|
1135
1220
|
|
1136
|
-
:param attr: Object to be serialized.
|
1221
|
+
:param int attr: Object to be serialized.
|
1137
1222
|
:rtype: int/long
|
1223
|
+
:return: serialized long
|
1138
1224
|
"""
|
1139
1225
|
return _long_type(attr)
|
1140
1226
|
|
1141
1227
|
@staticmethod
|
1142
|
-
def serialize_date(attr, **kwargs):
|
1228
|
+
def serialize_date(attr, **kwargs): # pylint: disable=unused-argument
|
1143
1229
|
"""Serialize Date object into ISO-8601 formatted string.
|
1144
1230
|
|
1145
1231
|
:param Date attr: Object to be serialized.
|
1146
1232
|
:rtype: str
|
1233
|
+
:return: serialized date
|
1147
1234
|
"""
|
1148
1235
|
if isinstance(attr, str):
|
1149
1236
|
attr = isodate.parse_date(attr)
|
@@ -1151,11 +1238,12 @@ class Serializer(object):
|
|
1151
1238
|
return t
|
1152
1239
|
|
1153
1240
|
@staticmethod
|
1154
|
-
def serialize_time(attr, **kwargs):
|
1241
|
+
def serialize_time(attr, **kwargs): # pylint: disable=unused-argument
|
1155
1242
|
"""Serialize Time object into ISO-8601 formatted string.
|
1156
1243
|
|
1157
1244
|
:param datetime.time attr: Object to be serialized.
|
1158
1245
|
:rtype: str
|
1246
|
+
:return: serialized time
|
1159
1247
|
"""
|
1160
1248
|
if isinstance(attr, str):
|
1161
1249
|
attr = isodate.parse_time(attr)
|
@@ -1165,30 +1253,32 @@ class Serializer(object):
|
|
1165
1253
|
return t
|
1166
1254
|
|
1167
1255
|
@staticmethod
|
1168
|
-
def serialize_duration(attr, **kwargs):
|
1256
|
+
def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
|
1169
1257
|
"""Serialize TimeDelta object into ISO-8601 formatted string.
|
1170
1258
|
|
1171
1259
|
:param TimeDelta attr: Object to be serialized.
|
1172
1260
|
:rtype: str
|
1261
|
+
:return: serialized duration
|
1173
1262
|
"""
|
1174
1263
|
if isinstance(attr, str):
|
1175
1264
|
attr = isodate.parse_duration(attr)
|
1176
1265
|
return isodate.duration_isoformat(attr)
|
1177
1266
|
|
1178
1267
|
@staticmethod
|
1179
|
-
def serialize_rfc(attr, **kwargs):
|
1268
|
+
def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
|
1180
1269
|
"""Serialize Datetime object into RFC-1123 formatted string.
|
1181
1270
|
|
1182
1271
|
:param Datetime attr: Object to be serialized.
|
1183
1272
|
:rtype: str
|
1184
1273
|
:raises: TypeError if format invalid.
|
1274
|
+
:return: serialized rfc
|
1185
1275
|
"""
|
1186
1276
|
try:
|
1187
1277
|
if not attr.tzinfo:
|
1188
1278
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
1189
1279
|
utc = attr.utctimetuple()
|
1190
|
-
except AttributeError:
|
1191
|
-
raise TypeError("RFC1123 object must be valid Datetime object.")
|
1280
|
+
except AttributeError as exc:
|
1281
|
+
raise TypeError("RFC1123 object must be valid Datetime object.") from exc
|
1192
1282
|
|
1193
1283
|
return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
|
1194
1284
|
Serializer.days[utc.tm_wday],
|
@@ -1201,12 +1291,13 @@ class Serializer(object):
|
|
1201
1291
|
)
|
1202
1292
|
|
1203
1293
|
@staticmethod
|
1204
|
-
def serialize_iso(attr, **kwargs):
|
1294
|
+
def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument
|
1205
1295
|
"""Serialize Datetime object into ISO-8601 formatted string.
|
1206
1296
|
|
1207
1297
|
:param Datetime attr: Object to be serialized.
|
1208
1298
|
:rtype: str
|
1209
1299
|
:raises: SerializationError if format invalid.
|
1300
|
+
:return: serialized iso
|
1210
1301
|
"""
|
1211
1302
|
if isinstance(attr, str):
|
1212
1303
|
attr = isodate.parse_datetime(attr)
|
@@ -1237,13 +1328,14 @@ class Serializer(object):
|
|
1237
1328
|
raise TypeError(msg) from err
|
1238
1329
|
|
1239
1330
|
@staticmethod
|
1240
|
-
def serialize_unix(attr, **kwargs):
|
1331
|
+
def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument
|
1241
1332
|
"""Serialize Datetime object into IntTime format.
|
1242
1333
|
This is represented as seconds.
|
1243
1334
|
|
1244
1335
|
:param Datetime attr: Object to be serialized.
|
1245
1336
|
:rtype: int
|
1246
1337
|
:raises: SerializationError if format invalid
|
1338
|
+
:return: serialied unix
|
1247
1339
|
"""
|
1248
1340
|
if isinstance(attr, int):
|
1249
1341
|
return attr
|
@@ -1251,11 +1343,11 @@ class Serializer(object):
|
|
1251
1343
|
if not attr.tzinfo:
|
1252
1344
|
_LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
|
1253
1345
|
return int(calendar.timegm(attr.utctimetuple()))
|
1254
|
-
except AttributeError:
|
1255
|
-
raise TypeError("Unix time object must be valid Datetime object.")
|
1346
|
+
except AttributeError as exc:
|
1347
|
+
raise TypeError("Unix time object must be valid Datetime object.") from exc
|
1256
1348
|
|
1257
1349
|
|
1258
|
-
def rest_key_extractor(attr, attr_desc, data):
|
1350
|
+
def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
1259
1351
|
key = attr_desc["key"]
|
1260
1352
|
working_data = data
|
1261
1353
|
|
@@ -1276,7 +1368,9 @@ def rest_key_extractor(attr, attr_desc, data):
|
|
1276
1368
|
return working_data.get(key)
|
1277
1369
|
|
1278
1370
|
|
1279
|
-
def rest_key_case_insensitive_extractor(
|
1371
|
+
def rest_key_case_insensitive_extractor( # pylint: disable=unused-argument, inconsistent-return-statements
|
1372
|
+
attr, attr_desc, data
|
1373
|
+
):
|
1280
1374
|
key = attr_desc["key"]
|
1281
1375
|
working_data = data
|
1282
1376
|
|
@@ -1299,17 +1393,31 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
|
|
1299
1393
|
return attribute_key_case_insensitive_extractor(key, None, working_data)
|
1300
1394
|
|
1301
1395
|
|
1302
|
-
def last_rest_key_extractor(attr, attr_desc, data):
|
1303
|
-
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
1396
|
+
def last_rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
1397
|
+
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
1398
|
+
|
1399
|
+
:param str attr: The attribute to extract
|
1400
|
+
:param dict attr_desc: The attribute description
|
1401
|
+
:param dict data: The data to extract from
|
1402
|
+
:rtype: object
|
1403
|
+
:returns: The extracted attribute
|
1404
|
+
"""
|
1304
1405
|
key = attr_desc["key"]
|
1305
1406
|
dict_keys = _FLATTEN.split(key)
|
1306
1407
|
return attribute_key_extractor(dict_keys[-1], None, data)
|
1307
1408
|
|
1308
1409
|
|
1309
|
-
def last_rest_key_case_insensitive_extractor(
|
1410
|
+
def last_rest_key_case_insensitive_extractor(
|
1411
|
+
attr, attr_desc, data
|
1412
|
+
): # pylint: disable=unused-argument
|
1310
1413
|
"""Extract the attribute in "data" based on the last part of the JSON path key.
|
1311
1414
|
|
1312
1415
|
This is the case insensitive version of "last_rest_key_extractor"
|
1416
|
+
:param str attr: The attribute to extract
|
1417
|
+
:param dict attr_desc: The attribute description
|
1418
|
+
:param dict data: The data to extract from
|
1419
|
+
:rtype: object
|
1420
|
+
:returns: The extracted attribute
|
1313
1421
|
"""
|
1314
1422
|
key = attr_desc["key"]
|
1315
1423
|
dict_keys = _FLATTEN.split(key)
|
@@ -1346,7 +1454,9 @@ def _extract_name_from_internal_type(internal_type):
|
|
1346
1454
|
return xml_name
|
1347
1455
|
|
1348
1456
|
|
1349
|
-
def xml_key_extractor(
|
1457
|
+
def xml_key_extractor(
|
1458
|
+
attr, attr_desc, data
|
1459
|
+
): # pylint: disable=unused-argument,too-many-return-statements
|
1350
1460
|
if isinstance(data, dict):
|
1351
1461
|
return None
|
1352
1462
|
|
@@ -1403,22 +1513,21 @@ def xml_key_extractor(attr, attr_desc, data):
|
|
1403
1513
|
if is_iter_type:
|
1404
1514
|
if is_wrapped:
|
1405
1515
|
return None # is_wrapped no node, we want None
|
1406
|
-
|
1407
|
-
return [] # not wrapped, assume empty list
|
1516
|
+
return [] # not wrapped, assume empty list
|
1408
1517
|
return None # Assume it's not there, maybe an optional node.
|
1409
1518
|
|
1410
1519
|
# If is_iter_type and not wrapped, return all found children
|
1411
1520
|
if is_iter_type:
|
1412
1521
|
if not is_wrapped:
|
1413
1522
|
return children
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
)
|
1523
|
+
# Iter and wrapped, should have found one node only (the wrap one)
|
1524
|
+
if len(children) != 1:
|
1525
|
+
raise DeserializationError(
|
1526
|
+
"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
|
1527
|
+
xml_name
|
1420
1528
|
)
|
1421
|
-
|
1529
|
+
)
|
1530
|
+
return list(children[0]) # Might be empty list and that's ok.
|
1422
1531
|
|
1423
1532
|
# Here it's not a itertype, we should have found one element only or empty
|
1424
1533
|
if len(children) > 1:
|
@@ -1438,7 +1547,7 @@ class Deserializer(object):
|
|
1438
1547
|
basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
|
1439
1548
|
|
1440
1549
|
valid_date = re.compile(
|
1441
|
-
r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}
|
1550
|
+
r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?"
|
1442
1551
|
)
|
1443
1552
|
|
1444
1553
|
def __init__(self, classes: Optional[Mapping[str, type]] = None):
|
@@ -1479,11 +1588,14 @@ class Deserializer(object):
|
|
1479
1588
|
:param str content_type: Swagger "produces" if available.
|
1480
1589
|
:raises: DeserializationError if deserialization fails.
|
1481
1590
|
:return: Deserialized object.
|
1591
|
+
:rtype: object
|
1482
1592
|
"""
|
1483
1593
|
data = self._unpack_content(response_data, content_type)
|
1484
1594
|
return self._deserialize(target_obj, data)
|
1485
1595
|
|
1486
|
-
def _deserialize(
|
1596
|
+
def _deserialize(
|
1597
|
+
self, target_obj, data
|
1598
|
+
): # pylint: disable=inconsistent-return-statements
|
1487
1599
|
"""Call the deserializer on a model.
|
1488
1600
|
|
1489
1601
|
Data needs to be already deserialized as JSON or XML ElementTree
|
@@ -1492,6 +1604,7 @@ class Deserializer(object):
|
|
1492
1604
|
:param object data: Object to deserialize.
|
1493
1605
|
:raises: DeserializationError if deserialization fails.
|
1494
1606
|
:return: Deserialized object.
|
1607
|
+
:rtype: object
|
1495
1608
|
"""
|
1496
1609
|
# This is already a model, go recursive just in case
|
1497
1610
|
if hasattr(data, "_attribute_map"):
|
@@ -1501,7 +1614,10 @@ class Deserializer(object):
|
|
1501
1614
|
if config.get("constant")
|
1502
1615
|
]
|
1503
1616
|
try:
|
1504
|
-
for
|
1617
|
+
for (
|
1618
|
+
attr,
|
1619
|
+
mapconfig,
|
1620
|
+
) in data._attribute_map.items(): # pylint: disable=protected-access
|
1505
1621
|
if attr in constants:
|
1506
1622
|
continue
|
1507
1623
|
value = getattr(data, attr)
|
@@ -1522,13 +1638,13 @@ class Deserializer(object):
|
|
1522
1638
|
|
1523
1639
|
if isinstance(response, str):
|
1524
1640
|
return self.deserialize_data(data, response)
|
1525
|
-
|
1641
|
+
if isinstance(response, type) and issubclass(response, Enum):
|
1526
1642
|
return self.deserialize_enum(data, response)
|
1527
1643
|
|
1528
1644
|
if data is None or data is CoreNull:
|
1529
1645
|
return data
|
1530
1646
|
try:
|
1531
|
-
attributes = response._attribute_map # type: ignore
|
1647
|
+
attributes = response._attribute_map # type: ignore # pylint: disable=protected-access
|
1532
1648
|
d_attrs = {}
|
1533
1649
|
for attr, attr_desc in attributes.items():
|
1534
1650
|
# Check empty string. If it's not empty, someone has a real "additionalProperties"...
|
@@ -1558,9 +1674,8 @@ class Deserializer(object):
|
|
1558
1674
|
except (AttributeError, TypeError, KeyError) as err:
|
1559
1675
|
msg = "Unable to deserialize to object: " + class_name # type: ignore
|
1560
1676
|
raise DeserializationError(msg) from err
|
1561
|
-
|
1562
|
-
|
1563
|
-
return self._instantiate_model(response, d_attrs, additional_properties)
|
1677
|
+
additional_properties = self._build_additional_properties(attributes, data)
|
1678
|
+
return self._instantiate_model(response, d_attrs, additional_properties)
|
1564
1679
|
|
1565
1680
|
def _build_additional_properties(self, attribute_map, data):
|
1566
1681
|
if not self.additional_properties_detection:
|
@@ -1590,6 +1705,8 @@ class Deserializer(object):
|
|
1590
1705
|
|
1591
1706
|
:param str target: The target object type to deserialize to.
|
1592
1707
|
:param str/dict data: The response data to deserialize.
|
1708
|
+
:return: The classified target object and its class name.
|
1709
|
+
:rtype: tuple
|
1593
1710
|
"""
|
1594
1711
|
if target is None:
|
1595
1712
|
return None, None
|
@@ -1601,7 +1718,7 @@ class Deserializer(object):
|
|
1601
1718
|
return target, target
|
1602
1719
|
|
1603
1720
|
try:
|
1604
|
-
target = target._classify(data, self.dependencies) # type: ignore
|
1721
|
+
target = target._classify(data, self.dependencies) # type: ignore # pylint: disable=protected-access
|
1605
1722
|
except AttributeError:
|
1606
1723
|
pass # Target is not a Model, no classify
|
1607
1724
|
return target, target.__class__.__name__ # type: ignore
|
@@ -1616,10 +1733,12 @@ class Deserializer(object):
|
|
1616
1733
|
:param str target_obj: The target object type to deserialize to.
|
1617
1734
|
:param str/dict data: The response data to deserialize.
|
1618
1735
|
:param str content_type: Swagger "produces" if available.
|
1736
|
+
:return: Deserialized object.
|
1737
|
+
:rtype: object
|
1619
1738
|
"""
|
1620
1739
|
try:
|
1621
1740
|
return self(target_obj, data, content_type=content_type)
|
1622
|
-
except:
|
1741
|
+
except: # pylint: disable=bare-except
|
1623
1742
|
_LOGGER.debug(
|
1624
1743
|
"Ran into a deserialization error. Ignoring since this is failsafe deserialization",
|
1625
1744
|
exc_info=True,
|
@@ -1638,10 +1757,12 @@ class Deserializer(object):
|
|
1638
1757
|
|
1639
1758
|
If raw_data is something else, bypass all logic and return it directly.
|
1640
1759
|
|
1641
|
-
:param raw_data: Data to be processed.
|
1642
|
-
:param content_type: How to parse if raw_data is a string/bytes.
|
1760
|
+
:param obj raw_data: Data to be processed.
|
1761
|
+
:param str content_type: How to parse if raw_data is a string/bytes.
|
1643
1762
|
:raises JSONDecodeError: If JSON is requested and parsing is impossible.
|
1644
1763
|
:raises UnicodeDecodeError: If bytes is not UTF8
|
1764
|
+
:rtype: object
|
1765
|
+
:return: Unpacked content.
|
1645
1766
|
"""
|
1646
1767
|
# Assume this is enough to detect a Pipeline Response without importing it
|
1647
1768
|
context = getattr(raw_data, "context", {})
|
@@ -1671,17 +1792,24 @@ class Deserializer(object):
|
|
1671
1792
|
def _instantiate_model(self, response, attrs, additional_properties=None):
|
1672
1793
|
"""Instantiate a response model passing in deserialized args.
|
1673
1794
|
|
1674
|
-
:param response: The response model class.
|
1675
|
-
:param
|
1795
|
+
:param Response response: The response model class.
|
1796
|
+
:param dict attrs: The deserialized response attributes.
|
1797
|
+
:param dict additional_properties: Additional properties to be set.
|
1798
|
+
:rtype: Response
|
1799
|
+
:return: The instantiated response model.
|
1676
1800
|
"""
|
1677
1801
|
if callable(response):
|
1678
1802
|
subtype = getattr(response, "_subtype_map", {})
|
1679
1803
|
try:
|
1680
1804
|
readonly = [
|
1681
|
-
k
|
1805
|
+
k
|
1806
|
+
for k, v in response._validation.items()
|
1807
|
+
if v.get("readonly") # pylint: disable=protected-access
|
1682
1808
|
]
|
1683
1809
|
const = [
|
1684
|
-
k
|
1810
|
+
k
|
1811
|
+
for k, v in response._validation.items()
|
1812
|
+
if v.get("constant") # pylint: disable=protected-access
|
1685
1813
|
]
|
1686
1814
|
kwargs = {
|
1687
1815
|
k: v
|
@@ -1696,7 +1824,7 @@ class Deserializer(object):
|
|
1696
1824
|
return response_obj
|
1697
1825
|
except TypeError as err:
|
1698
1826
|
msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
|
1699
|
-
raise DeserializationError(msg + str(err))
|
1827
|
+
raise DeserializationError(msg + str(err)) from err
|
1700
1828
|
else:
|
1701
1829
|
try:
|
1702
1830
|
for attr, value in attrs.items():
|
@@ -1705,15 +1833,18 @@ class Deserializer(object):
|
|
1705
1833
|
except Exception as exp:
|
1706
1834
|
msg = "Unable to populate response model. "
|
1707
1835
|
msg += "Type: {}, Error: {}".format(type(response), exp)
|
1708
|
-
raise DeserializationError(msg)
|
1836
|
+
raise DeserializationError(msg) from exp
|
1709
1837
|
|
1710
|
-
def deserialize_data(
|
1838
|
+
def deserialize_data(
|
1839
|
+
self, data, data_type
|
1840
|
+
): # pylint: disable=too-many-return-statements
|
1711
1841
|
"""Process data for deserialization according to data type.
|
1712
1842
|
|
1713
1843
|
:param str data: The response string to be deserialized.
|
1714
1844
|
:param str data_type: The type to deserialize to.
|
1715
1845
|
:raises: DeserializationError if deserialization fails.
|
1716
1846
|
:return: Deserialized object.
|
1847
|
+
:rtype: object
|
1717
1848
|
"""
|
1718
1849
|
if data is None:
|
1719
1850
|
return data
|
@@ -1729,7 +1860,14 @@ class Deserializer(object):
|
|
1729
1860
|
):
|
1730
1861
|
return data
|
1731
1862
|
|
1732
|
-
is_a_text_parsing_type =
|
1863
|
+
is_a_text_parsing_type = (
|
1864
|
+
lambda x: x
|
1865
|
+
not in [ # pylint: disable=unnecessary-lambda-assignment
|
1866
|
+
"object",
|
1867
|
+
"[]",
|
1868
|
+
r"{}",
|
1869
|
+
]
|
1870
|
+
)
|
1733
1871
|
if (
|
1734
1872
|
isinstance(data, ET.Element)
|
1735
1873
|
and is_a_text_parsing_type(data_type)
|
@@ -1753,14 +1891,14 @@ class Deserializer(object):
|
|
1753
1891
|
msg = "Unable to deserialize response data."
|
1754
1892
|
msg += " Data: {}, {}".format(data, data_type)
|
1755
1893
|
raise DeserializationError(msg) from err
|
1756
|
-
|
1757
|
-
return self._deserialize(obj_type, data)
|
1894
|
+
return self._deserialize(obj_type, data)
|
1758
1895
|
|
1759
1896
|
def deserialize_iter(self, attr, iter_type):
|
1760
1897
|
"""Deserialize an iterable.
|
1761
1898
|
|
1762
1899
|
:param list attr: Iterable to be deserialized.
|
1763
1900
|
:param str iter_type: The type of object in the iterable.
|
1901
|
+
:return: Deserialized iterable.
|
1764
1902
|
:rtype: list
|
1765
1903
|
"""
|
1766
1904
|
if attr is None:
|
@@ -1783,6 +1921,7 @@ class Deserializer(object):
|
|
1783
1921
|
:param dict/list attr: Dictionary to be deserialized. Also accepts
|
1784
1922
|
a list of key, value pairs.
|
1785
1923
|
:param str dict_type: The object type of the items in the dictionary.
|
1924
|
+
:return: Deserialized dictionary.
|
1786
1925
|
:rtype: dict
|
1787
1926
|
"""
|
1788
1927
|
if isinstance(attr, list):
|
@@ -1795,11 +1934,14 @@ class Deserializer(object):
|
|
1795
1934
|
attr = {el.tag: el.text for el in attr}
|
1796
1935
|
return {k: self.deserialize_data(v, dict_type) for k, v in attr.items()}
|
1797
1936
|
|
1798
|
-
def deserialize_object(
|
1937
|
+
def deserialize_object(
|
1938
|
+
self, attr, **kwargs
|
1939
|
+
): # pylint: disable=too-many-return-statements
|
1799
1940
|
"""Deserialize a generic object.
|
1800
1941
|
This will be handled as a dictionary.
|
1801
1942
|
|
1802
1943
|
:param dict attr: Dictionary to be deserialized.
|
1944
|
+
:return: Deserialized object.
|
1803
1945
|
:rtype: dict
|
1804
1946
|
:raises: TypeError if non-builtin datatype encountered.
|
1805
1947
|
"""
|
@@ -1834,11 +1976,12 @@ class Deserializer(object):
|
|
1834
1976
|
pass
|
1835
1977
|
return deserialized
|
1836
1978
|
|
1837
|
-
|
1838
|
-
|
1839
|
-
raise TypeError(error + str(obj_type))
|
1979
|
+
error = "Cannot deserialize generic object with type: "
|
1980
|
+
raise TypeError(error + str(obj_type))
|
1840
1981
|
|
1841
|
-
def deserialize_basic(
|
1982
|
+
def deserialize_basic(
|
1983
|
+
self, attr, data_type
|
1984
|
+
): # pylint: disable=too-many-return-statements
|
1842
1985
|
"""Deserialize basic builtin data type from string.
|
1843
1986
|
Will attempt to convert to str, int, float and bool.
|
1844
1987
|
This function will also accept '1', '0', 'true' and 'false' as
|
@@ -1846,6 +1989,7 @@ class Deserializer(object):
|
|
1846
1989
|
|
1847
1990
|
:param str attr: response string to be deserialized.
|
1848
1991
|
:param str data_type: deserialization data type.
|
1992
|
+
:return: Deserialized basic type.
|
1849
1993
|
:rtype: str, int, float or bool
|
1850
1994
|
:raises: TypeError if string format is not valid.
|
1851
1995
|
"""
|
@@ -1857,24 +2001,23 @@ class Deserializer(object):
|
|
1857
2001
|
if data_type == "str":
|
1858
2002
|
# None or '', node <a/> is empty string.
|
1859
2003
|
return ""
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
return None
|
2004
|
+
# None or '', node <a/> with a strong type is None.
|
2005
|
+
# Don't try to model "empty bool" or "empty int"
|
2006
|
+
return None
|
1864
2007
|
|
1865
2008
|
if data_type == "bool":
|
1866
2009
|
if attr in [True, False, 1, 0]:
|
1867
2010
|
return bool(attr)
|
1868
|
-
|
2011
|
+
if isinstance(attr, str):
|
1869
2012
|
if attr.lower() in ["true", "1"]:
|
1870
2013
|
return True
|
1871
|
-
|
2014
|
+
if attr.lower() in ["false", "0"]:
|
1872
2015
|
return False
|
1873
2016
|
raise TypeError("Invalid boolean value: {}".format(attr))
|
1874
2017
|
|
1875
2018
|
if data_type == "str":
|
1876
2019
|
return self.deserialize_unicode(attr)
|
1877
|
-
return eval(data_type)(attr) # nosec
|
2020
|
+
return eval(data_type)(attr) # nosec # pylint: disable=eval-used
|
1878
2021
|
|
1879
2022
|
@staticmethod
|
1880
2023
|
def deserialize_unicode(data):
|
@@ -1882,6 +2025,7 @@ class Deserializer(object):
|
|
1882
2025
|
as a string.
|
1883
2026
|
|
1884
2027
|
:param str data: response string to be deserialized.
|
2028
|
+
:return: Deserialized string.
|
1885
2029
|
:rtype: str or unicode
|
1886
2030
|
"""
|
1887
2031
|
# We might be here because we have an enum modeled as string,
|
@@ -1895,8 +2039,7 @@ class Deserializer(object):
|
|
1895
2039
|
return data
|
1896
2040
|
except NameError:
|
1897
2041
|
return str(data)
|
1898
|
-
|
1899
|
-
return str(data)
|
2042
|
+
return str(data)
|
1900
2043
|
|
1901
2044
|
@staticmethod
|
1902
2045
|
def deserialize_enum(data, enum_obj):
|
@@ -1908,6 +2051,7 @@ class Deserializer(object):
|
|
1908
2051
|
:param str data: Response string to be deserialized. If this value is
|
1909
2052
|
None or invalid it will be returned as-is.
|
1910
2053
|
:param Enum enum_obj: Enum object to deserialize to.
|
2054
|
+
:return: Deserialized enum object.
|
1911
2055
|
:rtype: Enum
|
1912
2056
|
"""
|
1913
2057
|
if isinstance(data, enum_obj) or data is None:
|
@@ -1918,9 +2062,9 @@ class Deserializer(object):
|
|
1918
2062
|
# Workaround. We might consider remove it in the future.
|
1919
2063
|
try:
|
1920
2064
|
return list(enum_obj.__members__.values())[data]
|
1921
|
-
except IndexError:
|
2065
|
+
except IndexError as exc:
|
1922
2066
|
error = "{!r} is not a valid index for enum {!r}"
|
1923
|
-
raise DeserializationError(error.format(data, enum_obj))
|
2067
|
+
raise DeserializationError(error.format(data, enum_obj)) from exc
|
1924
2068
|
try:
|
1925
2069
|
return enum_obj(str(data))
|
1926
2070
|
except ValueError:
|
@@ -1940,6 +2084,7 @@ class Deserializer(object):
|
|
1940
2084
|
"""Deserialize string into bytearray.
|
1941
2085
|
|
1942
2086
|
:param str attr: response string to be deserialized.
|
2087
|
+
:return: Deserialized bytearray
|
1943
2088
|
:rtype: bytearray
|
1944
2089
|
:raises: TypeError if string format invalid.
|
1945
2090
|
"""
|
@@ -1952,6 +2097,7 @@ class Deserializer(object):
|
|
1952
2097
|
"""Deserialize base64 encoded string into string.
|
1953
2098
|
|
1954
2099
|
:param str attr: response string to be deserialized.
|
2100
|
+
:return: Deserialized base64 string
|
1955
2101
|
:rtype: bytearray
|
1956
2102
|
:raises: TypeError if string format invalid.
|
1957
2103
|
"""
|
@@ -1967,8 +2113,9 @@ class Deserializer(object):
|
|
1967
2113
|
"""Deserialize string into Decimal object.
|
1968
2114
|
|
1969
2115
|
:param str attr: response string to be deserialized.
|
1970
|
-
:
|
2116
|
+
:return: Deserialized decimal
|
1971
2117
|
:raises: DeserializationError if string format invalid.
|
2118
|
+
:rtype: decimal
|
1972
2119
|
"""
|
1973
2120
|
if isinstance(attr, ET.Element):
|
1974
2121
|
attr = attr.text
|
@@ -1983,6 +2130,7 @@ class Deserializer(object):
|
|
1983
2130
|
"""Deserialize string into long (Py2) or int (Py3).
|
1984
2131
|
|
1985
2132
|
:param str attr: response string to be deserialized.
|
2133
|
+
:return: Deserialized int
|
1986
2134
|
:rtype: long or int
|
1987
2135
|
:raises: ValueError if string format invalid.
|
1988
2136
|
"""
|
@@ -1995,6 +2143,7 @@ class Deserializer(object):
|
|
1995
2143
|
"""Deserialize ISO-8601 formatted string into TimeDelta object.
|
1996
2144
|
|
1997
2145
|
:param str attr: response string to be deserialized.
|
2146
|
+
:return: Deserialized duration
|
1998
2147
|
:rtype: TimeDelta
|
1999
2148
|
:raises: DeserializationError if string format invalid.
|
2000
2149
|
"""
|
@@ -2005,14 +2154,14 @@ class Deserializer(object):
|
|
2005
2154
|
except (ValueError, OverflowError, AttributeError) as err:
|
2006
2155
|
msg = "Cannot deserialize duration object."
|
2007
2156
|
raise DeserializationError(msg) from err
|
2008
|
-
|
2009
|
-
return duration
|
2157
|
+
return duration
|
2010
2158
|
|
2011
2159
|
@staticmethod
|
2012
2160
|
def deserialize_date(attr):
|
2013
2161
|
"""Deserialize ISO-8601 formatted string into Date object.
|
2014
2162
|
|
2015
2163
|
:param str attr: response string to be deserialized.
|
2164
|
+
:return: Deserialized date
|
2016
2165
|
:rtype: Date
|
2017
2166
|
:raises: DeserializationError if string format invalid.
|
2018
2167
|
"""
|
@@ -2030,6 +2179,7 @@ class Deserializer(object):
|
|
2030
2179
|
"""Deserialize ISO-8601 formatted string into time object.
|
2031
2180
|
|
2032
2181
|
:param str attr: response string to be deserialized.
|
2182
|
+
:return: Deserialized time
|
2033
2183
|
:rtype: datetime.time
|
2034
2184
|
:raises: DeserializationError if string format invalid.
|
2035
2185
|
"""
|
@@ -2046,6 +2196,7 @@ class Deserializer(object):
|
|
2046
2196
|
"""Deserialize RFC-1123 formatted string into Datetime object.
|
2047
2197
|
|
2048
2198
|
:param str attr: response string to be deserialized.
|
2199
|
+
:return: Deserialized RFC datetime
|
2049
2200
|
:rtype: Datetime
|
2050
2201
|
:raises: DeserializationError if string format invalid.
|
2051
2202
|
"""
|
@@ -2064,14 +2215,14 @@ class Deserializer(object):
|
|
2064
2215
|
except ValueError as err:
|
2065
2216
|
msg = "Cannot deserialize to rfc datetime object."
|
2066
2217
|
raise DeserializationError(msg) from err
|
2067
|
-
|
2068
|
-
return date_obj
|
2218
|
+
return date_obj
|
2069
2219
|
|
2070
2220
|
@staticmethod
|
2071
2221
|
def deserialize_iso(attr):
|
2072
2222
|
"""Deserialize ISO-8601 formatted string into Datetime object.
|
2073
2223
|
|
2074
2224
|
:param str attr: response string to be deserialized.
|
2225
|
+
:return: Deserialized ISO datetime
|
2075
2226
|
:rtype: Datetime
|
2076
2227
|
:raises: DeserializationError if string format invalid.
|
2077
2228
|
"""
|
@@ -2101,8 +2252,7 @@ class Deserializer(object):
|
|
2101
2252
|
except (ValueError, OverflowError, AttributeError) as err:
|
2102
2253
|
msg = "Cannot deserialize datetime object."
|
2103
2254
|
raise DeserializationError(msg) from err
|
2104
|
-
|
2105
|
-
return date_obj
|
2255
|
+
return date_obj
|
2106
2256
|
|
2107
2257
|
@staticmethod
|
2108
2258
|
def deserialize_unix(attr):
|
@@ -2110,6 +2260,7 @@ class Deserializer(object):
|
|
2110
2260
|
This is represented as seconds.
|
2111
2261
|
|
2112
2262
|
:param int attr: Object to be serialized.
|
2263
|
+
:return: Deserialized datetime
|
2113
2264
|
:rtype: Datetime
|
2114
2265
|
:raises: DeserializationError if format invalid
|
2115
2266
|
"""
|
@@ -2121,5 +2272,4 @@ class Deserializer(object):
|
|
2121
2272
|
except ValueError as err:
|
2122
2273
|
msg = "Cannot deserialize to unix datetime object."
|
2123
2274
|
raise DeserializationError(msg) from err
|
2124
|
-
|
2125
|
-
return date_obj
|
2275
|
+
return date_obj
|