@autorest/python 5.15.0 → 5.16.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 +20 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +145 -73
- package/autorest/codegen/models/__init__.py +29 -18
- package/autorest/codegen/models/base_builder.py +48 -11
- package/autorest/codegen/models/base_model.py +6 -4
- package/autorest/codegen/models/base_schema.py +19 -18
- package/autorest/codegen/models/client.py +65 -21
- package/autorest/codegen/models/code_model.py +107 -61
- package/autorest/codegen/models/constant_schema.py +25 -13
- package/autorest/codegen/models/credential_model.py +23 -15
- package/autorest/codegen/models/credential_schema.py +18 -14
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +20 -17
- package/autorest/codegen/models/enum_schema.py +35 -25
- package/autorest/codegen/models/imports.py +70 -41
- package/autorest/codegen/models/list_schema.py +25 -13
- package/autorest/codegen/models/lro_operation.py +58 -22
- package/autorest/codegen/models/lro_paging_operation.py +2 -3
- package/autorest/codegen/models/object_schema.py +99 -49
- package/autorest/codegen/models/operation.py +236 -117
- package/autorest/codegen/models/operation_group.py +64 -34
- package/autorest/codegen/models/paging_operation.py +45 -18
- package/autorest/codegen/models/parameter.py +151 -83
- package/autorest/codegen/models/parameter_list.py +183 -162
- package/autorest/codegen/models/primitive_schemas.py +84 -55
- package/autorest/codegen/models/property.py +44 -26
- package/autorest/codegen/models/request_builder.py +65 -30
- package/autorest/codegen/models/request_builder_parameter.py +47 -23
- package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
- package/autorest/codegen/models/schema_request.py +16 -6
- package/autorest/codegen/models/schema_response.py +18 -13
- package/autorest/codegen/models/utils.py +5 -2
- package/autorest/codegen/serializers/__init__.py +182 -91
- package/autorest/codegen/serializers/builder_serializer.py +667 -331
- package/autorest/codegen/serializers/client_serializer.py +98 -37
- package/autorest/codegen/serializers/general_serializer.py +61 -26
- package/autorest/codegen/serializers/import_serializer.py +93 -31
- package/autorest/codegen/serializers/metadata_serializer.py +73 -24
- package/autorest/codegen/serializers/model_base_serializer.py +35 -15
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
- package/autorest/codegen/serializers/model_init_serializer.py +5 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +4 -1
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +35 -21
- package/autorest/codegen/templates/init.py.jinja2 +2 -2
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
- package/autorest/codegen/templates/operation.py.jinja2 +7 -9
- package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +13 -6
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +24 -17
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +18 -23
- package/autorest/multiapi/serializers/import_serializer.py +47 -17
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/namer/__init__.py +2 -4
- package/autorest/namer/name_converter.py +200 -103
- package/autorest/namer/python_mappings.py +10 -22
- package/package.json +2 -2
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/rest.py +0 -42
|
@@ -5,29 +5,40 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from itertools import chain
|
|
7
7
|
import logging
|
|
8
|
-
from typing import cast, Dict, List, Any, Optional, Union, Set
|
|
8
|
+
from typing import cast, Dict, List, Any, Optional, Union, Set, TYPE_CHECKING
|
|
9
9
|
|
|
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
|
|
14
|
-
|
|
13
|
+
from .parameter import (
|
|
14
|
+
Parameter,
|
|
15
|
+
ParameterMethodLocation,
|
|
16
|
+
get_parameter,
|
|
17
|
+
ParameterLocation,
|
|
18
|
+
)
|
|
19
|
+
from .parameter_list import ParameterList
|
|
15
20
|
from .base_schema import BaseSchema
|
|
16
21
|
from .object_schema import ObjectSchema
|
|
17
22
|
from .request_builder import RequestBuilder
|
|
18
23
|
from .schema_request import SchemaRequest
|
|
19
24
|
from .primitive_schemas import IOSchema
|
|
20
25
|
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from .code_model import CodeModel
|
|
28
|
+
|
|
21
29
|
_LOGGER = logging.getLogger(__name__)
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
|
|
32
|
+
class Operation(
|
|
33
|
+
BaseBuilder
|
|
34
|
+
): # pylint: disable=too-many-public-methods, too-many-instance-attributes
|
|
35
|
+
"""Represent an self."""
|
|
26
36
|
|
|
27
37
|
def __init__(
|
|
28
38
|
self,
|
|
29
|
-
code_model,
|
|
30
39
|
yaml_data: Dict[str, Any],
|
|
40
|
+
code_model: "CodeModel",
|
|
41
|
+
request_builder: RequestBuilder,
|
|
31
42
|
name: str,
|
|
32
43
|
description: str,
|
|
33
44
|
api_versions: Set[str],
|
|
@@ -39,6 +50,8 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
39
50
|
exceptions: Optional[List[SchemaResponse]] = None,
|
|
40
51
|
want_description_docstring: bool = True,
|
|
41
52
|
want_tracing: bool = True,
|
|
53
|
+
*,
|
|
54
|
+
abstract: bool = False,
|
|
42
55
|
) -> None:
|
|
43
56
|
super().__init__(
|
|
44
57
|
code_model=code_model,
|
|
@@ -49,33 +62,21 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
49
62
|
responses=responses,
|
|
50
63
|
schema_requests=schema_requests,
|
|
51
64
|
summary=summary,
|
|
65
|
+
abstract=abstract,
|
|
66
|
+
want_tracing=want_tracing,
|
|
52
67
|
)
|
|
53
68
|
self.multiple_content_type_parameters = multiple_content_type_parameters
|
|
54
69
|
self.api_versions = api_versions
|
|
55
70
|
self.multiple_content_type_parameters = multiple_content_type_parameters
|
|
56
71
|
self.exceptions = exceptions or []
|
|
57
72
|
self.want_description_docstring = want_description_docstring
|
|
58
|
-
self.
|
|
59
|
-
self._request_builder: Optional[RequestBuilder] = None
|
|
73
|
+
self.request_builder = request_builder
|
|
60
74
|
self.deprecated = False
|
|
61
75
|
|
|
62
76
|
@property
|
|
63
77
|
def python_name(self) -> str:
|
|
64
78
|
return self.name
|
|
65
79
|
|
|
66
|
-
@property
|
|
67
|
-
def request_builder(self) -> RequestBuilder:
|
|
68
|
-
if not self._request_builder:
|
|
69
|
-
raise ValueError(
|
|
70
|
-
"You're calling request_builder when you haven't linked up operation to its "
|
|
71
|
-
"request builder through the code model"
|
|
72
|
-
)
|
|
73
|
-
return self._request_builder
|
|
74
|
-
|
|
75
|
-
@request_builder.setter
|
|
76
|
-
def request_builder(self, r: RequestBuilder) -> None:
|
|
77
|
-
self._request_builder = r
|
|
78
|
-
|
|
79
80
|
@property
|
|
80
81
|
def is_stream_response(self) -> bool:
|
|
81
82
|
"""Is the response expected to be streamable, like a download."""
|
|
@@ -93,19 +94,22 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
93
94
|
|
|
94
95
|
# successful status codes of responses that have bodies
|
|
95
96
|
status_codes_for_responses_with_bodies = [
|
|
96
|
-
code
|
|
97
|
+
code
|
|
98
|
+
for code in self.success_status_code
|
|
97
99
|
if isinstance(code, int) and self.get_response_from_status(code).has_body
|
|
98
100
|
]
|
|
99
101
|
|
|
100
102
|
successful_responses = [
|
|
101
|
-
response
|
|
103
|
+
response
|
|
104
|
+
for response in self.responses
|
|
102
105
|
if any(code in self.success_status_code for code in response.status_codes)
|
|
103
106
|
]
|
|
104
107
|
|
|
105
108
|
return (
|
|
106
|
-
self.has_response_body
|
|
107
|
-
len(successful_responses) > 1
|
|
108
|
-
len(self.success_status_code)
|
|
109
|
+
self.has_response_body
|
|
110
|
+
and len(successful_responses) > 1
|
|
111
|
+
and len(self.success_status_code)
|
|
112
|
+
!= len(status_codes_for_responses_with_bodies)
|
|
109
113
|
)
|
|
110
114
|
|
|
111
115
|
@property
|
|
@@ -115,9 +119,11 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
115
119
|
|
|
116
120
|
@property
|
|
117
121
|
def has_response_body(self) -> bool:
|
|
118
|
-
"""Tell if at least one response has a body.
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
"""Tell if at least one response has a body."""
|
|
123
|
+
return any(
|
|
124
|
+
response.has_body or response.is_stream_response
|
|
125
|
+
for response in self.responses
|
|
126
|
+
)
|
|
121
127
|
|
|
122
128
|
@property
|
|
123
129
|
def any_response_has_headers(self) -> bool:
|
|
@@ -125,30 +131,45 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
125
131
|
|
|
126
132
|
@property
|
|
127
133
|
def default_exception(self) -> Optional[str]:
|
|
128
|
-
default_excp = [
|
|
134
|
+
default_excp = [
|
|
135
|
+
excp
|
|
136
|
+
for excp in self.exceptions
|
|
137
|
+
for code in excp.status_codes
|
|
138
|
+
if code == "default"
|
|
139
|
+
]
|
|
129
140
|
if not default_excp:
|
|
130
141
|
return None
|
|
131
142
|
excep_schema = default_excp[0].schema
|
|
132
143
|
if isinstance(excep_schema, ObjectSchema):
|
|
133
144
|
return f"_models.{excep_schema.name}"
|
|
134
145
|
# in this case, it's just an AnySchema
|
|
135
|
-
return "
|
|
146
|
+
return "'object'"
|
|
136
147
|
|
|
137
148
|
@property
|
|
138
149
|
def status_code_exceptions(self) -> List[SchemaResponse]:
|
|
139
|
-
return [
|
|
150
|
+
return [
|
|
151
|
+
excp for excp in self.exceptions if list(excp.status_codes) != ["default"]
|
|
152
|
+
]
|
|
140
153
|
|
|
141
154
|
@property
|
|
142
155
|
def status_code_exceptions_status_codes(self) -> List[Union[str, int]]:
|
|
143
156
|
"""Actually returns all of the status codes from exceptions (besides default)"""
|
|
144
|
-
return list(
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
return list(
|
|
158
|
+
chain.from_iterable(
|
|
159
|
+
[excp.status_codes for excp in self.status_code_exceptions]
|
|
160
|
+
)
|
|
161
|
+
)
|
|
147
162
|
|
|
148
|
-
def _imports_shared(
|
|
163
|
+
def _imports_shared(
|
|
164
|
+
self, async_mode: bool # pylint: disable=unused-argument
|
|
165
|
+
) -> FileImport:
|
|
149
166
|
file_import = FileImport()
|
|
150
|
-
file_import.add_submodule_import(
|
|
167
|
+
file_import.add_submodule_import(
|
|
168
|
+
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
169
|
+
)
|
|
151
170
|
for param in self.parameters.method:
|
|
171
|
+
if self.abstract and (param.is_multipart or param.is_data_input):
|
|
172
|
+
continue
|
|
152
173
|
file_import.merge(param.imports())
|
|
153
174
|
|
|
154
175
|
for param in self.multiple_content_type_parameters:
|
|
@@ -159,119 +180,178 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
159
180
|
if response.has_body:
|
|
160
181
|
file_import.merge(cast(BaseSchema, response.schema).imports())
|
|
161
182
|
|
|
162
|
-
response_types = [
|
|
183
|
+
response_types = [
|
|
184
|
+
r.type_annotation(is_operation_file=True)
|
|
185
|
+
for r in self.responses
|
|
186
|
+
if r.has_body
|
|
187
|
+
]
|
|
163
188
|
if len(set(response_types)) > 1:
|
|
164
|
-
file_import.add_submodule_import(
|
|
189
|
+
file_import.add_submodule_import(
|
|
190
|
+
"typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
191
|
+
)
|
|
165
192
|
|
|
166
193
|
if self.is_stream_response:
|
|
167
|
-
file_import.add_submodule_import(
|
|
194
|
+
file_import.add_submodule_import(
|
|
195
|
+
"typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
196
|
+
)
|
|
168
197
|
return file_import
|
|
169
198
|
|
|
170
|
-
|
|
171
|
-
|
|
199
|
+
def imports_for_multiapi(
|
|
200
|
+
self, async_mode: bool
|
|
201
|
+
) -> FileImport: # pylint: disable=unused-argument
|
|
172
202
|
return self._imports_shared(async_mode)
|
|
173
203
|
|
|
174
204
|
def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
|
|
175
205
|
file_import = self._imports_base(async_mode, is_python3_file)
|
|
176
|
-
if self.
|
|
206
|
+
if self.abstract:
|
|
207
|
+
return file_import
|
|
208
|
+
if (
|
|
209
|
+
self.has_response_body
|
|
210
|
+
and not self.has_optional_return_type
|
|
211
|
+
and not self.code_model.options["models_mode"]
|
|
212
|
+
):
|
|
177
213
|
file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
|
|
178
214
|
return file_import
|
|
179
215
|
|
|
180
216
|
@staticmethod
|
|
181
|
-
def has_kwargs_to_pop_with_default(
|
|
182
|
-
|
|
217
|
+
def has_kwargs_to_pop_with_default(
|
|
218
|
+
kwargs_to_pop: List[Parameter], location: ParameterLocation
|
|
219
|
+
) -> bool:
|
|
220
|
+
return any(
|
|
221
|
+
kwarg.has_default_value and kwarg.location == location
|
|
222
|
+
for kwarg in kwargs_to_pop
|
|
223
|
+
)
|
|
183
224
|
|
|
184
225
|
def _imports_base(self, async_mode: bool, is_python3_file: bool) -> FileImport:
|
|
185
226
|
file_import = self._imports_shared(async_mode)
|
|
186
227
|
|
|
187
228
|
# Exceptions
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
file_import.add_submodule_import("azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.AZURECORE)
|
|
191
|
-
file_import.add_submodule_import("azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE)
|
|
192
|
-
|
|
193
|
-
file_import.add_submodule_import("typing", "Callable", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
194
|
-
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
195
|
-
file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
196
|
-
file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
197
|
-
file_import.add_submodule_import("azure.core.pipeline", "PipelineResponse", ImportType.AZURECORE)
|
|
198
|
-
file_import.add_submodule_import("azure.core.rest", "HttpRequest", ImportType.AZURECORE)
|
|
199
|
-
kwargs_to_pop = self.parameters.kwargs_to_pop(is_python3_file)
|
|
200
|
-
if (self.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.Header) or
|
|
201
|
-
self.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.Query)):
|
|
202
|
-
file_import.add_submodule_import("azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE)
|
|
203
|
-
if async_mode:
|
|
204
|
-
file_import.add_submodule_import("azure.core.pipeline.transport", "AsyncHttpResponse", ImportType.AZURECORE)
|
|
229
|
+
if self.abstract:
|
|
230
|
+
file_import.add_import("abc", ImportType.STDLIB)
|
|
205
231
|
else:
|
|
206
|
-
file_import.add_submodule_import(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
file_import.add_submodule_import(
|
|
233
|
+
"azure.core.exceptions", "map_error", ImportType.AZURECORE
|
|
234
|
+
)
|
|
235
|
+
if self.code_model.options["azure_arm"]:
|
|
236
|
+
file_import.add_submodule_import(
|
|
237
|
+
"azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.AZURECORE
|
|
238
|
+
)
|
|
239
|
+
file_import.add_submodule_import(
|
|
240
|
+
"azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE
|
|
241
|
+
)
|
|
242
|
+
file_import.add_submodule_import(
|
|
243
|
+
"azure.core.exceptions",
|
|
244
|
+
"ClientAuthenticationError",
|
|
245
|
+
ImportType.AZURECORE,
|
|
246
|
+
)
|
|
247
|
+
file_import.add_submodule_import(
|
|
248
|
+
"azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE
|
|
249
|
+
)
|
|
250
|
+
file_import.add_submodule_import(
|
|
251
|
+
"azure.core.exceptions", "ResourceExistsError", ImportType.AZURECORE
|
|
252
|
+
)
|
|
210
253
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
254
|
+
kwargs_to_pop = self.parameters.kwargs_to_pop(is_python3_file)
|
|
255
|
+
if self.has_kwargs_to_pop_with_default(
|
|
256
|
+
kwargs_to_pop, ParameterLocation.Header
|
|
257
|
+
) or self.has_kwargs_to_pop_with_default(
|
|
258
|
+
kwargs_to_pop, ParameterLocation.Query
|
|
259
|
+
):
|
|
215
260
|
file_import.add_submodule_import(
|
|
216
|
-
|
|
217
|
-
builder_group_name,
|
|
218
|
-
import_type=ImportType.LOCAL,
|
|
219
|
-
alias=f"rest_{builder_group_name}"
|
|
261
|
+
"azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
|
|
220
262
|
)
|
|
221
|
-
|
|
263
|
+
if self.deprecated:
|
|
264
|
+
file_import.add_import("warnings", ImportType.STDLIB)
|
|
265
|
+
if self.code_model.options["builders_visibility"] != "embedded":
|
|
266
|
+
builder_group_name = self.request_builder.builder_group_name
|
|
267
|
+
rest_import_path = "..." if async_mode else ".."
|
|
268
|
+
if builder_group_name:
|
|
269
|
+
file_import.add_submodule_import(
|
|
270
|
+
f"{rest_import_path}{self.code_model.rest_layer_name}",
|
|
271
|
+
builder_group_name,
|
|
272
|
+
import_type=ImportType.LOCAL,
|
|
273
|
+
alias=f"rest_{builder_group_name}",
|
|
274
|
+
)
|
|
275
|
+
else:
|
|
276
|
+
file_import.add_submodule_import(
|
|
277
|
+
rest_import_path,
|
|
278
|
+
self.code_model.rest_layer_name,
|
|
279
|
+
import_type=ImportType.LOCAL,
|
|
280
|
+
alias="rest",
|
|
281
|
+
)
|
|
282
|
+
if self.code_model.need_request_converter:
|
|
283
|
+
relative_path = "..." if async_mode else ".."
|
|
222
284
|
file_import.add_submodule_import(
|
|
223
|
-
|
|
224
|
-
self.code_model.rest_layer_name,
|
|
225
|
-
import_type=ImportType.LOCAL,
|
|
226
|
-
alias="rest"
|
|
285
|
+
f"{relative_path}_vendor", "_convert_request", ImportType.LOCAL
|
|
227
286
|
)
|
|
228
|
-
if
|
|
229
|
-
file_import.merge(self.request_builder.imports())
|
|
230
|
-
if self.code_model.need_request_converter:
|
|
231
|
-
relative_path = "..." if async_mode else ".."
|
|
287
|
+
if async_mode:
|
|
232
288
|
file_import.add_submodule_import(
|
|
233
|
-
|
|
289
|
+
"azure.core.pipeline.transport",
|
|
290
|
+
"AsyncHttpResponse",
|
|
291
|
+
ImportType.AZURECORE,
|
|
234
292
|
)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
293
|
+
else:
|
|
294
|
+
file_import.add_submodule_import(
|
|
295
|
+
"azure.core.pipeline.transport", "HttpResponse", ImportType.AZURECORE
|
|
296
|
+
)
|
|
297
|
+
if (
|
|
298
|
+
self.code_model.options["builders_visibility"] == "embedded"
|
|
299
|
+
and not async_mode
|
|
239
300
|
):
|
|
240
|
-
file_import.
|
|
301
|
+
file_import.merge(self.request_builder.imports())
|
|
302
|
+
file_import.add_submodule_import(
|
|
303
|
+
"azure.core.pipeline", "PipelineResponse", ImportType.AZURECORE
|
|
304
|
+
)
|
|
305
|
+
file_import.add_submodule_import(
|
|
306
|
+
"azure.core.rest", "HttpRequest", ImportType.AZURECORE
|
|
307
|
+
)
|
|
308
|
+
file_import.add_submodule_import(
|
|
309
|
+
"typing", "Callable", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
310
|
+
)
|
|
311
|
+
file_import.add_submodule_import(
|
|
312
|
+
"typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
313
|
+
)
|
|
314
|
+
file_import.add_submodule_import(
|
|
315
|
+
"typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
316
|
+
)
|
|
317
|
+
file_import.add_submodule_import(
|
|
318
|
+
"typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
319
|
+
)
|
|
241
320
|
if self.code_model.options["tracing"] and self.want_tracing:
|
|
242
321
|
file_import.add_submodule_import(
|
|
243
322
|
f"azure.core.tracing.decorator{'_async' if async_mode else ''}",
|
|
244
323
|
f"distributed_trace{'_async' if async_mode else ''}",
|
|
245
324
|
ImportType.AZURECORE,
|
|
246
325
|
)
|
|
326
|
+
|
|
247
327
|
return file_import
|
|
248
328
|
|
|
249
329
|
def _get_body_param_from_body_kwarg(self, body_kwarg: Parameter) -> Parameter:
|
|
250
330
|
# determine which of the body parameters returned from m4 corresponds to this body_kwarg
|
|
251
331
|
if not self.multiple_content_type_parameters.has_body:
|
|
252
332
|
return self.parameters.body[0]
|
|
253
|
-
if body_kwarg.serialized_name == "data":
|
|
254
|
-
return next(p for p in self.multiple_content_type_parameters.body if p.is_data_input)
|
|
255
|
-
if body_kwarg.serialized_name == "files":
|
|
256
|
-
return next(p for p in self.multiple_content_type_parameters.body if p.is_multipart)
|
|
257
333
|
if body_kwarg.serialized_name == "json":
|
|
258
334
|
# first check if there's any non-binary. In the case of multiple content types, there's
|
|
259
335
|
# usually one binary (for content), and one schema parameter (for json)
|
|
260
336
|
try:
|
|
261
337
|
return next(
|
|
262
|
-
p
|
|
338
|
+
p
|
|
339
|
+
for p in self.multiple_content_type_parameters.body
|
|
263
340
|
if not isinstance(p.schema, IOSchema)
|
|
264
341
|
)
|
|
265
342
|
except StopIteration:
|
|
266
|
-
return next(
|
|
343
|
+
return next(
|
|
344
|
+
p
|
|
345
|
+
for p in self.multiple_content_type_parameters.body
|
|
346
|
+
if p.is_json_parameter
|
|
347
|
+
)
|
|
267
348
|
return self.multiple_content_type_parameters.body[0]
|
|
268
349
|
|
|
269
350
|
def link_body_kwargs_to_body_params(self) -> None:
|
|
270
351
|
if not self.parameters.has_body:
|
|
271
352
|
return
|
|
272
353
|
body_kwargs = [
|
|
273
|
-
p for p in self.request_builder.parameters.body
|
|
274
|
-
if p.content_types
|
|
354
|
+
p for p in self.request_builder.parameters.body if p.content_types
|
|
275
355
|
]
|
|
276
356
|
if len(body_kwargs) == 1:
|
|
277
357
|
self.parameters.body[0].body_kwargs = [body_kwargs[0]]
|
|
@@ -281,59 +361,96 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
281
361
|
body_param.body_kwargs.append(body_kwarg)
|
|
282
362
|
|
|
283
363
|
def convert_multiple_content_type_parameters(self) -> None:
|
|
284
|
-
type_annot = ", ".join(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
364
|
+
type_annot = ", ".join(
|
|
365
|
+
[
|
|
366
|
+
param.schema.type_annotation(is_operation_file=True)
|
|
367
|
+
for param in self.multiple_content_type_parameters
|
|
368
|
+
]
|
|
369
|
+
)
|
|
370
|
+
docstring_type = " or ".join(
|
|
371
|
+
[
|
|
372
|
+
param.schema.docstring_type
|
|
373
|
+
for param in self.multiple_content_type_parameters
|
|
374
|
+
]
|
|
375
|
+
)
|
|
291
376
|
try:
|
|
292
377
|
# get an optional param with object first. These params are the top choice
|
|
293
378
|
# bc they have more info about how to serialize the body
|
|
294
379
|
chosen_parameter = next(
|
|
295
|
-
p
|
|
380
|
+
p
|
|
381
|
+
for p in self.multiple_content_type_parameters
|
|
296
382
|
if not p.required and isinstance(p.schema, ObjectSchema)
|
|
297
383
|
)
|
|
298
384
|
except StopIteration: # pylint: disable=broad-except
|
|
299
385
|
# otherwise, we get the first optional param, if that exists. If not, we just grab the first one
|
|
300
|
-
optional_parameters = [
|
|
386
|
+
optional_parameters = [
|
|
387
|
+
p for p in self.multiple_content_type_parameters if not p.required
|
|
388
|
+
]
|
|
301
389
|
chosen_parameter = (
|
|
302
|
-
optional_parameters[0]
|
|
390
|
+
optional_parameters[0]
|
|
391
|
+
if optional_parameters
|
|
392
|
+
else self.multiple_content_type_parameters[0]
|
|
303
393
|
)
|
|
304
394
|
if not chosen_parameter:
|
|
305
|
-
raise ValueError(
|
|
395
|
+
raise ValueError(
|
|
396
|
+
"You are missing a parameter that has multiple media types"
|
|
397
|
+
)
|
|
306
398
|
chosen_parameter.multiple_content_types_type_annot = f"Union[{type_annot}]"
|
|
307
399
|
chosen_parameter.multiple_content_types_docstring_type = docstring_type
|
|
308
400
|
self.parameters.append(chosen_parameter)
|
|
309
401
|
|
|
310
402
|
@classmethod
|
|
311
|
-
def from_yaml(
|
|
403
|
+
def from_yaml(
|
|
404
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
405
|
+
) -> "Operation":
|
|
312
406
|
name = yaml_data["language"]["python"]["name"]
|
|
313
407
|
_LOGGER.debug("Parsing %s operation", name)
|
|
314
408
|
|
|
315
409
|
parameter_creator = get_parameter(code_model).from_yaml
|
|
316
|
-
|
|
317
|
-
|
|
410
|
+
schema_requests = [
|
|
411
|
+
SchemaRequest.from_yaml(yaml, code_model=code_model)
|
|
412
|
+
for yaml in yaml_data["requests"]
|
|
413
|
+
]
|
|
318
414
|
parameters, multiple_content_type_parameters = create_parameters(
|
|
319
415
|
yaml_data, code_model, parameter_creator
|
|
320
416
|
)
|
|
321
|
-
parameter_list =
|
|
322
|
-
multiple_content_type_parameter_list =
|
|
417
|
+
parameter_list = ParameterList(code_model, parameters, schema_requests)
|
|
418
|
+
multiple_content_type_parameter_list = ParameterList(
|
|
323
419
|
code_model, multiple_content_type_parameters, schema_requests
|
|
324
420
|
)
|
|
421
|
+
abstract = False
|
|
422
|
+
if code_model.options["version_tolerant"] and (
|
|
423
|
+
any(p for p in parameter_list if p.is_multipart or p.is_data_input)
|
|
424
|
+
or any(
|
|
425
|
+
p
|
|
426
|
+
for p in multiple_content_type_parameter_list
|
|
427
|
+
if p.is_multipart or p.is_data_input
|
|
428
|
+
)
|
|
429
|
+
):
|
|
430
|
+
_LOGGER.warning(
|
|
431
|
+
'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
|
|
432
|
+
"Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
|
|
433
|
+
'Please write your own custom operation in the "_patch.py" file '
|
|
434
|
+
"following https://aka.ms/azsdk/python/dpcodegen/python/customize",
|
|
435
|
+
name,
|
|
436
|
+
)
|
|
437
|
+
abstract = True
|
|
325
438
|
|
|
326
439
|
if len(parameter_list.content_types) > 1:
|
|
327
440
|
for p in parameter_list.parameters:
|
|
328
441
|
if p.rest_api_name == "Content-Type":
|
|
329
|
-
p.
|
|
442
|
+
p.method_location = ParameterMethodLocation.KEYWORD_ONLY
|
|
443
|
+
request_builder = code_model.lookup_request_builder(id(yaml_data))
|
|
330
444
|
|
|
331
445
|
return cls(
|
|
332
446
|
code_model=code_model,
|
|
333
447
|
yaml_data=yaml_data,
|
|
448
|
+
request_builder=request_builder,
|
|
334
449
|
name=name,
|
|
335
450
|
description=yaml_data["language"]["python"]["description"],
|
|
336
|
-
api_versions=set(
|
|
451
|
+
api_versions=set(
|
|
452
|
+
value_dict["version"] for value_dict in yaml_data["apiVersions"]
|
|
453
|
+
),
|
|
337
454
|
parameters=parameter_list,
|
|
338
455
|
multiple_content_type_parameters=multiple_content_type_parameter_list,
|
|
339
456
|
schema_requests=schema_requests,
|
|
@@ -345,6 +462,8 @@ class Operation(BaseBuilder): # pylint: disable=too-many-public-methods, too-ma
|
|
|
345
462
|
# Exception with no schema means default exception, we don't store them
|
|
346
463
|
exceptions=[
|
|
347
464
|
SchemaResponse.from_yaml(yaml, code_model=code_model)
|
|
348
|
-
for yaml in yaml_data.get("exceptions", [])
|
|
465
|
+
for yaml in yaml_data.get("exceptions", [])
|
|
466
|
+
if "schema" in yaml
|
|
349
467
|
],
|
|
468
|
+
abstract=abstract,
|
|
350
469
|
)
|