@autorest/python 6.2.6 → 6.2.8

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 (33) hide show
  1. package/autorest/black/__init__.py +3 -2
  2. package/autorest/codegen/__init__.py +1 -1
  3. package/autorest/codegen/models/base.py +9 -1
  4. package/autorest/codegen/models/client.py +4 -2
  5. package/autorest/codegen/models/operation.py +6 -6
  6. package/autorest/codegen/models/operation_group.py +0 -6
  7. package/autorest/codegen/models/primitive_types.py +50 -0
  8. package/autorest/codegen/serializers/__init__.py +17 -8
  9. package/autorest/codegen/serializers/builder_serializer.py +61 -24
  10. package/autorest/codegen/serializers/client_serializer.py +4 -3
  11. package/autorest/codegen/serializers/metadata_serializer.py +7 -1
  12. package/autorest/codegen/serializers/model_serializer.py +8 -12
  13. package/autorest/codegen/serializers/operation_groups_serializer.py +1 -0
  14. package/autorest/codegen/serializers/parameter_serializer.py +3 -3
  15. package/autorest/codegen/serializers/patch_serializer.py +2 -4
  16. package/autorest/codegen/serializers/sample_serializer.py +23 -14
  17. package/autorest/codegen/serializers/utils.py +6 -0
  18. package/autorest/codegen/templates/client.py.jinja2 +3 -12
  19. package/autorest/codegen/templates/config.py.jinja2 +2 -5
  20. package/autorest/codegen/templates/keywords.jinja2 +2 -2
  21. package/autorest/codegen/templates/metadata.json.jinja2 +2 -2
  22. package/autorest/codegen/templates/model_base.py.jinja2 +2 -4
  23. package/autorest/codegen/templates/model_dpg.py.jinja2 +1 -1
  24. package/autorest/codegen/templates/request_builder.py.jinja2 +1 -1
  25. package/autorest/codegen/templates/serialization.py.jinja2 +286 -325
  26. package/autorest/jsonrpc/stdstream.py +1 -1
  27. package/autorest/m2r/__init__.py +2 -2
  28. package/autorest/multiapi/models/imports.py +13 -5
  29. package/autorest/multiapi/serializers/import_serializer.py +1 -1
  30. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +2 -8
  31. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +1 -1
  32. package/autorest/postprocess/__init__.py +5 -4
  33. package/package.json +1 -1
@@ -25,6 +25,7 @@
25
25
  # --------------------------------------------------------------------------
26
26
 
27
27
  # pylint: skip-file
28
+ # pyright: reportUnnecessaryTypeIgnoreComment=false
28
29
 
29
30
  from base64 import b64decode, b64encode
30
31
  import calendar
@@ -37,34 +38,33 @@ import logging
37
38
  import re
38
39
  import sys
39
40
  import codecs
41
+ from typing import Optional, Union, AnyStr, IO, Mapping
42
+
40
43
  try:
41
44
  from urllib import quote # type: ignore
42
45
  except ImportError:
43
- from urllib.parse import quote # type: ignore
46
+ from urllib.parse import quote
44
47
  import xml.etree.ElementTree as ET
45
48
 
46
- import isodate
49
+ import isodate # type: ignore
47
50
 
48
- from typing import Dict, Any, cast, TYPE_CHECKING
51
+ from typing import Dict, Any, cast
49
52
 
50
53
  from azure.core.exceptions import DeserializationError, SerializationError, raise_with_traceback
51
54
 
52
- _BOM = codecs.BOM_UTF8.decode(encoding='utf-8')
55
+ _BOM = codecs.BOM_UTF8.decode(encoding="utf-8")
53
56
 
54
- if TYPE_CHECKING:
55
- from typing import Optional, Union, AnyStr, IO, Mapping
56
57
 
57
58
  class RawDeserializer:
58
59
 
59
60
  # Accept "text" because we're open minded people...
60
- JSON_REGEXP = re.compile(r'^(application|text)/([a-z+.]+\+)?json$')
61
+ JSON_REGEXP = re.compile(r"^(application|text)/([a-z+.]+\+)?json$")
61
62
 
62
63
  # Name used in context
63
64
  CONTEXT_NAME = "deserialized_data"
64
65
 
65
66
  @classmethod
66
- def deserialize_from_text(cls, data, content_type=None):
67
- # type: (Optional[Union[AnyStr, IO]], Optional[str]) -> Any
67
+ def deserialize_from_text(cls, data: Optional[Union[AnyStr, IO]], content_type: Optional[str] = None) -> Any:
68
68
  """Decode data according to content-type.
69
69
 
70
70
  Accept a stream of data as well, but will be load at once in memory for now.
@@ -75,12 +75,12 @@ class RawDeserializer:
75
75
  :type data: str or bytes or IO
76
76
  :param str content_type: The content type.
77
77
  """
78
- if hasattr(data, 'read'):
78
+ if hasattr(data, "read"):
79
79
  # Assume a stream
80
80
  data = cast(IO, data).read()
81
81
 
82
82
  if isinstance(data, bytes):
83
- data_as_str = data.decode(encoding='utf-8-sig')
83
+ data_as_str = data.decode(encoding="utf-8-sig")
84
84
  else:
85
85
  # Explain to mypy the correct type.
86
86
  data_as_str = cast(str, data)
@@ -116,7 +116,8 @@ class RawDeserializer:
116
116
  try:
117
117
  return True, json.loads(data)
118
118
  except ValueError:
119
- return False, None # Don't care about this one
119
+ return False, None # Don't care about this one
120
+
120
121
  success, json_result = _json_attemp(data)
121
122
  if success:
122
123
  return json_result
@@ -129,8 +130,7 @@ class RawDeserializer:
129
130
  raise DeserializationError("Cannot deserialize content-type: {}".format(content_type))
130
131
 
131
132
  @classmethod
132
- def deserialize_from_http_generics(cls, body_bytes, headers):
133
- # type: (Optional[Union[AnyStr, IO]], Mapping) -> Any
133
+ def deserialize_from_http_generics(cls, body_bytes: Optional[Union[AnyStr, IO]], headers: Mapping) -> Any:
134
134
  """Deserialize from HTTP response.
135
135
 
136
136
  Use bytes and headers to NOT use any requests/aiohttp or whatever
@@ -139,8 +139,8 @@ class RawDeserializer:
139
139
  """
140
140
  # Try to use content-type from headers if available
141
141
  content_type = None
142
- if 'content-type' in headers:
143
- content_type = headers['content-type'].split(";")[0].strip().lower()
142
+ if "content-type" in headers:
143
+ content_type = headers["content-type"].split(";")[0].strip().lower()
144
144
  # Ouch, this server did not declare what it sent...
145
145
  # Let's guess it's JSON...
146
146
  # Also, since Autorest was considering that an empty body was a valid JSON,
@@ -152,20 +152,22 @@ class RawDeserializer:
152
152
  return cls.deserialize_from_text(body_bytes, content_type)
153
153
  return None
154
154
 
155
+
155
156
  try:
156
157
  basestring # type: ignore
157
158
  unicode_str = unicode # type: ignore
158
159
  except NameError:
159
- basestring = str # type: ignore
160
- unicode_str = str # type: ignore
160
+ basestring = str
161
+ unicode_str = str
161
162
 
162
163
  _LOGGER = logging.getLogger(__name__)
163
164
 
164
165
  try:
165
- _long_type = long # type: ignore
166
+ _long_type = long # type: ignore
166
167
  except NameError:
167
168
  _long_type = int
168
169
 
170
+
169
171
  class UTC(datetime.tzinfo):
170
172
  """Time Zone info for handling UTC"""
171
173
 
@@ -181,9 +183,11 @@ class UTC(datetime.tzinfo):
181
183
  """No daylight saving for UTC."""
182
184
  return datetime.timedelta(hours=1)
183
185
 
186
+
184
187
  try:
185
- from datetime import timezone as _FixedOffset
188
+ from datetime import timezone as _FixedOffset # type: ignore
186
189
  except ImportError: # Python 2.7
190
+
187
191
  class _FixedOffset(datetime.tzinfo): # type: ignore
188
192
  """Fixed offset in minutes east from UTC.
189
193
  Copy/pasted from Python doc
@@ -197,7 +201,7 @@ except ImportError: # Python 2.7
197
201
  return self.__offset
198
202
 
199
203
  def tzname(self, dt):
200
- return str(self.__offset.total_seconds()/3600)
204
+ return str(self.__offset.total_seconds() / 3600)
201
205
 
202
206
  def __repr__(self):
203
207
  return "<FixedOffset {}>".format(self.tzname(None))
@@ -208,14 +212,17 @@ except ImportError: # Python 2.7
208
212
  def __getinitargs__(self):
209
213
  return (self.__offset,)
210
214
 
215
+
211
216
  try:
212
217
  from datetime import timezone
213
- TZ_UTC = timezone.utc # type: ignore
218
+
219
+ TZ_UTC = timezone.utc
214
220
  except ImportError:
215
221
  TZ_UTC = UTC() # type: ignore
216
222
 
217
223
  _FLATTEN = re.compile(r"(?<!\\)\.")
218
224
 
225
+
219
226
  def attribute_transformer(key, attr_desc, value):
220
227
  """A key transformer that returns the Python attribute.
