@autorest/python 6.4.2 → 6.4.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.
- package/autorest/_utils.py +0 -1
- package/autorest/codegen/__init__.py +0 -1
- package/autorest/codegen/models/model_type.py +0 -1
- package/autorest/codegen/models/operation.py +4 -0
- package/autorest/codegen/models/paging_operation.py +15 -2
- package/autorest/codegen/models/parameter_list.py +17 -15
- package/autorest/codegen/models/request_builder.py +9 -9
- package/autorest/codegen/serializers/builder_serializer.py +47 -24
- package/autorest/codegen/serializers/general_serializer.py +0 -1
- package/autorest/codegen/serializers/import_serializer.py +4 -4
- package/autorest/codegen/serializers/metadata_serializer.py +25 -0
- package/autorest/codegen/templates/metadata.json.jinja2 +2 -0
- package/autorest/jsonrpc/server.py +0 -1
- package/autorest/m4reformatter/__init__.py +13 -0
- package/autorest/multiapi/models/operation_mixin_group.py +14 -0
- package/autorest/multiapi/serializers/__init__.py +2 -1
- package/autorest/multiapi/serializers/import_serializer.py +3 -2
- package/autorest/preprocess/__init__.py +83 -71
- package/autorest/preprocess/helpers.py +0 -15
- package/autorest/preprocess/python_mappings.py +2 -0
- package/package.json +1 -1
- package/requirements.txt +1 -1
package/autorest/_utils.py
CHANGED
|
@@ -17,7 +17,6 @@ from ._utils import DEFAULT_HEADER_TEXT
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
20
|
-
|
|
21
20
|
if options["builders_visibility"] not in ["public", "hidden", "embedded"]:
|
|
22
21
|
raise ValueError(
|
|
23
22
|
"The value of --builders-visibility must be either 'public', 'hidden', "
|
|
@@ -163,7 +163,6 @@ class ModelType( # pylint: disable=abstract-method
|
|
|
163
163
|
)
|
|
164
164
|
|
|
165
165
|
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
166
|
-
|
|
167
166
|
is_polymorphic_subtype = (
|
|
168
167
|
self.discriminator_value and not self.discriminated_subtypes
|
|
169
168
|
)
|
|
@@ -83,6 +83,10 @@ class OperationBase( # pylint: disable=too-many-public-methods
|
|
|
83
83
|
)
|
|
84
84
|
self.include_documentation: bool = not self.is_lro_initial_operation
|
|
85
85
|
|
|
86
|
+
@property
|
|
87
|
+
def expose_stream_keyword(self) -> bool:
|
|
88
|
+
return self.yaml_data.get("exposeStreamKeyword", False)
|
|
89
|
+
|
|
86
90
|
@property
|
|
87
91
|
def operation_type(self) -> str:
|
|
88
92
|
return "operation"
|
|
@@ -84,17 +84,28 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
84
84
|
if not rest_api_name:
|
|
85
85
|
# That's an ok scenario, it just means no next page possible
|
|
86
86
|
return None
|
|
87
|
-
if self.code_model.options["models_mode"]:
|
|
87
|
+
if self.code_model.options["models_mode"] == "msrest":
|
|
88
88
|
return self._get_attr_name(rest_api_name)
|
|
89
89
|
return rest_api_name
|
|
90
90
|
|
|
91
91
|
@property
|
|
92
92
|
def item_name(self) -> str:
|
|
93
93
|
rest_api_name = self.yaml_data["itemName"]
|
|
94
|
-
if self.code_model.options["models_mode"]:
|
|
94
|
+
if self.code_model.options["models_mode"] == "msrest":
|
|
95
|
+
# we don't use the paging model for dpg
|
|
95
96
|
return self._get_attr_name(rest_api_name)
|
|
96
97
|
return rest_api_name
|
|
97
98
|
|
|
99
|
+
@property
|
|
100
|
+
def item_type(self) -> ModelType:
|
|
101
|
+
try:
|
|
102
|
+
item_type_yaml = self.yaml_data["itemType"]
|
|
103
|
+
except KeyError as e:
|
|
104
|
+
raise ValueError(
|
|
105
|
+
"Only call this for DPG paging model deserialization"
|
|
106
|
+
) from e
|
|
107
|
+
return cast(ModelType, self.code_model.types_map[id(item_type_yaml)])
|
|
108
|
+
|
|
98
109
|
@property
|
|
99
110
|
def operation_type(self) -> str:
|
|
100
111
|
return "paging"
|
|
@@ -144,6 +155,8 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
144
155
|
file_import.add_submodule_import(
|
|
145
156
|
"azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
|
|
146
157
|
)
|
|
158
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
159
|
+
file_import.merge(self.item_type.imports(**kwargs))
|
|
147
160
|
return file_import
|
|
148
161
|
|
|
149
162
|
|
|
@@ -118,9 +118,9 @@ class _ParameterListBase(
|
|
|
118
118
|
|
|
119
119
|
@staticmethod
|
|
120
120
|
@abstractmethod
|
|
121
|
-
def body_parameter_creator() ->
|
|
122
|
-
[Dict[str, Any], "CodeModel"], BodyParameterType
|
|
123
|
-
|
|
121
|
+
def body_parameter_creator() -> (
|
|
122
|
+
Callable[[Dict[str, Any], "CodeModel"], BodyParameterType]
|
|
123
|
+
):
|
|
124
124
|
"""Callable for creating body parameters"""
|
|
125
125
|
|
|
126
126
|
@property
|
|
@@ -317,9 +317,11 @@ class _ParameterList(
|
|
|
317
317
|
return Parameter.from_yaml
|
|
318
318
|
|
|
319
319
|
@staticmethod
|
|
320
|
-
def body_parameter_creator() ->
|
|
321
|
-
[
|
|
322
|
-
|
|
320
|
+
def body_parameter_creator() -> (
|
|
321
|
+
Callable[
|
|
322
|
+
[Dict[str, Any], "CodeModel"], Union[MultipartBodyParameter, BodyParameter]
|
|
323
|
+
]
|
|
324
|
+
):
|
|
323
325
|
return get_body_parameter
|
|
324
326
|
|
|
325
327
|
@property
|
|
@@ -345,15 +347,15 @@ class _RequestBuilderParameterList(
|
|
|
345
347
|
"""_RequestBuilderParameterList is base parameter list for RequestBuilder classes"""
|
|
346
348
|
|
|
347
349
|
@staticmethod
|
|
348
|
-
def parameter_creator() ->
|
|
349
|
-
[Dict[str, Any], "CodeModel"], RequestBuilderParameter
|
|
350
|
-
|
|
350
|
+
def parameter_creator() -> (
|
|
351
|
+
Callable[[Dict[str, Any], "CodeModel"], RequestBuilderParameter]
|
|
352
|
+
):
|
|
351
353
|
return RequestBuilderParameter.from_yaml
|
|
352
354
|
|
|
353
355
|
@staticmethod
|
|
354
|
-
def body_parameter_creator() ->
|
|
355
|
-
[Dict[str, Any], "CodeModel"], RequestBuilderBodyParameterType
|
|
356
|
-
|
|
356
|
+
def body_parameter_creator() -> (
|
|
357
|
+
Callable[[Dict[str, Any], "CodeModel"], RequestBuilderBodyParameterType]
|
|
358
|
+
):
|
|
357
359
|
return get_request_body_parameter
|
|
358
360
|
|
|
359
361
|
@property
|
|
@@ -422,9 +424,9 @@ class _ClientGlobalParameterList( # pylint: disable=abstract-method
|
|
|
422
424
|
"""Base parameter list for client and config classes"""
|
|
423
425
|
|
|
424
426
|
@staticmethod
|
|
425
|
-
def body_parameter_creator() ->
|
|
426
|
-
[Dict[str, Any], "CodeModel"], BodyParameter
|
|
427
|
-
|
|
427
|
+
def body_parameter_creator() -> (
|
|
428
|
+
Callable[[Dict[str, Any], "CodeModel"], BodyParameter]
|
|
429
|
+
):
|
|
428
430
|
return BodyParameter.from_yaml
|
|
429
431
|
|
|
430
432
|
@property
|
|
@@ -121,9 +121,9 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
|
|
|
121
121
|
|
|
122
122
|
@staticmethod
|
|
123
123
|
@abstractmethod
|
|
124
|
-
def parameter_list_type() ->
|
|
125
|
-
[Dict[str, Any], "CodeModel"], ParameterListType
|
|
126
|
-
|
|
124
|
+
def parameter_list_type() -> (
|
|
125
|
+
Callable[[Dict[str, Any], "CodeModel"], ParameterListType]
|
|
126
|
+
):
|
|
127
127
|
...
|
|
128
128
|
|
|
129
129
|
@classmethod
|
|
@@ -178,9 +178,9 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
|
|
|
178
178
|
|
|
179
179
|
class RequestBuilder(RequestBuilderBase[RequestBuilderParameterList]):
|
|
180
180
|
@staticmethod
|
|
181
|
-
def parameter_list_type() ->
|
|
182
|
-
[Dict[str, Any], "CodeModel"], RequestBuilderParameterList
|
|
183
|
-
|
|
181
|
+
def parameter_list_type() -> (
|
|
182
|
+
Callable[[Dict[str, Any], "CodeModel"], RequestBuilderParameterList]
|
|
183
|
+
):
|
|
184
184
|
return RequestBuilderParameterList.from_yaml
|
|
185
185
|
|
|
186
186
|
|
|
@@ -188,9 +188,9 @@ class OverloadedRequestBuilder(
|
|
|
188
188
|
RequestBuilderBase[OverloadedRequestBuilderParameterList]
|
|
189
189
|
):
|
|
190
190
|
@staticmethod
|
|
191
|
-
def parameter_list_type() ->
|
|
192
|
-
[Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList
|
|
193
|
-
|
|
191
|
+
def parameter_list_type() -> (
|
|
192
|
+
Callable[[Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList]
|
|
193
|
+
):
|
|
194
194
|
return OverloadedRequestBuilderParameterList.from_yaml
|
|
195
195
|
|
|
196
196
|
|
|
@@ -639,11 +639,17 @@ class _OperationSerializer(
|
|
|
639
639
|
|
|
640
640
|
def make_pipeline_call(self, builder: OperationType) -> List[str]:
|
|
641
641
|
type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
|
|
642
|
+
stream_value = (
|
|
643
|
+
'kwargs.pop("stream", False)'
|
|
644
|
+
if builder.expose_stream_keyword
|
|
645
|
+
else builder.has_stream_response
|
|
646
|
+
)
|
|
642
647
|
return [
|
|
648
|
+
f"_stream = {stream_value}",
|
|
643
649
|
f"pipeline_response: PipelineResponse = {self._call_method}self._client._pipeline.run( "
|
|
644
650
|
+ f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
|
|
645
651
|
" request,",
|
|
646
|
-
|
|
652
|
+
" stream=_stream,",
|
|
647
653
|
" **kwargs",
|
|
648
654
|
")",
|
|
649
655
|
]
|
|
@@ -669,6 +675,11 @@ class _OperationSerializer(
|
|
|
669
675
|
|
|
670
676
|
def param_description(self, builder: OperationType) -> List[str]:
|
|
671
677
|
description_list = super().param_description(builder)
|
|
678
|
+
if builder.expose_stream_keyword:
|
|
679
|
+
description_list.append(
|
|
680
|
+
":keyword bool stream: Whether to stream the response of this operation. "
|
|
681
|
+
"Defaults to False. You will have to context manage the returned stream."
|
|
682
|
+
)
|
|
672
683
|
if not self.code_model.options["version_tolerant"]:
|
|
673
684
|
description_list.append(
|
|
674
685
|
":keyword callable cls: A custom type or function that will be passed the direct response"
|
|
@@ -1014,6 +1025,7 @@ class _OperationSerializer(
|
|
|
1014
1025
|
|
|
1015
1026
|
def response_headers_and_deserialization(
|
|
1016
1027
|
self,
|
|
1028
|
+
builder: OperationType,
|
|
1017
1029
|
response: Response,
|
|
1018
1030
|
) -> List[str]:
|
|
1019
1031
|
retval: List[str] = [
|
|
@@ -1025,8 +1037,9 @@ class _OperationSerializer(
|
|
|
1025
1037
|
]
|
|
1026
1038
|
if response.headers:
|
|
1027
1039
|
retval.append("")
|
|
1040
|
+
deserialize_code: List[str] = []
|
|
1028
1041
|
if response.is_stream_response:
|
|
1029
|
-
|
|
1042
|
+
deserialize_code.append(
|
|
1030
1043
|
"deserialized = {}".format(
|
|
1031
1044
|
"response.iter_bytes()"
|
|
1032
1045
|
if self.code_model.options["version_tolerant"]
|
|
@@ -1035,11 +1048,11 @@ class _OperationSerializer(
|
|
|
1035
1048
|
)
|
|
1036
1049
|
elif response.type:
|
|
1037
1050
|
if self.code_model.options["models_mode"] == "msrest":
|
|
1038
|
-
|
|
1051
|
+
deserialize_code.append(
|
|
1039
1052
|
f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)"
|
|
1040
1053
|
)
|
|
1041
1054
|
elif self.code_model.options["models_mode"] == "dpg":
|
|
1042
|
-
|
|
1055
|
+
deserialize_code.append(
|
|
1043
1056
|
f"deserialized = _deserialize({response.type.type_annotation(is_operation_file=True)}"
|
|
1044
1057
|
", response.json())"
|
|
1045
1058
|
)
|
|
@@ -1049,10 +1062,18 @@ class _OperationSerializer(
|
|
|
1049
1062
|
if response.type.is_xml
|
|
1050
1063
|
else "response.json()"
|
|
1051
1064
|
)
|
|
1052
|
-
|
|
1053
|
-
|
|
1065
|
+
deserialize_code.append("if response.content:")
|
|
1066
|
+
deserialize_code.append(f" deserialized = {deserialized_value}")
|
|
1067
|
+
deserialize_code.append("else:")
|
|
1068
|
+
deserialize_code.append(" deserialized = None")
|
|
1069
|
+
if len(deserialize_code) > 0:
|
|
1070
|
+
if builder.expose_stream_keyword:
|
|
1071
|
+
retval.append("if _stream:")
|
|
1072
|
+
retval.append(" deserialized = response.iter_bytes()")
|
|
1054
1073
|
retval.append("else:")
|
|
1055
|
-
retval.
|
|
1074
|
+
retval.extend([f" {dc}" for dc in deserialize_code])
|
|
1075
|
+
else:
|
|
1076
|
+
retval.extend(deserialize_code)
|
|
1056
1077
|
return retval
|
|
1057
1078
|
|
|
1058
1079
|
def handle_error_response(self, builder: OperationType) -> List[str]:
|
|
@@ -1106,14 +1127,16 @@ class _OperationSerializer(
|
|
|
1106
1127
|
[
|
|
1107
1128
|
f" {line}"
|
|
1108
1129
|
for line in self.response_headers_and_deserialization(
|
|
1109
|
-
response
|
|
1130
|
+
builder, response
|
|
1110
1131
|
)
|
|
1111
1132
|
]
|
|
1112
1133
|
)
|
|
1113
1134
|
retval.append("")
|
|
1114
1135
|
else:
|
|
1115
1136
|
retval.extend(
|
|
1116
|
-
self.response_headers_and_deserialization(
|
|
1137
|
+
self.response_headers_and_deserialization(
|
|
1138
|
+
builder, builder.responses[0]
|
|
1139
|
+
)
|
|
1117
1140
|
)
|
|
1118
1141
|
retval.append("")
|
|
1119
1142
|
type_ignore = (
|
|
@@ -1362,32 +1385,32 @@ class _PagingOperationSerializer(
|
|
|
1362
1385
|
deserialized = f"self._deserialize(\n {deserialize_type}, pipeline_response{pylint_disable}\n)"
|
|
1363
1386
|
retval.append(f" deserialized = {deserialized}")
|
|
1364
1387
|
elif self.code_model.options["models_mode"] == "dpg":
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
if isinstance(response.type, ModelType) and not response.type.is_public
|
|
1368
|
-
else ""
|
|
1369
|
-
)
|
|
1370
|
-
deserialized = f"_deserialize({response.serialization_type}{pylint_disable}, pipeline_response)"
|
|
1371
|
-
retval.append(
|
|
1372
|
-
f" deserialized: {response.serialization_type} = ({pylint_disable}"
|
|
1373
|
-
)
|
|
1374
|
-
retval.append(f" {deserialized})")
|
|
1388
|
+
# we don't want to generate paging models for DPG
|
|
1389
|
+
retval.append(f" deserialized = {deserialized}")
|
|
1375
1390
|
else:
|
|
1376
1391
|
retval.append(f" deserialized = {deserialized}")
|
|
1377
1392
|
item_name = builder.item_name
|
|
1378
|
-
|
|
1393
|
+
access = (
|
|
1379
1394
|
f".{item_name}"
|
|
1380
|
-
if self.code_model.options["models_mode"]
|
|
1395
|
+
if self.code_model.options["models_mode"] == "msrest"
|
|
1381
1396
|
else f'["{item_name}"]'
|
|
1382
1397
|
)
|
|
1383
|
-
|
|
1398
|
+
list_of_elem_deserialized = ""
|
|
1399
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
1400
|
+
item_type = builder.item_type.type_annotation(is_operation_file=True)
|
|
1401
|
+
list_of_elem_deserialized = (
|
|
1402
|
+
f"_deserialize({item_type}, deserialized{access})"
|
|
1403
|
+
)
|
|
1404
|
+
else:
|
|
1405
|
+
list_of_elem_deserialized = f"deserialized{access}"
|
|
1406
|
+
retval.append(f" list_of_elem = {list_of_elem_deserialized}")
|
|
1384
1407
|
retval.append(" if cls:")
|
|
1385
1408
|
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1386
1409
|
|
|
1387
1410
|
continuation_token_name = builder.continuation_token_name
|
|
1388
1411
|
if not continuation_token_name:
|
|
1389
1412
|
cont_token_property = "None"
|
|
1390
|
-
elif self.code_model.options["models_mode"]:
|
|
1413
|
+
elif self.code_model.options["models_mode"] == "msrest":
|
|
1391
1414
|
cont_token_property = f"deserialized.{continuation_token_name} or None"
|
|
1392
1415
|
else:
|
|
1393
1416
|
cont_token_property = (
|
|
@@ -1559,7 +1582,7 @@ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
|
|
|
1559
1582
|
[
|
|
1560
1583
|
f" {line}"
|
|
1561
1584
|
for line in self.response_headers_and_deserialization(
|
|
1562
|
-
builder.lro_response
|
|
1585
|
+
builder, builder.lro_response
|
|
1563
1586
|
)
|
|
1564
1587
|
]
|
|
1565
1588
|
)
|
|
@@ -108,8 +108,8 @@ class FileImportSerializer:
|
|
|
108
108
|
"typing", "TYPE_CHECKING", ImportType.STDLIB
|
|
109
109
|
)
|
|
110
110
|
|
|
111
|
-
def
|
|
112
|
-
def
|
|
111
|
+
def get_typing_definitions(self) -> str:
|
|
112
|
+
def declare_definition(
|
|
113
113
|
type_name: str, type_definition: TypeDefinition
|
|
114
114
|
) -> List[str]:
|
|
115
115
|
ret: List[str] = []
|
|
@@ -125,7 +125,7 @@ class FileImportSerializer:
|
|
|
125
125
|
return ""
|
|
126
126
|
declarations: List[str] = [""]
|
|
127
127
|
for type_name, value in self.file_import.type_definitions.items():
|
|
128
|
-
declarations.extend(
|
|
128
|
+
declarations.extend(declare_definition(type_name, value))
|
|
129
129
|
return "\n".join(declarations)
|
|
130
130
|
|
|
131
131
|
def __str__(self) -> str:
|
|
@@ -151,4 +151,4 @@ class FileImportSerializer:
|
|
|
151
151
|
typing_imports += "\n\n ".join(
|
|
152
152
|
_get_import_clauses(typing_imports_list, "\n ")
|
|
153
153
|
)
|
|
154
|
-
return regular_imports + typing_imports + self.
|
|
154
|
+
return regular_imports + typing_imports + self.get_typing_definitions()
|
|
@@ -16,6 +16,7 @@ from ..models import (
|
|
|
16
16
|
CodeModel,
|
|
17
17
|
)
|
|
18
18
|
from .builder_serializer import get_operation_serializer
|
|
19
|
+
from .import_serializer import FileImportSerializer
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def _to_string(data: Union[Tuple[Any], List[Any], str]) -> str:
|
|
@@ -91,6 +92,24 @@ def _mixin_imports(
|
|
|
91
92
|
), _json_serialize_imports(async_mixin_imports.to_dict())
|
|
92
93
|
|
|
93
94
|
|
|
95
|
+
def _mixin_typing_definitions(
|
|
96
|
+
mixin_operation_group: Optional[OperationGroup],
|
|
97
|
+
) -> Tuple[Optional[str], Optional[str]]:
|
|
98
|
+
if not mixin_operation_group:
|
|
99
|
+
return None, None
|
|
100
|
+
|
|
101
|
+
sync_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=False)
|
|
102
|
+
async_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=True)
|
|
103
|
+
sync_mixin_typing_definitions = FileImportSerializer(
|
|
104
|
+
sync_mixin_imports, False
|
|
105
|
+
).get_typing_definitions()
|
|
106
|
+
async_mixin_typing_definitions = FileImportSerializer(
|
|
107
|
+
async_mixin_imports, True
|
|
108
|
+
).get_typing_definitions()
|
|
109
|
+
|
|
110
|
+
return sync_mixin_typing_definitions, async_mixin_typing_definitions
|
|
111
|
+
|
|
112
|
+
|
|
94
113
|
class MetadataSerializer:
|
|
95
114
|
def __init__(self, code_model: CodeModel, env: Environment) -> None:
|
|
96
115
|
self.code_model = code_model
|
|
@@ -141,6 +160,10 @@ class MetadataSerializer:
|
|
|
141
160
|
mixin_operation_group.operations if mixin_operation_group else []
|
|
142
161
|
)
|
|
143
162
|
sync_mixin_imports, async_mixin_imports = _mixin_imports(mixin_operation_group)
|
|
163
|
+
(
|
|
164
|
+
sync_mixin_typing_definitions,
|
|
165
|
+
async_mixin_typing_definitions,
|
|
166
|
+
) = _mixin_typing_definitions(mixin_operation_group)
|
|
144
167
|
|
|
145
168
|
chosen_version, total_api_version_list = self._choose_api_version()
|
|
146
169
|
|
|
@@ -161,6 +184,8 @@ class MetadataSerializer:
|
|
|
161
184
|
str=str,
|
|
162
185
|
sync_mixin_imports=sync_mixin_imports,
|
|
163
186
|
async_mixin_imports=async_mixin_imports,
|
|
187
|
+
sync_mixin_typing_definitions=sync_mixin_typing_definitions,
|
|
188
|
+
async_mixin_typing_definitions=async_mixin_typing_definitions,
|
|
164
189
|
sync_client_imports=_json_serialize_imports(
|
|
165
190
|
self.client.imports_for_multiapi(async_mode=False).to_dict()
|
|
166
191
|
),
|
|
@@ -115,6 +115,8 @@
|
|
|
115
115
|
"operation_mixins": {
|
|
116
116
|
"sync_imports": {{ str(sync_mixin_imports) | tojson }},
|
|
117
117
|
"async_imports": {{ str(async_mixin_imports) | tojson }},
|
|
118
|
+
"sync_mixin_typing_definitions": {{ str(sync_mixin_typing_definitions) | tojson }},
|
|
119
|
+
"async_mixin_typing_definitions": {{ str(async_mixin_typing_definitions) | tojson }},
|
|
118
120
|
"operations": {
|
|
119
121
|
{% for operation in mixin_operations %}
|
|
120
122
|
{{ operation.name | tojson }} : {
|
|
@@ -37,7 +37,6 @@ def Process(plugin_name: str, session_id: str) -> bool:
|
|
|
37
37
|
from .stdstream import StdStreamAutorestAPI
|
|
38
38
|
|
|
39
39
|
with contextlib.closing(StdStreamAutorestAPI(session_id)) as stdstream_connection:
|
|
40
|
-
|
|
41
40
|
_LOGGER.debug(
|
|
42
41
|
"Autorest called process with plugin_name '%s' and session_id: '%s'",
|
|
43
42
|
plugin_name,
|
|
@@ -595,6 +595,19 @@ class M4Reformatter(
|
|
|
595
595
|
operation["continuationTokenName"] = yaml_data["extensions"][
|
|
596
596
|
"x-ms-pageable"
|
|
597
597
|
].get("nextLinkName")
|
|
598
|
+
returned_response_object = (
|
|
599
|
+
operation["nextOperation"]["responses"][0]
|
|
600
|
+
if operation.get("nextOperation")
|
|
601
|
+
else operation["responses"][0]
|
|
602
|
+
)
|
|
603
|
+
if self.version_tolerant:
|
|
604
|
+
# if we're in version tolerant, hide the paging model
|
|
605
|
+
returned_response_object["type"]["isPublic"] = False
|
|
606
|
+
operation["itemType"] = next(
|
|
607
|
+
p["type"]
|
|
608
|
+
for p in returned_response_object["type"]["properties"]
|
|
609
|
+
if p["restApiName"] == operation["itemName"]
|
|
610
|
+
)
|
|
598
611
|
if yaml_data["language"]["default"]["paging"].get("nextLinkOperation"):
|
|
599
612
|
operation["nextOperation"] = self.update_operation(
|
|
600
613
|
group_name=group_name,
|
|
@@ -31,6 +31,20 @@ class OperationMixinGroup:
|
|
|
31
31
|
imports.merge(current_version_imports)
|
|
32
32
|
return imports
|
|
33
33
|
|
|
34
|
+
def typing_definitions(self, async_mode: bool) -> str:
|
|
35
|
+
key = (
|
|
36
|
+
"sync_mixin_typing_definitions"
|
|
37
|
+
if async_mode
|
|
38
|
+
else "async_mixin_typing_definitions"
|
|
39
|
+
)
|
|
40
|
+
origin = "".join(
|
|
41
|
+
[
|
|
42
|
+
metadata_json.get("operation_mixins", {}).get(key, "")
|
|
43
|
+
for metadata_json in self.version_path_to_metadata.values()
|
|
44
|
+
]
|
|
45
|
+
)
|
|
46
|
+
return "\n".join(set(origin.split("\n")))
|
|
47
|
+
|
|
34
48
|
def _use_metadata_of_default_api_version(
|
|
35
49
|
self, mixin_operations: List[MixinOperation]
|
|
36
50
|
) -> List[MixinOperation]:
|
|
@@ -101,7 +101,8 @@ class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
101
101
|
# serialize mixins
|
|
102
102
|
if code_model.operation_mixin_group.mixin_operations:
|
|
103
103
|
imports = FileImportSerializer(
|
|
104
|
-
code_model.operation_mixin_group.imports(async_mode)
|
|
104
|
+
code_model.operation_mixin_group.imports(async_mode),
|
|
105
|
+
code_model.operation_mixin_group.typing_definitions(async_mode),
|
|
105
106
|
)
|
|
106
107
|
self.write_file(
|
|
107
108
|
_get_file_path("_operations_mixin", async_mode),
|
|
@@ -135,8 +135,9 @@ def _get_import_clauses(
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
class FileImportSerializer:
|
|
138
|
-
def __init__(self, file_import: FileImport) -> None:
|
|
138
|
+
def __init__(self, file_import: FileImport, typing_definitions: str = "") -> None:
|
|
139
139
|
self._file_import = file_import
|
|
140
|
+
self._typing_definitions = typing_definitions
|
|
140
141
|
|
|
141
142
|
def _switch_typing_section_key(self, new_key: TypingSection):
|
|
142
143
|
switched_dictionary = {}
|
|
@@ -193,4 +194,4 @@ class FileImportSerializer:
|
|
|
193
194
|
_get_import_clauses(typing_imports_dict, "\n ")
|
|
194
195
|
)
|
|
195
196
|
|
|
196
|
-
return regular_imports + typing_imports
|
|
197
|
+
return regular_imports + typing_imports + self._typing_definitions
|
|
@@ -10,11 +10,11 @@ from typing import Callable, Dict, Any, List, Optional
|
|
|
10
10
|
|
|
11
11
|
from .._utils import to_snake_case
|
|
12
12
|
from .helpers import (
|
|
13
|
-
pad_reserved_words,
|
|
14
13
|
add_redefined_builtin_info,
|
|
15
14
|
pad_builtin_namespaces,
|
|
15
|
+
pad_special_chars,
|
|
16
16
|
)
|
|
17
|
-
from .python_mappings import PadType
|
|
17
|
+
from .python_mappings import CADL_RESERVED_WORDS, RESERVED_WORDS, PadType
|
|
18
18
|
|
|
19
19
|
from .. import YamlUpdatePlugin, YamlUpdatePluginAutorest
|
|
20
20
|
from .._utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNOWN_TYPES
|
|
@@ -168,51 +168,6 @@ def update_operation_group_class_name(
|
|
|
168
168
|
return class_name + "Operations"
|
|
169
169
|
|
|
170
170
|
|
|
171
|
-
def update_parameter(yaml_data: Dict[str, Any]) -> None:
|
|
172
|
-
yaml_data["description"] = update_description(yaml_data["description"])
|
|
173
|
-
if not (
|
|
174
|
-
yaml_data["location"] == "header"
|
|
175
|
-
and yaml_data["clientName"] in ("content_type", "accept")
|
|
176
|
-
):
|
|
177
|
-
yaml_data["clientName"] = pad_reserved_words(
|
|
178
|
-
yaml_data["clientName"].lower(), PadType.PARAMETER
|
|
179
|
-
)
|
|
180
|
-
if yaml_data.get("propertyToParameterName"):
|
|
181
|
-
# need to create a new one with padded keys and values
|
|
182
|
-
yaml_data["propertyToParameterName"] = {
|
|
183
|
-
pad_reserved_words(prop, PadType.PROPERTY)
|
|
184
|
-
.lower(): pad_reserved_words(param_name, PadType.PARAMETER)
|
|
185
|
-
.lower()
|
|
186
|
-
for prop, param_name in yaml_data["propertyToParameterName"].items()
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
def update_types(yaml_data: List[Dict[str, Any]]) -> None:
|
|
191
|
-
for type in yaml_data:
|
|
192
|
-
for property in type.get("properties", []):
|
|
193
|
-
property["description"] = update_description(property["description"])
|
|
194
|
-
property["clientName"] = pad_reserved_words(
|
|
195
|
-
property["clientName"].lower(), PadType.PROPERTY
|
|
196
|
-
)
|
|
197
|
-
add_redefined_builtin_info(property["clientName"], property)
|
|
198
|
-
if type.get("name"):
|
|
199
|
-
type["description"] = update_description(type["description"], type["name"])
|
|
200
|
-
type["snakeCaseName"] = to_snake_case(type["name"])
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def update_client(yaml_data: Dict[str, Any]) -> None:
|
|
204
|
-
yaml_data["description"] = update_description(
|
|
205
|
-
yaml_data["description"], default_description=yaml_data["name"]
|
|
206
|
-
)
|
|
207
|
-
yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
|
|
208
|
-
for parameter in yaml_data["parameters"]:
|
|
209
|
-
update_parameter(parameter)
|
|
210
|
-
prop_name = yaml_data["name"]
|
|
211
|
-
if prop_name.endswith("Client"):
|
|
212
|
-
prop_name = prop_name[: len(prop_name) - len("Client")]
|
|
213
|
-
yaml_data["builderPadName"] = to_snake_case(prop_name)
|
|
214
|
-
|
|
215
|
-
|
|
216
171
|
def update_paging_response(yaml_data: Dict[str, Any]) -> None:
|
|
217
172
|
yaml_data["discriminator"] = "paging"
|
|
218
173
|
yaml_data["pagerSync"] = yaml_data.get("pagerSync") or "azure.core.paging.ItemPaged"
|
|
@@ -230,9 +185,55 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
230
185
|
|
|
231
186
|
@property
|
|
232
187
|
def models_mode(self) -> Optional[str]:
|
|
233
|
-
return self.options.get(
|
|
234
|
-
|
|
188
|
+
return self.options.get("models-mode", "dpg" if self.is_cadl else None)
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def is_cadl(self) -> bool:
|
|
192
|
+
return self.options.get("cadl_file", False)
|
|
193
|
+
|
|
194
|
+
def pad_reserved_words(self, name: str, pad_type: PadType):
|
|
195
|
+
# we want to pad hidden variables as well
|
|
196
|
+
if not name:
|
|
197
|
+
# we'll pass in empty operation groups sometime etc.
|
|
198
|
+
return name
|
|
199
|
+
|
|
200
|
+
if self.is_cadl:
|
|
201
|
+
reserved_words = copy.copy(CADL_RESERVED_WORDS)
|
|
202
|
+
reserved_words.update(RESERVED_WORDS)
|
|
203
|
+
else:
|
|
204
|
+
reserved_words = RESERVED_WORDS
|
|
205
|
+
name = pad_special_chars(name)
|
|
206
|
+
name_prefix = "_" if name[0] == "_" else ""
|
|
207
|
+
name = name[1:] if name[0] == "_" else name
|
|
208
|
+
if name.lower() in reserved_words[pad_type]:
|
|
209
|
+
return name_prefix + name + pad_type
|
|
210
|
+
return name_prefix + name
|
|
211
|
+
|
|
212
|
+
def update_types(self, yaml_data: List[Dict[str, Any]]) -> None:
|
|
213
|
+
for type in yaml_data:
|
|
214
|
+
for property in type.get("properties", []):
|
|
215
|
+
property["description"] = update_description(property["description"])
|
|
216
|
+
property["clientName"] = self.pad_reserved_words(
|
|
217
|
+
property["clientName"].lower(), PadType.PROPERTY
|
|
218
|
+
)
|
|
219
|
+
add_redefined_builtin_info(property["clientName"], property)
|
|
220
|
+
if type.get("name"):
|
|
221
|
+
type["description"] = update_description(
|
|
222
|
+
type["description"], type["name"]
|
|
223
|
+
)
|
|
224
|
+
type["snakeCaseName"] = to_snake_case(type["name"])
|
|
225
|
+
|
|
226
|
+
def update_client(self, yaml_data: Dict[str, Any]) -> None:
|
|
227
|
+
yaml_data["description"] = update_description(
|
|
228
|
+
yaml_data["description"], default_description=yaml_data["name"]
|
|
235
229
|
)
|
|
230
|
+
yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
|
|
231
|
+
for parameter in yaml_data["parameters"]:
|
|
232
|
+
self.update_parameter(parameter)
|
|
233
|
+
prop_name = yaml_data["name"]
|
|
234
|
+
if prop_name.endswith("Client"):
|
|
235
|
+
prop_name = prop_name[: len(prop_name) - len("Client")]
|
|
236
|
+
yaml_data["builderPadName"] = to_snake_case(prop_name)
|
|
236
237
|
|
|
237
238
|
def get_operation_updater(
|
|
238
239
|
self, yaml_data: Dict[str, Any]
|
|
@@ -245,6 +246,24 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
245
246
|
return self.update_paging_operation
|
|
246
247
|
return self.update_operation
|
|
247
248
|
|
|
249
|
+
def update_parameter(self, yaml_data: Dict[str, Any]) -> None:
|
|
250
|
+
yaml_data["description"] = update_description(yaml_data["description"])
|
|
251
|
+
if not (
|
|
252
|
+
yaml_data["location"] == "header"
|
|
253
|
+
and yaml_data["clientName"] in ("content_type", "accept")
|
|
254
|
+
):
|
|
255
|
+
yaml_data["clientName"] = self.pad_reserved_words(
|
|
256
|
+
yaml_data["clientName"].lower(), PadType.PARAMETER
|
|
257
|
+
)
|
|
258
|
+
if yaml_data.get("propertyToParameterName"):
|
|
259
|
+
# need to create a new one with padded keys and values
|
|
260
|
+
yaml_data["propertyToParameterName"] = {
|
|
261
|
+
self.pad_reserved_words(prop, PadType.PROPERTY)
|
|
262
|
+
.lower(): self.pad_reserved_words(param_name, PadType.PARAMETER)
|
|
263
|
+
.lower()
|
|
264
|
+
for prop, param_name in yaml_data["propertyToParameterName"].items()
|
|
265
|
+
}
|
|
266
|
+
|
|
248
267
|
def update_operation(
|
|
249
268
|
self,
|
|
250
269
|
code_model: Dict[str, Any],
|
|
@@ -252,23 +271,23 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
252
271
|
*,
|
|
253
272
|
is_overload: bool = False,
|
|
254
273
|
) -> None:
|
|
255
|
-
yaml_data["groupName"] = pad_reserved_words(
|
|
274
|
+
yaml_data["groupName"] = self.pad_reserved_words(
|
|
256
275
|
yaml_data["groupName"], PadType.OPERATION_GROUP
|
|
257
276
|
)
|
|
258
277
|
yaml_data["groupName"] = to_snake_case(yaml_data["groupName"])
|
|
259
278
|
yaml_data["name"] = yaml_data["name"].lower()
|
|
260
|
-
yaml_data["name"] = pad_reserved_words(yaml_data["name"], PadType.METHOD)
|
|
279
|
+
yaml_data["name"] = self.pad_reserved_words(yaml_data["name"], PadType.METHOD)
|
|
261
280
|
yaml_data["description"] = update_description(
|
|
262
281
|
yaml_data["description"], yaml_data["name"]
|
|
263
282
|
)
|
|
264
283
|
yaml_data["summary"] = update_description(yaml_data.get("summary", ""))
|
|
265
284
|
body_parameter = yaml_data.get("bodyParameter")
|
|
266
285
|
for parameter in yaml_data["parameters"]:
|
|
267
|
-
update_parameter(parameter)
|
|
286
|
+
self.update_parameter(parameter)
|
|
268
287
|
if yaml_data.get("bodyParameter"):
|
|
269
|
-
update_parameter(yaml_data["bodyParameter"])
|
|
288
|
+
self.update_parameter(yaml_data["bodyParameter"])
|
|
270
289
|
for entry in yaml_data["bodyParameter"].get("entries", []):
|
|
271
|
-
update_parameter(entry)
|
|
290
|
+
self.update_parameter(entry)
|
|
272
291
|
for overload in yaml_data.get("overloads", []):
|
|
273
292
|
self.update_operation(code_model, overload, is_overload=True)
|
|
274
293
|
for response in yaml_data.get("responses", []):
|
|
@@ -337,30 +356,21 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
337
356
|
code_model: Dict[str, Any],
|
|
338
357
|
yaml_data: Dict[str, Any],
|
|
339
358
|
is_overload: bool = False,
|
|
359
|
+
item_type: Optional[Dict[str, Any]] = None,
|
|
340
360
|
) -> None:
|
|
341
361
|
self.update_operation(code_model, yaml_data, is_overload=is_overload)
|
|
342
362
|
if not yaml_data.get("pagerSync"):
|
|
343
363
|
yaml_data["pagerSync"] = "azure.core.paging.ItemPaged"
|
|
344
364
|
if not yaml_data.get("pagerAsync"):
|
|
345
365
|
yaml_data["pagerAsync"] = "azure.core.async_paging.AsyncItemPaged"
|
|
346
|
-
returned_response_object = (
|
|
347
|
-
yaml_data["nextOperation"]["responses"][0]
|
|
348
|
-
if yaml_data.get("nextOperation")
|
|
349
|
-
else yaml_data["responses"][0]
|
|
350
|
-
)
|
|
351
366
|
if self.version_tolerant:
|
|
352
367
|
# if we're in version tolerant, hide the paging model
|
|
353
|
-
returned_response_object["type"]["isPublic"] = False
|
|
354
368
|
_remove_paging_maxpagesize(yaml_data)
|
|
355
|
-
item_type =
|
|
356
|
-
p["type"]["elementType"]
|
|
357
|
-
for p in returned_response_object["type"]["properties"]
|
|
358
|
-
if p["restApiName"] == (yaml_data.get("itemName") or "value")
|
|
359
|
-
)
|
|
369
|
+
item_type = item_type or yaml_data["itemType"]["elementType"]
|
|
360
370
|
if yaml_data.get("nextOperation"):
|
|
361
371
|
if self.version_tolerant:
|
|
362
372
|
_remove_paging_maxpagesize(yaml_data["nextOperation"])
|
|
363
|
-
yaml_data["nextOperation"]["groupName"] = pad_reserved_words(
|
|
373
|
+
yaml_data["nextOperation"]["groupName"] = self.pad_reserved_words(
|
|
364
374
|
yaml_data["nextOperation"]["groupName"], PadType.OPERATION_GROUP
|
|
365
375
|
)
|
|
366
376
|
yaml_data["nextOperation"]["groupName"] = to_snake_case(
|
|
@@ -373,7 +383,9 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
373
383
|
update_paging_response(response)
|
|
374
384
|
response["itemType"] = item_type
|
|
375
385
|
for overload in yaml_data.get("overloads", []):
|
|
376
|
-
self.update_paging_operation(
|
|
386
|
+
self.update_paging_operation(
|
|
387
|
+
code_model, overload, is_overload=True, item_type=item_type
|
|
388
|
+
)
|
|
377
389
|
|
|
378
390
|
def update_operation_groups(
|
|
379
391
|
self, code_model: Dict[str, Any], client: Dict[str, Any]
|
|
@@ -381,7 +393,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
381
393
|
operation_groups_yaml_data = client["operationGroups"]
|
|
382
394
|
for operation_group in operation_groups_yaml_data:
|
|
383
395
|
operation_group["clientName"] = client["name"]
|
|
384
|
-
operation_group["propertyName"] = pad_reserved_words(
|
|
396
|
+
operation_group["propertyName"] = self.pad_reserved_words(
|
|
385
397
|
operation_group["propertyName"], PadType.OPERATION_GROUP
|
|
386
398
|
)
|
|
387
399
|
operation_group["propertyName"] = to_snake_case(
|
|
@@ -395,13 +407,13 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
|
395
407
|
|
|
396
408
|
def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
|
|
397
409
|
"""Convert in place the YAML str."""
|
|
398
|
-
update_types(yaml_data["types"])
|
|
410
|
+
self.update_types(yaml_data["types"])
|
|
399
411
|
for client in yaml_data["clients"]:
|
|
400
|
-
update_client(client)
|
|
412
|
+
self.update_client(client)
|
|
401
413
|
self.update_operation_groups(yaml_data, client)
|
|
402
414
|
for clients in yaml_data["subnamespaceToClients"].values():
|
|
403
415
|
for client in clients:
|
|
404
|
-
update_client(client)
|
|
416
|
+
self.update_client(client)
|
|
405
417
|
self.update_operation_groups(yaml_data, client)
|
|
406
418
|
if yaml_data.get("namespace"):
|
|
407
419
|
yaml_data["namespace"] = pad_builtin_namespaces(yaml_data["namespace"])
|
|
@@ -6,26 +6,11 @@
|
|
|
6
6
|
import re
|
|
7
7
|
from typing import Any, Dict
|
|
8
8
|
from .python_mappings import (
|
|
9
|
-
PadType,
|
|
10
|
-
RESERVED_WORDS,
|
|
11
9
|
REDEFINED_BUILTINS,
|
|
12
10
|
BUILTIN_PACKAGES,
|
|
13
11
|
)
|
|
14
12
|
|
|
15
13
|
|
|
16
|
-
def pad_reserved_words(name: str, pad_type: PadType):
|
|
17
|
-
# we want to pad hidden variables as well
|
|
18
|
-
if not name:
|
|
19
|
-
# we'll pass in empty operation groups sometime etc.
|
|
20
|
-
return name
|
|
21
|
-
name = pad_special_chars(name)
|
|
22
|
-
name_prefix = "_" if name[0] == "_" else ""
|
|
23
|
-
name = name[1:] if name[0] == "_" else name
|
|
24
|
-
if name.lower() in RESERVED_WORDS[pad_type]:
|
|
25
|
-
return name_prefix + name + pad_type
|
|
26
|
-
return name_prefix + name
|
|
27
|
-
|
|
28
|
-
|
|
29
14
|
def add_redefined_builtin_info(name: str, yaml_data: Dict[str, Any]) -> None:
|
|
30
15
|
if name in REDEFINED_BUILTINS:
|
|
31
16
|
yaml_data["pylintDisable"] = "redefined-builtin"
|
package/package.json
CHANGED