ignos-api-client 2024.5.28.9351__py3-none-any.whl → 20260205.5.1__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.
@@ -1,30 +1,12 @@
1
+ # pylint: disable=line-too-long,useless-suppression,too-many-lines
2
+ # coding=utf-8
1
3
  # --------------------------------------------------------------------------
2
- #
3
4
  # Copyright (c) Microsoft Corporation. All rights reserved.
4
- #
5
- # The MIT License (MIT)
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the ""Software""), to
9
- # deal in the Software without restriction, including without limitation the
10
- # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
- # sell copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in
15
- # all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
- # IN THE SOFTWARE.
24
- #
5
+ # Licensed under the MIT License. See License.txt in the project root for license information.
6
+ # Code generated by Microsoft (R) AutoRest Code Generator.
7
+ # Changes may cause incorrect behavior and will be lost if the code is regenerated.
25
8
  # --------------------------------------------------------------------------
26
9
 
27
- # pylint: skip-file
28
10
  # pyright: reportUnnecessaryTypeIgnoreComment=false
29
11
 
30
12
  from base64 import b64decode, b64encode
@@ -39,7 +21,6 @@ import re
39
21
  import sys
40
22
  import codecs
41
23
  from typing import (
42
- Dict,
43
24
  Any,
44
25
  cast,
45
26
  Optional,
@@ -48,11 +29,7 @@ from typing import (
48
29
  IO,
49
30
  Mapping,
50
31
  Callable,
51
- TypeVar,
52
32
  MutableMapping,
53
- Type,
54
- List,
55
- Mapping,
56
33
  )
57
34
 
58
35
  try:
@@ -62,13 +39,13 @@ except ImportError:
62
39
  import xml.etree.ElementTree as ET
63
40
 
64
41
  import isodate # type: ignore
42
+ from typing_extensions import Self
65
43
 
66
44
  from azure.core.exceptions import DeserializationError, SerializationError
67
45
  from azure.core.serialization import NULL as CoreNull
68
46
 
69
47
  _BOM = codecs.BOM_UTF8.decode(encoding="utf-8")
70
48
 
71
- ModelType = TypeVar("ModelType", bound="Model")
72
49
  JSON = MutableMapping[str, Any]
73
50
 
74
51
 
@@ -91,6 +68,8 @@ class RawDeserializer:
91
68
  :param data: Input, could be bytes or stream (will be decoded with UTF8) or text
92
69
  :type data: str or bytes or IO
93
70
  :param str content_type: The content type.
71
+ :return: The deserialized data.
72
+ :rtype: object
94
73
  """
95
74
  if hasattr(data, "read"):
96
75
  # Assume a stream
@@ -112,7 +91,7 @@ class RawDeserializer:
112
91
  try:
113
92
  return json.loads(data_as_str)
114
93
  except ValueError as err:
115
- raise DeserializationError("JSON is invalid: {}".format(err), err)
94
+ raise DeserializationError("JSON is invalid: {}".format(err), err) from err
116
95
  elif "xml" in (content_type or []):
117
96
  try:
118
97
 
@@ -144,6 +123,8 @@ class RawDeserializer:
144
123
  # context otherwise.
145
124
  _LOGGER.critical("Wasn't XML not JSON, failing")
146
125
  raise DeserializationError("XML is invalid") from err
126
+ elif content_type.startswith("text/"):
127
+ return data_as_str
147
128
  raise DeserializationError("Cannot deserialize content-type: {}".format(content_type))
148
129
 
149
130
  @classmethod
@@ -153,6 +134,11 @@ class RawDeserializer:
153
134
  Use bytes and headers to NOT use any requests/aiohttp or whatever
154
135
  specific implementation.
155
136
  Headers will tested for "content-type"
137
+
138
+ :param bytes body_bytes: The body of the response.
139
+ :param dict headers: The headers of the response.
140
+ :returns: The deserialized data.
141
+ :rtype: object
156
142
  """
157
143
  # Try to use content-type from headers if available
158
144
  content_type = None
@@ -177,80 +163,31 @@ try:
177
163
  except NameError:
178
164
  _long_type = int
179
165
 
180
-
181
- class UTC(datetime.tzinfo):
182
- """Time Zone info for handling UTC"""
183
-
184
- def utcoffset(self, dt):
185
- """UTF offset for UTC is 0."""
186
- return datetime.timedelta(0)
187
-
188
- def tzname(self, dt):
189
- """Timestamp representation."""
190
- return "Z"
191
-
192
- def dst(self, dt):
193
- """No daylight saving for UTC."""
194
- return datetime.timedelta(hours=1)
195
-
196
-
197
- try:
198
- from datetime import timezone as _FixedOffset # type: ignore
199
- except ImportError: # Python 2.7
200
-
201
- class _FixedOffset(datetime.tzinfo): # type: ignore
202
- """Fixed offset in minutes east from UTC.
203
- Copy/pasted from Python doc
204
- :param datetime.timedelta offset: offset in timedelta format
205
- """
206
-
207
- def __init__(self, offset):
208
- self.__offset = offset
209
-
210
- def utcoffset(self, dt):
211
- return self.__offset
212
-
213
- def tzname(self, dt):
214
- return str(self.__offset.total_seconds() / 3600)
215
-
216
- def __repr__(self):
217
- return "<FixedOffset {}>".format(self.tzname(None))
218
-
219
- def dst(self, dt):
220
- return datetime.timedelta(0)
221
-
222
- def __getinitargs__(self):
223
- return (self.__offset,)
224
-
225
-
226
- try:
227
- from datetime import timezone
228
-
229
- TZ_UTC = timezone.utc
230
- except ImportError:
231
- TZ_UTC = UTC() # type: ignore
166
+ TZ_UTC = datetime.timezone.utc
232
167
 
233
168
  _FLATTEN = re.compile(r"(?<!\\)\.")
234
169
 
235
170
 
236
- def attribute_transformer(key, attr_desc, value):
171
+ def attribute_transformer(key, attr_desc, value): # pylint: disable=unused-argument
237
172
  """A key transformer that returns the Python attribute.
238
173
 
239
174
  :param str key: The attribute name
240
175
  :param dict attr_desc: The attribute metadata
241
176
  :param object value: The value
242
177
  :returns: A key using attribute name
178
+ :rtype: str
243
179
  """
244
180
  return (key, value)
245
181
 
246
182
 
247
- def full_restapi_key_transformer(key, attr_desc, value):
183
+ def full_restapi_key_transformer(key, attr_desc, value): # pylint: disable=unused-argument
248
184
  """A key transformer that returns the full RestAPI key path.
249
185
 
250
- :param str _: The attribute name
186
+ :param str key: The attribute name
251
187
  :param dict attr_desc: The attribute metadata
252
188
  :param object value: The value
253
189
  :returns: A list of keys using RestAPI syntax.
190
+ :rtype: list
254
191
  """
255
192
  keys = _FLATTEN.split(attr_desc["key"])
256
193
  return ([_decode_attribute_map_key(k) for k in keys], value)
@@ -263,33 +200,40 @@ def last_restapi_key_transformer(key, attr_desc, value):
263
200
  :param dict attr_desc: The attribute metadata
264
201
  :param object value: The value
265
202
  :returns: The last RestAPI key.
203
+ :rtype: str
266
204
  """
267
205
  key, value = full_restapi_key_transformer(key, attr_desc, value)
268
206
  return (key[-1], value)
269
207
 
270
208
 
271
209
  def _create_xml_node(tag, prefix=None, ns=None):
272
- """Create a XML node."""
210
+ """Create a XML node.
211
+
212
+ :param str tag: The tag name
213
+ :param str prefix: The prefix
214
+ :param str ns: The namespace
215
+ :return: The XML node
216
+ :rtype: xml.etree.ElementTree.Element
217
+ """
273
218
  if prefix and ns:
274
219
  ET.register_namespace(prefix, ns)
275
220
  if ns:
276
221
  return ET.Element("{" + ns + "}" + tag)
277
- else:
278
- return ET.Element(tag)
222
+ return ET.Element(tag)
279
223
 
280
224
 
281
- class Model(object):
225
+ class Model:
282
226
  """Mixin for all client request body/response body models to support
283
227
  serialization and deserialization.
284
228
  """
285
229
 
286
- _subtype_map: Dict[str, Dict[str, Any]] = {}
287
- _attribute_map: Dict[str, Dict[str, Any]] = {}
288
- _validation: Dict[str, Dict[str, Any]] = {}
230
+ _subtype_map: dict[str, dict[str, Any]] = {}
231
+ _attribute_map: dict[str, dict[str, Any]] = {}
232
+ _validation: dict[str, dict[str, Any]] = {}
289
233
 
290
234
  def __init__(self, **kwargs: Any) -> None:
291
- self.additional_properties: Optional[Dict[str, Any]] = {}
292
- for k in kwargs:
235
+ self.additional_properties: Optional[dict[str, Any]] = {}
236
+ for k in kwargs: # pylint: disable=consider-using-dict-items
293
237
  if k not in self._attribute_map:
294
238
  _LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
295
239
  elif k in self._validation and self._validation[k].get("readonly", False):
@@ -298,13 +242,23 @@ class Model(object):
298
242
  setattr(self, k, kwargs[k])
299
243
 
300
244
  def __eq__(self, other: Any) -> bool:
301
- """Compare objects by comparing all attributes."""
245
+ """Compare objects by comparing all attributes.
246
+
247
+ :param object other: The object to compare
248
+ :returns: True if objects are equal
249
+ :rtype: bool
250
+ """
302
251
  if isinstance(other, self.__class__):
303
252
  return self.__dict__ == other.__dict__
304
253
  return False
305
254
 
306
255
  def __ne__(self, other: Any) -> bool:
307
- """Compare objects by comparing all attributes."""
256
+ """Compare objects by comparing all attributes.
257
+
258
+ :param object other: The object to compare
259
+ :returns: True if objects are not equal
260
+ :rtype: bool
261
+ """
308
262
  return not self.__eq__(other)
309
263
 
310
264
  def __str__(self) -> str:
@@ -324,7 +278,11 @@ class Model(object):
324
278
 
325
279
  @classmethod
326
280
  def _create_xml_node(cls):
327
- """Create XML node."""
281
+ """Create XML node.
282
+
283
+ :returns: The XML node
284
+ :rtype: xml.etree.ElementTree.Element
285
+ """
328
286
  try:
329
287
  xml_map = cls._xml_map # type: ignore
330
288
  except AttributeError:
@@ -344,12 +302,14 @@ class Model(object):
344
302
  :rtype: dict
345
303
  """
346
304
  serializer = Serializer(self._infer_class_models())
347
- return serializer._serialize(self, keep_readonly=keep_readonly, **kwargs) # type: ignore
305
+ return serializer._serialize( # type: ignore # pylint: disable=protected-access
306
+ self, keep_readonly=keep_readonly, **kwargs
307
+ )
348
308
 
349
309
  def as_dict(
350
310
  self,
351
311
  keep_readonly: bool = True,
352
- key_transformer: Callable[[str, Dict[str, Any], Any], Any] = attribute_transformer,
312
+ key_transformer: Callable[[str, dict[str, Any], Any], Any] = attribute_transformer,
353
313
  **kwargs: Any
354
314
  ) -> JSON:
355
315
  """Return a dict that can be serialized using json.dump.
@@ -378,12 +338,15 @@ class Model(object):
378
338
 
379
339
  If you want XML serialization, you can pass the kwargs is_xml=True.
380
340
 
341
+ :param bool keep_readonly: If you want to serialize the readonly attributes
381
342
  :param function key_transformer: A key transformer function.
382
343
  :returns: A dict JSON compatible object
383
344
  :rtype: dict
384
345
  """
385
346
  serializer = Serializer(self._infer_class_models())
386
- return serializer._serialize(self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs) # type: ignore
347
+ return serializer._serialize( # type: ignore # pylint: disable=protected-access
348
+ self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs
349
+ )
387
350
 
388
351
  @classmethod
389
352
  def _infer_class_models(cls):
@@ -393,30 +356,31 @@ class Model(object):
393
356
  client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
394
357
  if cls.__name__ not in client_models:
395
358
  raise ValueError("Not Autorest generated code")
396
- except Exception:
359
+ except Exception: # pylint: disable=broad-exception-caught
397
360
  # Assume it's not Autorest generated (tests?). Add ourselves as dependencies.
398
361
  client_models = {cls.__name__: cls}
399
362
  return client_models
400
363
 
401
364
  @classmethod
402
- def deserialize(cls: Type[ModelType], data: Any, content_type: Optional[str] = None) -> ModelType:
365
+ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Self:
403
366
  """Parse a str using the RestAPI syntax and return a model.
404
367
 
405
368
  :param str data: A str using RestAPI structure. JSON by default.
406
369
  :param str content_type: JSON by default, set application/xml if XML.
407
370
  :returns: An instance of this model
408
- :raises: DeserializationError if something went wrong
371
+ :raises DeserializationError: if something went wrong
372
+ :rtype: Self
409
373
  """
410
374
  deserializer = Deserializer(cls._infer_class_models())
411
375
  return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
412
376
 
413
377
  @classmethod
414
378
  def from_dict(
415
- cls: Type[ModelType],
379
+ cls,
416
380
  data: Any,
417
- key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None,
381
+ key_extractors: Optional[Callable[[str, dict[str, Any], Any], Any]] = None,
418
382
  content_type: Optional[str] = None,
419
- ) -> ModelType:
383
+ ) -> Self:
420
384
  """Parse a dict using given key extractor return a model.
421
385
 
422
386
  By default consider key
@@ -424,9 +388,11 @@ class Model(object):
424
388
  and last_rest_key_case_insensitive_extractor)
425
389
 
426
390
  :param dict data: A dict using RestAPI structure
391
+ :param function key_extractors: A key extractor function.
427
392
  :param str content_type: JSON by default, set application/xml if XML.
428
393
  :returns: An instance of this model
429
- :raises: DeserializationError if something went wrong
394
+ :raises DeserializationError: if something went wrong
395
+ :rtype: Self
430
396
  """
