@azure-tools/typespec-python 0.30.0 → 0.31.1

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