221
228
 
@@ -226,6 +233,7 @@ def attribute_transformer(key, attr_desc, value):
226
233
  """
227
234
  return (key, value)
228
235
 
236
+
229
237
  def full_restapi_key_transformer(key, attr_desc, value):
230
238
  """A key transformer that returns the full RestAPI key path.
231
239
 
@@ -234,9 +242,10 @@ def full_restapi_key_transformer(key, attr_desc, value):
234
242
  :param object value: The value
235
243
  :returns: A list of keys using RestAPI syntax.
236
244
  """
237
- keys = _FLATTEN.split(attr_desc['key'])
245
+ keys = _FLATTEN.split(attr_desc["key"])
238
246
  return ([_decode_attribute_map_key(k) for k in keys], value)
239
247
 
248
+
240
249
  def last_restapi_key_transformer(key, attr_desc, value):
241
250
  """A key transformer that returns the last RestAPI key.
242
251
 
@@ -248,23 +257,25 @@ def last_restapi_key_transformer(key, attr_desc, value):
248
257
  key, value = full_restapi_key_transformer(key, attr_desc, value)
249
258
  return (key[-1], value)
250
259
 
260
+
251
261
  def _create_xml_node(tag, prefix=None, ns=None):
252
262
  """Create a XML node."""
253
263
  if prefix and ns:
254
264
  ET.register_namespace(prefix, ns)
255
265
  if ns:
256
- return ET.Element("{"+ns+"}"+tag)
266
+ return ET.Element("{" + ns + "}" + tag)
257
267
  else:
258
268
  return ET.Element(tag)
259
269
 
270
+
260
271
  class Model(object):
261
272
  """Mixin for all client request body/response body models to support
262
273
  serialization and deserialization.
263
274
  """
264
275
 
265
- _subtype_map = {} # type: Dict[str, Dict[str, Any]]
266
- _attribute_map = {} # type: Dict[str, Dict[str, Any]]
267
- _validation = {} # type: Dict[str, Dict[str, Any]]
276
+ _subtype_map: Dict[str, Dict[str, Any]] = {}
277
+ _attribute_map: Dict[str, Dict[str, Any]] = {}
278
+ _validation: Dict[str, Dict[str, Any]] = {}
268
279
 
269
280
  def __init__(self, **kwargs):
270
281
  self.additional_properties = {}
@@ -291,30 +302,25 @@ class Model(object):
291
302
 
292
303
  @classmethod
293
304
  def enable_additional_properties_sending(cls):
294
- cls._attribute_map['additional_properties'] = {'key': '', 'type': '{object}'}
305
+ cls._attribute_map["additional_properties"] = {"key": "", "type": "{object}"}
295
306
 
296
307
  @classmethod
297
308
  def is_xml_model(cls):
298
309
  try:
299
- cls._xml_map
310
+ cls._xml_map # type: ignore
300
311
  except AttributeError:
301
312
  return False
302
313
  return True
303
314
 
304
315
  @classmethod
305
316
  def _create_xml_node(cls):
306
- """Create XML node.
307
- """
317
+ """Create XML node."""
308
318
  try:
309
- xml_map = cls._xml_map
319
+ xml_map = cls._xml_map # type: ignore
310
320
  except AttributeError:
311
321
  xml_map = {}
312
322
 
313
- return _create_xml_node(
314
- xml_map.get('name', cls.__name__),
315
- xml_map.get("prefix", None),
316
- xml_map.get("ns", None)
317
- )
323
+ return _create_xml_node(xml_map.get("name", cls.__name__), xml_map.get("prefix", None), xml_map.get("ns", None))
318
324
 
319
325
  def serialize(self, keep_readonly=False, **kwargs):
320
326
  """Return the JSON that would be sent to azure from this model.
@@ -367,7 +373,7 @@ class Model(object):
367
373
  @classmethod
368
374
  def _infer_class_models(cls):
369
375
  try:
370
- str_models = cls.__module__.rsplit('.', 1)[0]
376
+ str_models = cls.__module__.rsplit(".", 1)[0]
371
377
  models = sys.modules[str_models]
372
378
  client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
373
379
  if cls.__name__ not in client_models:
@@ -403,16 +409,20 @@ class Model(object):
403
409
  :raises: DeserializationError if something went wrong
404
410
  """
405
411
  deserializer = Deserializer(cls._infer_class_models())
406
- deserializer.key_extractors = [
407
- attribute_key_case_insensitive_extractor,
408
- rest_key_case_insensitive_extractor,
409
- last_rest_key_case_insensitive_extractor
410
- ] if key_extractors is None else key_extractors
412
+ deserializer.key_extractors = (
413
+ [
414
+ attribute_key_case_insensitive_extractor,
415
+ rest_key_case_insensitive_extractor,
416
+ last_rest_key_case_insensitive_extractor,
417
+ ]
418
+ if key_extractors is None
419
+ else key_extractors
420
+ )
411
421
  return deserializer(cls.__name__, data, content_type=content_type)
412
422
 
413
423
  @classmethod
414
424
  def _flatten_subtype(cls, key, objects):
415
- if '_subtype_map' not in cls.__dict__:
425
+ if "_subtype_map" not in cls.__dict__:
416
426
  return {}
417
427
  result = dict(cls._subtype_map[key])
418
428
  for valuetype in cls._subtype_map[key].values():
@@ -425,18 +435,14 @@ class Model(object):
425
435
  We want to ignore any inherited _subtype_maps.
426
436
  Remove the polymorphic key from the initial data.
427
437
  """
428
- for subtype_key in cls.__dict__.get('_subtype_map', {}).keys():
438
+ for subtype_key in cls.__dict__.get("_subtype_map", {}).keys():
429
439
  subtype_value = None
430
440
 
431
441
  if not isinstance(response, ET.Element):
432
442
  rest_api_response_key = cls._get_rest_key_parts(subtype_key)[-1]
433
443
  subtype_value = response.pop(rest_api_response_key, None) or response.pop(subtype_key, None)
434
444
  else:
435
- subtype_value = xml_key_extractor(
436
- subtype_key,
437
- cls._attribute_map[subtype_key],
438
- response
439
- )
445
+ subtype_value = xml_key_extractor(subtype_key, cls._attribute_map[subtype_key], response)
440
446
  if subtype_value:
441
447
  # Try to match base class. Can be class name only
442
448
  # (bug to fix in Autorest to support x-ms-discriminator-name)
@@ -444,7 +450,7 @@ class Model(object):
444
450
  return cls
445
451
  flatten_mapping_type = cls._flatten_subtype(subtype_key, objects)
446
452
  try:
447
- return objects[flatten_mapping_type[subtype_value]]
453
+ return objects[flatten_mapping_type[subtype_value]] # type: ignore
448
454
  except KeyError:
449
455
  _LOGGER.warning(
450
456
  "Subtype value %s has no mapping, use base class %s.",
@@ -453,11 +459,7 @@ class Model(object):
453
459
  )
454
460
  break
455
461
  else:
456
- _LOGGER.warning(
457
- "Discriminator %s is absent or null, use base class %s.",
458
- subtype_key,
459
- cls.__name__
460
- )
462
+ _LOGGER.warning("Discriminator %s is absent or null, use base class %s.", subtype_key, cls.__name__)
461
463
  break
462
464
  return cls
463
465
 
@@ -468,29 +470,40 @@ class Model(object):
468
470
  :returns: A list of RestAPI part
469
471
  :rtype: list
470
472
  """
471
- rest_split_key = _FLATTEN.split(cls._attribute_map[attr_key]['key'])
473
+ rest_split_key = _FLATTEN.split(cls._attribute_map[attr_key]["key"])
472
474
  return [_decode_attribute_map_key(key_part) for key_part in rest_split_key]
473
475
 
474
476
 
475
477
  def _decode_attribute_map_key(key):
476
478
  """This decode a key in an _attribute_map to the actual key we want to look at
477
- inside the received data.
479
+ inside the received data.
478
480
 
479
- :param str key: A key string from the generated code
481
+ :param str key: A key string from the generated code
480
482
  """
481
- return key.replace('\\.', '.')
483
+ return key.replace("\\.", ".")
482
484
 
483
485
 
484
486
  class Serializer(object):
485
487
  """Request object model serializer."""
486
488
 