431
397
  deserializer = Deserializer(cls._infer_class_models())
432
398
  deserializer.key_extractors = ( # type: ignore
@@ -446,21 +412,25 @@ class Model(object):
446
412
  return {}
447
413
  result = dict(cls._subtype_map[key])
448
414
  for valuetype in cls._subtype_map[key].values():
449
- result.update(objects[valuetype]._flatten_subtype(key, objects))
415
+ result |= objects[valuetype]._flatten_subtype(key, objects) # pylint: disable=protected-access
450
416
  return result
451
417
 
452
418
  @classmethod
453
419
  def _classify(cls, response, objects):
454
420
  """Check the class _subtype_map for any child classes.
455
421
  We want to ignore any inherited _subtype_maps.
456
- Remove the polymorphic key from the initial data.
422
+
423
+ :param dict response: The initial data
424
+ :param dict objects: The class objects
425
+ :returns: The class to be used
426
+ :rtype: class
457
427
  """
458
428
  for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
459
429
  subtype_value = None
460
430
 
461
431
  if not isinstance(response, ET.Element):
462
432
  rest_api_response_key = cls._get_rest_key_parts(subtype_key)[-1]
463
- subtype_value = response.pop(rest_api_response_key, None) or response.pop(subtype_key, None)
433
+ subtype_value = response.get(rest_api_response_key, None) or response.get(subtype_key, None)
464
434
  else:
465
435
  subtype_value = xml_key_extractor(subtype_key, cls._attribute_map[subtype_key], response)
466
436
  if subtype_value:
@@ -499,11 +469,13 @@ def _decode_attribute_map_key(key):
499
469
  inside the received data.
500
470
 
501
471
  :param str key: A key string from the generated code
472
+ :returns: The decoded key
473
+ :rtype: str
502
474
  """
503
475
  return key.replace("\\.", ".")
504
476
 
505
477
 
506
- class Serializer(object):
478
+ class Serializer: # pylint: disable=too-many-public-methods
507
479
  """Request object model serializer."""
508
480
 
509
481
  basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
@@ -538,7 +510,7 @@ class Serializer(object):
538
510
  "multiple": lambda x, y: x % y != 0,
539
511
  }
540
512
 
541
- def __init__(self, classes: Optional[Mapping[str, type]] = None):
513
+ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
542
514
  self.serialize_type = {
543
515
  "iso-8601": Serializer.serialize_iso,
544
516
  "rfc-1123": Serializer.serialize_rfc,
@@ -554,17 +526,20 @@ class Serializer(object):
554
526
  "[]": self.serialize_iter,
555
527
  "{}": self.serialize_dict,
556
528
  }
557
- self.dependencies: Dict[str, type] = dict(classes) if classes else {}
529
+ self.dependencies: dict[str, type] = dict(classes) if classes else {}
558
530
  self.key_transformer = full_restapi_key_transformer
559
531
  self.client_side_validation = True
560
532
 
561
- def _serialize(self, target_obj, data_type=None, **kwargs):
533
+ def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, too-many-statements, too-many-locals
534
+ self, target_obj, data_type=None, **kwargs
535
+ ):
562
536
  """Serialize data into a string according to type.
563
537
 
564
- :param target_obj: The data to be serialized.
538
+ :param object target_obj: The data to be serialized.
565
539
  :param str data_type: The type to be serialized from.
566
540
  :rtype: str, dict
567
- :raises: SerializationError if serialization fails.
541
+ :raises SerializationError: if serialization fails.
542
+ :returns: The serialized data.
568
543
  """
569
544
  key_transformer = kwargs.get("key_transformer", self.key_transformer)
570
545
  keep_readonly = kwargs.get("keep_readonly", False)
@@ -590,17 +565,19 @@ class Serializer(object):
590
565
 
591
566
  serialized = {}
592
567
  if is_xml_model_serialization:
593
- serialized = target_obj._create_xml_node()
568
+ serialized = target_obj._create_xml_node() # pylint: disable=protected-access
594
569
  try:
595
- attributes = target_obj._attribute_map
570
+ attributes = target_obj._attribute_map # pylint: disable=protected-access
596
571
  for attr, attr_desc in attributes.items():
597
572
  attr_name = attr
598
- if not keep_readonly and target_obj._validation.get(attr_name, {}).get("readonly", False):
573
+ if not keep_readonly and target_obj._validation.get( # pylint: disable=protected-access
574
+ attr_name, {}
575
+ ).get("readonly", False):
599
576
  continue
600
577
 
601
578
  if attr_name == "additional_properties" and attr_desc["key"] == "":
602
579
  if target_obj.additional_properties is not None:
603
- serialized.update(target_obj.additional_properties)
580
+ serialized |= target_obj.additional_properties
604
581
  continue
605
582
  try:
606
583
 
@@ -631,7 +608,8 @@ class Serializer(object):
631
608
  if isinstance(new_attr, list):
632
609
  serialized.extend(new_attr) # type: ignore
633
610
  elif isinstance(new_attr, ET.Element):
634
- # If the down XML has no XML/Name, we MUST replace the tag with the local tag. But keeping the namespaces.
611
+ # If the down XML has no XML/Name,
612
+ # we MUST replace the tag with the local tag. But keeping the namespaces.
635
613
  if "name" not in getattr(orig_attr, "_xml_map", {}):
636
614
  splitted_tag = new_attr.tag.split("}")
637
615
  if len(splitted_tag) == 2: # Namespace
@@ -662,17 +640,17 @@ class Serializer(object):
662
640
  except (AttributeError, KeyError, TypeError) as err:
663
641
  msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
664
642
  raise SerializationError(msg) from err
665
- else:
666
- return serialized
643
+ return serialized
667
644
 
668
645
  def body(self, data, data_type, **kwargs):
669
646
  """Serialize data intended for a request body.
670
647
 
671
- :param data: The data to be serialized.
648
+ :param object data: The data to be serialized.
672
649
  :param str data_type: The type to be serialized from.
673
650
  :rtype: dict
674
- :raises: SerializationError if serialization fails.
675
- :raises: ValueError if data is None
651
+ :raises SerializationError: if serialization fails.
652
+ :raises ValueError: if data is None
653
+ :returns: The serialized request body
676
654
  """
677
655
 
678
656
  # Just in case this is a dict
@@ -701,7 +679,7 @@ class Serializer(object):
701
679
  attribute_key_case_insensitive_extractor,
702
680
  last_rest_key_case_insensitive_extractor,
703
681
  ]
704
- data = deserializer._deserialize(data_type, data)
682
+ data = deserializer._deserialize(data_type, data) # pylint: disable=protected-access
705
683
  except DeserializationError as err:
706
684
  raise SerializationError("Unable to build a model: " + str(err)) from err
707
685
 
@@ -710,11 +688,13 @@ class Serializer(object):
710
688
  def url(self, name, data, data_type, **kwargs):
711
689
  """Serialize data intended for a URL path.
712
690
 
713
- :param data: The data to be serialized.
691
+ :param str name: The name of the URL path parameter.
692
+ :param object data: The data to be serialized.
714
693
  :param str data_type: The type to be serialized from.
715
694
  :rtype: str
716
- :raises: TypeError if serialization fails.
717
- :raises: ValueError if data is None
695
+ :returns: The serialized URL path
696
+ :raises TypeError: if serialization fails.
697
+ :raises ValueError: if data is None
718
698
  """
719
699
  try:
720
700
  output = self.serialize_data(data, data_type, **kwargs)
@@ -726,21 +706,20 @@ class Serializer(object):
726
706
  output = output.replace("{", quote("{")).replace("}", quote("}"))
727
707
  else:
728
708
  output = quote(str(output), safe="")
729
- except SerializationError:
730
- raise TypeError("{} must be type {}.".format(name, data_type))
731
- else:
732
- return output
709
+ except SerializationError as exc:
710
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
711
+ return output
733
712
 
734
713
  def query(self, name, data, data_type, **kwargs):
735
714
  """Serialize data intended for a URL query.
736
715
 
737
- :param data: The data to be serialized.
716
+ :param str name: The name of the query parameter.
717
+ :param object data: The data to be serialized.
738
718
  :param str data_type: The type to be serialized from.
739
- :keyword bool skip_quote: Whether to skip quote the serialized result.
740
- Defaults to False.
741
719
  :rtype: str, list
742
- :raises: TypeError if serialization fails.
743
- :raises: ValueError if data is None
720
+ :raises TypeError: if serialization fails.
721
+ :raises ValueError: if data is None
722
+ :returns: The serialized query parameter
744
723
  """
745
724
  try:
746
725
  # Treat the list aside, since we don't want to encode the div separator
@@ -757,19 +736,20 @@ class Serializer(object):
757
736
  output = str(output)
758
737
  else:
759
738
  output = quote(str(output), safe="")
760
- except SerializationError:
761
- raise TypeError("{} must be type {}.".format(name, data_type))
762
- else:
763
- return str(output)
739
+ except SerializationError as exc:
740
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
741
+ return str(output)
764
742
 
765
743
  def header(self, name, data, data_type, **kwargs):
766
744
  """Serialize data intended for a request header.
767
745
 
768
- :param data: The data to be serialized.
746
+ :param str name: The name of the header.
747
+ :param object data: The data to be serialized.
769
748
  :param str data_type: The type to be serialized from.
770
749
  :rtype: str
771
- :raises: TypeError if serialization fails.
772
- :raises: ValueError if data is None
750
+ :raises TypeError: if serialization fails.
751
+ :raises ValueError: if data is None
752
+ :returns: The serialized header
773
753
  """
774
754
  try:
775
755
  if data_type in ["[str]"]:
@@ -778,21 +758,20 @@ class Serializer(object):
778
758
  output = self.serialize_data(data, data_type, **kwargs)
779
759
  if data_type == "bool":
780
760
  output = json.dumps(output)
781
- except SerializationError:
782
- raise TypeError("{} must be type {}.".format(name, data_type))
783
- else:
784
- return str(output)
761
+ except SerializationError as exc:
762
+ raise TypeError("{} must be type {}.".format(name, data_type)) from exc
763
+ return str(output)
785
764
 
786
765
  def serialize_data(self, data, data_type, **kwargs):
787
766
  """Serialize generic data according to supplied data type.
788
767
 
789
- :param data: The data to be serialized.
768
+ :param object data: The data to be serialized.
790
769
  :param str data_type: The type to be serialized from.
791
- :param bool required: Whether it's essential that the data not be
792
- empty or None
793
- :raises: AttributeError if required data is None.
794
- :raises: ValueError if data is None
795
- :raises: SerializationError if serialization fails.
770
+ :raises AttributeError: if required data is None.
771
+ :raises ValueError: if data is None
772
+ :raises SerializationError: if serialization fails.
773
+ :returns: The serialized data.
774
+ :rtype: str, int, float, bool, dict, list
796
775
  """
797
776
  if data is None:
798
777
  raise ValueError("No value for given attribute")
@@ -803,12 +782,12 @@ class Serializer(object):
803
782
  if data_type in self.basic_types.values():
804
783
  return self.serialize_basic(data, data_type, **kwargs)
805
784
 
806
- elif data_type in self.serialize_type:
785
+ if data_type in self.serialize_type:
807
786
  return self.serialize_type[data_type](data, **kwargs)
808
787
 
809
788
  # If dependencies is empty, try with current data class
810
789
  # It has to be a subclass of Enum anyway
811
- enum_type = self.dependencies.get(data_type, data.__class__)
790
+ enum_type = self.dependencies.get(data_type, cast(type, data.__class__))
812
791
  if issubclass(enum_type, Enum):
813
792
  return Serializer.serialize_enum(data, enum_obj=enum_type)
814
793
 
@@ -819,11 +798,10 @@ class Serializer(object):
819
798
  except (ValueError, TypeError) as err:
820
799
  msg = "Unable to serialize value: {!r} as type: {!r}."
821
800
  raise SerializationError(msg.format(data, data_type)) from err
822
- else:
823
- return self._serialize(data, **kwargs)
801
+ return self._serialize(data, **kwargs)
824
802
 
825
803
  @classmethod
826
- def _get_custom_serializers(cls, data_type, **kwargs):
804
+ def _get_custom_serializers(cls, data_type, **kwargs): # pylint: disable=inconsistent-return-statements
827
805
  custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type)
828
806
  if custom_serializer:
829
807
  return custom_serializer
@@ -839,23 +817,33 @@ class Serializer(object):
839
817
  - basic_types_serializers dict[str, callable] : If set, use the callable as serializer
840
818
  - is_xml bool : If set, use xml_basic_types_serializers
841
819
 
842
- :param data: Object to be serialized.
820
+ :param obj data: Object to be serialized.
843
821
  :param str data_type: Type of object in the iterable.
822
+ :rtype: str, int, float, bool
823
+ :return: serialized object
824
+ :raises TypeError: raise if data_type is not one of str, int, float, bool.
844
825
  """
845
826
  custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
846
827
  if custom_serializer:
847
828
  return custom_serializer(data)
848
829
  if data_type == "str":
849
830
  return cls.serialize_unicode(data)
850
- return eval(data_type)(data) # nosec
831
+ if data_type == "int":
832
+ return int(data)
833
+ if data_type == "float":
834
+ return float(data)
835
+ if data_type == "bool":
836
+ return bool(data)
837
+ raise TypeError("Unknown basic data type: {}".format(data_type))
851
838
 
852
839
  @classmethod
853
840
  def serialize_unicode(cls, data):
854
841
  """Special handling for serializing unicode strings in Py2.
855
842
  Encode to UTF-8 if unicode, otherwise handle as a str.
856
843
 
857
- :param data: Object to be serialized.
844
+ :param str data: Object to be serialized.
858
845
  :rtype: str
846
+ :return: serialized object
859
847
  """
860
848
  try: # If I received an enum, return its value
861
849
  return data.value
@@ -869,8 +857,7 @@ class Serializer(object):
869
857
  return data
870
858
  except NameError:
871
859
  return str(data)
872
- else:
873
- return str(data)
860
+ return str(data)
874
861
 
875
862
  def serialize_iter(self, data, iter_type, div=None, **kwargs):
876
863
  """Serialize iterable.
@@ -880,15 +867,13 @@ class Serializer(object):
880
867
  serialization_ctxt['type'] should be same as data_type.
881
868
  - is_xml bool : If set, serialize as XML
882
869
 
883
- :param list attr: Object to be serialized.
870
+ :param list data: Object to be serialized.
884
871
  :param str iter_type: Type of object in the iterable.
885
- :param bool required: Whether the objects in the iterable must
886
- not be None or empty.
887
872
  :param str div: If set, this str will be used to combine the elements
888
873
  in the iterable into a combined string. Default is 'None'.
889
- :keyword bool do_quote: Whether to quote the serialized result of each iterable element.
890
874
  Defaults to False.
891
875
  :rtype: list, str
876
+ :return: serialized iterable
892
877
  """
893
878
  if isinstance(data, str):
894
879
  raise SerializationError("Refuse str type as a valid iter type.")
@@ -943,9 +928,8 @@ class Serializer(object):
943
928
 
944
929
  :param dict attr: Object to be serialized.
945
930
  :param str dict_type: Type of object in the dictionary.
946
- :param bool required: Whether the objects in the dictionary must
947
- not be None or empty.
948
931
  :rtype: dict
932
+ :return: serialized dictionary
949
933
  """
950
934
  serialization_ctxt = kwargs.get("serialization_ctxt", {})
951
935
  serialized = {}
@@ -969,7 +953,7 @@ class Serializer(object):
969
953
 
970
954
  return serialized
971
955
 
972
- def serialize_object(self, attr, **kwargs):
956
+ def serialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
973
957
  """Serialize a generic object.
974
958
  This will be handled as a dictionary. If object passed in is not
975
959
  a basic type (str, int, float, dict, list) it will simply be
@@ -977,6 +961,7 @@ class Serializer(object):
977
961
 
978
962
  :param dict attr: Object to be serialized.
979
963
  :rtype: dict or str
964
+ :return: serialized object
980
965
  """
981
966
  if attr is None:
982
967
  return None
@@ -1001,7 +986,7 @@ class Serializer(object):
1001
986
  return self.serialize_decimal(attr)
1002
987
 
1003
988
  # If it's a model or I know this dependency, serialize as a Model
1004
- elif obj_type in self.dependencies.values() or isinstance(attr, Model):
989
+ if obj_type in self.dependencies.values() or isinstance(attr, Model):
1005
990
  return self._serialize(attr)
1006
991
 
1007
992
  if obj_type == dict:
@@ -1032,56 +1017,61 @@ class Serializer(object):
1032
1017
  try:
1033
1018
  enum_obj(result) # type: ignore
1034
1019
  return result
1035
- except ValueError:
1020
+ except ValueError as exc:
1036
1021
  for enum_value in enum_obj: # type: ignore
1037
1022
  if enum_value.value.lower() == str(attr).lower():
1038
1023
  return enum_value.value
1039
1024
  error = "{!r} is not valid value for enum {!r}"
1040
- raise SerializationError(error.format(attr, enum_obj))
1025
+ raise SerializationError(error.format(attr, enum_obj)) from exc
1041
1026
 
1042
1027
  @staticmethod
1043
- def serialize_bytearray(attr, **kwargs):
1028
+ def serialize_bytearray(attr, **kwargs): # pylint: disable=unused-argument
1044
1029
  """Serialize bytearray into base-64 string.
1045
1030
 
1046
- :param attr: Object to be serialized.
1031
+ :param str attr: Object to be serialized.
1047
1032
  :rtype: str
1033
+ :return: serialized base64
1048
1034
  """
1049
1035
  return b64encode(attr).decode()
1050
1036
 
1051
1037
  @staticmethod
1052
- def serialize_base64(attr, **kwargs):
1038
+ def serialize_base64(attr, **kwargs): # pylint: disable=unused-argument
1053
1039
  """Serialize str into base-64 string.
1054
1040
 
1055
- :param attr: Object to be serialized.
1041
+ :param str attr: Object to be serialized.
1056
1042
  :rtype: str
1043
+ :return: serialized base64
1057
1044
  """
1058
1045
  encoded = b64encode(attr).decode("ascii")
1059
1046
  return encoded.strip("=").replace("+", "-").replace("/", "_")
1060
1047
 
1061
1048
  @staticmethod
1062
- def serialize_decimal(attr, **kwargs):
1049
+ def serialize_decimal(attr, **kwargs): # pylint: disable=unused-argument
1063
1050
  """Serialize Decimal object to float.
1064
1051
 
1065
- :param attr: Object to be serialized.
1052
+ :param decimal attr: Object to be serialized.
1066
1053
  :rtype: float
1054
+ :return: serialized decimal
1067
1055
  """
1068
1056
  return float(attr)
1069
1057
 
1070
1058
  @staticmethod
1071
- def serialize_long(attr, **kwargs):
1059
+ def serialize_long(attr, **kwargs): # pylint: disable=unused-argument
1072
1060
  """Serialize long (Py2) or int (Py3).
1073
1061
 
1074
- :param attr: Object to be serialized.
1062
+ :param int attr: Object to be serialized.
1075
1063
  :rtype: int/long
1064
+ :return: serialized long
1076
1065
  """
1077
1066
  return _long_type(attr)
1078
1067
 
1079
1068
  @staticmethod
1080
- def serialize_date(attr, **kwargs):
1069
+ def serialize_date(attr, **kwargs): # pylint: disable=unused-argument
1081
1070
  """Serialize Date object into ISO-8601 formatted string.
1082
1071
 
1083
1072
  :param Date attr: Object to be serialized.
1084
1073
  :rtype: str
1074
+ :return: serialized date
1085
1075
  """
1086
1076
  if isinstance(attr, str):
1087
1077
  attr = isodate.parse_date(attr)
@@ -1089,11 +1079,12 @@ class Serializer(object):
1089
1079
  return t
1090
1080
 
1091
1081
  @staticmethod
1092
- def serialize_time(attr, **kwargs):
1082
+ def serialize_time(attr, **kwargs): # pylint: disable=unused-argument
1093
1083
  """Serialize Time object into ISO-8601 formatted string.
1094
1084
 
1095
1085
  :param datetime.time attr: Object to be serialized.
1096
1086
  :rtype: str
1087
+ :return: serialized time
1097
1088
  """
1098
1089
  if isinstance(attr, str):
1099
1090
  attr = isodate.parse_time(attr)
@@ -1103,30 +1094,32 @@ class Serializer(object):
1103
1094
  return t
1104
1095
 
1105
1096
  @staticmethod
1106
- def serialize_duration(attr, **kwargs):
1097
+ def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
1107
1098
  """Serialize TimeDelta object into ISO-8601 formatted string.
1108
1099
 
1109
1100
  :param TimeDelta attr: Object to be serialized.
1110
1101
  :rtype: str
1102
+ :return: serialized duration
1111
1103
  """
1112
1104
  if isinstance(attr, str):
1113
1105
  attr = isodate.parse_duration(attr)
1114
1106
  return isodate.duration_isoformat(attr)
1115
1107
 
1116
1108
  @staticmethod
1117
- def serialize_rfc(attr, **kwargs):
1109
+ def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
1118
1110
  """Serialize Datetime object into RFC-1123 formatted string.
1119
1111
 
1120
1112
  :param Datetime attr: Object to be serialized.
1121
1113
  :rtype: str
1122
- :raises: TypeError if format invalid.
1114
+ :raises TypeError: if format invalid.
1115
+ :return: serialized rfc
1123
1116
  """
1124
1117
  try:
1125
1118
  if not attr.tzinfo:
1126
1119
  _LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
1127
1120
  utc = attr.utctimetuple()
1128
- except AttributeError:
1129
- raise TypeError("RFC1123 object must be valid Datetime object.")
1121
+ except AttributeError as exc:
1122
+ raise TypeError("RFC1123 object must be valid Datetime object.") from exc
1130
1123
 
1131
1124
  return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
1132
1125
  Serializer.days[utc.tm_wday],
@@ -1139,12 +1132,13 @@ class Serializer(object):
1139
1132
  )
1140
1133
 
1141
1134
  @staticmethod
1142
- def serialize_iso(attr, **kwargs):
1135
+ def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument
1143
1136
  """Serialize Datetime object into ISO-8601 formatted string.
1144
1137
 
1145
1138
  :param Datetime attr: Object to be serialized.
1146
1139
  :rtype: str
1147
- :raises: SerializationError if format invalid.
1140
+ :raises SerializationError: if format invalid.
1141
+ :return: serialized iso
1148
1142
  """
1149
1143
  if isinstance(attr, str):
1150
1144
  attr = isodate.parse_datetime(attr)
@@ -1170,13 +1164,14 @@ class Serializer(object):
1170
1164
  raise TypeError(msg) from err
1171
1165
 
1172
1166
  @staticmethod
1173
- def serialize_unix(attr, **kwargs):
1167
+ def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument
1174
1168
  """Serialize Datetime object into IntTime format.
1175
1169
  This is represented as seconds.
1176
1170
 
1177
1171
  :param Datetime attr: Object to be serialized.
1178
1172
  :rtype: int
1179
- :raises: SerializationError if format invalid
1173
+ :raises SerializationError: if format invalid
1174
+ :return: serialied unix
1180
1175
  """
1181
1176
  if isinstance(attr, int):
1182
1177
  return attr
@@ -1184,17 +1179,17 @@ class Serializer(object):
1184
1179
  if not attr.tzinfo:
1185
1180
  _LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
1186
1181
  return int(calendar.timegm(attr.utctimetuple()))
1187
- except AttributeError:
1188
- raise TypeError("Unix time object must be valid Datetime object.")
1182
+ except AttributeError as exc:
1183
+ raise TypeError("Unix time object must be valid Datetime object.") from exc
1189
1184
 
1190
1185
 
1191
- def rest_key_extractor(attr, attr_desc, data):
1186
+ def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
1192
1187
  key = attr_desc["key"]
1193
1188
  working_data = data
1194
1189
 
1195
1190
  while "." in key:
1196
1191
  # Need the cast, as for some reasons "split" is typed as list[str | Any]
1197
- dict_keys = cast(List[str], _FLATTEN.split(key))
1192
+ dict_keys = cast(list[str], _FLATTEN.split(key))
1198
1193
  if len(dict_keys) == 1:
1199
1194
  key = _decode_attribute_map_key(dict_keys[0])
1200
1195
  break
@@ -1209,7 +1204,9 @@ def rest_key_extractor(attr, attr_desc, data):
1209
1204
  return working_data.get(key)
1210
1205
 
1211
1206
 
1212
- def rest_key_case_insensitive_extractor(attr, attr_desc, data):
1207
+ def rest_key_case_insensitive_extractor( # pylint: disable=unused-argument, inconsistent-return-statements
1208
+ attr, attr_desc, data
1209
+ ):
1213
1210
  key = attr_desc["key"]
1214
1211
  working_data = data
1215
1212
 
@@ -1230,17 +1227,29 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
1230
1227
  return attribute_key_case_insensitive_extractor(key, None, working_data)
1231
1228
 
1232
1229
 
1233
- def last_rest_key_extractor(attr, attr_desc, data):
1234
- """Extract the attribute in "data" based on the last part of the JSON path key."""
1230
+ def last_rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
1231
+ """Extract the attribute in "data" based on the last part of the JSON path key.
1232
+
1233
+ :param str attr: The attribute to extract
1234
+ :param dict attr_desc: The attribute description
1235
+ :param dict data: The data to extract from
1236
+ :rtype: object
1237
+ :returns: The extracted attribute
1238
+ """
1235
1239
  key = attr_desc["key"]
1236
1240
  dict_keys = _FLATTEN.split(key)
1237
1241
  return attribute_key_extractor(dict_keys[-1], None, data)
1238
1242
 
1239
1243
 
1240
- def last_rest_key_case_insensitive_extractor(attr, attr_desc, data):
1244
+ def last_rest_key_case_insensitive_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
1241
1245
  """Extract the attribute in "data" based on the last part of the JSON path key.
1242
1246
 
1243
1247
  This is the case insensitive version of "last_rest_key_extractor"
1248
+ :param str attr: The attribute to extract
1249
+ :param dict attr_desc: The attribute description
1250
+ :param dict data: The data to extract from
1251
+ :rtype: object
1252
+ :returns: The extracted attribute
1244
1253
  """
1245
1254
  key = attr_desc["key"]
1246
1255
  dict_keys = _FLATTEN.split(key)
@@ -1277,7 +1286,7 @@ def _extract_name_from_internal_type(internal_type):
1277
1286
  return xml_name
1278
1287
 
1279
1288
 
1280
- def xml_key_extractor(attr, attr_desc, data):
1289
+ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument,too-many-return-statements
1281
1290
  if isinstance(data, dict):
1282
1291
  return None
1283
1292
 
@@ -1329,22 +1338,21 @@ def xml_key_extractor(attr, attr_desc, data):
1329
1338
  if is_iter_type:
1330
1339
  if is_wrapped:
1331
1340
  return None # is_wrapped no node, we want None
1332
- else:
1333
- return [] # not wrapped, assume empty list
1341
+ return [] # not wrapped, assume empty list
1334
1342
  return None # Assume it's not there, maybe an optional node.
1335
1343
 
1336
1344
  # If is_iter_type and not wrapped, return all found children
1337
1345
  if is_iter_type:
1338
1346
  if not is_wrapped:
1339
1347
  return children
1340
- else: # Iter and wrapped, should have found one node only (the wrap one)
1341
- if len(children) != 1:
1342
- raise DeserializationError(
1343
- "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
1344
- xml_name
1345
- )
1348
+ # 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
1346
1353
  )
1347
- return list(children[0]) # Might be empty list and that's ok.
1354
+ )
1355
+ return list(children[0]) # Might be empty list and that's ok.
1348
1356
 
1349
1357
  # Here it's not a itertype, we should have found one element only or empty
1350
1358
  if len(children) > 1:
@@ -1352,7 +1360,7 @@ def xml_key_extractor(attr, attr_desc, data):
1352
1360
  return children[0]
1353
1361
 
1354
1362
 
1355
- class Deserializer(object):
1363
+ class Deserializer:
1356
1364
  """Response object model deserializer.
1357
1365
 
1358
1366
  :param dict classes: Class type dictionary for deserializing complex types.
@@ -1361,9 +1369,9 @@ class Deserializer(object):
1361
1369
 
1362
1370
  basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
1363
1371
 
1364
- 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}]?")
1372
+ valid_date = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?")
1365
1373
 
