@autorest/python 5.11.2 → 5.12.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 +26 -0
- package/autorest/codegen/__init__.py +5 -5
- package/autorest/codegen/models/client.py +2 -2
- package/autorest/codegen/models/code_model.py +5 -1
- package/autorest/codegen/models/operation_group.py +5 -3
- package/autorest/codegen/models/parameter.py +4 -3
- package/autorest/codegen/models/parameter_list.py +30 -26
- package/autorest/codegen/models/request_builder.py +5 -1
- package/autorest/codegen/models/request_builder_parameter.py +4 -3
- package/autorest/codegen/models/request_builder_parameter_list.py +15 -6
- package/autorest/codegen/models/rest.py +3 -2
- package/autorest/codegen/serializers/__init__.py +48 -48
- package/autorest/codegen/serializers/builder_serializer.py +32 -27
- package/autorest/codegen/serializers/client_serializer.py +37 -9
- package/autorest/codegen/serializers/general_serializer.py +7 -5
- package/autorest/codegen/serializers/import_serializer.py +6 -6
- package/autorest/codegen/serializers/metadata_serializer.py +2 -2
- package/autorest/codegen/serializers/model_base_serializer.py +3 -3
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +1 -1
- package/autorest/codegen/serializers/{operation_group_serializer.py → operation_groups_serializer.py} +27 -29
- package/autorest/codegen/serializers/operations_init_serializer.py +34 -2
- package/autorest/codegen/serializers/patch_serializer.py +15 -0
- package/autorest/codegen/serializers/rest_serializer.py +9 -4
- package/autorest/codegen/serializers/utils.py +2 -2
- package/autorest/codegen/templates/config.py.jinja2 +1 -11
- package/autorest/codegen/templates/init.py.jinja2 +4 -5
- package/autorest/codegen/templates/metadata.json.jinja2 +2 -2
- package/autorest/codegen/templates/model_init.py.jinja2 +1 -1
- package/autorest/codegen/templates/{operations_class.py.jinja2 → operation_group.py.jinja2} +2 -0
- package/autorest/codegen/templates/{operations_container.py.jinja2 → operation_groups_container.py.jinja2} +7 -21
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +13 -0
- package/autorest/codegen/templates/patch.py.jinja2 +31 -0
- package/autorest/codegen/templates/request_builder.py.jinja2 +7 -2
- package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
- package/autorest/codegen/templates/setup.py.jinja2 +1 -1
- package/autorest/multiapi/serializers/__init__.py +3 -3
- package/autorest/multiapi/serializers/import_serializer.py +5 -5
- package/autorest/namer/name_converter.py +1 -0
- package/package.json +2 -2
- package/setup.py +1 -0
- package/autorest/codegen/templates/operations_class_mixin.py.jinja2 +0 -16
- package/autorest/codegen/templates/operations_container_init.py.jinja2 +0 -24
- package/autorest/codegen/templates/operations_container_mixin.py.jinja2 +0 -21
- package/autorest/codegen/templates/operations_init.py.jinja2 +0 -26
package/ChangeLog.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
### 2021-12-06 - 5.12.0
|
|
4
|
+
|
|
5
|
+
| Library | Min Version
|
|
6
|
+
| --------------- | -------
|
|
7
|
+
|`@autorest/core` | `3.6.2`
|
|
8
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
9
|
+
|`azure-core` dep of generated code | `1.20.1`
|
|
10
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
11
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
12
|
+
|
|
13
|
+
**Breaking Changes in Version Tolerant Generation**
|
|
14
|
+
|
|
15
|
+
- Remove metadata property for version tolerant and low level client generations #1090
|
|
16
|
+
- Generate SDKs with `--python3-only` defaulting to `True` for version tolerant and low level client #1087
|
|
17
|
+
|
|
18
|
+
**New Features**
|
|
19
|
+
|
|
20
|
+
- Generate a `_patch.py` file if one does not exist. These files are used to customize the generated code #1092
|
|
21
|
+
|
|
22
|
+
**Bug Fixes**
|
|
23
|
+
|
|
24
|
+
- Can now handle body params with names `json`, `content`, `data`, and `files` #1081
|
|
25
|
+
- Improve generated templates for `data` and `files` input body params by adding quotes around the keys #1082
|
|
26
|
+
- Using flag `--python3-only` will get you typed sync client and config files #1085
|
|
27
|
+
- Pin `mistune` dependency to less than `2.x.x` so autorest can be successfully installed #1106
|
|
28
|
+
|
|
3
29
|
### 2021-11-05 - 5.11.2
|
|
4
30
|
|
|
5
31
|
| Library | Min Version
|
|
@@ -60,7 +60,7 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
|
60
60
|
"to 'public' or 'hidden'."
|
|
61
61
|
)
|
|
62
62
|
|
|
63
|
-
if not options["show_operations"] and options["
|
|
63
|
+
if not options["show_operations"] and options["add_python3_operation_files"]:
|
|
64
64
|
raise ValueError(
|
|
65
65
|
"Can not add typed sync operation files if you are not showing operations. "
|
|
66
66
|
"If you want typed synced operation files, you have to add flag "
|
|
@@ -256,7 +256,7 @@ class CodeGenerator(Plugin):
|
|
|
256
256
|
version_tolerant = self._autorestapi.get_boolean_value("version-tolerant", False)
|
|
257
257
|
show_operations = self._autorestapi.get_boolean_value("show-operations", not low_level_client)
|
|
258
258
|
models_mode_default = "none" if low_level_client or version_tolerant else "msrest"
|
|
259
|
-
|
|
259
|
+
python3_only = self._autorestapi.get_boolean_value("python3-only", low_level_client or version_tolerant)
|
|
260
260
|
|
|
261
261
|
options: Dict[str, Any] = {
|
|
262
262
|
"azure_arm": azure_arm,
|
|
@@ -282,13 +282,13 @@ class CodeGenerator(Plugin):
|
|
|
282
282
|
"only_path_and_body_params_positional": self._autorestapi.get_boolean_value(
|
|
283
283
|
"only-path-and-body-params-positional", low_level_client or version_tolerant
|
|
284
284
|
),
|
|
285
|
-
"
|
|
286
|
-
"add-python3-operation-files",
|
|
285
|
+
"add_python3_operation_files": self._autorestapi.get_boolean_value(
|
|
286
|
+
"add-python3-operation-files", python3_only and not low_level_client
|
|
287
287
|
),
|
|
288
288
|
"version_tolerant": version_tolerant,
|
|
289
289
|
"low_level_client": low_level_client,
|
|
290
290
|
"combine_operation_files": self._autorestapi.get_boolean_value("combine-operation-files", version_tolerant),
|
|
291
|
-
"
|
|
291
|
+
"python3_only": python3_only,
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
if options["builders_visibility"] is None:
|
|
@@ -96,6 +96,6 @@ class Client:
|
|
|
96
96
|
pass
|
|
97
97
|
return file_import
|
|
98
98
|
|
|
99
|
-
def send_request_signature(self, async_mode) -> List[str]:
|
|
99
|
+
def send_request_signature(self, async_mode: bool, is_python3_file: bool) -> List[str]:
|
|
100
100
|
request_signature = ["request: HttpRequest," if async_mode else "request, # type: HttpRequest"]
|
|
101
|
-
return request_signature + self.parameters.method_signature_kwargs(
|
|
101
|
+
return request_signature + self.parameters.method_signature_kwargs(is_python3_file)
|
|
@@ -29,7 +29,7 @@ from .rest import Rest
|
|
|
29
29
|
|
|
30
30
|
_LOGGER = logging.getLogger(__name__)
|
|
31
31
|
|
|
32
|
-
class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
32
|
+
class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
|
|
33
33
|
"""Holds all of the information we have parsed out of the yaml file. The CodeModel is what gets
|
|
34
34
|
serialized by the serializers.
|
|
35
35
|
|
|
@@ -203,6 +203,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
203
203
|
operation for operation in operation_group.operations if operation not in next_operations
|
|
204
204
|
]
|
|
205
205
|
|
|
206
|
+
@property
|
|
207
|
+
def has_schemas(self):
|
|
208
|
+
return self.schemas or self.enums
|
|
209
|
+
|
|
206
210
|
@property
|
|
207
211
|
def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
|
|
208
212
|
return ARMChallengeAuthenticationPolicy if self.options['azure_arm'] else BearerTokenCredentialPolicy
|
|
@@ -56,7 +56,7 @@ class OperationGroup(BaseModel):
|
|
|
56
56
|
file_import.merge(operation.imports_for_multiapi(async_mode))
|
|
57
57
|
return file_import
|
|
58
58
|
|
|
59
|
-
def imports(self, async_mode: bool
|
|
59
|
+
def imports(self, async_mode: bool) -> FileImport:
|
|
60
60
|
file_import = FileImport()
|
|
61
61
|
file_import.add_from_import("azure.core.exceptions", "ClientAuthenticationError", ImportType.AZURECORE)
|
|
62
62
|
file_import.add_from_import("azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE)
|
|
@@ -73,7 +73,7 @@ class OperationGroup(BaseModel):
|
|
|
73
73
|
"azure.core.tracing.decorator", "distributed_trace", ImportType.AZURECORE,
|
|
74
74
|
)
|
|
75
75
|
local_path = "..." if async_mode else ".."
|
|
76
|
-
if has_schemas and self.code_model.options["models_mode"]:
|
|
76
|
+
if self.code_model.has_schemas and self.code_model.options["models_mode"]:
|
|
77
77
|
file_import.add_from_import(local_path, "models", ImportType.LOCAL, alias="_models")
|
|
78
78
|
if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
|
|
79
79
|
if not self.code_model.options["combine_operation_files"]:
|
|
@@ -85,7 +85,9 @@ class OperationGroup(BaseModel):
|
|
|
85
85
|
else:
|
|
86
86
|
operation_group_builders = self.code_model.rest.request_builders
|
|
87
87
|
for request_builder in operation_group_builders:
|
|
88
|
-
|
|
88
|
+
python3_only = self.code_model.options["python3_only"]
|
|
89
|
+
typed_sync_operation_file = self.code_model.options["add_python3_operation_files"]
|
|
90
|
+
suffix = "_py3" if typed_sync_operation_file and not python3_only else ""
|
|
89
91
|
file_import.add_from_import(
|
|
90
92
|
f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
|
|
91
93
|
request_builder.name,
|
|
@@ -97,6 +97,7 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
97
97
|
self.is_data_input = yaml_data.get("isPartialBody", False) and not self.is_multipart
|
|
98
98
|
self.content_types = content_types or []
|
|
99
99
|
self.body_kwargs: List[Parameter] = []
|
|
100
|
+
self.is_body_kwarg = False
|
|
100
101
|
|
|
101
102
|
def __hash__(self) -> int:
|
|
102
103
|
return hash(self.serialized_name)
|
|
@@ -167,7 +168,7 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
167
168
|
@property
|
|
168
169
|
def pre_semicolon_content_types(self) -> List[str]:
|
|
169
170
|
"""Splits on semicolon of media types and returns the first half.
|
|
170
|
-
I.e. ["text/plain;
|
|
171
|
+
I.e. ["text/plain; charset=UTF-8"] -> ["text/plain"]
|
|
171
172
|
"""
|
|
172
173
|
return [content_type.split(";")[0] for content_type in self.content_types]
|
|
173
174
|
|
|
@@ -282,8 +283,8 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
|
|
|
282
283
|
def has_default_value(self):
|
|
283
284
|
return self.default_value is not None or not self.required
|
|
284
285
|
|
|
285
|
-
def method_signature(self,
|
|
286
|
-
if
|
|
286
|
+
def method_signature(self, is_python3_file: bool) -> str:
|
|
287
|
+
if is_python3_file:
|
|
287
288
|
if self.has_default_value:
|
|
288
289
|
return f"{self.serialized_name}: {self.type_annotation} = {self.default_value_declaration},"
|
|
289
290
|
return f"{self.serialized_name}: {self.type_annotation},"
|
|
@@ -172,11 +172,15 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
172
172
|
|
|
173
173
|
@property
|
|
174
174
|
def multipart(self) -> List[Parameter]:
|
|
175
|
-
return self.get_from_predicate(
|
|
175
|
+
return self.get_from_predicate(
|
|
176
|
+
lambda parameter: parameter.is_multipart and not parameter.is_body_kwarg
|
|
177
|
+
)
|
|
176
178
|
|
|
177
179
|
@property
|
|
178
180
|
def data_inputs(self) -> List[Parameter]:
|
|
179
|
-
return self.get_from_predicate(
|
|
181
|
+
return self.get_from_predicate(
|
|
182
|
+
lambda parameter: parameter.is_data_input and not parameter.is_body_kwarg
|
|
183
|
+
)
|
|
180
184
|
|
|
181
185
|
def _filter_out_multiple_content_type(self, kwarg_params):
|
|
182
186
|
"""We don't want multiple content type kwargs in the method signature"""
|
|
@@ -214,24 +218,24 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
214
218
|
return signature_parameters
|
|
215
219
|
|
|
216
220
|
|
|
217
|
-
def method_signature(self,
|
|
221
|
+
def method_signature(self, is_python3_file: bool) -> List[str]:
|
|
218
222
|
return _method_signature_helper(
|
|
219
|
-
positional=self.method_signature_positional(
|
|
220
|
-
keyword_only=self.method_signature_keyword_only(
|
|
221
|
-
kwarg_params=self.method_signature_kwargs(
|
|
223
|
+
positional=self.method_signature_positional(is_python3_file),
|
|
224
|
+
keyword_only=self.method_signature_keyword_only(is_python3_file),
|
|
225
|
+
kwarg_params=self.method_signature_kwargs(is_python3_file)
|
|
222
226
|
)
|
|
223
227
|
|
|
224
|
-
def method_signature_positional(self,
|
|
225
|
-
return [parameter.method_signature(
|
|
228
|
+
def method_signature_positional(self, is_python3_file: bool) -> List[str]:
|
|
229
|
+
return [parameter.method_signature(is_python3_file) for parameter in self.positional]
|
|
226
230
|
|
|
227
|
-
def method_signature_keyword_only(self,
|
|
228
|
-
if not (self.keyword_only and
|
|
231
|
+
def method_signature_keyword_only(self, is_python3_file: bool) -> List[str]:
|
|
232
|
+
if not (self.keyword_only and is_python3_file):
|
|
229
233
|
return []
|
|
230
|
-
return ["*,"] + [parameter.method_signature(
|
|
234
|
+
return ["*,"] + [parameter.method_signature(is_python3_file) for parameter in self.keyword_only]
|
|
231
235
|
|
|
232
236
|
@staticmethod
|
|
233
|
-
def method_signature_kwargs(
|
|
234
|
-
return ["**kwargs: Any"] if
|
|
237
|
+
def method_signature_kwargs(is_python3_file: bool) -> List[str]:
|
|
238
|
+
return ["**kwargs: Any"] if is_python3_file else ["**kwargs # type: Any"]
|
|
235
239
|
|
|
236
240
|
@property
|
|
237
241
|
def positional(self) -> List[Parameter]:
|
|
@@ -245,9 +249,9 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
|
|
|
245
249
|
def kwargs(self) -> List[Parameter]:
|
|
246
250
|
return [p for p in self.method if p.is_kwarg]
|
|
247
251
|
|
|
248
|
-
def kwargs_to_pop(self,
|
|
252
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
249
253
|
kwargs_to_pop = self.kwargs
|
|
250
|
-
if not
|
|
254
|
+
if not is_python3_file:
|
|
251
255
|
kwargs_to_pop += self.keyword_only
|
|
252
256
|
return kwargs_to_pop
|
|
253
257
|
|
|
@@ -433,41 +437,41 @@ class GlobalParameterList(ParameterList):
|
|
|
433
437
|
return True
|
|
434
438
|
return serialized_name != self.host_variable_name
|
|
435
439
|
|
|
436
|
-
def kwargs_to_pop(self,
|
|
440
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
437
441
|
return [
|
|
438
|
-
k for k in super().kwargs_to_pop(
|
|
442
|
+
k for k in super().kwargs_to_pop(is_python3_file)
|
|
439
443
|
if not self._param_is_in_config_method(k.serialized_name)
|
|
440
444
|
]
|
|
441
445
|
|
|
442
|
-
def config_kwargs_to_pop(self,
|
|
443
|
-
current_kwargs_to_pop = super().kwargs_to_pop(
|
|
446
|
+
def config_kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
447
|
+
current_kwargs_to_pop = super().kwargs_to_pop(is_python3_file)
|
|
444
448
|
return [k for k in current_kwargs_to_pop if self._param_is_in_config_method(k.serialized_name)]
|
|
445
449
|
|
|
446
450
|
@property
|
|
447
451
|
def config_method(self) -> List[Parameter]:
|
|
448
452
|
return [p for p in self.method if self._param_is_in_config_method(p.serialized_name)]
|
|
449
453
|
|
|
450
|
-
def client_method_signature(self,
|
|
451
|
-
return self.method_signature(
|
|
454
|
+
def client_method_signature(self, is_python3_file: bool) -> List[str]:
|
|
455
|
+
return self.method_signature(is_python3_file)
|
|
452
456
|
|
|
453
|
-
def config_method_signature(self,
|
|
457
|
+
def config_method_signature(self, is_python3_file: bool) -> List[str]:
|
|
454
458
|
|
|
455
459
|
positional = [
|
|
456
|
-
p.method_signature(
|
|
460
|
+
p.method_signature(is_python3_file)
|
|
457
461
|
for p in self.positional
|
|
458
462
|
if self._param_is_in_config_method(p.serialized_name)
|
|
459
463
|
]
|
|
460
464
|
keyword_only_params = [p for p in self.keyword_only if self._param_is_in_config_method(p.serialized_name)]
|
|
461
465
|
keyword_only_method_signature = []
|
|
462
|
-
if
|
|
466
|
+
if is_python3_file:
|
|
463
467
|
keyword_only_method_signature = (
|
|
464
468
|
["*,"] +
|
|
465
469
|
[
|
|
466
|
-
p.method_signature(
|
|
470
|
+
p.method_signature(is_python3_file) for p in keyword_only_params
|
|
467
471
|
]
|
|
468
472
|
) if keyword_only_params else []
|
|
469
473
|
return _method_signature_helper(
|
|
470
474
|
positional=positional,
|
|
471
475
|
keyword_only=keyword_only_method_signature,
|
|
472
|
-
kwarg_params=self.method_signature_kwargs(
|
|
476
|
+
kwarg_params=self.method_signature_kwargs(is_python3_file)
|
|
473
477
|
)
|
|
@@ -80,13 +80,17 @@ class RequestBuilder(BaseBuilder):
|
|
|
80
80
|
file_import.add_from_import(
|
|
81
81
|
f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
|
|
82
82
|
)
|
|
83
|
+
if self.parameters.headers or self.parameters.query:
|
|
84
|
+
file_import.add_from_import(
|
|
85
|
+
"typing", "Dict", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
|
|
86
|
+
)
|
|
83
87
|
file_import.add_from_import(
|
|
84
88
|
"typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
|
|
85
89
|
)
|
|
86
90
|
file_import.add_from_import("msrest", "Serializer", ImportType.AZURECORE)
|
|
87
91
|
if self.parameters.has_body and (
|
|
88
92
|
self.code_model.options["builders_visibility"] != "embedded" or
|
|
89
|
-
self.code_model.options["
|
|
93
|
+
self.code_model.options["add_python3_operation_files"]
|
|
90
94
|
):
|
|
91
95
|
file_import.define_mypy_type("JSONType", "Any")
|
|
92
96
|
return file_import
|
|
@@ -29,12 +29,13 @@ class RequestBuilderParameter(ParameterOnlyPathAndBodyPositional):
|
|
|
29
29
|
|
|
30
30
|
@property
|
|
31
31
|
def name_in_high_level_operation(self) -> str:
|
|
32
|
+
template = "{}" if self.code_model.options["version_tolerant"] else "_{}"
|
|
32
33
|
if self.is_multipart:
|
|
33
|
-
return "files"
|
|
34
|
+
return template.format("files")
|
|
34
35
|
if self.is_data_input:
|
|
35
|
-
return "data"
|
|
36
|
+
return template.format("data")
|
|
36
37
|
if self.is_body and not self.constant:
|
|
37
|
-
return self.serialized_name
|
|
38
|
+
return f"_{self.serialized_name}"
|
|
38
39
|
name = self.yaml_data["language"]["python"]["name"]
|
|
39
40
|
if self.implementation == "Client" and self.in_method_code:
|
|
40
41
|
# for these, we're passing the client params to the request builder.
|
|
@@ -44,6 +44,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
44
44
|
def _change_body_param_name(self, parameter: Parameter, name: str) -> None:
|
|
45
45
|
self.body_kwarg_names[name] = None
|
|
46
46
|
parameter.serialized_name = name
|
|
47
|
+
parameter.is_body_kwarg = True
|
|
47
48
|
|
|
48
49
|
def _is_json(self, body_method_param: Parameter) -> bool:
|
|
49
50
|
if 'json' in body_method_param.serialization_formats:
|
|
@@ -97,7 +98,6 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
97
98
|
"Multipart input for files. See the template in our example to find the input shape. " +
|
|
98
99
|
file_kwarg.description
|
|
99
100
|
)
|
|
100
|
-
file_kwarg.is_multipart = False
|
|
101
101
|
file_kwarg.content_types = [
|
|
102
102
|
c for c in content_types_to_assign
|
|
103
103
|
if c == "multipart/form-data"
|
|
@@ -119,7 +119,6 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
119
119
|
"Pass in dictionary that contains form data to include in the body of the request. " +
|
|
120
120
|
data_kwarg.description
|
|
121
121
|
)
|
|
122
|
-
data_kwarg.is_data_input = False
|
|
123
122
|
data_kwarg.content_types = [
|
|
124
123
|
c for c in content_types_to_assign
|
|
125
124
|
if c == "application/x-www-form-urlencoded"
|
|
@@ -208,7 +207,7 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
208
207
|
if not self._json_body:
|
|
209
208
|
try:
|
|
210
209
|
json_param = next(
|
|
211
|
-
b for b in self.body if b.
|
|
210
|
+
b for b in self.body if not b.is_body_kwarg and
|
|
212
211
|
b.is_json_parameter
|
|
213
212
|
)
|
|
214
213
|
self._json_body = json_param.schema
|
|
@@ -217,10 +216,10 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
217
216
|
raise ValueError("There is no JSON body in these parameters")
|
|
218
217
|
return self._json_body
|
|
219
218
|
|
|
220
|
-
def kwargs_to_pop(self,
|
|
219
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
221
220
|
# we don't want to pop the body kwargs in py2.7. We send them straight to HttpRequest
|
|
222
221
|
kwargs_to_pop = self.kwargs
|
|
223
|
-
if not
|
|
222
|
+
if not is_python3_file:
|
|
224
223
|
kwargs_to_pop += [k for k in self.keyword_only if not (k.is_body and not k.constant)]
|
|
225
224
|
return kwargs_to_pop
|
|
226
225
|
|
|
@@ -240,9 +239,19 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
240
239
|
seen_content_type = False
|
|
241
240
|
|
|
242
241
|
for parameter in parameters:
|
|
242
|
+
|
|
243
|
+
if (
|
|
244
|
+
parameter.location == ParameterLocation.Body and
|
|
245
|
+
(parameter.is_data_input or parameter.is_multipart) and
|
|
246
|
+
not parameter.is_body_kwarg
|
|
247
|
+
):
|
|
248
|
+
# if i am a part of files or data, and i'm not the files or
|
|
249
|
+
# data kwarg, ignore me
|
|
250
|
+
continue
|
|
243
251
|
if (
|
|
244
252
|
parameter.location == ParameterLocation.Body and
|
|
245
|
-
parameter.
|
|
253
|
+
not parameter.is_body_kwarg and
|
|
254
|
+
not parameter.constant
|
|
246
255
|
):
|
|
247
256
|
# we keep the original body param from the swagger for documentation purposes
|
|
248
257
|
# we don't want it in the method signature
|
|
@@ -19,10 +19,11 @@ class Rest(BaseModel):
|
|
|
19
19
|
super(Rest, self). __init__(yaml_data=yaml_data)
|
|
20
20
|
self.request_builders = request_builders
|
|
21
21
|
|
|
22
|
-
def imports(self) -> FileImport:
|
|
22
|
+
def imports(self, builder_group_name: str) -> FileImport:
|
|
23
23
|
file_import = FileImport()
|
|
24
24
|
for request_builder in self.request_builders:
|
|
25
|
-
|
|
25
|
+
if request_builder.builder_group_name == builder_group_name:
|
|
26
|
+
file_import.merge(request_builder.imports())
|
|
26
27
|
return file_import
|
|
27
28
|
|
|
28
29
|
@classmethod
|
|
@@ -3,29 +3,32 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import List, Optional
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from jinja2 import PackageLoader, Environment
|
|
9
9
|
from autorest.codegen.models.operation_group import OperationGroup
|
|
10
10
|
|
|
11
11
|
from ...jsonrpc import AutorestAPI
|
|
12
|
-
from ..models import
|
|
13
|
-
|
|
12
|
+
from ..models import (
|
|
13
|
+
CodeModel,
|
|
14
|
+
OperationGroup,
|
|
15
|
+
RequestBuilder,
|
|
16
|
+
)
|
|
14
17
|
from .enum_serializer import EnumSerializer
|
|
15
18
|
from .general_serializer import GeneralSerializer
|
|
16
19
|
from .model_generic_serializer import ModelGenericSerializer
|
|
17
20
|
from .model_init_serializer import ModelInitSerializer
|
|
18
21
|
from .model_python3_serializer import ModelPython3Serializer
|
|
19
22
|
from .operations_init_serializer import OperationsInitSerializer
|
|
20
|
-
from .
|
|
23
|
+
from .operation_groups_serializer import OperationGroupsSerializer
|
|
21
24
|
from .metadata_serializer import MetadataSerializer
|
|
22
25
|
from .rest_serializer import RestPython3Serializer, RestGenericSerializer, RestSerializer
|
|
26
|
+
from .patch_serializer import PatchSerializer
|
|
23
27
|
|
|
24
28
|
__all__ = [
|
|
25
29
|
"JinjaSerializer",
|
|
26
30
|
]
|
|
27
31
|
|
|
28
|
-
|
|
29
32
|
class JinjaSerializer:
|
|
30
33
|
def __init__(self, autorestapi: AutorestAPI) -> None:
|
|
31
34
|
self._autorestapi = autorestapi
|
|
@@ -45,8 +48,8 @@ class JinjaSerializer:
|
|
|
45
48
|
)
|
|
46
49
|
|
|
47
50
|
# if there was a patch file before, we keep it
|
|
48
|
-
self._keep_patch_file(namespace_path / Path("_patch.py"))
|
|
49
|
-
self._keep_patch_file(namespace_path / Path("aio") / Path("_patch.py"))
|
|
51
|
+
self._keep_patch_file(namespace_path / Path("_patch.py"), env)
|
|
52
|
+
self._keep_patch_file(namespace_path / Path("aio") / Path("_patch.py"), env)
|
|
50
53
|
|
|
51
54
|
self._serialize_and_write_top_level_folder(code_model=code_model, env=env, namespace_path=namespace_path)
|
|
52
55
|
|
|
@@ -70,16 +73,18 @@ class JinjaSerializer:
|
|
|
70
73
|
|
|
71
74
|
|
|
72
75
|
|
|
73
|
-
def _keep_patch_file(self, path_file: Path):
|
|
76
|
+
def _keep_patch_file(self, path_file: Path, env: Environment):
|
|
74
77
|
if self._autorestapi.read_file(path_file):
|
|
75
78
|
self._autorestapi.write_file(path_file, self._autorestapi.read_file(path_file))
|
|
79
|
+
else:
|
|
80
|
+
self._autorestapi.write_file(path_file, PatchSerializer(env=env).serialize())
|
|
76
81
|
|
|
77
82
|
|
|
78
83
|
def _serialize_and_write_models_folder(self, code_model: CodeModel, env: Environment, namespace_path: Path) -> None:
|
|
79
84
|
# Write the models folder
|
|
80
85
|
models_path = namespace_path / Path("models")
|
|
81
86
|
if code_model.schemas:
|
|
82
|
-
if not code_model.options['
|
|
87
|
+
if not code_model.options['python3_only']:
|
|
83
88
|
self._autorestapi.write_file(
|
|
84
89
|
models_path / Path("_models.py"), ModelGenericSerializer(code_model=code_model, env=env).serialize()
|
|
85
90
|
)
|
|
@@ -144,36 +149,49 @@ class JinjaSerializer:
|
|
|
144
149
|
).serialize_init()
|
|
145
150
|
)
|
|
146
151
|
|
|
147
|
-
def
|
|
152
|
+
def _serialize_and_write_operations_file(
|
|
148
153
|
self,
|
|
149
154
|
code_model: CodeModel,
|
|
150
155
|
env: Environment,
|
|
151
156
|
namespace_path: Path,
|
|
152
|
-
|
|
153
|
-
filename: str
|
|
157
|
+
operation_group: Optional[OperationGroup] = None
|
|
154
158
|
) -> None:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
filename = operation_group.filename if operation_group else "_operations"
|
|
160
|
+
# write first sync file
|
|
161
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
162
|
+
code_model=code_model,
|
|
163
|
+
env=env,
|
|
164
|
+
async_mode=False,
|
|
165
|
+
is_python3_file=code_model.options['python3_only'],
|
|
166
|
+
operation_group=operation_group
|
|
167
|
+
)
|
|
168
|
+
self._autorestapi.write_file(
|
|
169
|
+
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}.py"),
|
|
170
|
+
operation_group_serializer.serialize(),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if not code_model.options['python3_only'] and code_model.options["add_python3_operation_files"]:
|
|
174
|
+
# write typed second file if not python 3 only
|
|
175
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
158
176
|
code_model=code_model,
|
|
159
177
|
env=env,
|
|
160
|
-
operation_groups=operation_groups,
|
|
161
178
|
async_mode=False,
|
|
162
|
-
|
|
179
|
+
is_python3_file=True,
|
|
180
|
+
|
|
163
181
|
)
|
|
164
182
|
self._autorestapi.write_file(
|
|
165
|
-
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}.py"),
|
|
183
|
+
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}_py3.py"),
|
|
166
184
|
operation_group_serializer.serialize(),
|
|
167
185
|
)
|
|
168
186
|
|
|
169
187
|
if not code_model.options["no_async"]:
|
|
170
188
|
# write async operation group and operation files
|
|
171
|
-
operation_group_async_serializer =
|
|
189
|
+
operation_group_async_serializer = OperationGroupsSerializer(
|
|
172
190
|
code_model=code_model,
|
|
173
191
|
env=env,
|
|
174
|
-
operation_groups=operation_groups,
|
|
175
192
|
async_mode=True,
|
|
176
|
-
|
|
193
|
+
is_python3_file=True,
|
|
194
|
+
operation_group=operation_group
|
|
177
195
|
)
|
|
178
196
|
self._autorestapi.write_file(
|
|
179
197
|
(
|
|
@@ -185,20 +203,6 @@ class JinjaSerializer:
|
|
|
185
203
|
operation_group_async_serializer.serialize(),
|
|
186
204
|
)
|
|
187
205
|
|
|
188
|
-
if code_model.options["add_python_3_operation_files"]:
|
|
189
|
-
# write typed sync operation files
|
|
190
|
-
operation_group_serializer = OperationGroupSerializer(
|
|
191
|
-
code_model=code_model,
|
|
192
|
-
env=env,
|
|
193
|
-
operation_groups=operation_groups,
|
|
194
|
-
async_mode=False,
|
|
195
|
-
is_python_3_file=True,
|
|
196
|
-
)
|
|
197
|
-
self._autorestapi.write_file(
|
|
198
|
-
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}_py3.py"),
|
|
199
|
-
operation_group_serializer.serialize(),
|
|
200
|
-
)
|
|
201
|
-
|
|
202
206
|
def _serialize_and_write_operations_folder(
|
|
203
207
|
self, code_model: CodeModel, env: Environment, namespace_path: Path
|
|
204
208
|
) -> None:
|
|
@@ -217,24 +221,20 @@ class JinjaSerializer:
|
|
|
217
221
|
operations_async_init_serializer.serialize(),
|
|
218
222
|
)
|
|
219
223
|
|
|
220
|
-
if
|
|
224
|
+
if code_model.options["combine_operation_files"]:
|
|
225
|
+
self._serialize_and_write_operations_file(
|
|
226
|
+
code_model=code_model,
|
|
227
|
+
env=env,
|
|
228
|
+
namespace_path=namespace_path,
|
|
229
|
+
)
|
|
230
|
+
else:
|
|
221
231
|
for operation_group in code_model.operation_groups:
|
|
222
|
-
self.
|
|
232
|
+
self._serialize_and_write_operations_file(
|
|
223
233
|
code_model=code_model,
|
|
224
234
|
env=env,
|
|
225
235
|
namespace_path=namespace_path,
|
|
226
|
-
|
|
227
|
-
filename=operation_group.filename
|
|
236
|
+
operation_group=operation_group,
|
|
228
237
|
)
|
|
229
|
-
else:
|
|
230
|
-
self._serialize_and_write_operations_folder_process(
|
|
231
|
-
code_model=code_model,
|
|
232
|
-
env=env,
|
|
233
|
-
namespace_path=namespace_path,
|
|
234
|
-
operation_groups=code_model.operation_groups,
|
|
235
|
-
filename="_operations"
|
|
236
|
-
)
|
|
237
|
-
|
|
238
238
|
|
|
239
239
|
def _serialize_and_write_version_file(
|
|
240
240
|
self, code_model: CodeModel, namespace_path: Path, general_serializer: GeneralSerializer
|