487
- basic_types = {str: 'str', int: 'int', bool: 'bool', float: 'float'}
488
-
489
- _xml_basic_types_serializers = {'bool': lambda x:str(x).lower()}
490
- days = {0: "Mon", 1: "Tue", 2: "Wed", 3: "Thu",
491
- 4: "Fri", 5: "Sat", 6: "Sun"}
492
- months = {1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun",
493
- 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Dec"}
489
+ basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
490
+
491
+ _xml_basic_types_serializers = {"bool": lambda x: str(x).lower()}
492
+ days = {0: "Mon", 1: "Tue", 2: "Wed", 3: "Thu", 4: "Fri", 5: "Sat", 6: "Sun"}
493
+ months = {
494
+ 1: "Jan",
495
+ 2: "Feb",
496
+ 3: "Mar",
497
+ 4: "Apr",
498
+ 5: "May",
499
+ 6: "Jun",
500
+ 7: "Jul",
501
+ 8: "Aug",
502
+ 9: "Sep",
503
+ 10: "Oct",
504
+ 11: "Nov",
505
+ 12: "Dec",
506
+ }
494
507
  validation = {
495
508
  "min_length": lambda x, y: len(x) < y,
496
509
  "max_length": lambda x, y: len(x) > y,
@@ -502,25 +515,25 @@ class Serializer(object):
502
515
  "max_items": lambda x, y: len(x) > y,
503
516
  "pattern": lambda x, y: not re.match(y, x, re.UNICODE),
504
517
  "unique": lambda x, y: len(x) != len(set(x)),
505
- "multiple": lambda x, y: x % y != 0
506
- }
518
+ "multiple": lambda x, y: x % y != 0,
519
+ }
507
520
 
508
521
  def __init__(self, classes=None):
509
522
  self.serialize_type = {
510
- 'iso-8601': Serializer.serialize_iso,
511
- 'rfc-1123': Serializer.serialize_rfc,
512
- 'unix-time': Serializer.serialize_unix,
513
- 'duration': Serializer.serialize_duration,
514
- 'date': Serializer.serialize_date,
515
- 'time': Serializer.serialize_time,
516
- 'decimal': Serializer.serialize_decimal,
517
- 'long': Serializer.serialize_long,
518
- 'bytearray': Serializer.serialize_bytearray,
519
- 'base64': Serializer.serialize_base64,
520
- 'object': self.serialize_object,
521
- '[]': self.serialize_iter,
522
- '{}': self.serialize_dict
523
- }
523
+ "iso-8601": Serializer.serialize_iso,
524
+ "rfc-1123": Serializer.serialize_rfc,
525
+ "unix-time": Serializer.serialize_unix,
526
+ "duration": Serializer.serialize_duration,
527
+ "date": Serializer.serialize_date,
528
+ "time": Serializer.serialize_time,
529
+ "decimal": Serializer.serialize_decimal,
530
+ "long": Serializer.serialize_long,
531
+ "bytearray": Serializer.serialize_bytearray,
532
+ "base64": Serializer.serialize_base64,
533
+ "object": self.serialize_object,
534
+ "[]": self.serialize_iter,
535
+ "{}": self.serialize_dict,
536
+ }
524
537
  self.dependencies = dict(classes) if classes else {}
525
538
  self.key_transformer = full_restapi_key_transformer
526
539
  self.client_side_validation = True
@@ -542,14 +555,12 @@ class Serializer(object):
542
555
  class_name = target_obj.__class__.__name__
543
556
 
544
557
  if data_type:
545
- return self.serialize_data(
546
- target_obj, data_type, **kwargs)
558
+ return self.serialize_data(target_obj, data_type, **kwargs)
547
559
 
548
560
  if not hasattr(target_obj, "_attribute_map"):
549
561
  data_type = type(target_obj).__name__
550
562
  if data_type in self.basic_types.values():
551
- return self.serialize_data(
552
- target_obj, data_type, **kwargs)
563
+ return self.serialize_data(target_obj, data_type, **kwargs)
553
564
 
554
565
  # Force "is_xml" kwargs if we detect a XML model
555
566
  try:
@@ -564,79 +575,72 @@ class Serializer(object):
564
575
  attributes = target_obj._attribute_map
565
576
  for attr, attr_desc in attributes.items():
566
577
  attr_name = attr
567
- if not keep_readonly and target_obj._validation.get(attr_name, {}).get('readonly', False):
578
+ if not keep_readonly and target_obj._validation.get(attr_name, {}).get("readonly", False):
568
579
  continue
569
580
 
570
- if attr_name == "additional_properties" and attr_desc["key"] == '':
581
+ if attr_name == "additional_properties" and attr_desc["key"] == "":
571
582
  if target_obj.additional_properties is not None:
572
583
  serialized.update(target_obj.additional_properties)
573
584
  continue
574
585
  try:
575
- ### Extract sub-data to serialize from model ###
586
+
576
587
  orig_attr = getattr(target_obj, attr)
577
588
  if is_xml_model_serialization:
578
- pass # Don't provide "transformer" for XML for now. Keep "orig_attr"
579
- else: # JSON
589
+ pass # Don't provide "transformer" for XML for now. Keep "orig_attr"
590
+ else: # JSON
580
591
  keys, orig_attr = key_transformer(attr, attr_desc.copy(), orig_attr)
581
592
  keys = keys if isinstance(keys, list) else [keys]
582
593
 
583
- ### Serialize this data ###
584
594
  kwargs["serialization_ctxt"] = attr_desc
585
- new_attr = self.serialize_data(orig_attr, attr_desc['type'], **kwargs)
595
+ new_attr = self.serialize_data(orig_attr, attr_desc["type"], **kwargs)
586
596
 
587
- ### Incorporate this data in the right place ###
588
597
  if is_xml_model_serialization:
589
- xml_desc = attr_desc.get('xml', {})
590
- xml_name = xml_desc.get('name', attr_desc['key'])
591
- xml_prefix = xml_desc.get('prefix', None)
592
- xml_ns = xml_desc.get('ns', None)
598
+ xml_desc = attr_desc.get("xml", {})
599
+ xml_name = xml_desc.get("name", attr_desc["key"])
600
+ xml_prefix = xml_desc.get("prefix", None)
601
+ xml_ns = xml_desc.get("ns", None)
593
602
  if xml_desc.get("attr", False):
594
603
  if xml_ns:
595
604
  ET.register_namespace(xml_prefix, xml_ns)
596
- xml_name = "{{{}}}{}".format(xml_ns, xml_name)
597
- serialized.set(xml_name, new_attr)
605
+ xml_name = "{}{}".format(xml_ns, xml_name)
606
+ serialized.set(xml_name, new_attr) # type: ignore
598
607
  continue
599
608
  if xml_desc.get("text", False):
600
- serialized.text = new_attr
609
+ serialized.text = new_attr # type: ignore
601
610
  continue
602
611
  if isinstance(new_attr, list):
603
- serialized.extend(new_attr)
612
+ serialized.extend(new_attr) # type: ignore
604
613
  elif isinstance(new_attr, ET.Element):
605
614
  # If the down XML has no XML/Name, we MUST replace the tag with the local tag. But keeping the namespaces.
606
- if 'name' not in getattr(orig_attr, '_xml_map', {}):
615
+ if "name" not in getattr(orig_attr, "_xml_map", {}):
607
616
  splitted_tag = new_attr.tag.split("}")
608
- if len(splitted_tag) == 2: # Namespace
617
+ if len(splitted_tag) == 2: # Namespace
609
618
  new_attr.tag = "}".join([splitted_tag[0], xml_name])
610
619
  else:
611
620
  new_attr.tag = xml_name
612
- serialized.append(new_attr)
621
+ serialized.append(new_attr) # type: ignore
613
622
  else: # That's a basic type
614
623
  # Integrate namespace if necessary
615
- local_node = _create_xml_node(
616
- xml_name,
617
- xml_prefix,
618
- xml_ns
619
- )
624
+ local_node = _create_xml_node(xml_name, xml_prefix, xml_ns)
620
625
  local_node.text = unicode_str(new_attr)
621
- serialized.append(local_node)
622
- else: # JSON
623
- for k in reversed(keys):
626
+ serialized.append(local_node) # type: ignore
627
+ else: # JSON
628
+ for k in reversed(keys): # type: ignore
624
629
  unflattened = {k: new_attr}
625
630
  new_attr = unflattened
626
631
 
627
632
  _new_attr = new_attr
628
633
  _serialized = serialized
629
- for k in keys:
634
+ for k in keys: # type: ignore
630
635
  if k not in _serialized:
631
- _serialized.update(_new_attr)
632
- _new_attr = _new_attr[k]
636
+ _serialized.update(_new_attr) # type: ignore
637
+ _new_attr = _new_attr[k] # type: ignore
633
638
  _serialized = _serialized[k]
634
639
  except ValueError:
635
640
  continue
636
641
 
637
642
  except (AttributeError, KeyError, TypeError) as err:
638
- msg = "Attribute {} in object {} cannot be serialized.\n{}".format(
639
- attr_name, class_name, str(target_obj))
643
+ msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
640
644
  raise_with_traceback(SerializationError, msg, err)
641
645
  else:
642
646
  return serialized