1366
- def __init__(self, classes: Optional[Mapping[str, type]] = None):
1374
+ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
1367
1375
  self.deserialize_type = {
1368
1376
  "iso-8601": Deserializer.deserialize_iso,
1369
1377
  "rfc-1123": Deserializer.deserialize_rfc,
@@ -1383,7 +1391,7 @@ class Deserializer(object):
1383
1391
  "duration": (isodate.Duration, datetime.timedelta),
1384
1392
  "iso-8601": (datetime.datetime),
1385
1393
  }
1386
- self.dependencies: Dict[str, type] = dict(classes) if classes else {}
1394
+ self.dependencies: dict[str, type] = dict(classes) if classes else {}
1387
1395
  self.key_extractors = [rest_key_extractor, xml_key_extractor]
1388
1396
  # Additional properties only works if the "rest_key_extractor" is used to
1389
1397
  # extract the keys. Making it to work whatever the key extractor is too much
@@ -1399,27 +1407,29 @@ class Deserializer(object):
1399
1407
  :param str target_obj: Target data type to deserialize to.
1400
1408
  :param requests.Response response_data: REST response object.
1401
1409
  :param str content_type: Swagger "produces" if available.
1402
- :raises: DeserializationError if deserialization fails.
1410
+ :raises DeserializationError: if deserialization fails.
1403
1411
  :return: Deserialized object.
