@autorest/python 5.10.0 → 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 +74 -0
- package/autorest/codegen/__init__.py +7 -7
- package/autorest/codegen/models/__init__.py +2 -1
- package/autorest/codegen/models/base_builder.py +16 -8
- package/autorest/codegen/models/client.py +5 -3
- package/autorest/codegen/models/code_model.py +19 -5
- package/autorest/codegen/models/imports.py +7 -0
- package/autorest/codegen/models/lro_operation.py +7 -3
- package/autorest/codegen/models/object_schema.py +3 -3
- package/autorest/codegen/models/operation.py +69 -38
- package/autorest/codegen/models/operation_group.py +13 -8
- package/autorest/codegen/models/paging_operation.py +5 -2
- package/autorest/codegen/models/parameter.py +46 -13
- package/autorest/codegen/models/parameter_list.py +62 -70
- package/autorest/codegen/models/primitive_schemas.py +11 -0
- package/autorest/codegen/models/request_builder.py +21 -8
- package/autorest/codegen/models/request_builder_parameter.py +9 -5
- package/autorest/codegen/models/request_builder_parameter_list.py +179 -77
- package/autorest/codegen/models/rest.py +3 -2
- package/autorest/codegen/models/schema_request.py +4 -17
- package/autorest/codegen/models/schema_response.py +4 -4
- package/autorest/codegen/serializers/__init__.py +57 -53
- package/autorest/codegen/serializers/builder_serializer.py +76 -46
- 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 +22 -7
- 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_groups_serializer.py +70 -0
- 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 -7
- 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/operation_groups_container.py.jinja2 +26 -0
- package/autorest/codegen/templates/operation_tools.jinja2 +7 -0
- 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 +3 -3
- 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 +48 -3
- package/package.json +2 -2
- package/setup.py +1 -0
- package/autorest/codegen/serializers/operation_group_serializer.py +0 -71
- package/autorest/codegen/templates/operations_class_mixin.py.jinja2 +0 -16
- package/autorest/codegen/templates/operations_container.py.jinja2 +0 -42
- package/autorest/codegen/templates/operations_container_init.py.jinja2 +0 -24
- package/autorest/codegen/templates/operations_container_mixin.py.jinja2 +0 -23
package/ChangeLog.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
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
|
+
|
|
29
|
+
### 2021-11-05 - 5.11.2
|
|
30
|
+
|
|
31
|
+
| Library | Min Version
|
|
32
|
+
| --------------- | -------
|
|
33
|
+
|`@autorest/core` | `3.6.2`
|
|
34
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
35
|
+
|`azure-core` dep of generated code | `1.20.0`
|
|
36
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
37
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
38
|
+
|
|
39
|
+
**Bug Fixes**
|
|
40
|
+
|
|
41
|
+
- Respect no client side validation for low level client generations #1080
|
|
42
|
+
|
|
43
|
+
### 2021-11-05 - 5.11.1
|
|
44
|
+
|
|
45
|
+
| Library | Min Version
|
|
46
|
+
| --------------- | -------
|
|
47
|
+
|`@autorest/core` | `3.6.2`
|
|
48
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
49
|
+
|`azure-core` dep of generated code | `1.20.0`
|
|
50
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
51
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
52
|
+
|
|
53
|
+
**Bug Fixes**
|
|
54
|
+
|
|
55
|
+
- Hide mixin operations for version tolerant generation #1071
|
|
56
|
+
|
|
57
|
+
### 2021-11-04 - 5.11.0
|
|
58
|
+
|
|
59
|
+
| Library | Min Version
|
|
60
|
+
| --------------- | -------
|
|
61
|
+
|`@autorest/core` | `3.6.2`
|
|
62
|
+
|`@autorest/modelerfour` | `4.19.1`
|
|
63
|
+
|`azure-core` dep of generated code | `1.20.0`
|
|
64
|
+
|`msrest` dep of generated code | `0.6.21`
|
|
65
|
+
|`azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0`
|
|
66
|
+
|
|
67
|
+
**New Features**
|
|
68
|
+
|
|
69
|
+
- Add `_patch.py` support for `aio` folder #1070
|
|
70
|
+
|
|
71
|
+
**Bug Fixes**
|
|
72
|
+
|
|
73
|
+
- Fix documentation for HEAD calls that perform boolean checks on returned status codes in version tolerant code #1072
|
|
74
|
+
- Fix body grouping by content types for binary bodies #1076
|
|
75
|
+
- Fix default content type determination #1078
|
|
76
|
+
|
|
3
77
|
### 2021-11-01 - 5.10.0
|
|
4
78
|
|
|
5
79
|
| Library | Min Version
|
|
@@ -31,9 +31,9 @@ def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -
|
|
|
31
31
|
code_model.sort_schemas()
|
|
32
32
|
|
|
33
33
|
if code_model.options["show_operations"]:
|
|
34
|
-
code_model.link_operation_to_request_builder()
|
|
35
34
|
code_model.add_schema_link_to_operation()
|
|
36
|
-
code_model.
|
|
35
|
+
code_model.generate_single_parameter_from_multiple_content_types_operation()
|
|
36
|
+
code_model.link_operation_to_request_builder()
|
|
37
37
|
# LRO operation
|
|
38
38
|
code_model.format_lro_operations()
|
|
39
39
|
code_model.remove_next_operation()
|
|
@@ -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:
|
|
@@ -10,7 +10,7 @@ from .credential_schema import AzureKeyCredentialSchema, TokenCredentialSchema
|
|
|
10
10
|
from .object_schema import ObjectSchema, get_object_schema, HiddenModelObjectSchema
|
|
11
11
|
from .dictionary_schema import DictionarySchema
|
|
12
12
|
from .list_schema import ListSchema
|
|
13
|
-
from .primitive_schemas import get_primitive_schema, AnySchema, PrimitiveSchema
|
|
13
|
+
from .primitive_schemas import get_primitive_schema, AnySchema, PrimitiveSchema, IOSchema
|
|
14
14
|
from .enum_schema import EnumSchema, HiddenModelEnumSchema, get_enum_schema
|
|
15
15
|
from .base_schema import BaseSchema
|
|
16
16
|
from .constant_schema import ConstantSchema
|
|
@@ -62,6 +62,7 @@ __all__ = [
|
|
|
62
62
|
"RequestBuilderParameter",
|
|
63
63
|
"HiddenModelObjectSchema",
|
|
64
64
|
"ParameterStyle",
|
|
65
|
+
"IOSchema",
|
|
65
66
|
]
|
|
66
67
|
|
|
67
68
|
def _generate_as_object_schema(yaml_data: Dict[str, Any]) -> bool:
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
from typing import Any, Callable, Dict, List, Optional, Union, TYPE_CHECKING
|
|
7
7
|
from .base_model import BaseModel
|
|
8
8
|
from .schema_response import SchemaResponse
|
|
9
|
+
from .schema_request import SchemaRequest
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from . import ParameterListType
|
|
@@ -13,11 +14,16 @@ if TYPE_CHECKING:
|
|
|
13
14
|
|
|
14
15
|
_M4_HEADER_PARAMETERS = ["content_type", "accept"]
|
|
15
16
|
|
|
16
|
-
def create_parameters(
|
|
17
|
+
def create_parameters(
|
|
18
|
+
yaml_data: Dict[str, Any], code_model, parameter_creator: Callable
|
|
19
|
+
):
|
|
17
20
|
multiple_requests = len(yaml_data["requests"]) > 1
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
parameters = [
|
|
22
|
+
multiple_content_type_parameters = []
|
|
23
|
+
parameters = [
|
|
24
|
+
parameter_creator(yaml, code_model=code_model)
|
|
25
|
+
for yaml in yaml_data.get("parameters", [])
|
|
26
|
+
]
|
|
21
27
|
|
|
22
28
|
for request in yaml_data["requests"]:
|
|
23
29
|
for yaml in request.get("parameters", []):
|
|
@@ -26,14 +32,14 @@ def create_parameters(yaml_data: Dict[str, Any], code_model, parameter_creator:
|
|
|
26
32
|
if name in _M4_HEADER_PARAMETERS:
|
|
27
33
|
parameters.append(parameter)
|
|
28
34
|
elif multiple_requests:
|
|
29
|
-
parameter.
|
|
30
|
-
|
|
35
|
+
parameter.has_multiple_content_types = True
|
|
36
|
+
multiple_content_type_parameters.append(parameter)
|
|
31
37
|
else:
|
|
32
38
|
parameters.append(parameter)
|
|
33
39
|
|
|
34
|
-
if
|
|
40
|
+
if multiple_content_type_parameters:
|
|
35
41
|
body_parameters_name_set = set(
|
|
36
|
-
p.serialized_name for p in
|
|
42
|
+
p.serialized_name for p in multiple_content_type_parameters
|
|
37
43
|
)
|
|
38
44
|
if len(body_parameters_name_set) > 1:
|
|
39
45
|
raise ValueError(
|
|
@@ -53,7 +59,7 @@ def create_parameters(yaml_data: Dict[str, Any], code_model, parameter_creator:
|
|
|
53
59
|
if parameter_original_id in parameters_index:
|
|
54
60
|
parameter.original_parameter = parameters_index[parameter_original_id]
|
|
55
61
|
|
|
56
|
-
return parameters,
|
|
62
|
+
return parameters, multiple_content_type_parameters
|
|
57
63
|
|
|
58
64
|
class BaseBuilder(BaseModel):
|
|
59
65
|
"""Base class for Operations and Request Builders"""
|
|
@@ -65,6 +71,7 @@ class BaseBuilder(BaseModel):
|
|
|
65
71
|
name: str,
|
|
66
72
|
description: str,
|
|
67
73
|
parameters: "ParameterListType",
|
|
74
|
+
schema_requests: List[SchemaRequest],
|
|
68
75
|
responses: Optional[List[SchemaResponse]] = None,
|
|
69
76
|
summary: Optional[str] = None,
|
|
70
77
|
) -> None:
|
|
@@ -75,6 +82,7 @@ class BaseBuilder(BaseModel):
|
|
|
75
82
|
self.parameters = parameters
|
|
76
83
|
self.responses = responses or []
|
|
77
84
|
self.summary = summary
|
|
85
|
+
self.schema_requests = schema_requests
|
|
78
86
|
|
|
79
87
|
@property
|
|
80
88
|
def default_content_type_declaration(self) -> str:
|
|
@@ -73,7 +73,9 @@ class Client:
|
|
|
73
73
|
)
|
|
74
74
|
file_import.add_from_import("azure.core.rest", "HttpRequest", ImportType.AZURECORE, TypingSection.CONDITIONAL)
|
|
75
75
|
for og in self.code_model.operation_groups:
|
|
76
|
-
file_import.add_from_import(
|
|
76
|
+
file_import.add_from_import(
|
|
77
|
+
f".{self.code_model.operations_folder_name}", og.class_name, ImportType.LOCAL
|
|
78
|
+
)
|
|
77
79
|
|
|
78
80
|
if self.code_model.sorted_schemas:
|
|
79
81
|
path_to_models = ".." if async_mode else "."
|
|
@@ -94,6 +96,6 @@ class Client:
|
|
|
94
96
|
pass
|
|
95
97
|
return file_import
|
|
96
98
|
|
|
97
|
-
def send_request_signature(self, async_mode) -> List[str]:
|
|
99
|
+
def send_request_signature(self, async_mode: bool, is_python3_file: bool) -> List[str]:
|
|
98
100
|
request_signature = ["request: HttpRequest," if async_mode else "request, # type: HttpRequest"]
|
|
99
|
-
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
|
|
@@ -238,6 +242,15 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
238
242
|
|
|
239
243
|
return properties
|
|
240
244
|
|
|
245
|
+
@property
|
|
246
|
+
def operations_folder_name(self) -> str:
|
|
247
|
+
name = "operations"
|
|
248
|
+
if self.options["version_tolerant"] and not any(
|
|
249
|
+
og for og in self.operation_groups if not og.is_empty_operation_group
|
|
250
|
+
):
|
|
251
|
+
name = f"_{name}"
|
|
252
|
+
return name
|
|
253
|
+
|
|
241
254
|
def _add_properties_from_inheritance(self) -> None:
|
|
242
255
|
"""Adds properties from base classes to schemas with parents.
|
|
243
256
|
|
|
@@ -316,7 +329,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
316
329
|
for operation in operation_group.operations:
|
|
317
330
|
for obj in chain(
|
|
318
331
|
operation.parameters,
|
|
319
|
-
operation.
|
|
332
|
+
operation.multiple_content_type_parameters or [],
|
|
320
333
|
operation.responses,
|
|
321
334
|
operation.exceptions,
|
|
322
335
|
chain.from_iterable(response.headers for response in operation.responses),
|
|
@@ -337,11 +350,11 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
337
350
|
for parameter in self.global_parameters:
|
|
338
351
|
self._populate_schema(parameter)
|
|
339
352
|
|
|
340
|
-
def
|
|
353
|
+
def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
|
|
341
354
|
for operation_group in self.operation_groups:
|
|
342
355
|
for operation in operation_group.operations:
|
|
343
|
-
if operation.
|
|
344
|
-
operation.
|
|
356
|
+
if operation.multiple_content_type_parameters:
|
|
357
|
+
operation.convert_multiple_content_type_parameters()
|
|
345
358
|
|
|
346
359
|
@property
|
|
347
360
|
def need_vendored_code(self) -> bool:
|
|
@@ -383,3 +396,4 @@ class CodeModel: # pylint: disable=too-many-instance-attributes
|
|
|
383
396
|
if isinstance(operation, LROOperation):
|
|
384
397
|
request_builder.name = request_builder.name + "_initial"
|
|
385
398
|
operation.request_builder = request_builder
|
|
399
|
+
operation.link_body_kwargs_to_body_params()
|
|
@@ -36,6 +36,8 @@ class FileImport:
|
|
|
36
36
|
TypingSection,
|
|
37
37
|
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]
|
|
38
38
|
] = imports or dict()
|
|
39
|
+
# has sync and async type definitions
|
|
40
|
+
self.type_definitions: Dict[str, Tuple[str, str]] = {}
|
|
39
41
|
|
|
40
42
|
def _add_import(
|
|
41
43
|
self,
|
|
@@ -82,6 +84,10 @@ class FileImport:
|
|
|
82
84
|
]:
|
|
83
85
|
return self._imports
|
|
84
86
|
|
|
87
|
+
def define_mypy_type(self, type_name: str, type_value: str, async_type_value: Optional[str] = None):
|
|
88
|
+
self._add_import("typing", ImportType.STDLIB, "TypeVar", TypingSection.CONDITIONAL)
|
|
89
|
+
self.type_definitions[type_name] = (type_value, async_type_value or type_value)
|
|
90
|
+
|
|
85
91
|
def merge(self, file_import: "FileImport") -> None:
|
|
86
92
|
"""Merge the given file import format."""
|
|
87
93
|
for typing_section, import_type_dict in file_import.imports.items():
|
|
@@ -89,3 +95,4 @@ class FileImport:
|
|
|
89
95
|
for package_name, module_list in package_list.items():
|
|
90
96
|
for module_name in module_list:
|
|
91
97
|
self._add_import(package_name, import_type, module_name, typing_section)
|
|
98
|
+
self.type_definitions.update(file_import.type_definitions)
|
|
@@ -11,6 +11,7 @@ from .parameter_list import ParameterList
|
|
|
11
11
|
from .schema_response import SchemaResponse
|
|
12
12
|
from .imports import ImportType, TypingSection
|
|
13
13
|
from .base_schema import BaseSchema
|
|
14
|
+
from .schema_request import SchemaRequest
|
|
14
15
|
|
|
15
16
|
_LOGGER = logging.getLogger(__name__)
|
|
16
17
|
|
|
@@ -24,7 +25,8 @@ class LROOperation(Operation):
|
|
|
24
25
|
description: str,
|
|
25
26
|
api_versions: Set[str],
|
|
26
27
|
parameters: ParameterList,
|
|
27
|
-
|
|
28
|
+
multiple_content_type_parameters: ParameterList,
|
|
29
|
+
schema_requests: List[SchemaRequest],
|
|
28
30
|
summary: Optional[str] = None,
|
|
29
31
|
responses: Optional[List[SchemaResponse]] = None,
|
|
30
32
|
exceptions: Optional[List[SchemaResponse]] = None,
|
|
@@ -38,7 +40,8 @@ class LROOperation(Operation):
|
|
|
38
40
|
description,
|
|
39
41
|
api_versions,
|
|
40
42
|
parameters,
|
|
41
|
-
|
|
43
|
+
multiple_content_type_parameters,
|
|
44
|
+
schema_requests,
|
|
42
45
|
summary,
|
|
43
46
|
responses,
|
|
44
47
|
exceptions,
|
|
@@ -86,7 +89,8 @@ class LROOperation(Operation):
|
|
|
86
89
|
description="",
|
|
87
90
|
api_versions=self.api_versions,
|
|
88
91
|
parameters=self.parameters,
|
|
89
|
-
|
|
92
|
+
schema_requests=self.schema_requests,
|
|
93
|
+
multiple_content_type_parameters=self.multiple_content_type_parameters,
|
|
90
94
|
summary=self.summary,
|
|
91
95
|
responses=self.responses,
|
|
92
96
|
want_description_docstring=False,
|
|
@@ -224,15 +224,15 @@ class HiddenModelObjectSchema(ObjectSchema):
|
|
|
224
224
|
|
|
225
225
|
@property
|
|
226
226
|
def type_annotation(self) -> str:
|
|
227
|
-
return "
|
|
227
|
+
return "JSONType"
|
|
228
228
|
|
|
229
229
|
@property
|
|
230
230
|
def operation_type_annotation(self) -> str:
|
|
231
|
-
return "
|
|
231
|
+
return "JSONType"
|
|
232
232
|
|
|
233
233
|
@property
|
|
234
234
|
def docstring_type(self) -> str:
|
|
235
|
-
return "
|
|
235
|
+
return "JSONType"
|
|
236
236
|
|
|
237
237
|
@property
|
|
238
238
|
def docstring_text(self) -> str:
|
|
@@ -10,11 +10,13 @@ from typing import cast, Dict, List, Any, Optional, Union, Set
|
|
|
10
10
|
from .base_builder import BaseBuilder, create_parameters
|
|
11
11
|
from .imports import FileImport, ImportType, TypingSection
|
|
12
12
|
from .schema_response import SchemaResponse
|
|
13
|
-
from .parameter import get_parameter
|
|
13
|
+
from .parameter import Parameter, get_parameter
|
|
14
14
|
from .parameter_list import ParameterList, get_parameter_list
|
|
15
15
|
from .base_schema import BaseSchema
|
|
16
16
|
from .object_schema import ObjectSchema
|
|
17
17
|
from .request_builder import RequestBuilder
|
|
18
|
+
from .schema_request import SchemaRequest
|
|
19
|
+
from .primitive_schemas import IOSchema
|
|
18
20
|
|
|
19
21
|
_LOGGER = logging.getLogger(__name__)
|
|
20
22
|
|
|
@@ -30,7 +32,8 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
30
32
|
description: str,
|
|
31
33
|
api_versions: Set[str],
|
|
32
34
|
parameters: ParameterList,
|
|
33
|
-
|
|
35
|
+
multiple_content_type_parameters: ParameterList,
|
|
36
|
+
schema_requests: List[SchemaRequest],
|
|
34
37
|
summary: Optional[str] = None,
|
|
35
38
|
responses: Optional[List[SchemaResponse]] = None,
|
|
36
39
|
exceptions: Optional[List[SchemaResponse]] = None,
|
|
@@ -44,11 +47,12 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
44
47
|
description=description,
|
|
45
48
|
parameters=parameters,
|
|
46
49
|
responses=responses,
|
|
50
|
+
schema_requests=schema_requests,
|
|
47
51
|
summary=summary,
|
|
48
52
|
)
|
|
49
|
-
self.
|
|
53
|
+
self.multiple_content_type_parameters = multiple_content_type_parameters
|
|
50
54
|
self.api_versions = api_versions
|
|
51
|
-
self.
|
|
55
|
+
self.multiple_content_type_parameters = multiple_content_type_parameters
|
|
52
56
|
self.exceptions = exceptions or []
|
|
53
57
|
self.want_description_docstring = want_description_docstring
|
|
54
58
|
self.want_tracing = want_tracing
|
|
@@ -79,28 +83,7 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
79
83
|
|
|
80
84
|
@property
|
|
81
85
|
def body_kwargs_to_pass_to_request_builder(self) -> List[str]:
|
|
82
|
-
|
|
83
|
-
if not self.parameters.has_body:
|
|
84
|
-
return []
|
|
85
|
-
body_kwarg_names = self.request_builder.parameters.body_kwarg_names
|
|
86
|
-
for kwarg in body_kwarg_names:
|
|
87
|
-
if kwarg == "content":
|
|
88
|
-
if self.request_builder.is_stream:
|
|
89
|
-
kwargs.append("content")
|
|
90
|
-
else:
|
|
91
|
-
kwargs.append(kwarg)
|
|
92
|
-
if not kwargs and not self.parameters.body[0].constant:
|
|
93
|
-
kwargs.append("content")
|
|
94
|
-
return kwargs
|
|
95
|
-
|
|
96
|
-
@property
|
|
97
|
-
def serialized_body_kwarg(self) -> str:
|
|
98
|
-
# body serialization can be passed to either "json" or "content"
|
|
99
|
-
if "json" in self.body_kwargs_to_pass_to_request_builder:
|
|
100
|
-
return "json"
|
|
101
|
-
if not self.request_builder.is_stream:
|
|
102
|
-
return "content"
|
|
103
|
-
raise ValueError("You should not be trying to serialize this body")
|
|
86
|
+
return [p.serialized_name for p in self.request_builder.body_kwargs_to_get]
|
|
104
87
|
|
|
105
88
|
@property
|
|
106
89
|
def has_optional_return_type(self) -> bool:
|
|
@@ -168,7 +151,7 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
168
151
|
for param in self.parameters.method:
|
|
169
152
|
file_import.merge(param.imports())
|
|
170
153
|
|
|
171
|
-
for param in self.
|
|
154
|
+
for param in self.multiple_content_type_parameters:
|
|
172
155
|
file_import.merge(param.imports())
|
|
173
156
|
|
|
174
157
|
for response in self.responses:
|
|
@@ -239,30 +222,72 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
239
222
|
file_import.add_from_import(
|
|
240
223
|
f"{relative_path}_vendor", "_convert_request", ImportType.LOCAL
|
|
241
224
|
)
|
|
225
|
+
if self.code_model.options["version_tolerant"] and (
|
|
226
|
+
self.parameters.has_body or
|
|
227
|
+
any(r for r in self.responses if r.has_body)
|
|
228
|
+
):
|
|
229
|
+
file_import.define_mypy_type("JSONType", "Any")
|
|
242
230
|
return file_import
|
|
243
231
|
|
|
244
|
-
def
|
|
232
|
+
def _get_body_param_from_body_kwarg(self, body_kwarg: Parameter) -> Parameter:
|
|
233
|
+
# determine which of the body parameters returned from m4 corresponds to this body_kwarg
|
|
234
|
+
if not self.multiple_content_type_parameters.has_body:
|
|
235
|
+
return self.parameters.body[0]
|
|
236
|
+
if body_kwarg.serialized_name == "data":
|
|
237
|
+
return next(p for p in self.multiple_content_type_parameters.body if p.is_data_input)
|
|
238
|
+
if body_kwarg.serialized_name == "files":
|
|
239
|
+
return next(p for p in self.multiple_content_type_parameters.body if p.is_multipart)
|
|
240
|
+
if body_kwarg.serialized_name == "json":
|
|
241
|
+
# first check if there's any non-binary. In the case of multiple content types, there's
|
|
242
|
+
# usually one binary (for content), and one schema parameter (for json)
|
|
243
|
+
try:
|
|
244
|
+
return next(
|
|
245
|
+
p for p in self.multiple_content_type_parameters.body
|
|
246
|
+
if not isinstance(p.schema, IOSchema)
|
|
247
|
+
)
|
|
248
|
+
except StopIteration:
|
|
249
|
+
return next(p for p in self.multiple_content_type_parameters.body if p.is_json_parameter)
|
|
250
|
+
return self.multiple_content_type_parameters.body[0]
|
|
251
|
+
|
|
252
|
+
def link_body_kwargs_to_body_params(self) -> None:
|
|
253
|
+
if not self.parameters.has_body:
|
|
254
|
+
return
|
|
255
|
+
body_kwargs = [
|
|
256
|
+
p for p in self.request_builder.parameters.body
|
|
257
|
+
if p.content_types
|
|
258
|
+
]
|
|
259
|
+
if len(body_kwargs) == 1:
|
|
260
|
+
self.parameters.body[0].body_kwargs = [body_kwargs[0]]
|
|
261
|
+
return
|
|
262
|
+
for body_kwarg in body_kwargs:
|
|
263
|
+
body_param = self._get_body_param_from_body_kwarg(body_kwarg)
|
|
264
|
+
body_param.body_kwargs.append(body_kwarg)
|
|
265
|
+
|
|
266
|
+
def convert_multiple_content_type_parameters(self) -> None:
|
|
245
267
|
type_annot = ", ".join([
|
|
246
268
|
param.schema.operation_type_annotation
|
|
247
|
-
for param in self.
|
|
269
|
+
for param in self.multiple_content_type_parameters
|
|
248
270
|
])
|
|
249
271
|
docstring_type = " or ".join([
|
|
250
|
-
param.schema.docstring_type for param in self.
|
|
272
|
+
param.schema.docstring_type for param in self.multiple_content_type_parameters
|
|
251
273
|
])
|
|
252
274
|
try:
|
|
253
275
|
# get an optional param with object first. These params are the top choice
|
|
254
276
|
# bc they have more info about how to serialize the body
|
|
255
277
|
chosen_parameter = next(
|
|
256
|
-
p for p in self.
|
|
278
|
+
p for p in self.multiple_content_type_parameters
|
|
279
|
+
if not p.required and isinstance(p.schema, ObjectSchema)
|
|
257
280
|
)
|
|
258
281
|
except StopIteration: # pylint: disable=broad-except
|
|
259
282
|
# otherwise, we get the first optional param, if that exists. If not, we just grab the first one
|
|
260
|
-
optional_parameters = [p for p in self.
|
|
261
|
-
chosen_parameter =
|
|
283
|
+
optional_parameters = [p for p in self.multiple_content_type_parameters if not p.required]
|
|
284
|
+
chosen_parameter = (
|
|
285
|
+
optional_parameters[0] if optional_parameters else self.multiple_content_type_parameters[0]
|
|
286
|
+
)
|
|
262
287
|
if not chosen_parameter:
|
|
263
288
|
raise ValueError("You are missing a parameter that has multiple media types")
|
|
264
|
-
chosen_parameter.
|
|
265
|
-
chosen_parameter.
|
|
289
|
+
chosen_parameter.multiple_content_types_type_annot = f"Union[{type_annot}]"
|
|
290
|
+
chosen_parameter.multiple_content_types_docstring_type = docstring_type
|
|
266
291
|
self.parameters.append(chosen_parameter)
|
|
267
292
|
|
|
268
293
|
@classmethod
|
|
@@ -272,7 +297,10 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
272
297
|
|
|
273
298
|
parameter_creator = get_parameter(code_model).from_yaml
|
|
274
299
|
parameter_list_creator = get_parameter_list(code_model)
|
|
275
|
-
|
|
300
|
+
schema_requests = [SchemaRequest.from_yaml(yaml, code_model=code_model) for yaml in yaml_data["requests"]]
|
|
301
|
+
parameters, multiple_content_type_parameters = create_parameters(
|
|
302
|
+
yaml_data, code_model, parameter_creator
|
|
303
|
+
)
|
|
276
304
|
|
|
277
305
|
return cls(
|
|
278
306
|
code_model=code_model,
|
|
@@ -280,8 +308,11 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
280
308
|
name=name,
|
|
281
309
|
description=yaml_data["language"]["python"]["description"],
|
|
282
310
|
api_versions=set(value_dict["version"] for value_dict in yaml_data["apiVersions"]),
|
|
283
|
-
parameters=parameter_list_creator(code_model, parameters),
|
|
284
|
-
|
|
311
|
+
parameters=parameter_list_creator(code_model, parameters, schema_requests),
|
|
312
|
+
multiple_content_type_parameters=parameter_list_creator(
|
|
313
|
+
code_model, multiple_content_type_parameters, schema_requests
|
|
314
|
+
),
|
|
315
|
+
schema_requests=schema_requests,
|
|
285
316
|
summary=yaml_data["language"]["python"].get("summary"),
|
|
286
317
|
responses=[SchemaResponse.from_yaml(yaml) for yaml in yaml_data.get("responses", [])],
|
|
287
318
|
# Exception with no schema means default exception, we don't store them
|
|
@@ -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,25 +85,30 @@ 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
|
+
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 ""
|
|
88
91
|
file_import.add_from_import(
|
|
89
|
-
f"...
|
|
92
|
+
f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
|
|
90
93
|
request_builder.name,
|
|
91
94
|
import_type=ImportType.LOCAL
|
|
92
95
|
)
|
|
93
|
-
|
|
96
|
+
type_value = "Optional[Callable[[PipelineResponse[HttpRequest, {}HttpResponse], T, Dict[str, Any]], Any]]"
|
|
97
|
+
file_import.define_mypy_type(
|
|
98
|
+
"ClsType",
|
|
99
|
+
type_value.format(""),
|
|
100
|
+
type_value.format("Async")
|
|
101
|
+
)
|
|
94
102
|
return file_import
|
|
95
103
|
|
|
96
104
|
|
|
97
105
|
@property
|
|
98
106
|
def filename(self) -> str:
|
|
99
|
-
if self.code_model.options["combine_operation_files"]:
|
|
100
|
-
return "_operations"
|
|
101
|
-
|
|
102
107
|
basename = self.name
|
|
103
108
|
if self.is_empty_operation_group:
|
|
104
109
|
basename = self.code_model.module_name
|
|
105
110
|
|
|
106
|
-
if basename == "operations":
|
|
111
|
+
if basename == "operations" or self.code_model.options["combine_operation_files"]:
|
|
107
112
|
return f"_operations"
|
|
108
113
|
return f"_{basename}_operations"
|
|
109
114
|
|
|
@@ -11,6 +11,7 @@ from .schema_response import SchemaResponse
|
|
|
11
11
|
from .request_builder import RequestBuilder
|
|
12
12
|
from .imports import ImportType, FileImport, TypingSection
|
|
13
13
|
from .object_schema import ObjectSchema
|
|
14
|
+
from .schema_request import SchemaRequest
|
|
14
15
|
from .parameter_list import ParameterList
|
|
15
16
|
|
|
16
17
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -25,7 +26,8 @@ class PagingOperation(Operation):
|
|
|
25
26
|
description: str,
|
|
26
27
|
api_versions: Set[str],
|
|
27
28
|
parameters: ParameterList,
|
|
28
|
-
|
|
29
|
+
multiple_content_type_parameters: ParameterList,
|
|
30
|
+
schema_requests: List[SchemaRequest],
|
|
29
31
|
summary: Optional[str] = None,
|
|
30
32
|
responses: Optional[List[SchemaResponse]] = None,
|
|
31
33
|
exceptions: Optional[List[SchemaResponse]] = None,
|
|
@@ -41,7 +43,8 @@ class PagingOperation(Operation):
|
|
|
41
43
|
description,
|
|
42
44
|
api_versions,
|
|
43
45
|
parameters,
|
|
44
|
-
|
|
46
|
+
multiple_content_type_parameters,
|
|
47
|
+
schema_requests,
|
|
45
48
|
summary,
|
|
46
49
|
responses,
|
|
47
50
|
exceptions,
|