@@ -652,7 +656,7 @@ class Serializer(object):
652
656
  """
653
657
 
654
658
  # Just in case this is a dict
655
- internal_data_type = data_type.strip('[]{}')
659
+ internal_data_type = data_type.strip("[]{}")
656
660
  internal_data_type = self.dependencies.get(internal_data_type, None)
657
661
  try:
658
662
  is_xml_model_serialization = kwargs["is_xml"]
@@ -668,19 +672,18 @@ class Serializer(object):
668
672
  # We're not able to deal with additional properties for now.
669
673
  deserializer.additional_properties_detection = False
670
674
  if is_xml_model_serialization:
671
- deserializer.key_extractors = [
675
+ deserializer.key_extractors = [ # type: ignore
672
676
  attribute_key_case_insensitive_extractor,
673
677
  ]
674
678
  else:
675
679
  deserializer.key_extractors = [
676
680
  rest_key_case_insensitive_extractor,
677
681
  attribute_key_case_insensitive_extractor,
678
- last_rest_key_case_insensitive_extractor
682
+ last_rest_key_case_insensitive_extractor,
679
683
  ]
680
684
  data = deserializer._deserialize(data_type, data)
681
685
  except DeserializationError as err:
682
- raise_with_traceback(
683
- SerializationError, "Unable to build a model: "+str(err), err)
686
+ raise_with_traceback(SerializationError, "Unable to build a model: " + str(err), err)
684
687
 
685
688
  return self._serialize(data, data_type, **kwargs)
686
689
 
@@ -695,13 +698,13 @@ class Serializer(object):
695
698
  """
696
699
  try:
697
700
  output = self.serialize_data(data, data_type, **kwargs)
698
- if data_type == 'bool':
701
+ if data_type == "bool":
699
702
  output = json.dumps(output)
700
703
 
701
- if kwargs.get('skip_quote') is True:
704
+ if kwargs.get("skip_quote") is True:
702
705
  output = str(output)
703
706
  else:
704
- output = quote(str(output), safe='')
707
+ output = quote(str(output), safe="")
705
708
  except SerializationError:
706
709
  raise TypeError("{} must be type {}.".format(name, data_type))
707
710
  else:
@@ -720,27 +723,19 @@ class Serializer(object):
720
723
  # Treat the list aside, since we don't want to encode the div separator
721
724
  if data_type.startswith("["):
722
725
  internal_data_type = data_type[1:-1]
723
- data = [
724
- self.serialize_data(d, internal_data_type, **kwargs) if d is not None else ""
725
- for d
726
- in data
727
- ]
728
- if not kwargs.get('skip_quote', False):
729
- data = [
730
- quote(str(d), safe='')
731
- for d
732
- in data
733
- ]
726
+ data = [self.serialize_data(d, internal_data_type, **kwargs) if d is not None else "" for d in data]
727
+ if not kwargs.get("skip_quote", False):
728
+ data = [quote(str(d), safe="") for d in data]
734
729
  return str(self.serialize_iter(data, internal_data_type, **kwargs))
735
730
 
736
731
  # Not a list, regular serialization
737
732
  output = self.serialize_data(data, data_type, **kwargs)
738
- if data_type == 'bool':
733
+ if data_type == "bool":
739
734
  output = json.dumps(output)
740
- if kwargs.get('skip_quote') is True:
735
+ if kwargs.get("skip_quote") is True:
741
736
  output = str(output)
742
737
  else:
743
- output = quote(str(output), safe='')
738
+ output = quote(str(output), safe="")
744
739
  except SerializationError:
745
740
  raise TypeError("{} must be type {}.".format(name, data_type))
746
741
  else:
@@ -756,11 +751,11 @@ class Serializer(object):
756
751
  :raises: ValueError if data is None
757
752
  """
758
753
  try:
759
- if data_type in ['[str]']:
754
+ if data_type in ["[str]"]:
760
755
  data = ["" if d is None else d for d in data]
761
756
 
762
757
  output = self.serialize_data(data, data_type, **kwargs)
763
- if data_type == 'bool':
758
+ if data_type == "bool":
764
759
  output = json.dumps(output)
765
760
  except SerializationError:
766
761
  raise TypeError("{} must be type {}.".format(name, data_type))
@@ -796,13 +791,11 @@ class Serializer(object):
796
791
 
797
792
  iter_type = data_type[0] + data_type[-1]
798
793
  if iter_type in self.serialize_type:
799
- return self.serialize_type[iter_type](
800
- data, data_type[1:-1], **kwargs)
794
+ return self.serialize_type[iter_type](data, data_type[1:-1], **kwargs)
801
795
 
802
796
  except (ValueError, TypeError) as err:
803
797
  msg = "Unable to serialize value: {!r} as type: {!r}."
804
- raise_with_traceback(
805
- SerializationError, msg.format(data, data_type), err)
798
+ raise_with_traceback(SerializationError, msg.format(data, data_type), err)
806
799
  else:
807
800
  return self._serialize(data, **kwargs)
808
801
 
@@ -829,7 +822,7 @@ class Serializer(object):
829
822
  custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
830
823
  if custom_serializer:
831
824
  return custom_serializer(data)
832
- if data_type == 'str':
825
+ if data_type == "str":
833
826
  return cls.serialize_unicode(data)
834
827
  return eval(data_type)(data) # nosec
835
828
 
@@ -847,7 +840,7 @@ class Serializer(object):
847
840
  pass
848
841
 
849
842
  try:
850
- if isinstance(data, unicode):
843
+ if isinstance(data, unicode): # type: ignore
851
844
  # Don't change it, JSON and XML ElementTree are totally able
852
845
  # to serialize correctly u'' strings
853
846
  return data
@@ -886,25 +879,21 @@ class Serializer(object):
886
879
  serialized.append(None)
887
880
 
888
881
  if div:
889
- serialized = ['' if s is None else str(s) for s in serialized]
882
+ serialized = ["" if s is None else str(s) for s in serialized]
890
883
  serialized = div.join(serialized)
891
884
 
892
- if 'xml' in serialization_ctxt or is_xml:
885
+ if "xml" in serialization_ctxt or is_xml:
893
886
  # XML serialization is more complicated
894
- xml_desc = serialization_ctxt.get('xml', {})
895
- xml_name = xml_desc.get('name')
887
+ xml_desc = serialization_ctxt.get("xml", {})
888
+ xml_name = xml_desc.get("name")
896
889
  if not xml_name:
897
- xml_name = serialization_ctxt['key']
890
+ xml_name = serialization_ctxt["key"]
898
891
 
899
892
  # Create a wrap node if necessary (use the fact that Element and list have "append")
900
893
  is_wrapped = xml_desc.get("wrapped", False)
901
894
  node_name = xml_desc.get("itemsName", xml_name)
902
895
  if is_wrapped:
903
- final_result = _create_xml_node(
904
- xml_name,
905
- xml_desc.get('prefix', None),
906
- xml_desc.get('ns', None)
907
- )
896
+ final_result = _create_xml_node(xml_name, xml_desc.get("prefix", None), xml_desc.get("ns", None))
908
897
  else:
909
898
  final_result = []
910
899
  # All list elements to "local_node"
@@ -912,11 +901,7 @@ class Serializer(object):
912
901
  if isinstance(el, ET.Element):
913
902
  el_node = el
914
903
  else:
915
- el_node = _create_xml_node(
916
- node_name,
917
- xml_desc.get('prefix', None),
918
- xml_desc.get('ns', None)
919
- )
904
+ el_node = _create_xml_node(node_name, xml_desc.get("prefix", None), xml_desc.get("ns", None))
920
905
  if el is not None: # Otherwise it writes "None" :-p
921
906
  el_node.text = str(el)
922
907
  final_result.append(el_node)
@@ -936,21 +921,16 @@ class Serializer(object):
936
921
  serialized = {}
937
922
  for key, value in attr.items():
938
923
  try:
939
- serialized[self.serialize_unicode(key)] = self.serialize_data(
940
- value, dict_type, **kwargs)
924
+ serialized[self.serialize_unicode(key)] = self.serialize_data(value, dict_type, **kwargs)
941
925
  except ValueError:
942
926
  serialized[self.serialize_unicode(key)] = None
943
927
 
944
- if 'xml' in serialization_ctxt:
928
+ if "xml" in serialization_ctxt:
945
929
  # XML serialization is more complicated
946
- xml_desc = serialization_ctxt['xml']
947
- xml_name = xml_desc['name']
930
+ xml_desc = serialization_ctxt["xml"]
931
+ xml_name = xml_desc["name"]
948
932
 
949
- final_result = _create_xml_node(
950
- xml_name,
951
- xml_desc.get('prefix', None),
952
- xml_desc.get('ns', None)
953
- )
933
+ final_result = _create_xml_node(xml_name, xml_desc.get("prefix", None), xml_desc.get("ns", None))
954
934
  for key, value in serialized.items():
955
935
  ET.SubElement(final_result, key).text = value
956
936
  return final_result
@@ -996,8 +976,7 @@ class Serializer(object):
996
976
  serialized = {}
997
977
  for key, value in attr.items():
998
978
  try:
999
- serialized[self.serialize_unicode(key)] = self.serialize_object(
1000
- value, **kwargs)
979
+ serialized[self.serialize_unicode(key)] = self.serialize_object(value, **kwargs)
1001
980
  except ValueError:
1002
981
  serialized[self.serialize_unicode(key)] = None
1003
982
  return serialized
@@ -1006,8 +985,7 @@ class Serializer(object):
1006
985
  serialized = []
1007
986
  for obj in attr:
1008
987
  try:
1009
- serialized.append(self.serialize_object(
1010
- obj, **kwargs))
988
+ serialized.append(self.serialize_object(obj, **kwargs))
1011
989
  except ValueError:
1012
990
  pass
1013
991
  return serialized
@@ -1020,10 +998,10 @@ class Serializer(object):
1020
998
  except AttributeError:
1021
999
  result = attr
1022
1000
  try:
1023
- enum_obj(result)
1001
+ enum_obj(result) # type: ignore
1024
1002
  return result
1025
1003
  except ValueError:
1026
- for enum_value in enum_obj:
1004
+ for enum_value in enum_obj: # type: ignore
1027
1005
  if enum_value.value.lower() == str(attr).lower():
1028
1006
  return enum_value.value
1029
1007
  error = "{!r} is not valid value for enum {!r}"
@@ -1045,8 +1023,8 @@ class Serializer(object):
1045
1023
  :param attr: Object to be serialized.
1046
1024
  :rtype: str
1047
1025
  """