1412
+ :rtype: object
1404
1413
  """
1405
1414
  data = self._unpack_content(response_data, content_type)
1406
1415
  return self._deserialize(target_obj, data)
1407
1416
 
1408
- def _deserialize(self, target_obj, data):
1417
+ def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return-statements
1409
1418
  """Call the deserializer on a model.
1410
1419
 
1411
1420
  Data needs to be already deserialized as JSON or XML ElementTree
1412
1421
 
1413
1422
  :param str target_obj: Target data type to deserialize to.
1414
1423
  :param object data: Object to deserialize.
1415
- :raises: DeserializationError if deserialization fails.
1424
+ :raises DeserializationError: if deserialization fails.
1416
1425
  :return: Deserialized object.
1426
+ :rtype: object
1417
1427
  """
1418
1428
  # This is already a model, go recursive just in case
1419
1429
  if hasattr(data, "_attribute_map"):
1420
1430
  constants = [name for name, config in getattr(data, "_validation", {}).items() if config.get("constant")]
1421
1431
  try:
1422
- for attr, mapconfig in data._attribute_map.items():
1432
+ for attr, mapconfig in data._attribute_map.items(): # pylint: disable=protected-access
1423
1433
  if attr in constants:
1424
1434
  continue
1425
1435
  value = getattr(data, attr)
@@ -1438,13 +1448,13 @@ class Deserializer(object):
1438
1448
 
1439
1449
  if isinstance(response, str):
1440
1450
  return self.deserialize_data(data, response)
1441
- elif isinstance(response, type) and issubclass(response, Enum):
1451
+ if isinstance(response, type) and issubclass(response, Enum):
1442
1452
  return self.deserialize_enum(data, response)
1443
1453
 
1444
- if data is None:
1454
+ if data is None or data is CoreNull:
1445
1455
  return data
1446
1456
  try:
1447
- attributes = response._attribute_map # type: ignore
1457
+ attributes = response._attribute_map # type: ignore # pylint: disable=protected-access
1448
1458
  d_attrs = {}
1449
1459
  for attr, attr_desc in attributes.items():
1450
1460
  # Check empty string. If it's not empty, someone has a real "additionalProperties"...
@@ -1474,9 +1484,8 @@ class Deserializer(object):
1474
1484
  except (AttributeError, TypeError, KeyError) as err:
1475
1485
  msg = "Unable to deserialize to object: " + class_name # type: ignore
1476
1486
  raise DeserializationError(msg) from err
1477
- else:
1478
- additional_properties = self._build_additional_properties(attributes, data)
1479
- return self._instantiate_model(response, d_attrs, additional_properties)
1487
+ additional_properties = self._build_additional_properties(attributes, data)
1488
+ return self._instantiate_model(response, d_attrs, additional_properties)
1480
1489
 
1481
1490
  def _build_additional_properties(self, attribute_map, data):
1482
1491
  if not self.additional_properties_detection:
@@ -1503,6 +1512,8 @@ class Deserializer(object):
1503
1512
 
1504
1513
  :param str target: The target object type to deserialize to.
1505
1514
  :param str/dict data: The response data to deserialize.
1515
+ :return: The classified target object and its class name.
1516
+ :rtype: tuple
1506
1517
  """
