@autorest/python 5.12.6 → 5.15.0
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.
- package/ChangeLog.md +205 -125
- package/autorest/black/__init__.py +3 -0
- package/autorest/codegen/__init__.py +120 -48
- package/autorest/codegen/models/__init__.py +2 -1
- package/autorest/codegen/models/base_schema.py +2 -6
- package/autorest/codegen/models/client.py +6 -0
- package/autorest/codegen/models/code_model.py +43 -74
- package/autorest/codegen/models/constant_schema.py +7 -7
- package/autorest/codegen/models/credential_model.py +47 -0
- package/autorest/codegen/models/credential_schema.py +5 -4
- package/autorest/codegen/models/dictionary_schema.py +7 -7
- package/autorest/codegen/models/enum_schema.py +8 -39
- package/autorest/codegen/models/imports.py +3 -1
- package/autorest/codegen/models/list_schema.py +18 -8
- package/autorest/codegen/models/lro_operation.py +3 -3
- package/autorest/codegen/models/lro_paging_operation.py +3 -3
- package/autorest/codegen/models/object_schema.py +17 -13
- package/autorest/codegen/models/operation.py +38 -10
- package/autorest/codegen/models/operation_group.py +7 -2
- package/autorest/codegen/models/paging_operation.py +3 -3
- package/autorest/codegen/models/parameter.py +71 -22
- package/autorest/codegen/models/parameter_list.py +11 -5
- package/autorest/codegen/models/primitive_schemas.py +15 -25
- package/autorest/codegen/models/property.py +5 -5
- package/autorest/codegen/models/request_builder.py +4 -4
- package/autorest/codegen/models/request_builder_parameter.py +17 -5
- package/autorest/codegen/models/schema_response.py +23 -10
- package/autorest/codegen/models/utils.py +20 -0
- package/autorest/codegen/serializers/__init__.py +184 -87
- package/autorest/codegen/serializers/builder_serializer.py +113 -47
- package/autorest/codegen/serializers/client_serializer.py +16 -6
- package/autorest/codegen/serializers/general_serializer.py +28 -4
- package/autorest/codegen/serializers/import_serializer.py +1 -1
- package/autorest/codegen/serializers/metadata_serializer.py +1 -1
- package/autorest/codegen/serializers/model_base_serializer.py +8 -0
- package/autorest/codegen/serializers/model_python3_serializer.py +2 -2
- package/autorest/codegen/serializers/operation_groups_serializer.py +1 -0
- package/autorest/codegen/serializers/patch_serializer.py +12 -3
- package/autorest/codegen/serializers/utils.py +29 -4
- package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
- package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
- package/autorest/codegen/templates/README.md.jinja2 +105 -0
- package/autorest/codegen/templates/config.py.jinja2 +4 -4
- package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
- package/autorest/codegen/templates/enum.py.jinja2 +1 -1
- package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +1 -1
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
- package/autorest/codegen/templates/metadata.json.jinja2 +3 -3
- package/autorest/codegen/templates/model.py.jinja2 +1 -6
- package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
- package/autorest/codegen/templates/operation.py.jinja2 +2 -3
- package/autorest/codegen/templates/operation_group.py.jinja2 +20 -17
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +1 -1
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +4 -6
- package/autorest/codegen/templates/setup.py.jinja2 +79 -20
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/multiapi/models/imports.py +21 -11
- package/autorest/multiapi/serializers/import_serializer.py +3 -1
- package/autorest/namer/name_converter.py +1 -1
- package/package.json +2 -2
- package/run-python3.js +1 -7
- package/venvtools.py +2 -2
|
@@ -27,6 +27,7 @@ from ..models import (
|
|
|
27
27
|
SchemaResponse,
|
|
28
28
|
IOSchema,
|
|
29
29
|
ParameterStyle,
|
|
30
|
+
ParameterLocation
|
|
30
31
|
)
|
|
31
32
|
from . import utils
|
|
32
33
|
|
|
@@ -109,12 +110,6 @@ def _serialize_files_and_data_body(builder, param_name: str) -> List[str]:
|
|
|
109
110
|
retval.append("}")
|
|
110
111
|
return retval
|
|
111
112
|
|
|
112
|
-
def _pop_parameters_kwarg(
|
|
113
|
-
function_name: str,
|
|
114
|
-
kwarg_name: str,
|
|
115
|
-
) -> str:
|
|
116
|
-
return f'_{function_name}_parameters = kwargs.pop("{kwarg_name}", {{}}) # type: Dict[str, Any]'
|
|
117
|
-
|
|
118
113
|
def _serialize_grouped_body(builder) -> List[str]:
|
|
119
114
|
retval: List[str] = []
|
|
120
115
|
for grouped_parameter in builder.parameters.grouped:
|
|
@@ -152,12 +147,21 @@ def _serialize_flattened_body(builder) -> List[str]:
|
|
|
152
147
|
return retval
|
|
153
148
|
|
|
154
149
|
def _content_type_docstring(builder) -> str:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
150
|
+
content_types = [f'"{c}"' for c in builder.parameters.content_types]
|
|
151
|
+
if len(content_types) == 2:
|
|
152
|
+
possible_values_str = " or ".join(content_types)
|
|
153
|
+
else:
|
|
154
|
+
possible_values_str = ", ".join(
|
|
155
|
+
content_types[: len(content_types) - 1]
|
|
156
|
+
) + f", and {content_types[-1]}"
|
|
157
|
+
default_value = next(
|
|
158
|
+
p for p in builder.parameters.method if p.rest_api_name == "Content-Type"
|
|
159
|
+
).default_value_declaration
|
|
160
|
+
return (
|
|
161
|
+
":keyword content_type: Media type of the body sent to the API. " +
|
|
162
|
+
f"Known values are: {possible_values_str}. " +
|
|
163
|
+
f"Default value is {default_value}."
|
|
159
164
|
)
|
|
160
|
-
return content_type_str
|
|
161
165
|
|
|
162
166
|
class _BuilderSerializerProtocol(ABC):
|
|
163
167
|
@property
|
|
@@ -304,13 +308,14 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
|
|
|
304
308
|
description_list.append(
|
|
305
309
|
f":{param.docstring_type_keyword} { param.serialized_name }: { param.docstring_type }"
|
|
306
310
|
)
|
|
307
|
-
try:
|
|
308
|
-
request_builder: RequestBuilder = cast(Operation, builder).request_builder
|
|
309
|
-
except AttributeError:
|
|
310
|
-
request_builder = cast(RequestBuilder, builder)
|
|
311
311
|
|
|
312
|
-
if len(
|
|
313
|
-
description_list
|
|
312
|
+
if len(builder.parameters.content_types) > 1:
|
|
313
|
+
description_list = [
|
|
314
|
+
_content_type_docstring(builder) if l.startswith(":keyword content_type:") else l
|
|
315
|
+
for l in description_list
|
|
316
|
+
]
|
|
317
|
+
if not any(l for l in description_list if l.startswith(":keyword content_type:")):
|
|
318
|
+
description_list.append(_content_type_docstring(builder))
|
|
314
319
|
return description_list
|
|
315
320
|
|
|
316
321
|
def param_description_and_response_docstring(self, builder) -> List[str]:
|
|
@@ -400,10 +405,11 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
|
|
|
400
405
|
...
|
|
401
406
|
|
|
402
407
|
def _serialize_parameter(
|
|
403
|
-
self, param: Parameter,
|
|
408
|
+
self, param: Parameter, kwarg_name: str
|
|
404
409
|
) -> List[str]:
|
|
405
|
-
|
|
406
|
-
|
|
410
|
+
function_name = "header" if kwarg_name == "headers" else "query"
|
|
411
|
+
set_parameter = "_{}['{}'] = {}".format(
|
|
412
|
+
kwarg_name,
|
|
407
413
|
param.rest_api_name,
|
|
408
414
|
utils.build_serialize_data_call(param, function_name, self.serializer_name)
|
|
409
415
|
)
|
|
@@ -423,10 +429,6 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
|
|
|
423
429
|
template.extend(f"response.json() == {response_body}".splitlines())
|
|
424
430
|
return template
|
|
425
431
|
|
|
426
|
-
|
|
427
|
-
def pop_kwargs_from_signature(self, builder) -> List[str]:
|
|
428
|
-
return utils.pop_kwargs_from_signature(self._get_kwargs_to_pop(builder))
|
|
429
|
-
|
|
430
432
|
def serialize_path(self, builder) -> List[str]:
|
|
431
433
|
return utils.serialize_path(builder.parameters.path, self.serializer_name)
|
|
432
434
|
|
|
@@ -452,6 +454,21 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
|
|
|
452
454
|
def serializer_name(self) -> str:
|
|
453
455
|
return "_SERIALIZER"
|
|
454
456
|
|
|
457
|
+
@staticmethod
|
|
458
|
+
def declare_non_inputtable_constants(builder) -> List[str]:
|
|
459
|
+
def _get_value(param: Parameter):
|
|
460
|
+
if param.location in [ParameterLocation.Header, ParameterLocation.Query]:
|
|
461
|
+
kwarg_dict = "headers" if param.location == ParameterLocation.Header else "params"
|
|
462
|
+
return f"_{kwarg_dict}.pop('{param.rest_api_name}', {param.constant_declaration})"
|
|
463
|
+
return f"{param.constant_declaration}"
|
|
464
|
+
return [
|
|
465
|
+
f"{p.serialized_name} = {_get_value(p)}"
|
|
466
|
+
for p in builder.parameters.constant
|
|
467
|
+
if p.original_parameter is None and
|
|
468
|
+
p.in_method_code and
|
|
469
|
+
not p.in_method_signature
|
|
470
|
+
]
|
|
471
|
+
|
|
455
472
|
def want_example_template(self, builder) -> bool:
|
|
456
473
|
if self.code_model.options["builders_visibility"] != "public":
|
|
457
474
|
return False # if we're not exposing rest layer, don't need to generate
|
|
@@ -496,14 +513,24 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
|
|
|
496
513
|
def _body_params_to_pass_to_request_creation(self, builder) -> List[str]:
|
|
497
514
|
...
|
|
498
515
|
|
|
516
|
+
def pop_kwargs_from_signature(self, builder) -> List[str]:
|
|
517
|
+
return utils.pop_kwargs_from_signature(
|
|
518
|
+
self._get_kwargs_to_pop(builder),
|
|
519
|
+
check_kwarg_dict=True,
|
|
520
|
+
pop_headers_kwarg=utils.PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.headers)
|
|
521
|
+
else utils.PopKwargType.NO,
|
|
522
|
+
pop_params_kwarg=utils.PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.query)
|
|
523
|
+
else utils.PopKwargType.NO,
|
|
524
|
+
)
|
|
525
|
+
|
|
499
526
|
def create_http_request(self, builder) -> List[str]:
|
|
500
527
|
retval = ["return HttpRequest("]
|
|
501
528
|
retval.append(f' method="{builder.method}",')
|
|
502
529
|
retval.append(" url=_url,")
|
|
503
530
|
if builder.parameters.query:
|
|
504
|
-
retval.append(" params=
|
|
531
|
+
retval.append(" params=_params,")
|
|
505
532
|
if builder.parameters.headers:
|
|
506
|
-
retval.append(" headers=
|
|
533
|
+
retval.append(" headers=_headers,")
|
|
507
534
|
if builder.parameters.has_body:
|
|
508
535
|
retval.extend([
|
|
509
536
|
f" {body_kwarg}={body_kwarg},"
|
|
@@ -515,21 +542,19 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
|
|
|
515
542
|
|
|
516
543
|
def serialize_headers(self, builder) -> List[str]:
|
|
517
544
|
retval = ["# Construct headers"]
|
|
518
|
-
retval.append(_pop_parameters_kwarg("header", "headers"))
|
|
519
545
|
for parameter in builder.parameters.headers:
|
|
520
546
|
retval.extend(self._serialize_parameter(
|
|
521
547
|
parameter,
|
|
522
|
-
|
|
548
|
+
kwarg_name="headers",
|
|
523
549
|
))
|
|
524
550
|
return retval
|
|
525
551
|
|
|
526
552
|
def serialize_query(self, builder) -> List[str]:
|
|
527
553
|
retval = ["# Construct parameters"]
|
|
528
|
-
retval.append(_pop_parameters_kwarg("query", "params"))
|
|
529
554
|
for parameter in builder.parameters.query:
|
|
530
555
|
retval.extend(self._serialize_parameter(
|
|
531
556
|
parameter,
|
|
532
|
-
|
|
557
|
+
kwarg_name="params",
|
|
533
558
|
))
|
|
534
559
|
return retval
|
|
535
560
|
|
|
@@ -633,7 +658,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
633
658
|
return "bool"
|
|
634
659
|
response_body_annotations: OrderedSet[str] = {}
|
|
635
660
|
for response in [r for r in builder.responses if r.has_body]:
|
|
636
|
-
response_body_annotations[response.
|
|
661
|
+
response_body_annotations[response.type_annotation(is_operation_file=True)] = None
|
|
637
662
|
response_str = ", ".join(response_body_annotations.keys()) or "None"
|
|
638
663
|
if len(response_body_annotations) > 1:
|
|
639
664
|
response_str = f"Union[{response_str}]"
|
|
@@ -641,6 +666,19 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
641
666
|
response_str = f"Optional[{response_str}]"
|
|
642
667
|
return response_str
|
|
643
668
|
|
|
669
|
+
def pop_kwargs_from_signature(self, builder) -> List[str]:
|
|
670
|
+
kwargs_to_pop = self._get_kwargs_to_pop(builder)
|
|
671
|
+
kwargs = utils.pop_kwargs_from_signature(
|
|
672
|
+
kwargs_to_pop,
|
|
673
|
+
check_kwarg_dict=True,
|
|
674
|
+
pop_headers_kwarg=utils.PopKwargType.CASE_INSENSITIVE if builder.has_kwargs_to_pop_with_default(
|
|
675
|
+
kwargs_to_pop, ParameterLocation.Header) else utils.PopKwargType.SIMPLE,
|
|
676
|
+
pop_params_kwarg=utils.PopKwargType.CASE_INSENSITIVE if builder.has_kwargs_to_pop_with_default(
|
|
677
|
+
kwargs_to_pop, ParameterLocation.Query) else utils.PopKwargType.SIMPLE,
|
|
678
|
+
)
|
|
679
|
+
kwargs.append(f"cls = kwargs.pop('cls', None) {self.cls_type_annotation(builder)}")
|
|
680
|
+
return kwargs
|
|
681
|
+
|
|
644
682
|
def cls_type_annotation(self, builder) -> str:
|
|
645
683
|
return f"# type: ClsType[{self._response_type_annotation(builder, modify_if_head_as_boolean=False)}]"
|
|
646
684
|
|
|
@@ -769,6 +807,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
769
807
|
if len(body_kwargs) == 1:
|
|
770
808
|
retval.extend(self._set_body_content_kwarg(builder, builder.parameters.body[0], body_kwargs[0]))
|
|
771
809
|
else:
|
|
810
|
+
retval.append('content_type = content_type or ""')
|
|
772
811
|
for idx, body_kwarg in enumerate(body_kwargs):
|
|
773
812
|
body_param = next(
|
|
774
813
|
b for b in builder_params
|
|
@@ -788,6 +827,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
788
827
|
builder,
|
|
789
828
|
request_builder: RequestBuilder,
|
|
790
829
|
template_url: Optional[str] = None,
|
|
830
|
+
is_next_request: bool = False,
|
|
791
831
|
) -> List[str]:
|
|
792
832
|
retval = []
|
|
793
833
|
if len(builder.body_kwargs_to_pass_to_request_builder) > 1:
|
|
@@ -827,11 +867,23 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
827
867
|
parameter.serialized_name not in builder.body_kwargs_to_pass_to_request_builder
|
|
828
868
|
):
|
|
829
869
|
continue
|
|
870
|
+
if (
|
|
871
|
+
is_next_request and
|
|
872
|
+
not bool(builder.next_request_builder) and
|
|
873
|
+
not self.code_model.options["reformat_next_link"] and
|
|
874
|
+
parameter.location == ParameterLocation.Query
|
|
875
|
+
):
|
|
876
|
+
# if we don't want to reformat query parameters for next link calls
|
|
877
|
+
# in paging operations with a single swagger operation defintion,
|
|
878
|
+
# we skip passing query params when building the next request
|
|
879
|
+
continue
|
|
830
880
|
high_level_name = cast(RequestBuilderParameter, parameter).name_in_high_level_operation
|
|
831
881
|
retval.append(f" {parameter.serialized_name}={high_level_name},")
|
|
832
882
|
if not self.code_model.options["version_tolerant"]:
|
|
833
883
|
template_url = template_url or f"self.{builder.name}.metadata['url']"
|
|
834
884
|
retval.append(f" template_url={template_url},")
|
|
885
|
+
retval.append(' headers=_headers,')
|
|
886
|
+
retval.append(' params=_params,')
|
|
835
887
|
retval.append(f")")
|
|
836
888
|
if not self.code_model.options["version_tolerant"]:
|
|
837
889
|
pass_files = ""
|
|
@@ -844,7 +896,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
844
896
|
if self.code_model.options["version_tolerant"] and template_url:
|
|
845
897
|
url_to_format = template_url
|
|
846
898
|
retval.append(
|
|
847
|
-
"request.url = self._client.format_url({}{})".format(
|
|
899
|
+
"request.url = self._client.format_url({}{}) # type: ignore".format(
|
|
848
900
|
url_to_format,
|
|
849
901
|
", **path_format_arguments" if builder.parameters.path else ""
|
|
850
902
|
)
|
|
@@ -879,12 +931,11 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
879
931
|
retval.append(f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)")
|
|
880
932
|
else:
|
|
881
933
|
is_xml = any(["xml" in ct for ct in response.content_types])
|
|
882
|
-
deserialized_value = ""
|
|
883
934
|
deserialized_value = "ET.fromstring(response.text())" if is_xml else "response.json()"
|
|
884
935
|
retval.append(f"if response.content:")
|
|
885
936
|
retval.append(f" deserialized = {deserialized_value}")
|
|
886
937
|
retval.append("else:")
|
|
887
|
-
retval.append(" deserialized = None")
|
|
938
|
+
retval.append(f" deserialized = None")
|
|
888
939
|
return retval
|
|
889
940
|
|
|
890
941
|
@property
|
|
@@ -932,14 +983,18 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
932
983
|
builder.responses[0]
|
|
933
984
|
))
|
|
934
985
|
retval.append("")
|
|
986
|
+
if builder.has_optional_return_type or self.code_model.options["models_mode"]:
|
|
987
|
+
deserialized = "deserialized"
|
|
988
|
+
else:
|
|
989
|
+
deserialized = f"cast({self._response_type_annotation(builder)}, deserialized)"
|
|
935
990
|
retval.append("if cls:")
|
|
936
991
|
retval.append(" return cls(pipeline_response, {}, {})".format(
|
|
937
|
-
|
|
992
|
+
deserialized if builder.has_response_body else "None",
|
|
938
993
|
"response_headers" if builder.any_response_has_headers else '{}'
|
|
939
994
|
))
|
|
940
995
|
if builder.has_response_body:
|
|
941
996
|
retval.append("")
|
|
942
|
-
retval.append("return deserialized")
|
|
997
|
+
retval.append(f"return {deserialized}")
|
|
943
998
|
if builder.request_builder.method == 'HEAD' and self.code_model.options['head_as_boolean']:
|
|
944
999
|
retval.append("return 200 <= response.status_code <= 299")
|
|
945
1000
|
return retval
|
|
@@ -988,7 +1043,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
|
|
|
988
1043
|
else:
|
|
989
1044
|
retval.append(" 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError")
|
|
990
1045
|
retval.append("}")
|
|
991
|
-
retval.append("error_map.update(kwargs.pop('error_map', {}))")
|
|
1046
|
+
retval.append("error_map.update(kwargs.pop('error_map', {}) or {})")
|
|
992
1047
|
return retval
|
|
993
1048
|
|
|
994
1049
|
@staticmethod
|
|
@@ -1073,11 +1128,13 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
|
|
|
1073
1128
|
else:
|
|
1074
1129
|
request_builder = builder.request_builder
|
|
1075
1130
|
template_url = "next_link"
|
|
1131
|
+
|
|
1076
1132
|
request_builder = builder.next_request_builder or builder.request_builder
|
|
1077
1133
|
return self._call_request_builder_helper(
|
|
1078
1134
|
builder,
|
|
1079
1135
|
request_builder,
|
|
1080
1136
|
template_url=template_url,
|
|
1137
|
+
is_next_request=True
|
|
1081
1138
|
)
|
|
1082
1139
|
|
|
1083
1140
|
def _prepare_request_callback(self, builder) -> List[str]:
|
|
@@ -1161,7 +1218,7 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
|
|
|
1161
1218
|
return retval
|
|
1162
1219
|
|
|
1163
1220
|
def set_up_params_for_pager(self, builder) -> List[str]:
|
|
1164
|
-
retval = [
|
|
1221
|
+
retval = []
|
|
1165
1222
|
retval.extend(self.error_map(builder))
|
|
1166
1223
|
retval.extend(self._prepare_request_callback(builder))
|
|
1167
1224
|
retval.append("")
|
|
@@ -1252,19 +1309,20 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
|
|
|
1252
1309
|
|
|
1253
1310
|
def initial_call(self, builder) -> List[str]:
|
|
1254
1311
|
retval = [f"polling = kwargs.pop('polling', True) # type: Union[bool, {self._polling_method_type}]"]
|
|
1255
|
-
retval.append(f"cls = kwargs.pop('cls', None) {self.cls_type_annotation(builder)}")
|
|
1256
1312
|
retval.append("lro_delay = kwargs.pop(")
|
|
1257
1313
|
retval.append(" 'polling_interval',")
|
|
1258
1314
|
retval.append(" self._config.polling_interval")
|
|
1259
1315
|
retval.append(")")
|
|
1260
1316
|
retval.append("cont_token = kwargs.pop('continuation_token', None) # type: Optional[str]")
|
|
1261
1317
|
retval.append("if cont_token is None:")
|
|
1262
|
-
retval.append(f" raw_result = {self._call_method}self.{builder.initial_operation.name}(")
|
|
1318
|
+
retval.append(f" raw_result = {self._call_method}self.{builder.initial_operation.name}( # type: ignore")
|
|
1263
1319
|
retval.extend([
|
|
1264
1320
|
f" {parameter.serialized_name}={parameter.serialized_name},"
|
|
1265
1321
|
for parameter in builder.parameters.method
|
|
1266
1322
|
])
|
|
1267
1323
|
retval.append(" cls=lambda x,y,z: x,")
|
|
1324
|
+
retval.append(" headers=_headers,")
|
|
1325
|
+
retval.append(" params=_params,")
|
|
1268
1326
|
retval.append(" **kwargs")
|
|
1269
1327
|
retval.append(" )")
|
|
1270
1328
|
retval.append("kwargs.pop('error_map', None)")
|
|
@@ -1273,20 +1331,27 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
|
|
|
1273
1331
|
def return_lro_poller(self, builder) -> List[str]:
|
|
1274
1332
|
retval = []
|
|
1275
1333
|
lro_options_str = (
|
|
1276
|
-
"
|
|
1334
|
+
"lro_options={'final-state-via': '" + builder.lro_options['final-state-via'] + "'},"
|
|
1277
1335
|
if builder.lro_options else ""
|
|
1278
1336
|
)
|
|
1279
1337
|
path_format_arguments_str = ""
|
|
1280
1338
|
if builder.parameters.path:
|
|
1281
|
-
path_format_arguments_str = "
|
|
1339
|
+
path_format_arguments_str = "path_format_arguments=path_format_arguments,"
|
|
1282
1340
|
retval.extend(self.serialize_path(builder))
|
|
1283
1341
|
retval.append("")
|
|
1284
|
-
retval.
|
|
1285
|
-
|
|
1286
|
-
f"(
|
|
1342
|
+
retval.extend([
|
|
1343
|
+
"if polling is True:",
|
|
1344
|
+
f" polling_method = cast({self._polling_method_type}, {self._default_polling_method(builder)}(",
|
|
1345
|
+
" lro_delay,",
|
|
1346
|
+
f" {lro_options_str}",
|
|
1347
|
+
f" {path_format_arguments_str}",
|
|
1348
|
+
" **kwargs",
|
|
1349
|
+
f")) # type: {self._polling_method_type}",
|
|
1350
|
+
]
|
|
1287
1351
|
)
|
|
1288
1352
|
retval.append(
|
|
1289
|
-
f"elif polling is False: polling_method = {self.
|
|
1353
|
+
f"elif polling is False: polling_method = cast({self._polling_method_type}, "
|
|
1354
|
+
f"{self._default_no_polling_method(builder)}())"
|
|
1290
1355
|
)
|
|
1291
1356
|
retval.append("else: polling_method = polling")
|
|
1292
1357
|
retval.append("if cont_token:")
|
|
@@ -1307,7 +1372,8 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
|
|
|
1307
1372
|
if builder.lro_response:
|
|
1308
1373
|
if builder.lro_response.has_headers:
|
|
1309
1374
|
retval.append(" response_headers = {}")
|
|
1310
|
-
|
|
1375
|
+
if not self.code_model.options["models_mode"] or builder.lro_response.has_headers:
|
|
1376
|
+
retval.append(" response = pipeline_response.http_response")
|
|
1311
1377
|
retval.extend([
|
|
1312
1378
|
f" {line}"
|
|
1313
1379
|
for line in self.response_headers_and_deserialization(builder.lro_response)
|
|
@@ -32,9 +32,14 @@ class ClientSerializer:
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
|
|
35
|
-
return utils.pop_kwargs_from_signature(
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
return utils.pop_kwargs_from_signature(
|
|
36
|
+
self.code_model.service_client.parameters.kwargs_to_pop(
|
|
37
|
+
async_mode or self.is_python3_file,
|
|
38
|
+
),
|
|
39
|
+
check_kwarg_dict=False,
|
|
40
|
+
pop_headers_kwarg=utils.PopKwargType.NO,
|
|
41
|
+
pop_params_kwarg=utils.PopKwargType.NO,
|
|
42
|
+
)
|
|
38
43
|
|
|
39
44
|
def class_definition(self, async_mode) -> str:
|
|
40
45
|
class_name = self.code_model.class_name
|
|
@@ -212,9 +217,14 @@ class ConfigSerializer:
|
|
|
212
217
|
)
|
|
213
218
|
|
|
214
219
|
def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
|
|
215
|
-
return utils.pop_kwargs_from_signature(
|
|
216
|
-
|
|
217
|
-
|
|
220
|
+
return utils.pop_kwargs_from_signature(
|
|
221
|
+
self.code_model.global_parameters.config_kwargs_to_pop(
|
|
222
|
+
async_mode or self.is_python3_file
|
|
223
|
+
),
|
|
224
|
+
check_kwarg_dict=False,
|
|
225
|
+
pop_headers_kwarg=utils.PopKwargType.NO,
|
|
226
|
+
pop_params_kwarg=utils.PopKwargType.NO,
|
|
227
|
+
)
|
|
218
228
|
|
|
219
229
|
def set_constants(self) -> List[str]:
|
|
220
230
|
return [
|
|
@@ -50,7 +50,7 @@ class GeneralSerializer:
|
|
|
50
50
|
|
|
51
51
|
if (
|
|
52
52
|
self.code_model.options['credential'] and
|
|
53
|
-
isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
53
|
+
isinstance(self.code_model.credential_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
54
54
|
):
|
|
55
55
|
self._correct_credential_parameter()
|
|
56
56
|
|
|
@@ -77,12 +77,33 @@ class GeneralSerializer:
|
|
|
77
77
|
ImportType.AZURECORE,
|
|
78
78
|
)
|
|
79
79
|
|
|
80
|
+
if self.code_model.need_mixin_abc:
|
|
81
|
+
file_import.add_submodule_import(
|
|
82
|
+
"abc",
|
|
83
|
+
"ABC",
|
|
84
|
+
ImportType.STDLIB,
|
|
85
|
+
)
|
|
86
|
+
file_import.add_submodule_import(
|
|
87
|
+
"azure.core",
|
|
88
|
+
f"{'Async' if self.async_mode else ''}PipelineClient",
|
|
89
|
+
ImportType.AZURECORE,
|
|
90
|
+
TypingSection.TYPING,
|
|
91
|
+
)
|
|
92
|
+
file_import.add_submodule_import(
|
|
93
|
+
"._configuration",
|
|
94
|
+
f"{self.code_model.class_name}Configuration",
|
|
95
|
+
ImportType.LOCAL
|
|
96
|
+
)
|
|
97
|
+
file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING)
|
|
98
|
+
file_import.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING)
|
|
99
|
+
|
|
80
100
|
return template.render(
|
|
81
101
|
code_model=self.code_model,
|
|
82
102
|
imports=FileImportSerializer(
|
|
83
103
|
file_import,
|
|
84
104
|
is_python3_file=self.async_mode,
|
|
85
|
-
)
|
|
105
|
+
),
|
|
106
|
+
async_mode=self.async_mode,
|
|
86
107
|
)
|
|
87
108
|
|
|
88
109
|
|
|
@@ -95,7 +116,7 @@ class GeneralSerializer:
|
|
|
95
116
|
|
|
96
117
|
if (
|
|
97
118
|
self.code_model.options['credential'] and
|
|
98
|
-
isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
119
|
+
isinstance(self.code_model.credential_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
99
120
|
):
|
|
100
121
|
self._correct_credential_parameter()
|
|
101
122
|
|
|
@@ -119,4 +140,7 @@ class GeneralSerializer:
|
|
|
119
140
|
|
|
120
141
|
def serialize_setup_file(self) -> str:
|
|
121
142
|
template = self.env.get_template("setup.py.jinja2")
|
|
122
|
-
|
|
143
|
+
params = {}
|
|
144
|
+
params.update(self.code_model.options)
|
|
145
|
+
params.update(self.code_model.package_dependency)
|
|
146
|
+
return template.render(code_model=self.code_model, **params)
|
|
@@ -12,7 +12,7 @@ def _serialize_package(
|
|
|
12
12
|
) -> str:
|
|
13
13
|
buffer = []
|
|
14
14
|
if any(i for i in imports if i.submodule_name is None):
|
|
15
|
-
buffer.append(f"import {imports[0].module_name}")
|
|
15
|
+
buffer.append(f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}")
|
|
16
16
|
else:
|
|
17
17
|
import_str = ", ".join(sorted([
|
|
18
18
|
f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
|
|
@@ -145,7 +145,7 @@ class MetadataSerializer:
|
|
|
145
145
|
async_global_parameters = self.code_model.global_parameters
|
|
146
146
|
if (
|
|
147
147
|
self.code_model.options['credential'] and
|
|
148
|
-
isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
148
|
+
isinstance(self.code_model.credential_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
149
149
|
):
|
|
150
150
|
# this ensures that the TokenCredentialSchema showing up in the list of code model's global parameters
|
|
151
151
|
# is sync. This way we only have to make a copy for an async_credential
|
|
@@ -40,6 +40,7 @@ class ModelBaseSerializer:
|
|
|
40
40
|
init_args=self.init_args,
|
|
41
41
|
input_documentation_string=ModelBaseSerializer.input_documentation_string,
|
|
42
42
|
variable_documentation_string=ModelBaseSerializer.variable_documentation_string,
|
|
43
|
+
declare_model=ModelBaseSerializer.declare_model,
|
|
43
44
|
)
|
|
44
45
|
|
|
45
46
|
def imports(self) -> FileImport:
|
|
@@ -62,6 +63,13 @@ class ModelBaseSerializer:
|
|
|
62
63
|
properties_to_initialize = model.properties
|
|
63
64
|
return properties_to_initialize
|
|
64
65
|
|
|
66
|
+
@staticmethod
|
|
67
|
+
def declare_model(model: ObjectSchema) -> str:
|
|
68
|
+
basename = "msrest.serialization.Model"
|
|
69
|
+
if model.base_models:
|
|
70
|
+
basename = ", ".join([cast(ObjectSchema, m).name for m in model.base_models])
|
|
71
|
+
return f"class {model.name}({basename}):"
|
|
72
|
+
|
|
65
73
|
@staticmethod
|
|
66
74
|
def input_documentation_string(prop: Property) -> List[str]:
|
|
67
75
|
# building the param line of the property doc
|
|
@@ -46,11 +46,11 @@ class ModelPython3Serializer(ModelBaseSerializer):
|
|
|
46
46
|
return ", ".join(properties_to_pass_to_super)
|
|
47
47
|
|
|
48
48
|
def required_property_no_default_init(self, prop: Property) -> str:
|
|
49
|
-
return f"{prop.name}: {prop.type_annotation}"
|
|
49
|
+
return f"{prop.name}: {prop.type_annotation()}"
|
|
50
50
|
|
|
51
51
|
def optional_property_init(self, prop: Property) -> str:
|
|
52
52
|
default = prop.default_value_declaration
|
|
53
|
-
return f"{prop.name}: {prop.type_annotation} = {default}"
|
|
53
|
+
return f"{prop.name}: {prop.type_annotation()} = {default}"
|
|
54
54
|
|
|
55
55
|
def initialize_standard_arg(self, prop: Property) -> str:
|
|
56
56
|
return f"self.{prop.name} = {prop.name}"
|
|
@@ -43,6 +43,7 @@ class OperationGroupsSerializer:
|
|
|
43
43
|
for operation_group in operation_groups:
|
|
44
44
|
imports.merge(operation_group.imports(
|
|
45
45
|
async_mode=self.async_mode,
|
|
46
|
+
is_python3_file=self.is_python3_file,
|
|
46
47
|
))
|
|
47
48
|
|
|
48
49
|
template = self.env.get_or_select_template("operation_groups_container.py.jinja2")
|
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from jinja2 import Environment
|
|
7
|
-
|
|
7
|
+
from .import_serializer import FileImportSerializer
|
|
8
|
+
from ..models import CodeModel, FileImport, ImportType, TypingSection
|
|
8
9
|
|
|
9
10
|
class PatchSerializer:
|
|
10
|
-
def __init__(self, env: Environment) -> None:
|
|
11
|
+
def __init__(self, env: Environment, code_model: CodeModel) -> None:
|
|
11
12
|
self.env = env
|
|
13
|
+
self.code_model = code_model
|
|
12
14
|
|
|
13
15
|
def serialize(self) -> str:
|
|
14
16
|
template = self.env.get_template("patch.py.jinja2")
|
|
15
|
-
|
|
17
|
+
imports = FileImport()
|
|
18
|
+
imports.add_submodule_import("typing", "List", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
19
|
+
is_python3_file = self.code_model.options["python3_only"]
|
|
20
|
+
return template.render(
|
|
21
|
+
code_model=self.code_model,
|
|
22
|
+
imports=FileImportSerializer(imports, is_python3_file=is_python3_file),
|
|
23
|
+
is_python3_file=is_python3_file,
|
|
24
|
+
)
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
from enum import Enum, auto
|
|
6
7
|
from typing import List
|
|
7
|
-
from ..models import ParameterStyle, ListSchema, Parameter
|
|
8
|
+
from ..models import ParameterStyle, ListSchema, Parameter, ParameterLocation
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def serialize_method(
|
|
@@ -102,16 +103,40 @@ def method_signature_and_response_type_annotation_template(
|
|
|
102
103
|
return f"{method_signature} -> {response_type_annotation}:"
|
|
103
104
|
return f"{method_signature}:\n # type: (...) -> {response_type_annotation}"
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
class PopKwargType(Enum):
|
|
107
|
+
NO = auto()
|
|
108
|
+
SIMPLE = auto()
|
|
109
|
+
CASE_INSENSITIVE = auto()
|
|
110
|
+
|
|
111
|
+
def pop_kwargs_from_signature(
|
|
112
|
+
kwargs_to_pop: List[Parameter],
|
|
113
|
+
check_kwarg_dict: bool,
|
|
114
|
+
pop_headers_kwarg: PopKwargType,
|
|
115
|
+
pop_params_kwarg: PopKwargType,
|
|
116
|
+
) -> List[str]:
|
|
106
117
|
retval = []
|
|
118
|
+
def append_pop_kwarg(key: str, pop_type: PopKwargType) -> None:
|
|
119
|
+
if PopKwargType.CASE_INSENSITIVE == pop_type:
|
|
120
|
+
retval.append(f'_{key} = case_insensitive_dict(kwargs.pop("{key}", {{}}) or {{}})')
|
|
121
|
+
elif PopKwargType.SIMPLE == pop_type:
|
|
122
|
+
retval.append(f'_{key} = kwargs.pop("{key}", {{}}) or {{}}')
|
|
123
|
+
append_pop_kwarg("headers", pop_headers_kwarg)
|
|
124
|
+
append_pop_kwarg("params", pop_params_kwarg)
|
|
125
|
+
if pop_headers_kwarg != PopKwargType.NO or pop_params_kwarg != PopKwargType.NO:
|
|
126
|
+
retval.append("")
|
|
107
127
|
for kwarg in kwargs_to_pop:
|
|
108
128
|
if kwarg.has_default_value:
|
|
129
|
+
default_value = kwarg.default_value_declaration
|
|
130
|
+
if check_kwarg_dict and (kwarg.location in [ParameterLocation.Header, ParameterLocation.Query]):
|
|
131
|
+
kwarg_dict = "headers" if kwarg.location == ParameterLocation.Header else "params"
|
|
132
|
+
default_value = f"_{kwarg_dict}.pop('{kwarg.rest_api_name}', {default_value})"
|
|
109
133
|
retval.append(
|
|
110
134
|
f"{kwarg.serialized_name} = kwargs.pop('{kwarg.serialized_name}', "
|
|
111
|
-
+ f"{
|
|
135
|
+
+ f"{default_value}) # type: {kwarg.type_annotation(is_operation_file=True)}"
|
|
112
136
|
)
|
|
113
137
|
else:
|
|
138
|
+
type_annot = kwarg.type_annotation(is_operation_file=True)
|
|
114
139
|
retval.append(
|
|
115
|
-
f"{kwarg.serialized_name} = kwargs.pop('{kwarg.serialized_name}') # type: {
|
|
140
|
+
f"{kwarg.serialized_name} = kwargs.pop('{kwarg.serialized_name}') # type: {type_annot}"
|
|
116
141
|
)
|
|
117
142
|
return retval
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Copyright (c) Microsoft Corporation.
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|