1048
- encoded = b64encode(attr).decode('ascii')
1049
- return encoded.strip('=').replace('+', '-').replace('/', '_')
1026
+ encoded = b64encode(attr).decode("ascii")
1027
+ return encoded.strip("=").replace("+", "-").replace("/", "_")
1050
1028
 
1051
1029
  @staticmethod
1052
1030
  def serialize_decimal(attr, **kwargs):
@@ -1113,16 +1091,20 @@ class Serializer(object):
1113
1091
  """
1114
1092
  try:
1115
1093
  if not attr.tzinfo:
1116
- _LOGGER.warning(
1117
- "Datetime with no tzinfo will be considered UTC.")
1094
+ _LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
1118
1095
  utc = attr.utctimetuple()
1119
1096
  except AttributeError:
1120
1097
  raise TypeError("RFC1123 object must be valid Datetime object.")
1121
1098
 
1122
1099
  return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
1123
- Serializer.days[utc.tm_wday], utc.tm_mday,
1124
- Serializer.months[utc.tm_mon], utc.tm_year,
1125
- utc.tm_hour, utc.tm_min, utc.tm_sec)
1100
+ Serializer.days[utc.tm_wday],
1101
+ utc.tm_mday,
1102
+ Serializer.months[utc.tm_mon],
1103
+ utc.tm_year,
1104
+ utc.tm_hour,
1105
+ utc.tm_min,
1106
+ utc.tm_sec,
1107
+ )
1126
1108
 
1127
1109
  @staticmethod
1128
1110
  def serialize_iso(attr, **kwargs):
@@ -1136,19 +1118,18 @@ class Serializer(object):
1136
1118
  attr = isodate.parse_datetime(attr)
1137
1119
  try:
1138
1120
  if not attr.tzinfo:
1139
- _LOGGER.warning(
1140
- "Datetime with no tzinfo will be considered UTC.")
1121
+ _LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
1141
1122
  utc = attr.utctimetuple()
1142
1123
  if utc.tm_year > 9999 or utc.tm_year < 1:
1143
1124
  raise OverflowError("Hit max or min date")
1144
1125
 
1145
- microseconds = str(attr.microsecond).rjust(6,'0').rstrip('0').ljust(3, '0')
1126
+ microseconds = str(attr.microsecond).rjust(6, "0").rstrip("0").ljust(3, "0")
1146
1127
  if microseconds:
1147
- microseconds = '.'+microseconds
1128
+ microseconds = "." + microseconds
1148
1129
  date = "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}".format(
1149
- utc.tm_year, utc.tm_mon, utc.tm_mday,
1150
- utc.tm_hour, utc.tm_min, utc.tm_sec)
1151
- return date + microseconds + 'Z'
1130
+ utc.tm_year, utc.tm_mon, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec
1131
+ )
1132
+ return date + microseconds + "Z"
1152
1133
  except (ValueError, OverflowError) as err:
1153
1134
  msg = "Unable to serialize datetime object."
1154
1135
  raise_with_traceback(SerializationError, msg, err)
@@ -1169,17 +1150,17 @@ class Serializer(object):
1169
1150
  return attr
1170
1151
  try:
1171
1152
  if not attr.tzinfo:
1172
- _LOGGER.warning(
1173
- "Datetime with no tzinfo will be considered UTC.")
1153
+ _LOGGER.warning("Datetime with no tzinfo will be considered UTC.")
1174
1154
  return int(calendar.timegm(attr.utctimetuple()))
1175
1155
  except AttributeError:
1176
1156
  raise TypeError("Unix time object must be valid Datetime object.")
1177
1157
 
1158
+
1178
1159
  def rest_key_extractor(attr, attr_desc, data):
1179
- key = attr_desc['key']
1160
+ key = attr_desc["key"]
1180
1161
  working_data = data
1181
1162
 
1182
- while '.' in key:
1163
+ while "." in key:
1183
1164
  dict_keys = _FLATTEN.split(key)
1184
1165
  if len(dict_keys) == 1:
1185
1166
  key = _decode_attribute_map_key(dict_keys[0])
@@ -1191,15 +1172,16 @@ def rest_key_extractor(attr, attr_desc, data):
1191
1172
  # that all properties under are None as well
1192
1173
  # https://github.com/Azure/msrest-for-python/issues/197
1193
1174
  return None
1194
- key = '.'.join(dict_keys[1:])
1175
+ key = ".".join(dict_keys[1:])
1195
1176
 
1196
1177
  return working_data.get(key)
1197
1178
 
1179
+
1198
1180
  def rest_key_case_insensitive_extractor(attr, attr_desc, data):
1199
- key = attr_desc['key']
1181
+ key = attr_desc["key"]
1200
1182
  working_data = data
1201
1183
 
1202
- while '.' in key:
1184
+ while "." in key:
1203
1185
  dict_keys = _FLATTEN.split(key)
1204
1186
  if len(dict_keys) == 1:
1205
1187
  key = _decode_attribute_map_key(dict_keys[0])
@@ -1211,30 +1193,33 @@ def rest_key_case_insensitive_extractor(attr, attr_desc, data):
1211
1193
  # that all properties under are None as well
1212
1194
  # https://github.com/Azure/msrest-for-python/issues/197
1213
1195
  return None
1214
- key = '.'.join(dict_keys[1:])
1196
+ key = ".".join(dict_keys[1:])
1215
1197
 
1216
1198
  if working_data:
1217
1199
  return attribute_key_case_insensitive_extractor(key, None, working_data)
1218
1200
 
1201
+
1219
1202
  def last_rest_key_extractor(attr, attr_desc, data):
1220
- """Extract the attribute in "data" based on the last part of the JSON path key.
1221
- """
1222
- key = attr_desc['key']
1203
+ """Extract the attribute in "data" based on the last part of the JSON path key."""
1204
+ key = attr_desc["key"]
1223
1205
  dict_keys = _FLATTEN.split(key)
1224
1206
  return attribute_key_extractor(dict_keys[-1], None, data)
1225
1207
 
1208
+
1226
1209
  def last_rest_key_case_insensitive_extractor(attr, attr_desc, data):
1227
1210
  """Extract the attribute in "data" based on the last part of the JSON path key.
1228
1211
 
1229
1212
  This is the case insensitive version of "last_rest_key_extractor"
1230
1213
  """
1231
- key = attr_desc['key']
1214
+ key = attr_desc["key"]
1232
1215
  dict_keys = _FLATTEN.split(key)
1233
1216
  return attribute_key_case_insensitive_extractor(dict_keys[-1], None, data)
1234
1217
 
1218
+
1235
1219
  def attribute_key_extractor(attr, _, data):
1236
1220
  return data.get(attr)
1237
1221
 
1222
+
1238
1223
  def attribute_key_case_insensitive_extractor(attr, _, data):
1239
1224
  found_key = None
1240
1225
  lower_attr = attr.lower()
@@ -1245,6 +1230,7 @@ def attribute_key_case_insensitive_extractor(attr, _, data):
1245
1230
 
1246
1231
  return data.get(found_key)
1247
1232
 
1233
+
1248
1234
  def _extract_name_from_internal_type(internal_type):
1249
1235
  """Given an internal type XML description, extract correct XML name with namespace.
1250
1236
 
@@ -1253,10 +1239,10 @@ def _extract_name_from_internal_type(internal_type):
1253
1239
  :returns: A tuple XML name + namespace dict