1507
1518
  if target is None:
1508
1519
  return None, None
@@ -1514,7 +1525,7 @@ class Deserializer(object):
1514
1525
  return target, target
1515
1526
 
1516
1527
  try:
1517
- target = target._classify(data, self.dependencies) # type: ignore
1528
+ target = target._classify(data, self.dependencies) # type: ignore # pylint: disable=protected-access
1518
1529
  except AttributeError:
1519
1530
  pass # Target is not a Model, no classify
1520
1531
  return target, target.__class__.__name__ # type: ignore
@@ -1529,10 +1540,12 @@ class Deserializer(object):
1529
1540
  :param str target_obj: The target object type to deserialize to.
1530
1541
  :param str/dict data: The response data to deserialize.
1531
1542
  :param str content_type: Swagger "produces" if available.
1543
+ :return: Deserialized object.
1544
+ :rtype: object
1532
1545
  """
1533
1546
  try:
1534
1547
  return self(target_obj, data, content_type=content_type)
1535
- except:
1548
+ except: # pylint: disable=bare-except
1536
1549
  _LOGGER.debug(
1537
1550
  "Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True
1538
1551
  )
@@ -1550,10 +1563,12 @@ class Deserializer(object):
1550
1563
 
1551
1564
  If raw_data is something else, bypass all logic and return it directly.
1552
1565
 
1553
- :param raw_data: Data to be processed.
1554
- :param content_type: How to parse if raw_data is a string/bytes.
1566
+ :param obj raw_data: Data to be processed.
1567
+ :param str content_type: How to parse if raw_data is a string/bytes.
1555
1568
  :raises JSONDecodeError: If JSON is requested and parsing is impossible.
1556
1569
  :raises UnicodeDecodeError: If bytes is not UTF8
1570
+ :rtype: object
1571
+ :return: Unpacked content.
1557
1572
  """
