@autorest/python 6.7.3 → 6.7.4
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.
|
@@ -751,7 +751,7 @@ class _OperationSerializer(
|
|
|
751
751
|
elif self.code_model.options["models_mode"] == "dpg":
|
|
752
752
|
create_body_call = (
|
|
753
753
|
f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
|
|
754
|
-
"cls=AzureJSONEncoder) # type: ignore"
|
|
754
|
+
"cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore"
|
|
755
755
|
)
|
|
756
756
|
else:
|
|
757
757
|
create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
|
|
@@ -128,10 +128,16 @@ def _is_readonly(p):
|
|
|
128
128
|
class AzureJSONEncoder(JSONEncoder):
|
|
129
129
|
"""A JSON encoder that's capable of serializing datetime objects and bytes."""
|
|
130
130
|
|
|
131
|
+
def __init__(self, *args, exclude_readonly: bool = False, **kwargs):
|
|
132
|
+
super().__init__(*args, **kwargs)
|
|
133
|
+
self.exclude_readonly = exclude_readonly
|
|
134
|
+
|
|
131
135
|
def default(self, o): # pylint: disable=too-many-return-statements
|
|
132
136
|
if _is_model(o):
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
if self.exclude_readonly:
|
|
138
|
+
readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)]
|
|
139
|
+
return {k: v for k, v in o.items() if k not in readonly_props}
|
|
140
|
+
return dict(o.items())
|
|
135
141
|
if isinstance(o, (bytes, bytearray)):
|
|
136
142
|
return base64.b64encode(o).decode()
|
|
137
143
|
if isinstance(o, _Null):
|
|
@@ -295,11 +301,29 @@ def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] =
|
|
|
295
301
|
return _DESERIALIZE_MAPPING.get(annotation)
|
|
296
302
|
|
|
297
303
|
|
|
304
|
+
def _get_type_alias_type(module_name: str, alias_name: str):
|
|
305
|
+
types = {
|
|
306
|
+
k: v
|
|
307
|
+
for k, v in sys.modules[module_name].__dict__.items()
|
|
308
|
+
if isinstance(v, typing._GenericAlias) # type: ignore
|
|
309
|
+
}
|
|
310
|
+
if alias_name not in types:
|
|
311
|
+
return alias_name
|
|
312
|
+
return types[alias_name]
|
|
313
|
+
|
|
314
|
+
|
|
298
315
|
def _get_model(module_name: str, model_name: str):
|
|
299
|
-
models = {
|
|
316
|
+
models = {
|
|
317
|
+
k: v
|
|
318
|
+
for k, v in sys.modules[module_name].__dict__.items()
|
|
319
|
+
if isinstance(v, type)
|
|
320
|
+
}
|
|
300
321
|
module_end = module_name.rsplit(".", 1)[0]
|
|
301
|
-
|
|
302
|
-
|
|
322
|
+
models.update({
|
|
323
|
+
k: v
|
|
324
|
+
for k, v in sys.modules[module_end].__dict__.items()
|
|
325
|
+
if isinstance(v, type)
|
|
326
|
+
})
|
|
303
327
|
if isinstance(model_name, str):
|
|
304
328
|
model_name = model_name.split(".")[-1]
|
|
305
329
|
if model_name not in models:
|
|
@@ -461,7 +485,7 @@ class Model(_MyMutableMapping):
|
|
|
461
485
|
raise TypeError(f"{class_name}.__init__() got an unexpected keyword argument '{non_attr_kwargs[0]}'")
|
|
462
486
|
dict_to_pass.update(
|
|
463
487
|
{
|
|
464
|
-
self._attr_to_rest_field[k]._rest_name:
|
|
488
|
+
self._attr_to_rest_field[k]._rest_name: _create_value(self._attr_to_rest_field[k], v)
|
|
465
489
|
for k, v in kwargs.items()
|
|
466
490
|
if v is not None
|
|
467
491
|
}
|
|
@@ -499,24 +523,60 @@ class Model(_MyMutableMapping):
|
|
|
499
523
|
base.__mapping__[discriminator or cls.__name__] = cls # type: ignore # pylint: disable=no-member
|
|
500
524
|
|
|
501
525
|
@classmethod
|
|
502
|
-
def _get_discriminator(cls) -> typing.Optional[str]:
|
|
526
|
+
def _get_discriminator(cls, exist_discriminators) -> typing.Optional[str]:
|
|
503
527
|
for v in cls.__dict__.values():
|
|
504
|
-
if isinstance(v, _RestField) and v._is_discriminator: # pylint: disable=protected-access
|
|
528
|
+
if isinstance(v, _RestField) and v._is_discriminator and v._rest_name not in exist_discriminators: # pylint: disable=protected-access
|
|
505
529
|
return v._rest_name # pylint: disable=protected-access
|
|
506
530
|
return None
|
|
507
531
|
|
|
508
532
|
@classmethod
|
|
509
|
-
def _deserialize(cls, data):
|
|
533
|
+
def _deserialize(cls, data, exist_discriminators):
|
|
510
534
|
if not hasattr(cls, "__mapping__"): # pylint: disable=no-member
|
|
511
535
|
return cls(data)
|
|
512
|
-
discriminator = cls._get_discriminator()
|
|
513
|
-
|
|
536
|
+
discriminator = cls._get_discriminator(exist_discriminators)
|
|
537
|
+
exist_discriminators.append(discriminator)
|
|
538
|
+
mapped_cls = cls.__mapping__.get(
|
|
539
|
+
data.get(discriminator), cls
|
|
540
|
+
) # pylint: disable=no-member
|
|
514
541
|
if mapped_cls == cls:
|
|
515
542
|
return cls(data)
|
|
516
|
-
return mapped_cls._deserialize(data) # pylint: disable=protected-access
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
543
|
+
return mapped_cls._deserialize(data, exist_discriminators) # pylint: disable=protected-access
|
|
544
|
+
|
|
545
|
+
def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.Any]:
|
|
546
|
+
"""Return a dict that can be JSONify using json.dump.
|
|
547
|
+
|
|
548
|
+
:keyword bool exclude_readonly: Whether to remove the readonly properties.
|
|
549
|
+
:returns: A dict JSON compatible object
|
|
550
|
+
:rtype: dict
|
|
551
|
+
"""
|
|
552
|
+
|
|
553
|
+
result = {}
|
|
554
|
+
if exclude_readonly:
|
|
555
|
+
readonly_props = [p._rest_name for p in self._attr_to_rest_field.values() if _is_readonly(p)]
|
|
556
|
+
for k, v in self.items():
|
|
557
|
+
if exclude_readonly and k in readonly_props: # pyright: reportUnboundVariable=false
|
|
558
|
+
continue
|
|
559
|
+
result[k] = Model._as_dict_value(v, exclude_readonly=exclude_readonly)
|
|
560
|
+
return result
|
|
561
|
+
|
|
562
|
+
@staticmethod
|
|
563
|
+
def _as_dict_value(v: typing.Any, exclude_readonly: bool = False) -> typing.Any:
|
|
564
|
+
if v is None or isinstance(v, _Null):
|
|
565
|
+
return None
|
|
566
|
+
if isinstance(v, (list, tuple, set)):
|
|
567
|
+
return [
|
|
568
|
+
Model._as_dict_value(x, exclude_readonly=exclude_readonly)
|
|
569
|
+
for x in v
|
|
570
|
+
]
|
|
571
|
+
if isinstance(v, dict):
|
|
572
|
+
return {
|
|
573
|
+
dk: Model._as_dict_value(dv, exclude_readonly=exclude_readonly)
|
|
574
|
+
for dk, dv in v.items()
|
|
575
|
+
}
|
|
576
|
+
return v.as_dict(exclude_readonly=exclude_readonly) if hasattr(v, "as_dict") else v
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915, R0912
|
|
520
580
|
annotation: typing.Any,
|
|
521
581
|
module: typing.Optional[str],
|
|
522
582
|
rf: typing.Optional["_RestField"] = None,
|
|
@@ -524,8 +584,22 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
|
|
|
524
584
|
if not annotation or annotation in [int, float]:
|
|
525
585
|
return None
|
|
526
586
|
|
|
587
|
+
# is it a type alias?
|
|
588
|
+
if isinstance(annotation, str):
|
|
589
|
+
if module is not None:
|
|
590
|
+
annotation = _get_type_alias_type(module, annotation)
|
|
591
|
+
|
|
592
|
+
# is it a forward ref / in quotes?
|
|
593
|
+
if isinstance(annotation, (str, typing.ForwardRef)):
|
|
594
|
+
try:
|
|
595
|
+
model_name = annotation.__forward_arg__ # type: ignore
|
|
596
|
+
except AttributeError:
|
|
597
|
+
model_name = annotation
|
|
598
|
+
if module is not None:
|
|
599
|
+
annotation = _get_model(module, model_name)
|
|
600
|
+
|
|
527
601
|
try:
|
|
528
|
-
if module and _is_model(
|
|
602
|
+
if module and _is_model(annotation):
|
|
529
603
|
if rf:
|
|
530
604
|
rf._is_model = True
|
|
531
605
|
|
|
@@ -534,7 +608,7 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
|
|
|
534
608
|
return obj
|
|
535
609
|
return _deserialize(model_deserializer, obj)
|
|
536
610
|
|
|
537
|
-
return functools.partial(_deserialize_model,
|
|
611
|
+
return functools.partial(_deserialize_model, annotation)
|
|
538
612
|
except Exception:
|
|
539
613
|
pass
|
|
540
614
|
|
|
@@ -552,22 +626,8 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
|
|
|
552
626
|
except AttributeError:
|
|
553
627
|
pass
|
|
554
628
|
|
|
555
|
-
if getattr(annotation, "__origin__", None) is typing.Union:
|
|
556
|
-
|
|
557
|
-
def _deserialize_with_union(union_annotation, obj):
|
|
558
|
-
for t in union_annotation.__args__:
|
|
559
|
-
try:
|
|
560
|
-
return _deserialize(t, obj, module, rf)
|
|
561
|
-
except DeserializationError:
|
|
562
|
-
pass
|
|
563
|
-
raise DeserializationError()
|
|
564
|
-
|
|
565
|
-
return functools.partial(_deserialize_with_union, annotation)
|
|
566
|
-
|
|
567
629
|
# is it optional?
|
|
568
630
|
try:
|
|
569
|
-
# right now, assuming we don't have unions, since we're getting rid of the only
|
|
570
|
-
# union we used to have in msrest models, which was union of str and enum
|
|
571
631
|
if any(a for a in annotation.__args__ if a == type(None)):
|
|
572
632
|
if_obj_deserializer = _get_deserialize_callable_from_annotation(
|
|
573
633
|
next(a for a in annotation.__args__ if a != type(None)), module, rf
|
|
@@ -582,14 +642,18 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
|
|
|
582
642
|
except AttributeError:
|
|
583
643
|
pass
|
|
584
644
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
645
|
+
if getattr(annotation, "__origin__", None) is typing.Union:
|
|
646
|
+
deserializers = [_get_deserialize_callable_from_annotation(arg, module, rf) for arg in annotation.__args__]
|
|
647
|
+
|
|
648
|
+
def _deserialize_with_union(deserializers, obj):
|
|
649
|
+
for deserializer in deserializers:
|
|
650
|
+
try:
|
|
651
|
+
return _deserialize(deserializer, obj)
|
|
652
|
+
except DeserializationError:
|
|
653
|
+
pass
|
|
654
|
+
raise DeserializationError()
|
|
655
|
+
|
|
656
|
+
return functools.partial(_deserialize_with_union, deserializers)
|
|
593
657
|
|
|
594
658
|
try:
|
|
595
659
|
if annotation._name == "Dict":
|
|
@@ -680,7 +744,7 @@ def _deserialize_with_callable(
|
|
|
680
744
|
# for unknown value, return raw value
|
|
681
745
|
return value
|
|
682
746
|
if isinstance(deserializer, type) and issubclass(deserializer, Model):
|
|
683
|
-
return deserializer._deserialize(value)
|
|
747
|
+
return deserializer._deserialize(value, [])
|
|
684
748
|
return typing.cast(typing.Callable[[typing.Any], typing.Any], deserializer)(value)
|
|
685
749
|
except Exception as e:
|
|
686
750
|
raise DeserializationError() from e
|
|
@@ -730,6 +794,8 @@ class _RestField:
|
|
|
730
794
|
item = obj.get(self._rest_name)
|
|
731
795
|
if item is None:
|
|
732
796
|
return item
|
|
797
|
+
if self._is_model:
|
|
798
|
+
return item
|
|
733
799
|
return _deserialize(self._type, _serialize(item, self._format), rf=self)
|
|
734
800
|
|
|
735
801
|
def __set__(self, obj: Model, value) -> None:
|
|
@@ -740,8 +806,11 @@ class _RestField:
|
|
|
740
806
|
except KeyError:
|
|
741
807
|
pass
|
|
742
808
|
return
|
|
743
|
-
if self._is_model
|
|
744
|
-
|
|
809
|
+
if self._is_model:
|
|
810
|
+
if not _is_model(value):
|
|
811
|
+
value = _deserialize(self._type, value)
|
|
812
|
+
obj.__setitem__(self._rest_name, value)
|
|
813
|
+
return
|
|
745
814
|
obj.__setitem__(self._rest_name, _serialize(value, self._format))
|
|
746
815
|
|
|
747
816
|
def _get_deserialize_callable_from_annotation(
|
|
@@ -82,15 +82,15 @@ def main() -> None:
|
|
|
82
82
|
"AUTOREST_PYTHON_ATTACH_VSCODE_DEBUG", False
|
|
83
83
|
):
|
|
84
84
|
try:
|
|
85
|
-
import
|
|
85
|
+
import debugpy # pylint: disable=import-outside-toplevel
|
|
86
86
|
except ImportError as exc:
|
|
87
87
|
raise SystemExit(
|
|
88
88
|
"Please pip install ptvsd in order to use VSCode debugging"
|
|
89
89
|
) from exc
|
|
90
90
|
|
|
91
91
|
# 5678 is the default attach port in the VS Code debug configurations
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
debugpy.listen(("localhost", 5678))
|
|
93
|
+
debugpy.wait_for_client()
|
|
94
94
|
breakpoint() # pylint: disable=undefined-variable,forgotten-debug-statement
|
|
95
95
|
|
|
96
96
|
_LOGGER.debug("Starting JSON RPC server")
|
|
@@ -1020,9 +1020,7 @@ class M4Reformatter(
|
|
|
1020
1020
|
retval = {
|
|
1021
1021
|
"type": OAUTH_TYPE,
|
|
1022
1022
|
"policy": {
|
|
1023
|
-
"type": "
|
|
1024
|
-
if self.azure_arm
|
|
1025
|
-
else "BearerTokenCredentialPolicy",
|
|
1023
|
+
"type": "BearerTokenCredentialPolicy",
|
|
1026
1024
|
"credentialScopes": credential_scopes,
|
|
1027
1025
|
},
|
|
1028
1026
|
}
|
|
@@ -1068,11 +1066,7 @@ class M4Reformatter(
|
|
|
1068
1066
|
return credential_scopes
|
|
1069
1067
|
|
|
1070
1068
|
def update_credential_from_flags(self) -> Dict[str, Any]:
|
|
1071
|
-
default_auth_policy =
|
|
1072
|
-
"ARMChallengeAuthenticationPolicy"
|
|
1073
|
-
if self.azure_arm
|
|
1074
|
-
else "BearerTokenCredentialPolicy"
|
|
1075
|
-
)
|
|
1069
|
+
default_auth_policy = "BearerTokenCredentialPolicy"
|
|
1076
1070
|
auth_policy = (
|
|
1077
1071
|
self._autorestapi.get_value("credential-default-policy-type")
|
|
1078
1072
|
or default_auth_policy
|
|
@@ -210,6 +210,10 @@ def headers_convert(yaml_data: Dict[str, Any], replace_data: Any) -> None:
|
|
|
210
210
|
class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
211
211
|
"""Add Python naming information."""
|
|
212
212
|
|
|
213
|
+
@property
|
|
214
|
+
def azure_arm(self) -> bool:
|
|
215
|
+
return self.options.get("azure-arm", False)
|
|
216
|
+
|
|
213
217
|
@property
|
|
214
218
|
def version_tolerant(self) -> bool:
|
|
215
219
|
return self.options.get("version-tolerant", True)
|
|
@@ -285,6 +289,18 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
285
289
|
yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
|
|
286
290
|
for parameter in yaml_data["parameters"]:
|
|
287
291
|
self.update_parameter(parameter)
|
|
292
|
+
if parameter["clientName"] == "credential":
|
|
293
|
+
policy = parameter["type"].get("policy")
|
|
294
|
+
if (
|
|
295
|
+
policy
|
|
296
|
+
and policy["type"] == "BearerTokenCredentialPolicy"
|
|
297
|
+
and self.azure_arm
|
|
298
|
+
):
|
|
299
|
+
policy["type"] = "ARMChallengeAuthenticationPolicy"
|
|
300
|
+
policy["credentialScopes"] = [
|
|
301
|
+
"https://management.azure.com/.default"
|
|
302
|
+
]
|
|
303
|
+
|
|
288
304
|
prop_name = yaml_data["name"]
|
|
289
305
|
if prop_name.endswith("Client"):
|
|
290
306
|
prop_name = prop_name[: len(prop_name) - len("Client")]
|
|
@@ -380,7 +396,6 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
380
396
|
add_overloads_for_body_param(yaml_data)
|
|
381
397
|
|
|
382
398
|
def _update_lro_operation_helper(self, yaml_data: Dict[str, Any]) -> None:
|
|
383
|
-
azure_arm = self.options.get("azure-arm", False)
|
|
384
399
|
for response in yaml_data.get("responses", []):
|
|
385
400
|
response["discriminator"] = "lro"
|
|
386
401
|
response["pollerSync"] = (
|
|
@@ -392,13 +407,13 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
392
407
|
if not response.get("pollingMethodSync"):
|
|
393
408
|
response["pollingMethodSync"] = (
|
|
394
409
|
"azure.mgmt.core.polling.arm_polling.ARMPolling"
|
|
395
|
-
if azure_arm
|
|
410
|
+
if self.azure_arm
|
|
396
411
|
else "azure.core.polling.base_polling.LROBasePolling"
|
|
397
412
|
)
|
|
398
413
|
if not response.get("pollingMethodAsync"):
|
|
399
414
|
response["pollingMethodAsync"] = (
|
|
400
415
|
"azure.mgmt.core.polling.async_arm_polling.AsyncARMPolling"
|
|
401
|
-
if azure_arm
|
|
416
|
+
if self.azure_arm
|
|
402
417
|
else "azure.core.polling.async_base_polling.AsyncLROBasePolling"
|
|
403
418
|
)
|
|
404
419
|
|