1254
1240
  """
1255
1241
  internal_type_xml_map = getattr(internal_type, "_xml_map", {})
1256
- xml_name = internal_type_xml_map.get('name', internal_type.__name__)
1242
+ xml_name = internal_type_xml_map.get("name", internal_type.__name__)
1257
1243
  xml_ns = internal_type_xml_map.get("ns", None)
1258
1244
  if xml_ns:
1259
- xml_name = "{{{}}}{}".format(xml_ns, xml_name)
1245
+ xml_name = "{}{}".format(xml_ns, xml_name)
1260
1246
  return xml_name
1261
1247
 
1262
1248
 
@@ -1268,19 +1254,19 @@ def xml_key_extractor(attr, attr_desc, data):
1268
1254
  if not isinstance(data, ET.Element):
1269
1255
  return None
1270
1256
 
1271
- xml_desc = attr_desc.get('xml', {})
1272
- xml_name = xml_desc.get('name', attr_desc['key'])
1257
+ xml_desc = attr_desc.get("xml", {})
1258
+ xml_name = xml_desc.get("name", attr_desc["key"])
1273
1259
 
1274
1260
  # Look for a children
1275
- is_iter_type = attr_desc['type'].startswith("[")
1261
+ is_iter_type = attr_desc["type"].startswith("[")
1276
1262
  is_wrapped = xml_desc.get("wrapped", False)
1277
1263
  internal_type = attr_desc.get("internalType", None)
1278
1264
  internal_type_xml_map = getattr(internal_type, "_xml_map", {})
1279
1265
 
1280
1266
  # Integrate namespace if necessary
1281
- xml_ns = xml_desc.get('ns', internal_type_xml_map.get("ns", None))
1267
+ xml_ns = xml_desc.get("ns", internal_type_xml_map.get("ns", None))
1282
1268
  if xml_ns:
1283
- xml_name = "{{{}}}{}".format(xml_ns, xml_name)
1269
+ xml_name = "{}{}".format(xml_ns, xml_name)
1284
1270
 
1285
1271
  # If it's an attribute, that's simple
1286
1272
  if xml_desc.get("attr", False):
@@ -1294,15 +1280,15 @@ def xml_key_extractor(attr, attr_desc, data):
1294
1280
  # - Wrapped node
1295
1281
  # - Internal type is an enum (considered basic types)
1296
1282
  # - Internal type has no XML/Name node
1297
- if is_wrapped or (internal_type and (issubclass(internal_type, Enum) or 'name' not in internal_type_xml_map)):
1283
+ if is_wrapped or (internal_type and (issubclass(internal_type, Enum) or "name" not in internal_type_xml_map)):
1298
1284
  children = data.findall(xml_name)
1299
1285
  # If internal type has a local name and it's not a list, I use that name
1300
- elif not is_iter_type and internal_type and 'name' in internal_type_xml_map:
1286
+ elif not is_iter_type and internal_type and "name" in internal_type_xml_map:
1301
1287
  xml_name = _extract_name_from_internal_type(internal_type)
1302
1288
  children = data.findall(xml_name)
1303
1289
  # That's an array
1304
1290
  else:
1305
- if internal_type: # Complex type, ignore itemsName and use the complex type name
1291
+ if internal_type: # Complex type, ignore itemsName and use the complex type name
1306
1292
  items_name = _extract_name_from_internal_type(internal_type)
1307
1293
  else:
1308
1294
  items_name = xml_desc.get("itemsName", xml_name)
@@ -1311,21 +1297,22 @@ def xml_key_extractor(attr, attr_desc, data):
1311
1297
  if len(children) == 0:
1312
1298
  if is_iter_type:
1313
1299
  if is_wrapped:
1314
- return None # is_wrapped no node, we want None
1300
+ return None # is_wrapped no node, we want None
1315
1301
  else:
1316
- return [] # not wrapped, assume empty list
1302
+ return [] # not wrapped, assume empty list
1317
1303
  return None # Assume it's not there, maybe an optional node.
1318
1304
 
1319
1305
  # If is_iter_type and not wrapped, return all found children
1320
1306
  if is_iter_type:
1321
1307
  if not is_wrapped:
1322
1308
  return children
1323
- else: # Iter and wrapped, should have found one node only (the wrap one)
1309
+ else: # Iter and wrapped, should have found one node only (the wrap one)
1324
1310
  if len(children) != 1:
1325
1311
  raise DeserializationError(
1326
1312
  "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
1327
1313
  xml_name
1328
- ))
1314
+ )
1315
+ )
1329
1316
  return list(children[0]) # Might be empty list and that's ok.
1330
1317
 
1331
1318
  # Here it's not a itertype, we should have found one element only or empty
@@ -1333,6 +1320,7 @@ def xml_key_extractor(attr, attr_desc, data):
1333
1320
  raise DeserializationError("Find several XML '{}' where it was not expected".format(xml_name))
1334
1321
  return children[0]
1335
1322
 
1323
+
1336
1324
  class Deserializer(object):
1337
1325
  """Response object model deserializer.
1338
1326
 
@@ -1340,37 +1328,32 @@ class Deserializer(object):
1340
1328
  :ivar list key_extractors: Ordered list of extractors to be used by this deserializer.
1341
1329
  """
1342
1330
 
1343
- basic_types = {str: 'str', int: 'int', bool: 'bool', float: 'float'}
1331
+ basic_types = {str: "str", int: "int", bool: "bool", float: "float"}
1344
1332
 
1345
- valid_date = re.compile(
1346
- r'\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}'
1347
- r'\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?')
1333
+ 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}]?")
1348
1334
 
1349
1335
  def __init__(self, classes=None):
1350
1336
  self.deserialize_type = {
1351
- 'iso-8601': Deserializer.deserialize_iso,
1352
- 'rfc-1123': Deserializer.deserialize_rfc,
1353
- 'unix-time': Deserializer.deserialize_unix,
1354
- 'duration': Deserializer.deserialize_duration,
1355
- 'date': Deserializer.deserialize_date,
1356
- 'time': Deserializer.deserialize_time,
1357
- 'decimal': Deserializer.deserialize_decimal,
1358
- 'long': Deserializer.deserialize_long,
1359
- 'bytearray': Deserializer.deserialize_bytearray,
1360
- 'base64': Deserializer.deserialize_base64,
1361
- 'object': self.deserialize_object,
1362
- '[]': self.deserialize_iter,
1363
- '{}': self.deserialize_dict
1364
- }
1337
+ "iso-8601": Deserializer.deserialize_iso,
1338
+ "rfc-1123": Deserializer.deserialize_rfc,
1339
+ "unix-time": Deserializer.deserialize_unix,
1340
+ "duration": Deserializer.deserialize_duration,
1341
+ "date": Deserializer.deserialize_date,
1342
+ "time": Deserializer.deserialize_time,
1343
+ "decimal": Deserializer.deserialize_decimal,
1344
+ "long": Deserializer.deserialize_long,
1345
+ "bytearray": Deserializer.deserialize_bytearray,
1346
+ "base64": Deserializer.deserialize_base64,
1347
+ "object": self.deserialize_object,
1348
+ "[]": self.deserialize_iter,
1349
+ "{}": self.deserialize_dict,
1350
+ }
1365
1351
  self.deserialize_expected_types = {
1366
- 'duration': (isodate.Duration, datetime.timedelta),
1367
- 'iso-8601': (datetime.datetime)
1352
+ "duration": (isodate.Duration, datetime.timedelta),
1353
+ "iso-8601": (datetime.datetime),
1368
1354
  }
1369
1355
  self.dependencies = dict(classes) if classes else {}
1370
- self.key_extractors = [
1371
- rest_key_extractor,
1372
- xml_key_extractor
1373
- ]
1356
+ self.key_extractors = [rest_key_extractor, xml_key_extractor]
1374
1357
  # Additional properties only works if the "rest_key_extractor" is used to
1375
1358
  # extract the keys. Making it to work whatever the key extractor is too much
1376
1359
  # complicated, with no real scenario for now.
@@ -1403,8 +1386,7 @@ class Deserializer(object):
1403
1386
  """
1404
1387
  # This is already a model, go recursive just in case
1405
1388
  if hasattr(data, "_attribute_map"):
1406
- constants = [name for name, config in getattr(data, '_validation', {}).items()
1407
- if config.get('constant')]
1389
+ constants = [name for name, config in getattr(data, "_validation", {}).items() if config.get("constant")]
1408
1390
  try:
1409
1391
  for attr, mapconfig in data._attribute_map.items():
1410
1392
  if attr in constants:
@@ -1412,15 +1394,11 @@ class Deserializer(object):
1412
1394
  value = getattr(data, attr)
1413
1395
  if value is None:
1414
1396
  continue
1415
- local_type = mapconfig['type']
1416
- internal_data_type = local_type.strip('[]{}')
1397
+ local_type = mapconfig["type"]
1398
+ internal_data_type = local_type.strip("[]{}")
1417
1399
  if internal_data_type not in self.dependencies or isinstance(internal_data_type, Enum):
1418
1400
  continue
1419
- setattr(
1420
- data,
1421
- attr,
1422
- self._deserialize(local_type, value)
1423
- )
1401
+ setattr(data, attr, self._deserialize(local_type, value))
1424
1402
  return data
1425
1403
  except AttributeError:
1426
1404
  return