1558
1573
  # Assume this is enough to detect a Pipeline Response without importing it
1559
1574
  context = getattr(raw_data, "context", {})
@@ -1577,24 +1592,35 @@ class Deserializer(object):
1577
1592
  def _instantiate_model(self, response, attrs, additional_properties=None):
1578
1593
  """Instantiate a response model passing in deserialized args.
1579
1594
 
1580
- :param response: The response model class.
1581
- :param d_attrs: The deserialized response attributes.
1595
+ :param Response response: The response model class.
1596
+ :param dict attrs: The deserialized response attributes.
1597
+ :param dict additional_properties: Additional properties to be set.
1598
+ :rtype: Response
1599
+ :return: The instantiated response model.
1582
1600
  """
1583
1601
  if callable(response):
1584
1602
  subtype = getattr(response, "_subtype_map", {})
1585
1603
  try:
1586
- readonly = [k for k, v in response._validation.items() if v.get("readonly")]
1587
- const = [k for k, v in response._validation.items() if v.get("constant")]
1604
+ readonly = [
1605
+ k
1606
+ for k, v in response._validation.items() # pylint: disable=protected-access # type: ignore
1607
+ if v.get("readonly")
1608
+ ]
1609
+ const = [
1610
+ k
1611
+ for k, v in response._validation.items() # pylint: disable=protected-access # type: ignore
1612
+ if v.get("constant")
1613
+ ]
1588
1614
  kwargs = {k: v for k, v in attrs.items() if k not in subtype and k not in readonly + const}
