@autorest/python 5.13.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 +67 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +239 -105
- 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 +21 -24
- package/autorest/codegen/models/client.py +70 -20
- package/autorest/codegen/models/code_model.py +144 -129
- package/autorest/codegen/models/constant_schema.py +32 -16
- package/autorest/codegen/models/credential_model.py +55 -0
- package/autorest/codegen/models/credential_schema.py +21 -16
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +27 -24
- package/autorest/codegen/models/enum_schema.py +41 -62
- package/autorest/codegen/models/imports.py +72 -41
- package/autorest/codegen/models/list_schema.py +40 -18
- package/autorest/codegen/models/lro_operation.py +61 -25
- package/autorest/codegen/models/lro_paging_operation.py +5 -6
- package/autorest/codegen/models/object_schema.py +113 -59
- package/autorest/codegen/models/operation.py +251 -111
- package/autorest/codegen/models/operation_group.py +67 -32
- package/autorest/codegen/models/paging_operation.py +48 -21
- package/autorest/codegen/models/parameter.py +182 -90
- package/autorest/codegen/models/parameter_list.py +184 -163
- package/autorest/codegen/models/primitive_schemas.py +89 -70
- package/autorest/codegen/models/property.py +49 -31
- package/autorest/codegen/models/request_builder.py +67 -32
- package/autorest/codegen/models/request_builder_parameter.py +54 -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 +35 -17
- package/autorest/codegen/models/utils.py +24 -1
- package/autorest/codegen/serializers/__init__.py +273 -89
- package/autorest/codegen/serializers/builder_serializer.py +711 -333
- package/autorest/codegen/serializers/client_serializer.py +114 -43
- package/autorest/codegen/serializers/general_serializer.py +84 -25
- 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 +42 -14
- 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 +9 -8
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +60 -21
- package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
- package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
- package/autorest/codegen/templates/README.md.jinja2 +105 -0
- package/autorest/codegen/templates/config.py.jinja2 +4 -4
- package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
- package/autorest/codegen/templates/enum.py.jinja2 +1 -1
- package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
- package/autorest/codegen/templates/model.py.jinja2 +1 -6
- package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
- package/autorest/codegen/templates/operation.py.jinja2 +8 -11
- package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
- package/autorest/codegen/templates/setup.py.jinja2 +79 -20
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- 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 +35 -18
- 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 -15
- 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 +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/rest.py +0 -42
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from typing import List
|
|
7
|
+
|
|
7
8
|
from . import utils
|
|
8
9
|
from ..models import CodeModel
|
|
10
|
+
from ..models.parameter import ParameterMethodLocation
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class ClientSerializer:
|
|
@@ -32,13 +34,20 @@ class ClientSerializer:
|
|
|
32
34
|
)
|
|
33
35
|
|
|
34
36
|
def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
|
|
35
|
-
return utils.pop_kwargs_from_signature(
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
return utils.pop_kwargs_from_signature(
|
|
38
|
+
self.code_model.service_client.parameters.kwargs_to_pop(
|
|
39
|
+
async_mode or self.is_python3_file,
|
|
40
|
+
),
|
|
41
|
+
check_kwarg_dict=False,
|
|
42
|
+
pop_headers_kwarg=utils.PopKwargType.NO,
|
|
43
|
+
pop_params_kwarg=utils.PopKwargType.NO,
|
|
44
|
+
)
|
|
38
45
|
|
|
39
46
|
def class_definition(self, async_mode) -> str:
|
|
40
47
|
class_name = self.code_model.class_name
|
|
41
|
-
has_mixin_og = any(
|
|
48
|
+
has_mixin_og = any(
|
|
49
|
+
og for og in self.code_model.operation_groups if og.is_empty_operation_group
|
|
50
|
+
)
|
|
42
51
|
base_class = ""
|
|
43
52
|
if has_mixin_og:
|
|
44
53
|
base_class = f"{class_name}OperationsMixin"
|
|
@@ -54,12 +63,22 @@ class ClientSerializer:
|
|
|
54
63
|
def property_descriptions(self, async_mode: bool) -> List[str]:
|
|
55
64
|
retval: List[str] = []
|
|
56
65
|
operations_folder = ".aio.operations." if async_mode else ".operations."
|
|
57
|
-
for og in [
|
|
66
|
+
for og in [
|
|
67
|
+
og
|
|
68
|
+
for og in self.code_model.operation_groups
|
|
69
|
+
if not og.is_empty_operation_group
|
|
70
|
+
]:
|
|
58
71
|
retval.append(f":ivar {og.name}: {og.class_name} operations")
|
|
59
|
-
retval.append(
|
|
72
|
+
retval.append(
|
|
73
|
+
f":vartype {og.name}: {self.code_model.namespace}{operations_folder}{og.class_name}"
|
|
74
|
+
)
|
|
60
75
|
for param in self.code_model.service_client.parameters.client_method:
|
|
61
|
-
retval.append(
|
|
62
|
-
|
|
76
|
+
retval.append(
|
|
77
|
+
f":{param.description_keyword} {param.serialized_name}: {param.description}"
|
|
78
|
+
)
|
|
79
|
+
retval.append(
|
|
80
|
+
f":{param.docstring_type_keyword} {param.serialized_name}: {param.docstring_type}"
|
|
81
|
+
)
|
|
63
82
|
if self.code_model.has_lro_operations:
|
|
64
83
|
retval.append(
|
|
65
84
|
":keyword int polling_interval: Default waiting time between two polls for LRO operations "
|
|
@@ -74,38 +93,57 @@ class ClientSerializer:
|
|
|
74
93
|
[
|
|
75
94
|
f"{p.serialized_name}={p.serialized_name}"
|
|
76
95
|
for p in self.code_model.service_client.parameters.config_method
|
|
77
|
-
if not p.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
]
|
|
96
|
+
if not p.method_location
|
|
97
|
+
in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
|
|
98
|
+
]
|
|
99
|
+
+ ["**kwargs"]
|
|
100
|
+
)
|
|
81
101
|
return f"self._config = {config_name}({config_call})"
|
|
82
102
|
|
|
83
103
|
def initialize_pipeline_client(self, async_mode: bool) -> str:
|
|
84
|
-
host_variable_name =
|
|
104
|
+
host_variable_name = (
|
|
105
|
+
self.code_model.service_client.parameters.host_variable_name
|
|
106
|
+
)
|
|
85
107
|
if self.code_model.service_client.has_parameterized_host:
|
|
86
|
-
host_variable_name =
|
|
108
|
+
host_variable_name = (
|
|
109
|
+
"_" + host_variable_name
|
|
110
|
+
) # we don't want potential conflicts with input params
|
|
87
111
|
pipeline_client_name = self.code_model.service_client.pipeline_class(async_mode)
|
|
88
112
|
return f"self._client = {pipeline_client_name}(base_url={host_variable_name}, config=self._config, **kwargs)"
|
|
89
113
|
|
|
90
114
|
def serializers_and_operation_groups_properties(self) -> List[str]:
|
|
91
115
|
retval = []
|
|
92
116
|
if self.code_model.sorted_schemas:
|
|
93
|
-
client_models_value =
|
|
117
|
+
client_models_value = (
|
|
118
|
+
"{k: v for k, v in models.__dict__.items() if isinstance(v, type)}"
|
|
119
|
+
)
|
|
94
120
|
else:
|
|
95
121
|
client_models_value = "{} # type: Dict[str, Any]"
|
|
96
122
|
if self.code_model.options["models_mode"]:
|
|
97
123
|
retval.append(f"client_models = {client_models_value}")
|
|
98
|
-
client_models_str =
|
|
124
|
+
client_models_str = (
|
|
125
|
+
"client_models" if self.code_model.options["models_mode"] else ""
|
|
126
|
+
)
|
|
99
127
|
retval.append(f"self._serialize = Serializer({client_models_str})")
|
|
100
128
|
retval.append(f"self._deserialize = Deserializer({client_models_str})")
|
|
101
129
|
if not self.code_model.options["client_side_validation"]:
|
|
102
130
|
retval.append("self._serialize.client_side_validation = False")
|
|
103
|
-
operation_groups = [
|
|
104
|
-
|
|
131
|
+
operation_groups = [
|
|
132
|
+
og
|
|
133
|
+
for og in self.code_model.operation_groups
|
|
134
|
+
if not og.is_empty_operation_group
|
|
135
|
+
]
|
|
136
|
+
for og in operation_groups:
|
|
137
|
+
disable_check = (
|
|
138
|
+
" # type: ignore # pylint: disable=abstract-class-instantiated"
|
|
139
|
+
if og.has_abstract_operations
|
|
140
|
+
else ""
|
|
141
|
+
)
|
|
105
142
|
retval.extend(
|
|
106
143
|
[
|
|
107
|
-
f"self.{og.name} = {og.class_name}(
|
|
108
|
-
|
|
144
|
+
f"self.{og.name} = {og.class_name}({disable_check}",
|
|
145
|
+
" self._client, self._config, self._serialize, self._deserialize",
|
|
146
|
+
")",
|
|
109
147
|
]
|
|
110
148
|
)
|
|
111
149
|
return retval
|
|
@@ -120,12 +158,16 @@ class ClientSerializer:
|
|
|
120
158
|
),
|
|
121
159
|
)
|
|
122
160
|
|
|
123
|
-
def send_request_signature_and_response_type_annotation(
|
|
161
|
+
def send_request_signature_and_response_type_annotation(
|
|
162
|
+
self, async_mode: bool
|
|
163
|
+
) -> str:
|
|
124
164
|
send_request_signature = self._send_request_signature(async_mode)
|
|
125
165
|
return utils.method_signature_and_response_type_annotation_template(
|
|
126
166
|
is_python3_file=async_mode or self.is_python3_file,
|
|
127
167
|
method_signature=send_request_signature,
|
|
128
|
-
response_type_annotation="Awaitable[AsyncHttpResponse]"
|
|
168
|
+
response_type_annotation="Awaitable[AsyncHttpResponse]"
|
|
169
|
+
if async_mode
|
|
170
|
+
else "HttpResponse",
|
|
129
171
|
)
|
|
130
172
|
|
|
131
173
|
def _example_make_call(self, async_mode: bool) -> List[str]:
|
|
@@ -138,23 +180,35 @@ class ClientSerializer:
|
|
|
138
180
|
|
|
139
181
|
def _request_builder_example(self, async_mode: bool) -> List[str]:
|
|
140
182
|
retval = [
|
|
141
|
-
"We have helper methods to create requests specific to this service in "
|
|
142
|
-
f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
|
|
183
|
+
"We have helper methods to create requests specific to this service in "
|
|
184
|
+
+ f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
|
|
143
185
|
]
|
|
144
|
-
retval.append(
|
|
186
|
+
retval.append(
|
|
187
|
+
"Use these helper methods to create the request you pass to this method."
|
|
188
|
+
)
|
|
145
189
|
retval.append("")
|
|
146
190
|
|
|
147
|
-
request_builder = self.code_model.
|
|
148
|
-
request_builder_signature = ", ".join(
|
|
191
|
+
request_builder = self.code_model.request_builders[0]
|
|
192
|
+
request_builder_signature = ", ".join(
|
|
193
|
+
request_builder.parameters.call(async_mode)
|
|
194
|
+
)
|
|
149
195
|
if request_builder.builder_group_name:
|
|
150
196
|
rest_imported = request_builder.builder_group_name
|
|
151
|
-
request_builder_name =
|
|
197
|
+
request_builder_name = (
|
|
198
|
+
f"{request_builder.builder_group_name}.{request_builder.name}"
|
|
199
|
+
)
|
|
152
200
|
else:
|
|
153
201
|
rest_imported = request_builder.name
|
|
154
202
|
request_builder_name = request_builder.name
|
|
155
|
-
retval.append(
|
|
156
|
-
|
|
157
|
-
|
|
203
|
+
retval.append(
|
|
204
|
+
f">>> from {self.code_model.namespace}.{self.code_model.rest_layer_name} import {rest_imported}"
|
|
205
|
+
)
|
|
206
|
+
retval.append(
|
|
207
|
+
f">>> request = {request_builder_name}({request_builder_signature})"
|
|
208
|
+
)
|
|
209
|
+
retval.append(
|
|
210
|
+
f"<HttpRequest [{request_builder.method}], url: '{request_builder.url}'>"
|
|
211
|
+
)
|
|
158
212
|
retval.extend(self._example_make_call(async_mode))
|
|
159
213
|
return retval
|
|
160
214
|
|
|
@@ -173,22 +227,30 @@ class ClientSerializer:
|
|
|
173
227
|
else:
|
|
174
228
|
retval.extend(self._rest_request_example(async_mode))
|
|
175
229
|
retval.append("")
|
|
176
|
-
retval.append(
|
|
230
|
+
retval.append(
|
|
231
|
+
"For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart"
|
|
232
|
+
)
|
|
177
233
|
retval.append(f"")
|
|
178
234
|
retval.append(":param request: The network request you want to make. Required.")
|
|
179
235
|
retval.append(f":type request: ~azure.core.rest.HttpRequest")
|
|
180
|
-
retval.append(
|
|
181
|
-
|
|
236
|
+
retval.append(
|
|
237
|
+
":keyword bool stream: Whether the response payload will be streamed. Defaults to False."
|
|
238
|
+
)
|
|
239
|
+
retval.append(
|
|
240
|
+
":return: The response of your network call. Does not do error handling on your response."
|
|
241
|
+
)
|
|
182
242
|
http_response = "AsyncHttpResponse" if async_mode else "HttpResponse"
|
|
183
243
|
retval.append(f":rtype: ~azure.core.rest.{http_response}")
|
|
184
244
|
retval.append('"""')
|
|
185
245
|
return retval
|
|
186
246
|
|
|
187
247
|
def serialize_path(self) -> List[str]:
|
|
188
|
-
return utils.serialize_path(
|
|
248
|
+
return utils.serialize_path(
|
|
249
|
+
self.code_model.global_parameters.path, "self._serialize"
|
|
250
|
+
)
|
|
189
251
|
|
|
190
|
-
class ConfigSerializer:
|
|
191
252
|
|
|
253
|
+
class ConfigSerializer:
|
|
192
254
|
def __init__(self, code_model: CodeModel, is_python3_file: bool) -> None:
|
|
193
255
|
self.code_model = code_model
|
|
194
256
|
self.is_python3_file = is_python3_file
|
|
@@ -212,9 +274,14 @@ class ConfigSerializer:
|
|
|
212
274
|
)
|
|
213
275
|
|
|
214
276
|
def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
|
|
215
|
-
return utils.pop_kwargs_from_signature(
|
|
216
|
-
|
|
217
|
-
|
|
277
|
+
return utils.pop_kwargs_from_signature(
|
|
278
|
+
self.code_model.global_parameters.config_kwargs_to_pop(
|
|
279
|
+
async_mode or self.is_python3_file
|
|
280
|
+
),
|
|
281
|
+
check_kwarg_dict=False,
|
|
282
|
+
pop_headers_kwarg=utils.PopKwargType.NO,
|
|
283
|
+
pop_params_kwarg=utils.PopKwargType.NO,
|
|
284
|
+
)
|
|
218
285
|
|
|
219
286
|
def set_constants(self) -> List[str]:
|
|
220
287
|
return [
|
|
@@ -225,8 +292,8 @@ class ConfigSerializer:
|
|
|
225
292
|
|
|
226
293
|
def check_required_parameters(self) -> List[str]:
|
|
227
294
|
return [
|
|
228
|
-
f
|
|
229
|
-
f
|
|
295
|
+
f"if {p.serialized_name} is None:\n"
|
|
296
|
+
f" raise ValueError(\"Parameter '{p.serialized_name}' must not be None.\")"
|
|
230
297
|
for p in self.code_model.global_parameters.config_method
|
|
231
298
|
if p.required and not p.constant
|
|
232
299
|
]
|
|
@@ -234,7 +301,11 @@ class ConfigSerializer:
|
|
|
234
301
|
def property_descriptions(self) -> List[str]:
|
|
235
302
|
retval: List[str] = []
|
|
236
303
|
for p in self.code_model.global_parameters.config_method:
|
|
237
|
-
retval.append(
|
|
238
|
-
|
|
304
|
+
retval.append(
|
|
305
|
+
f":{p.description_keyword} {p.serialized_name}: {p.description}"
|
|
306
|
+
)
|
|
307
|
+
retval.append(
|
|
308
|
+
f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}"
|
|
309
|
+
)
|
|
239
310
|
retval.append('"""')
|
|
240
311
|
return retval
|
|
@@ -5,27 +5,54 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from jinja2 import Environment
|
|
7
7
|
from .import_serializer import FileImportSerializer, TypingSection
|
|
8
|
-
from ..models import
|
|
8
|
+
from ..models import (
|
|
9
|
+
FileImport,
|
|
10
|
+
ImportType,
|
|
11
|
+
CodeModel,
|
|
12
|
+
TokenCredentialSchema,
|
|
13
|
+
ParameterList,
|
|
14
|
+
)
|
|
9
15
|
from .client_serializer import ClientSerializer, ConfigSerializer
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
|
|
18
|
+
def config_imports(
|
|
19
|
+
code_model, global_parameters: ParameterList, async_mode: bool
|
|
20
|
+
) -> FileImport:
|
|
12
21
|
file_import = FileImport()
|
|
13
|
-
file_import.add_submodule_import(
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
file_import.add_submodule_import(
|
|
23
|
+
"azure.core.configuration", "Configuration", ImportType.AZURECORE
|
|
24
|
+
)
|
|
25
|
+
file_import.add_submodule_import(
|
|
26
|
+
"azure.core.pipeline", "policies", ImportType.AZURECORE
|
|
27
|
+
)
|
|
28
|
+
file_import.add_submodule_import(
|
|
29
|
+
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
30
|
+
)
|
|
16
31
|
if code_model.options["package_version"]:
|
|
17
|
-
file_import.add_submodule_import(
|
|
32
|
+
file_import.add_submodule_import(
|
|
33
|
+
".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL
|
|
34
|
+
)
|
|
18
35
|
for gp in global_parameters:
|
|
19
36
|
file_import.merge(gp.imports())
|
|
20
37
|
if code_model.options["azure_arm"]:
|
|
21
|
-
policy =
|
|
22
|
-
|
|
23
|
-
|
|
38
|
+
policy = (
|
|
39
|
+
"AsyncARMChallengeAuthenticationPolicy"
|
|
40
|
+
if async_mode
|
|
41
|
+
else "ARMChallengeAuthenticationPolicy"
|
|
42
|
+
)
|
|
43
|
+
file_import.add_submodule_import(
|
|
44
|
+
"azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE
|
|
45
|
+
)
|
|
46
|
+
file_import.add_submodule_import(
|
|
47
|
+
"azure.mgmt.core.policies", policy, ImportType.AZURECORE
|
|
48
|
+
)
|
|
24
49
|
return file_import
|
|
25
50
|
|
|
26
51
|
|
|
27
52
|
class GeneralSerializer:
|
|
28
|
-
def __init__(
|
|
53
|
+
def __init__(
|
|
54
|
+
self, code_model: CodeModel, env: Environment, async_mode: bool
|
|
55
|
+
) -> None:
|
|
29
56
|
self.code_model = code_model
|
|
30
57
|
self.env = env
|
|
31
58
|
self.async_mode = async_mode
|
|
@@ -40,7 +67,9 @@ class GeneralSerializer:
|
|
|
40
67
|
|
|
41
68
|
def _correct_credential_parameter(self):
|
|
42
69
|
credential_param = [
|
|
43
|
-
gp
|
|
70
|
+
gp
|
|
71
|
+
for gp in self.code_model.global_parameters.parameters
|
|
72
|
+
if isinstance(gp.schema, TokenCredentialSchema)
|
|
44
73
|
][0]
|
|
45
74
|
credential_param.schema = TokenCredentialSchema(async_mode=self.async_mode)
|
|
46
75
|
|
|
@@ -48,9 +77,9 @@ class GeneralSerializer:
|
|
|
48
77
|
|
|
49
78
|
template = self.env.get_template("service_client.py.jinja2")
|
|
50
79
|
|
|
51
|
-
if (
|
|
52
|
-
self.code_model.
|
|
53
|
-
|
|
80
|
+
if self.code_model.options["credential"] and isinstance(
|
|
81
|
+
self.code_model.credential_model.credential_schema_policy.credential,
|
|
82
|
+
TokenCredentialSchema,
|
|
54
83
|
):
|
|
55
84
|
self._correct_credential_parameter()
|
|
56
85
|
|
|
@@ -61,7 +90,7 @@ class GeneralSerializer:
|
|
|
61
90
|
serializer=ClientSerializer(self.code_model, is_python3_file=python3_only),
|
|
62
91
|
imports=FileImportSerializer(
|
|
63
92
|
self.code_model.service_client.imports(self.async_mode),
|
|
64
|
-
is_python3_file=self.async_mode or python3_only
|
|
93
|
+
is_python3_file=self.async_mode or python3_only,
|
|
65
94
|
),
|
|
66
95
|
)
|
|
67
96
|
|
|
@@ -77,25 +106,51 @@ class GeneralSerializer:
|
|
|
77
106
|
ImportType.AZURECORE,
|
|
78
107
|
)
|
|
79
108
|
|
|
109
|
+
if self.code_model.need_mixin_abc:
|
|
110
|
+
file_import.add_submodule_import(
|
|
111
|
+
"abc",
|
|
112
|
+
"ABC",
|
|
113
|
+
ImportType.STDLIB,
|
|
114
|
+
)
|
|
115
|
+
file_import.add_submodule_import(
|
|
116
|
+
"azure.core",
|
|
117
|
+
f"{'Async' if self.async_mode else ''}PipelineClient",
|
|
118
|
+
ImportType.AZURECORE,
|
|
119
|
+
TypingSection.TYPING,
|
|
120
|
+
)
|
|
121
|
+
file_import.add_submodule_import(
|
|
122
|
+
"._configuration",
|
|
123
|
+
f"{self.code_model.class_name}Configuration",
|
|
124
|
+
ImportType.LOCAL,
|
|
125
|
+
)
|
|
126
|
+
file_import.add_submodule_import(
|
|
127
|
+
"msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING
|
|
128
|
+
)
|
|
129
|
+
file_import.add_submodule_import(
|
|
130
|
+
"msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING
|
|
131
|
+
)
|
|
132
|
+
|
|
80
133
|
return template.render(
|
|
81
134
|
code_model=self.code_model,
|
|
82
135
|
imports=FileImportSerializer(
|
|
83
136
|
file_import,
|
|
84
137
|
is_python3_file=self.async_mode,
|
|
85
|
-
)
|
|
138
|
+
),
|
|
139
|
+
async_mode=self.async_mode,
|
|
86
140
|
)
|
|
87
141
|
|
|
88
|
-
|
|
89
142
|
def serialize_config_file(self) -> str:
|
|
90
143
|
|
|
91
|
-
package_name = self.code_model.options[
|
|
144
|
+
package_name = self.code_model.options["package_name"]
|
|
92
145
|
if package_name and package_name.startswith("azure-"):
|
|
93
|
-
package_name = package_name[len("azure-"):]
|
|
94
|
-
sdk_moniker =
|
|
146
|
+
package_name = package_name[len("azure-") :]
|
|
147
|
+
sdk_moniker = (
|
|
148
|
+
package_name if package_name else self.code_model.class_name.lower()
|
|
149
|
+
)
|
|
95
150
|
|
|
96
|
-
if (
|
|
97
|
-
self.code_model.
|
|
98
|
-
|
|
151
|
+
if self.code_model.options["credential"] and isinstance(
|
|
152
|
+
self.code_model.credential_model.credential_schema_policy.credential,
|
|
153
|
+
TokenCredentialSchema,
|
|
99
154
|
):
|
|
100
155
|
self._correct_credential_parameter()
|
|
101
156
|
|
|
@@ -107,7 +162,8 @@ class GeneralSerializer:
|
|
|
107
162
|
imports=FileImportSerializer(
|
|
108
163
|
config_imports(
|
|
109
164
|
self.code_model, self.code_model.global_parameters, self.async_mode
|
|
110
|
-
),
|
|
165
|
+
),
|
|
166
|
+
is_python3_file=self.async_mode or python3_only,
|
|
111
167
|
),
|
|
112
168
|
serializer=ConfigSerializer(self.code_model, is_python3_file=python3_only),
|
|
113
169
|
sdk_moniker=sdk_moniker,
|
|
@@ -119,4 +175,7 @@ class GeneralSerializer:
|
|
|
119
175
|
|
|
120
176
|
def serialize_setup_file(self) -> str:
|
|
121
177
|
template = self.env.get_template("setup.py.jinja2")
|
|
122
|
-
|
|
178
|
+
params = {}
|
|
179
|
+
params.update(self.code_model.options)
|
|
180
|
+
params.update(self.code_model.package_dependency)
|
|
181
|
+
return template.render(code_model=self.code_model, **params)
|
|
@@ -5,49 +5,68 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from copy import deepcopy
|
|
7
7
|
from typing import List
|
|
8
|
-
from ..models.imports import
|
|
8
|
+
from ..models.imports import (
|
|
9
|
+
ImportType,
|
|
10
|
+
FileImport,
|
|
11
|
+
ImportModel,
|
|
12
|
+
TypingSection,
|
|
13
|
+
TypeDefinition,
|
|
14
|
+
)
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
) -> str:
|
|
16
|
+
|
|
17
|
+
def _serialize_package(imports: List[ImportModel], delimiter: str) -> str:
|
|
13
18
|
buffer = []
|
|
14
19
|
if any(i for i in imports if i.submodule_name is None):
|
|
15
|
-
buffer.append(
|
|
20
|
+
buffer.append(
|
|
21
|
+
f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}"
|
|
22
|
+
)
|
|
16
23
|
else:
|
|
17
|
-
import_str = ", ".join(
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
import_str = ", ".join(
|
|
25
|
+
sorted(
|
|
26
|
+
[
|
|
27
|
+
f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
|
|
28
|
+
]
|
|
29
|
+
)
|
|
30
|
+
)
|
|
20
31
|
buffer.append(f"from {imports[0].module_name} import {import_str}")
|
|
21
32
|
return delimiter.join(buffer)
|
|
22
33
|
|
|
34
|
+
|
|
23
35
|
def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
|
|
24
36
|
"""Serialize a given import type."""
|
|
25
37
|
import_list = []
|
|
26
38
|
for module_name in sorted(set(i.module_name for i in imports)):
|
|
27
39
|
|
|
28
|
-
import_list.append(
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
import_list.append(
|
|
41
|
+
_serialize_package(
|
|
42
|
+
[i for i in imports if i.module_name == module_name], delimiter
|
|
43
|
+
)
|
|
44
|
+
)
|
|
31
45
|
return delimiter.join(import_list)
|
|
32
46
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
) -> List[str]:
|
|
47
|
+
|
|
48
|
+
def _get_import_clauses(imports: List[ImportModel], delimiter: str) -> List[str]:
|
|
36
49
|
import_clause = []
|
|
37
50
|
for import_type in ImportType:
|
|
38
51
|
imports_with_import_type = [i for i in imports if i.import_type == import_type]
|
|
39
52
|
if imports_with_import_type:
|
|
40
|
-
import_clause.append(
|
|
53
|
+
import_clause.append(
|
|
54
|
+
_serialize_import_type(imports_with_import_type, delimiter)
|
|
55
|
+
)
|
|
41
56
|
return import_clause
|
|
42
57
|
|
|
43
58
|
|
|
44
59
|
class FileImportSerializer:
|
|
45
|
-
def __init__(
|
|
60
|
+
def __init__(
|
|
61
|
+
self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False
|
|
62
|
+
) -> None:
|
|
46
63
|
self.file_import = file_import
|
|
47
64
|
self.is_python3_file = is_python3_file
|
|
48
65
|
self.async_mode = async_mode
|
|
49
66
|
|
|
50
|
-
def _get_imports_list(
|
|
67
|
+
def _get_imports_list(
|
|
68
|
+
self, baseline_typing_section: TypingSection, add_conditional_typing: bool
|
|
69
|
+
):
|
|
51
70
|
# If this is a python 3 file, our regular imports include the CONDITIONAL category
|
|
52
71
|
# If this is not a python 3 file, our typing imports include the CONDITIONAL category
|
|
53
72
|
file_import_copy = deepcopy(self.file_import)
|
|
@@ -62,33 +81,73 @@ class FileImportSerializer:
|
|
|
62
81
|
return file_import_copy.get_imports_from_section(baseline_typing_section)
|
|
63
82
|
|
|
64
83
|
def _add_type_checking_import(self):
|
|
65
|
-
any_typing = any(
|
|
84
|
+
any_typing = any(
|
|
85
|
+
self.file_import.get_imports_from_section(TypingSection.TYPING)
|
|
86
|
+
)
|
|
66
87
|
conditional_and_not_py3 = not self.is_python3_file and any(
|
|
67
88
|
self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
|
|
68
89
|
)
|
|
69
90
|
if any_typing or conditional_and_not_py3:
|
|
70
|
-
self.file_import.add_submodule_import(
|
|
91
|
+
self.file_import.add_submodule_import(
|
|
92
|
+
"typing", "TYPE_CHECKING", ImportType.STDLIB
|
|
93
|
+
)
|
|
71
94
|
|
|
72
95
|
def _get_typing_definitions(self) -> str:
|
|
96
|
+
def declare_defintion(
|
|
97
|
+
spacing: str, type_name: str, type_definition: TypeDefinition
|
|
98
|
+
) -> List[str]:
|
|
99
|
+
ret: List[str] = []
|
|
100
|
+
definition_value = (
|
|
101
|
+
type_definition.async_definition
|
|
102
|
+
if self.async_mode
|
|
103
|
+
else type_definition.sync_definition
|
|
104
|
+
)
|
|
105
|
+
if type_definition.version_imports is not None:
|
|
106
|
+
versions = type_definition.version_imports.keys()
|
|
107
|
+
for i, version in enumerate(
|
|
108
|
+
sorted(
|
|
109
|
+
versions, key=lambda x: x if x is not None else (), reverse=True
|
|
110
|
+
)
|
|
111
|
+
):
|
|
112
|
+
if version is not None:
|
|
113
|
+
ret.append(
|
|
114
|
+
"{}{} sys.version_info >= {}:".format(
|
|
115
|
+
spacing, "if" if i == 0 else "elif", version
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
elif i > 0:
|
|
119
|
+
ret.append("{}else:".format(spacing))
|
|
120
|
+
for import_clause in _get_import_clauses(
|
|
121
|
+
[type_definition.version_imports[version]], "\n"
|
|
122
|
+
):
|
|
123
|
+
ret.append(
|
|
124
|
+
"{}{}{}".format(
|
|
125
|
+
" "
|
|
126
|
+
if len(versions) > 1 or version is not None
|
|
127
|
+
else "",
|
|
128
|
+
spacing,
|
|
129
|
+
import_clause,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
if i > 0:
|
|
133
|
+
ret[-1] += " # type: ignore"
|
|
134
|
+
ret.append("{}{} = {}".format(spacing, type_name, definition_value))
|
|
135
|
+
return ret
|
|
136
|
+
|
|
73
137
|
if not self.file_import.type_definitions:
|
|
74
138
|
return ""
|
|
75
139
|
spacing = "" if self.is_python3_file else " "
|
|
76
|
-
declarations: List[str] = [
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
spacing,
|
|
80
|
-
type_name,
|
|
81
|
-
values[1] if self.async_mode else values[0]
|
|
82
|
-
)
|
|
83
|
-
for type_name, values in self.file_import.type_definitions.items()
|
|
84
|
-
])
|
|
140
|
+
declarations: List[str] = [""]
|
|
141
|
+
for type_name, value in self.file_import.type_definitions.items():
|
|
142
|
+
declarations.extend(declare_defintion(spacing, type_name, value))
|
|
85
143
|
return "\n".join(declarations)
|
|
86
144
|
|
|
87
145
|
def __str__(self) -> str:
|
|
88
146
|
self._add_type_checking_import()
|
|
89
147
|
regular_imports = ""
|
|
90
148
|
regular_imports_list = self._get_imports_list(
|
|
91
|
-
baseline_typing_section=TypingSection.REGULAR,
|
|
149
|
+
baseline_typing_section=TypingSection.REGULAR,
|
|
150
|
+
add_conditional_typing=self.is_python3_file,
|
|
92
151
|
)
|
|
93
152
|
|
|
94
153
|
if regular_imports_list:
|
|
@@ -98,9 +157,12 @@ class FileImportSerializer:
|
|
|
98
157
|
|
|
99
158
|
typing_imports = ""
|
|
100
159
|
typing_imports_list = self._get_imports_list(
|
|
101
|
-
baseline_typing_section=TypingSection.TYPING,
|
|
160
|
+
baseline_typing_section=TypingSection.TYPING,
|
|
161
|
+
add_conditional_typing=not self.is_python3_file,
|
|
102
162
|
)
|
|
103
163
|
if typing_imports_list:
|
|
104
164
|
typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
|
|
105
|
-
typing_imports += "\n\n ".join(
|
|
165
|
+
typing_imports += "\n\n ".join(
|
|
166
|
+
_get_import_clauses(typing_imports_list, "\n ")
|
|
167
|
+
)
|
|
106
168
|
return regular_imports + typing_imports + self._get_typing_definitions()
|