@@ -1435,16 +1413,16 @@ class Deserializer(object):
1435
1413
  if data is None:
1436
1414
  return data
1437
1415
  try:
1438
- attributes = response._attribute_map
1416
+ attributes = response._attribute_map # type: ignore
1439
1417
  d_attrs = {}
1440
1418
  for attr, attr_desc in attributes.items():
1441
1419
  # Check empty string. If it's not empty, someone has a real "additionalProperties"...
1442
- if attr == "additional_properties" and attr_desc["key"] == '':
1420
+ if attr == "additional_properties" and attr_desc["key"] == "":
1443
1421
  continue
1444
1422
  raw_value = None
1445
1423
  # Enhance attr_desc with some dynamic data
1446
- attr_desc = attr_desc.copy() # Do a copy, do not change the real one
1447
- internal_data_type = attr_desc["type"].strip('[]{}')
1424
+ attr_desc = attr_desc.copy() # Do a copy, do not change the real one
1425
+ internal_data_type = attr_desc["type"].strip("[]{}")
1448
1426
  if internal_data_type in self.dependencies:
1449
1427
  attr_desc["internalType"] = self.dependencies[internal_data_type]
1450
1428
 
@@ -1452,21 +1430,18 @@ class Deserializer(object):
1452
1430
  found_value = key_extractor(attr, attr_desc, data)
1453
1431
  if found_value is not None:
1454
1432
  if raw_value is not None and raw_value != found_value:
1455
- msg = ("Ignoring extracted value '%s' from %s for key '%s'"
1456
- " (duplicate extraction, follow extractors order)" )
1457
- _LOGGER.warning(
1458
- msg,
1459
- found_value,
1460
- key_extractor,
1461
- attr
1433
+ msg = (
1434
+ "Ignoring extracted value '%s' from %s for key '%s'"
1435
+ " (duplicate extraction, follow extractors order)"
1462
1436
  )
1437
+ _LOGGER.warning(msg, found_value, key_extractor, attr)
1463
1438
  continue
1464
1439
  raw_value = found_value
1465
1440
 
1466
- value = self.deserialize_data(raw_value, attr_desc['type'])
1441
+ value = self.deserialize_data(raw_value, attr_desc["type"])
1467
1442
  d_attrs[attr] = value
1468
1443
  except (AttributeError, TypeError, KeyError) as err:
1469
- msg = "Unable to deserialize to object: " + class_name
1444
+ msg = "Unable to deserialize to object: " + class_name # type: ignore
1470
1445
  raise_with_traceback(DeserializationError, msg, err)
1471
1446
  else:
1472
1447
  additional_properties = self._build_additional_properties(attributes, data)
@@ -1475,14 +1450,17 @@ class Deserializer(object):
1475
1450
  def _build_additional_properties(self, attribute_map, data):
1476
1451
  if not self.additional_properties_detection:
1477
1452
  return None
1478
- if "additional_properties" in attribute_map and attribute_map.get("additional_properties", {}).get("key") != '':
1453
+ if "additional_properties" in attribute_map and attribute_map.get("additional_properties", {}).get("key") != "":
1479
1454
  # Check empty string. If it's not empty, someone has a real "additionalProperties"
1480
1455
  return None
1481
1456
  if isinstance(data, ET.Element):
1482
1457
  data = {el.tag: el.text for el in data}
1483
1458
 
1484
- known_keys = {_decode_attribute_map_key(_FLATTEN.split(desc['key'])[0])
1485
- for desc in attribute_map.values() if desc['key'] != ''}
1459
+ known_keys = {
1460
+ _decode_attribute_map_key(_FLATTEN.split(desc["key"])[0])
1461
+ for desc in attribute_map.values()
1462
+ if desc["key"] != ""
1463
+ }
1486
1464
  present_keys = set(data.keys())
1487
1465
  missing_keys = present_keys - known_keys
1488
1466
  return {key: data[key] for key in missing_keys}
@@ -1525,8 +1503,7 @@ class Deserializer(object):
1525
1503
  return self(target_obj, data, content_type=content_type)
1526
1504
  except:
1527
1505
  _LOGGER.debug(
1528
- "Ran into a deserialization error. Ignoring since this is failsafe deserialization",
1529
- exc_info=True
1506
+ "Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True
1530
1507
  )
1531
1508
  return None
1532
1509
 
@@ -1554,22 +1531,16 @@ class Deserializer(object):
1554
1531
  return context[RawDeserializer.CONTEXT_NAME]
1555
1532
  raise ValueError("This pipeline didn't have the RawDeserializer policy; can't deserialize")
1556
1533
 
1557
- #Assume this is enough to recognize universal_http.ClientResponse without importing it
1534
+ # Assume this is enough to recognize universal_http.ClientResponse without importing it
1558
1535
  if hasattr(raw_data, "body"):
1559
- return RawDeserializer.deserialize_from_http_generics(
1560
- raw_data.text(),
1561
- raw_data.headers
1562
- )
1536
+ return RawDeserializer.deserialize_from_http_generics(raw_data.text(), raw_data.headers)
1563
1537
 
1564
1538
  # Assume this enough to recognize requests.Response without importing it.
1565
- if hasattr(raw_data, '_content_consumed'):
1566
- return RawDeserializer.deserialize_from_http_generics(
1567
- raw_data.text,
1568
- raw_data.headers
1569
- )
1539
+ if hasattr(raw_data, "_content_consumed"):
1540
+ return RawDeserializer.deserialize_from_http_generics(raw_data.text, raw_data.headers)
1570
1541
 
1571
- if isinstance(raw_data, (basestring, bytes)) or hasattr(raw_data, 'read'):
1572
- return RawDeserializer.deserialize_from_text(raw_data, content_type)
1542
+ if isinstance(raw_data, (basestring, bytes)) or hasattr(raw_data, "read"):
1543
+ return RawDeserializer.deserialize_from_text(raw_data, content_type) # type: ignore
1573
1544
  return raw_data
1574
1545
 
1575
1546
  def _instantiate_model(self, response, attrs, additional_properties=None):
@@ -1579,14 +1550,11 @@ class Deserializer(object):
1579
1550
  :param d_attrs: The deserialized response attributes.
1580
1551
  """
1581
1552
  if callable(response):
1582
- subtype = getattr(response, '_subtype_map', {})
1553
+ subtype = getattr(response, "_subtype_map", {})
1583
1554
  try:
1584
- readonly = [k for k, v in response._validation.items()
1585
- if v.get('readonly')]
1586
- const = [k for k, v in response._validation.items()
1587
- if v.get('constant')]
1588
- kwargs = {k: v for k, v in attrs.items()
1589
- if k not in subtype and k not in readonly + const}
1555
+ readonly = [k for k, v in response._validation.items() if v.get("readonly")]
1556
+ const = [k for k, v in response._validation.items() if v.get("constant")]
1557
+ kwargs = {k: v for k, v in attrs.items() if k not in subtype and k not in readonly + const}
1590
1558
  response_obj = response(**kwargs)
1591
1559
  for attr in readonly:
1592
1560
  setattr(response_obj, attr, attrs.get(attr))
@@ -1594,8 +1562,7 @@ class Deserializer(object):
1594
1562
  response_obj.additional_properties = additional_properties
1595
1563
  return response_obj
1596
1564
  except TypeError as err:
1597
- msg = "Unable to deserialize {} into model {}. ".format(
1598
- kwargs, response)
1565
+ msg = "Unable to deserialize {} into model {}. ".format(kwargs, response) # type: ignore
1599
1566
  raise DeserializationError(msg + str(err))
1600
1567
  else:
1601
1568
  try:
@@ -1659,13 +1626,10 @@ class Deserializer(object):
1659
1626
  """
1660
1627
  if attr is None:
1661
1628
  return None
1662
- if isinstance(attr, ET.Element): # If I receive an element here, get the children
1629
+ if isinstance(attr, ET.Element): # If I receive an element here, get the children
1663
1630
  attr = list(attr)
1664
1631
  if not isinstance(attr, (list, set)):
1665
- raise DeserializationError("Cannot deserialize as [{}] an object of type {}".format(
1666
- iter_type,
1667
- type(attr)
1668
- ))
1632
+ raise DeserializationError("Cannot deserialize as [{}] an object of type {}".format(iter_type, type(attr)))
1669
1633
  return [self.deserialize_data(a, iter_type) for a in attr]
1670
1634
 
1671
1635
  def deserialize_dict(self, attr, dict_type):
@@ -1677,7 +1641,7 @@ class Deserializer(object):
1677
1641
  :rtype: dict
1678
1642
  """
1679
1643
  if isinstance(attr, list):
1680
- return {x['key']: self.deserialize_data(x['value'], dict_type) for x in attr}
1644
+ return {x["key"]: self.deserialize_data(x["value"], dict_type) for x in attr}
1681
1645
 
1682
1646
  if isinstance(attr, ET.Element):
1683
1647
  # Transform <Key>value</Key> into {"Key": "value"}
@@ -1698,7 +1662,7 @@ class Deserializer(object):
1698
1662
  # Do no recurse on XML, just return the tree as-is
1699
1663
  return attr
1700
1664
  if isinstance(attr, basestring):
1701
- return self.deserialize_basic(attr, 'str')
1665
+ return self.deserialize_basic(attr, "str")
1702
1666
  obj_type = type(attr)
1703
1667
  if obj_type in self.basic_types:
1704
1668
  return self.deserialize_basic(attr, self.basic_types[obj_type])
@@ -1709,8 +1673,7 @@ class Deserializer(object):
1709
1673
  deserialized = {}
1710
1674
  for key, value in attr.items():
1711
1675
  try:
1712
- deserialized[key] = self.deserialize_object(
1713
- value, **kwargs)
1676
+ deserialized[key] = self.deserialize_object(value, **kwargs)
1714
1677
  except ValueError:
1715
1678
  deserialized[key] = None
1716
1679
  return deserialized
@@ -1719,8 +1682,7 @@ class Deserializer(object):
1719
1682
  deserialized = []
1720
1683
  for obj in attr:
1721
1684
  try:
1722
- deserialized.append(self.deserialize_object(
1723
- obj, **kwargs))
1685
+ deserialized.append(self.deserialize_object(obj, **kwargs))
1724
1686
  except ValueError:
1725
1687
  pass
1726
1688
  return deserialized
@@ -1747,23 +1709,23 @@ class Deserializer(object):
1747
1709
  if not attr:
1748
1710
  if data_type == "str":
1749
1711
  # None or '', node <a/> is empty string.
1750
- return ''
1712
+ return ""
1751
1713
  else:
1752
1714
  # None or '', node <a/> with a strong type is None.
1753
1715
  # Don't try to model "empty bool" or "empty int"
1754
1716
  return None
1755
1717
 
1756
- if data_type == 'bool':
1718
+ if data_type == "bool":
1757
1719
  if attr in [True, False, 1, 0]:
1758
1720
  return bool(attr)
1759
1721
  elif isinstance(attr, basestring):
1760
- if attr.lower() in ['true', '1']:
1722
+ if attr.lower() in ["true", "1"]:
1761
1723
  return True
1762
- elif attr.lower() in ['false', '0']:
1724
+ elif attr.lower() in ["false", "0"]:
1763
1725
  return False
1764
1726
  raise TypeError("Invalid boolean value: {}".format(attr))
1765
1727
 
1766
- if data_type == 'str':
1728
+ if data_type == "str":
1767
1729
  return self.deserialize_unicode(attr)
1768
1730
  return eval(data_type)(attr) # nosec
1769
1731
 
@@ -1782,7 +1744,7 @@ class Deserializer(object):
1782
1744
 
1783
1745
  # Consider this is real string
1784
1746
  try:
1785
- if isinstance(data, unicode):
1747
+ if isinstance(data, unicode): # type: ignore
1786
1748
  return data
1787
1749
  except NameError:
1788
1750
  return str(data)
@@ -1833,7 +1795,7 @@ class Deserializer(object):
1833
1795
  """
1834
1796
  if isinstance(attr, ET.Element):
1835
1797
  attr = attr.text
1836
- return bytearray(b64decode(attr))
1798
+ return bytearray(b64decode(attr)) # type: ignore
1837
1799
 
1838
1800
  @staticmethod
1839
1801
  def deserialize_base64(attr):
@@ -1845,9 +1807,9 @@ class Deserializer(object):
1845
1807
  """
1846
1808
  if isinstance(attr, ET.Element):
1847
1809
  attr = attr.text
1848
- padding = '=' * (3 - (len(attr) + 3) % 4)
1849
- attr = attr + padding
1850
- encoded = attr.replace('-', '+').replace('_', '/')
1810
+ padding = "=" * (3 - (len(attr) + 3) % 4) # type: ignore
1811
+ attr = attr + padding # type: ignore
1812
+ encoded = attr.replace("-", "+").replace("_", "/")
1851
1813
  return b64decode(encoded)
1852
1814
 
1853
1815
  @staticmethod
@@ -1861,7 +1823,7 @@ class Deserializer(object):
1861
1823
  if isinstance(attr, ET.Element):
1862
1824
  attr = attr.text
1863
1825
  try:
1864
- return decimal.Decimal(attr)
1826
+ return decimal.Decimal(attr) # type: ignore
1865
1827
  except decimal.DecimalException as err:
1866
1828
  msg = "Invalid decimal {}".format(attr)
1867
1829
  raise_with_traceback(DeserializationError, msg, err)
@@ -1876,7 +1838,7 @@ class Deserializer(object):
1876
1838
  """
1877
1839
  if isinstance(attr, ET.Element):
1878
1840
  attr = attr.text
1879
- return _long_type(attr)
1841
+ return _long_type(attr) # type: ignore
1880
1842
 
1881
1843
  @staticmethod
1882
1844
  def deserialize_duration(attr):
@@ -1890,7 +1852,7 @@ class Deserializer(object):
1890
1852
  attr = attr.text
1891
1853
  try:
1892
1854
  duration = isodate.parse_duration(attr)
1893
- except(ValueError, OverflowError, AttributeError) as err:
1855
+ except (ValueError, OverflowError, AttributeError) as err:
1894
1856
  msg = "Cannot deserialize duration object."
1895
1857
  raise_with_traceback(DeserializationError, msg, err)
1896
1858
  else:
@@ -1906,7 +1868,7 @@ class Deserializer(object):
1906
1868
  """
1907
1869
  if isinstance(attr, ET.Element):
1908
1870
  attr = attr.text
1909
- if re.search(r"[^\W\d_]", attr, re.I + re.U):
1871
+ if re.search(r"[^\W\d_]", attr, re.I + re.U): # type: ignore
1910
1872
  raise DeserializationError("Date must have only digits and -. Received: %s" % attr)
1911
1873
  # This must NOT use defaultmonth/defaultday. Using None ensure this raises an exception.
1912
1874
  return isodate.parse_date(attr, defaultmonth=None, defaultday=None)
@@ -1921,7 +1883,7 @@ class Deserializer(object):
1921
1883
  """
1922
1884
  if isinstance(attr, ET.Element):
1923
1885
  attr = attr.text
1924
- if re.search(r"[^\W\d_]", attr, re.I + re.U):
1886
+ if re.search(r"[^\W\d_]", attr, re.I + re.U): # type: ignore
1925
1887
  raise DeserializationError("Date must have only digits and -. Received: %s" % attr)
1926
1888
  return isodate.parse_time(attr)
1927
1889
 
@@ -1936,10 +1898,9 @@ class Deserializer(object):
1936
1898
  if isinstance(attr, ET.Element):
1937
1899
  attr = attr.text
1938
1900
  try:
1939
- parsed_date = email.utils.parsedate_tz(attr)
1901
+ parsed_date = email.utils.parsedate_tz(attr) # type: ignore
1940
1902
  date_obj = datetime.datetime(
1941
- *parsed_date[:6],
1942
- tzinfo=_FixedOffset(datetime.timedelta(minutes=(parsed_date[9] or 0)/60))
1903
+ *parsed_date[:6], tzinfo=_FixedOffset(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60))
1943
1904
  )