1589
1615
  response_obj = response(**kwargs)
1590
1616
  for attr in readonly:
1591
1617
  setattr(response_obj, attr, attrs.get(attr))
1592
1618
  if additional_properties:
1593
- response_obj.additional_properties = additional_properties
1619
+ response_obj.additional_properties = additional_properties # type: ignore
1594
1620
  return response_obj
1595
1621
  except TypeError as err:
1596
1622
  msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
1597
- raise DeserializationError(msg + str(err))
1623
+ raise DeserializationError(msg + str(err)) from err
1598
1624
  else:
1599
1625
  try:
1600
1626
  for attr, value in attrs.items():
@@ -1603,15 +1629,16 @@ class Deserializer(object):
1603
1629
  except Exception as exp:
1604
1630
  msg = "Unable to populate response model. "
1605
1631
  msg += "Type: {}, Error: {}".format(type(response), exp)
1606
- raise DeserializationError(msg)
1632
+ raise DeserializationError(msg) from exp
1607
1633
 
1608
- def deserialize_data(self, data, data_type):
1634
+ def deserialize_data(self, data, data_type): # pylint: disable=too-many-return-statements
1609
1635
  """Process data for deserialization according to data type.
1610
1636
 
1611
1637
  :param str data: The response string to be deserialized.
1612
1638
  :param str data_type: The type to deserialize to.
1613
- :raises: DeserializationError if deserialization fails.
1639
+ :raises DeserializationError: if deserialization fails.
1614
1640
  :return: Deserialized object.
1641
+ :rtype: object
1615
1642
  """
1616
1643
  if data is None:
1617
1644
  return data
@@ -1625,7 +1652,11 @@ class Deserializer(object):
1625
1652
  if isinstance(data, self.deserialize_expected_types.get(data_type, tuple())):
1626
1653
  return data
1627
1654
 
1628
- is_a_text_parsing_type = lambda x: x not in ["object", "[]", r"{}"]
1655
+ is_a_text_parsing_type = lambda x: x not in [ # pylint: disable=unnecessary-lambda-assignment
1656
+ "object",
1657
+ "[]",
1658
+ r"{}",
1659
+ ]
1629
1660
  if isinstance(data, ET.Element) and is_a_text_parsing_type(data_type) and not data.text:
1630
1661
  return None
1631
1662
  data_val = self.deserialize_type[data_type](data)
@@ -1645,14 +1676,14 @@ class Deserializer(object):
1645
1676
  msg = "Unable to deserialize response data."
1646
1677
  msg += " Data: {}, {}".format(data, data_type)
1647
1678
  raise DeserializationError(msg) from err
1648
- else:
1649
- return self._deserialize(obj_type, data)
1679
+ return self._deserialize(obj_type, data)
1650
1680
 
1651
1681
  def deserialize_iter(self, attr, iter_type):
1652
1682
  """Deserialize an iterable.
1653
1683
 
1654
1684
  :param list attr: Iterable to be deserialized.
1655
1685
  :param str iter_type: The type of object in the iterable.
1686
+ :return: Deserialized iterable.
1656
1687
  :rtype: list
1657
1688
  """
1658
1689
  if attr is None:
@@ -1669,6 +1700,7 @@ class Deserializer(object):
1669
1700
  :param dict/list attr: Dictionary to be deserialized. Also accepts
1670
1701
  a list of key, value pairs.
1671
1702
  :param str dict_type: The object type of the items in the dictionary.
1703
+ :return: Deserialized dictionary.
1672
1704
  :rtype: dict
1673
1705
  """
1674
1706
  if isinstance(attr, list):
@@ -1679,13 +1711,14 @@ class Deserializer(object):
1679
1711
  attr = {el.tag: el.text for el in attr}
1680
1712
  return {k: self.deserialize_data(v, dict_type) for k, v in attr.items()}
1681
1713
 
1682
- def deserialize_object(self, attr, **kwargs):
1714
+ def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return-statements
1683
1715
  """Deserialize a generic object.
1684
1716
  This will be handled as a dictionary.
1685
1717
 
1686
1718
  :param dict attr: Dictionary to be deserialized.
1719
+ :return: Deserialized object.
1687
1720
  :rtype: dict
1688
- :raises: TypeError if non-builtin datatype encountered.
1721
+ :raises TypeError: if non-builtin datatype encountered.
1689
1722
  """
1690
1723
  if attr is None:
1691
1724
  return None
@@ -1718,11 +1751,10 @@ class Deserializer(object):
1718
1751
  pass
1719
1752
  return deserialized
1720
1753
 
1721
- else:
1722
- error = "Cannot deserialize generic object with type: "
1723
- raise TypeError(error + str(obj_type))
1754
+ error = "Cannot deserialize generic object with type: "
1755
+ raise TypeError(error + str(obj_type))
1724
1756
 
1725
- def deserialize_basic(self, attr, data_type):
1757
+ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return-statements
1726
1758
  """Deserialize basic builtin data type from string.
1727
1759
  Will attempt to convert to str, int, float and bool.
1728
1760
  This function will also accept '1', '0', 'true' and 'false' as
@@ -1730,8 +1762,9 @@ class Deserializer(object):
1730
1762
 
1731
1763
  :param str attr: response string to be deserialized.
1732
1764
  :param str data_type: deserialization data type.
1765
+ :return: Deserialized basic type.
1733
1766
  :rtype: str, int, float or bool
1734
- :raises: TypeError if string format is not valid.
1767
+ :raises TypeError: if string format is not valid or data_type is not one of str, int, float, bool.
1735
1768
  """
1736
1769
  # If we're here, data is supposed to be a basic type.
1737
1770
  # If it's still an XML node, take the text
@@ -1741,24 +1774,27 @@ class Deserializer(object):
1741
1774
  if data_type == "str":
1742
1775
  # None or '', node <a/> is empty string.
1743
1776
  return ""
1744
- else:
1745
- # None or '', node <a/> with a strong type is None.
1746
- # Don't try to model "empty bool" or "empty int"
1747
- return None
1777
+ # None or '', node <a/> with a strong type is None.
1778
+ # Don't try to model "empty bool" or "empty int"
1779
+ return None
1748
1780
 
1749
1781
  if data_type == "bool":
1750
1782
  if attr in [True, False, 1, 0]:
1751
1783
  return bool(attr)
1752
- elif isinstance(attr, str):
1784
+ if isinstance(attr, str):
1753
1785
  if attr.lower() in ["true", "1"]:
1754
1786
  return True
1755
- elif attr.lower() in ["false", "0"]:
1787
+ if attr.lower() in ["false", "0"]:
1756
1788
  return False
1757
1789
  raise TypeError("Invalid boolean value: {}".format(attr))
1758
1790
 
1759
1791
  if data_type == "str":
1760
1792
  return self.deserialize_unicode(attr)
1761
- return eval(data_type)(attr) # nosec
1793
+ if data_type == "int":
1794
+ return int(attr)
1795
+ if data_type == "float":
1796
+ return float(attr)
1797
+ raise TypeError("Unknown basic data type: {}".format(data_type))
1762
1798
 
1763
1799
  @staticmethod
1764
1800
  def deserialize_unicode(data):
@@ -1766,6 +1802,7 @@ class Deserializer(object):
1766
1802
  as a string.
1767
1803
 
1768
1804
  :param str data: response string to be deserialized.
1805
+ :return: Deserialized string.
1769
1806
  :rtype: str or unicode
1770
1807
  """
1771
1808
  # We might be here because we have an enum modeled as string,
@@ -1779,8 +1816,7 @@ class Deserializer(object):
1779
1816
  return data
1780
1817
  except NameError:
1781
1818
  return str(data)
1782
- else:
1783
- return str(data)
1819
+ return str(data)
1784
1820
 
1785
1821
  @staticmethod
1786
1822
  def deserialize_enum(data, enum_obj):
@@ -1792,6 +1828,7 @@ class Deserializer(object):
1792
1828
  :param str data: Response string to be deserialized. If this value is
1793
1829
  None or invalid it will be returned as-is.
1794
1830
  :param Enum enum_obj: Enum object to deserialize to.
1831
+ :return: Deserialized enum object.
1795
1832
  :rtype: Enum
1796
1833
  """
1797
1834
  if isinstance(data, enum_obj) or data is None:
@@ -1802,9 +1839,9 @@ class Deserializer(object):
1802
1839
  # Workaround. We might consider remove it in the future.
1803
1840
  try:
1804
1841
  return list(enum_obj.__members__.values())[data]
1805
- except IndexError:
1842
+ except IndexError as exc:
1806
1843
  error = "{!r} is not a valid index for enum {!r}"
1807
- raise DeserializationError(error.format(data, enum_obj))
1844
+ raise DeserializationError(error.format(data, enum_obj)) from exc
1808
1845
  try:
1809
1846
  return enum_obj(str(data))
1810
1847
  except ValueError:
@@ -1820,8 +1857,9 @@ class Deserializer(object):
1820
1857
  """Deserialize string into bytearray.
1821
1858
 
1822
1859
  :param str attr: response string to be deserialized.
1860
+ :return: Deserialized bytearray
1823
1861
  :rtype: bytearray
1824
- :raises: TypeError if string format invalid.
1862
+ :raises TypeError: if string format invalid.
1825
1863
  """
1826
1864
  if isinstance(attr, ET.Element):
1827
1865
  attr = attr.text
@@ -1832,8 +1870,9 @@ class Deserializer(object):
1832
1870
  """Deserialize base64 encoded string into string.
1833
1871
 
1834
1872
  :param str attr: response string to be deserialized.
1873
+ :return: Deserialized base64 string
1835
1874
  :rtype: bytearray
1836
- :raises: TypeError if string format invalid.
1875
+ :raises TypeError: if string format invalid.
1837
1876
  """
1838
1877
  if isinstance(attr, ET.Element):
1839
1878
  attr = attr.text
@@ -1847,8 +1886,9 @@ class Deserializer(object):
1847
1886
  """Deserialize string into Decimal object.
1848
1887
 
1849
1888
  :param str attr: response string to be deserialized.
1850
- :rtype: Decimal
1851
- :raises: DeserializationError if string format invalid.
1889
+ :return: Deserialized decimal
1890
+ :raises DeserializationError: if string format invalid.
1891
+ :rtype: decimal
1852
1892
  """
1853
1893
  if isinstance(attr, ET.Element):
1854
1894
  attr = attr.text
@@ -1863,8 +1903,9 @@ class Deserializer(object):
1863
1903
  """Deserialize string into long (Py2) or int (Py3).
1864
1904
 
1865
1905
  :param str attr: response string to be deserialized.
1906
+ :return: Deserialized int
1866
1907
  :rtype: long or int
1867
- :raises: ValueError if string format invalid.
1908
+ :raises ValueError: if string format invalid.
1868
1909
  """
1869
1910
  if isinstance(attr, ET.Element):
1870
1911
  attr = attr.text
@@ -1875,8 +1916,9 @@ class Deserializer(object):
1875
1916
  """Deserialize ISO-8601 formatted string into TimeDelta object.
1876
1917
 
1877
1918
  :param str attr: response string to be deserialized.
1919
+ :return: Deserialized duration
1878
1920
  :rtype: TimeDelta
1879
- :raises: DeserializationError if string format invalid.
1921
+ :raises DeserializationError: if string format invalid.
1880
1922
  """
1881
1923
  if isinstance(attr, ET.Element):
1882
1924
  attr = attr.text
@@ -1885,16 +1927,16 @@ class Deserializer(object):
1885
1927
  except (ValueError, OverflowError, AttributeError) as err:
1886
1928
  msg = "Cannot deserialize duration object."
1887
1929
  raise DeserializationError(msg) from err
1888
- else:
1889
- return duration
1930
+ return duration
1890
1931
 
1891
1932
  @staticmethod
1892
1933
  def deserialize_date(attr):
1893
1934
  """Deserialize ISO-8601 formatted string into Date object.
1894
1935
 
1895
1936
  :param str attr: response string to be deserialized.
1937
+ :return: Deserialized date
1896
1938
  :rtype: Date
1897
- :raises: DeserializationError if string format invalid.
1939
+ :raises DeserializationError: if string format invalid.
1898
1940
  """
1899
1941
  if isinstance(attr, ET.Element):
1900
1942
  attr = attr.text
@@ -1908,8 +1950,9 @@ class Deserializer(object):
1908
1950
  """Deserialize ISO-8601 formatted string into time object.
1909
1951
 
1910
1952
  :param str attr: response string to be deserialized.
1953
+ :return: Deserialized time
1911
1954
  :rtype: datetime.time
1912
- :raises: DeserializationError if string format invalid.
1955
+ :raises DeserializationError: if string format invalid.
1913
1956
  """
1914
1957
  if isinstance(attr, ET.Element):
1915
1958
  attr = attr.text
@@ -1922,31 +1965,32 @@ class Deserializer(object):
1922
1965
  """Deserialize RFC-1123 formatted string into Datetime object.
1923
1966
 
1924
1967
  :param str attr: response string to be deserialized.
1968
+ :return: Deserialized RFC datetime
1925
1969
  :rtype: Datetime
1926
- :raises: DeserializationError if string format invalid.
1970
+ :raises DeserializationError: if string format invalid.
1927
1971
  """
1928
1972
  if isinstance(attr, ET.Element):
1929
1973
  attr = attr.text
1930
1974
  try:
1931
1975
  parsed_date = email.utils.parsedate_tz(attr) # type: ignore
1932
1976
  date_obj = datetime.datetime(
1933
- *parsed_date[:6], tzinfo=_FixedOffset(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60))
1977
+ *parsed_date[:6], tzinfo=datetime.timezone(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60))
1934
1978
  )
1935
1979
  if not date_obj.tzinfo:
1936
1980
  date_obj = date_obj.astimezone(tz=TZ_UTC)
1937
1981
  except ValueError as err:
1938
1982
  msg = "Cannot deserialize to rfc datetime object."
1939
1983
  raise DeserializationError(msg) from err
1940
- else:
1941
- return date_obj
1984
+ return date_obj
1942
1985
 
1943
1986
  @staticmethod
1944
1987
  def deserialize_iso(attr):
1945
1988
  """Deserialize ISO-8601 formatted string into Datetime object.
1946
1989
 
1947
1990
  :param str attr: response string to be deserialized.
1991
+ :return: Deserialized ISO datetime
1948
1992
  :rtype: Datetime
1949
- :raises: DeserializationError if string format invalid.
1993
+ :raises DeserializationError: if string format invalid.
1950
1994
  """
1951
1995
  if isinstance(attr, ET.Element):
1952
1996
  attr = attr.text
@@ -1974,8 +2018,7 @@ class Deserializer(object):
1974
2018
  except (ValueError, OverflowError, AttributeError) as err:
1975
2019
  msg = "Cannot deserialize datetime object."
1976
2020
  raise DeserializationError(msg) from err
1977
- else:
1978
- return date_obj
2021
+ return date_obj
1979
2022
 
1980
2023
  @staticmethod
1981
2024
  def deserialize_unix(attr):
@@ -1983,8 +2026,9 @@ class Deserializer(object):
1983
2026
  This is represented as seconds.
1984
2027
 
1985
2028
  :param int attr: Object to be serialized.
2029
+ :return: Deserialized datetime
1986
2030
  :rtype: Datetime
1987
- :raises: DeserializationError if format invalid
2031
+ :raises DeserializationError: if format invalid
1988
2032
  """
1989
2033
  if isinstance(attr, ET.Element):
1990
2034
  attr = int(attr.text) # type: ignore
@@ -1994,5 +2038,4 @@ class Deserializer(object):
1994
2038
  except ValueError as err:
1995
2039
  msg = "Cannot deserialize to unix datetime object."
1996
2040
  raise DeserializationError(msg) from err
1997
- else:
1998
- return date_obj
2041
+ return date_obj