1944
1905
  if not date_obj.tzinfo:
1945
1906
  date_obj = date_obj.astimezone(tz=TZ_UTC)
@@ -1960,12 +1921,12 @@ class Deserializer(object):
1960
1921
  if isinstance(attr, ET.Element):
1961
1922
  attr = attr.text
1962
1923
  try:
1963
- attr = attr.upper()
1924
+ attr = attr.upper() # type: ignore
1964
1925
  match = Deserializer.valid_date.match(attr)
1965
1926
  if not match:
1966
1927
  raise ValueError("Invalid datetime string: " + attr)
1967
1928
 
1968
- check_decimal = attr.split('.')
1929
+ check_decimal = attr.split(".")
1969
1930
  if len(check_decimal) > 1:
1970
1931
  decimal_str = ""
1971
1932
  for digit in check_decimal[1]:
@@ -1980,7 +1941,7 @@ class Deserializer(object):
1980
1941
  test_utc = date_obj.utctimetuple()
1981
1942
  if test_utc.tm_year > 9999 or test_utc.tm_year < 1:
1982
1943
  raise OverflowError("Hit max or min date")
1983
- except(ValueError, OverflowError, AttributeError) as err:
1944
+ except (ValueError, OverflowError, AttributeError) as err:
1984
1945
  msg = "Cannot deserialize datetime object."
1985
1946
  raise_with_traceback(DeserializationError, msg, err)
1986
1947
  else:
@@ -1996,7 +1957,7 @@ class Deserializer(object):
1996
1957
  :raises: DeserializationError if format invalid
1997
1958
  """
1998
1959
  if isinstance(attr, ET.Element):
1999
- attr = int(attr.text)
1960
+ attr = int(attr.text) # type: ignore
2000
1961
  try:
2001
1962
  date_obj = datetime.datetime.fromtimestamp(attr, TZ_UTC)
2002
1963
  except ValueError as err: