@typespec/http-client-python 0.11.0 → 0.11.2
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/dist/emitter/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +21 -6
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +2 -17
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +0 -7
- package/dist/emitter/lib.js.map +1 -1
- package/emitter/src/emitter.ts +21 -6
- package/emitter/src/lib.ts +0 -7
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/mypy.ini +4 -1
- package/eng/scripts/ci/regenerate.ts +3 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
- package/generator/build/lib/pygen/codegen/models/code_model.py +22 -11
- package/generator/build/lib/pygen/codegen/models/imports.py +13 -9
- package/generator/build/lib/pygen/codegen/models/lro_operation.py +1 -1
- package/generator/build/lib/pygen/codegen/models/model_type.py +3 -2
- package/generator/build/lib/pygen/codegen/models/operation.py +10 -3
- package/generator/build/lib/pygen/codegen/models/operation_group.py +27 -31
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +3 -1
- package/generator/build/lib/pygen/codegen/models/parameter.py +1 -1
- package/generator/build/lib/pygen/codegen/models/primitive_types.py +2 -2
- package/generator/build/lib/pygen/codegen/models/property.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +31 -29
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +10 -21
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +4 -3
- package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
- package/generator/build/lib/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/code_model.py +22 -11
- package/generator/pygen/codegen/models/imports.py +13 -9
- package/generator/pygen/codegen/models/lro_operation.py +1 -1
- package/generator/pygen/codegen/models/model_type.py +3 -2
- package/generator/pygen/codegen/models/operation.py +10 -3
- package/generator/pygen/codegen/models/operation_group.py +27 -31
- package/generator/pygen/codegen/models/paging_operation.py +3 -1
- package/generator/pygen/codegen/models/parameter.py +1 -1
- package/generator/pygen/codegen/models/primitive_types.py +2 -2
- package/generator/pygen/codegen/models/property.py +1 -1
- package/generator/pygen/codegen/serializers/__init__.py +31 -29
- package/generator/pygen/codegen/serializers/builder_serializer.py +1 -1
- package/generator/pygen/codegen/serializers/general_serializer.py +10 -21
- package/generator/pygen/codegen/serializers/model_serializer.py +4 -3
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
- package/generator/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
- package/generator/pygen.egg-info/SOURCES.txt +1 -1
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +1 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +1 -1
- package/generator/test/generic_mock_api_tests/test_encode_bytes.py +1 -0
- package/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py +1 -1
- package/generator/test/unittests/conftest.py +1 -0
- package/generator/test/unittests/test_model_base_serialization.py +1 -1
- package/generator/test/unittests/test_model_base_xml_serialization.py +1 -1
- package/package.json +31 -31
|
@@ -242,16 +242,26 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
242
242
|
"""
|
|
243
243
|
return client_namespace == self.namespace
|
|
244
244
|
|
|
245
|
-
def
|
|
246
|
-
"""Whether we need to vendor code in the _vendor.py in specific namespace"""
|
|
245
|
+
def need_utils_folder(self, async_mode: bool, client_namespace: str) -> bool:
|
|
247
246
|
return (
|
|
248
|
-
self.
|
|
249
|
-
or self.
|
|
250
|
-
or self.
|
|
251
|
-
or self.need_vendored_mixin(client_namespace)
|
|
247
|
+
self.need_utils_utils(async_mode, client_namespace)
|
|
248
|
+
or self.need_utils_serialization
|
|
249
|
+
or self.options["models_mode"] == "dpg"
|
|
252
250
|
)
|
|
253
251
|
|
|
254
|
-
|
|
252
|
+
@property
|
|
253
|
+
def need_utils_serialization(self) -> bool:
|
|
254
|
+
return not self.options["client_side_validation"]
|
|
255
|
+
|
|
256
|
+
def need_utils_utils(self, async_mode: bool, client_namespace: str) -> bool:
|
|
257
|
+
return (
|
|
258
|
+
self.need_utils_form_data(async_mode, client_namespace)
|
|
259
|
+
or self.need_utils_etag(client_namespace)
|
|
260
|
+
or self.need_utils_abstract(client_namespace)
|
|
261
|
+
or self.need_utils_mixin
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def need_utils_form_data(self, async_mode: bool, client_namespace: str) -> bool:
|
|
255
265
|
return (
|
|
256
266
|
(not async_mode)
|
|
257
267
|
and self.is_top_namespace(client_namespace)
|
|
@@ -259,14 +269,15 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
259
269
|
and self.options["models_mode"] == "dpg"
|
|
260
270
|
)
|
|
261
271
|
|
|
262
|
-
def
|
|
272
|
+
def need_utils_etag(self, client_namespace: str) -> bool:
|
|
263
273
|
return self.is_top_namespace(client_namespace) and self.has_etag
|
|
264
274
|
|
|
265
|
-
def
|
|
275
|
+
def need_utils_abstract(self, client_namespace: str) -> bool:
|
|
266
276
|
return self.is_top_namespace(client_namespace) and self.has_abstract_operations
|
|
267
277
|
|
|
268
|
-
|
|
269
|
-
|
|
278
|
+
@property
|
|
279
|
+
def need_utils_mixin(self) -> bool:
|
|
280
|
+
return any(c_n for c_n in self.client_namespace_types if self.has_mixin(c_n))
|
|
270
281
|
|
|
271
282
|
def has_mixin(self, client_namespace: str) -> bool:
|
|
272
283
|
return any(c for c in self.get_clients(client_namespace) if c.has_mixin)
|
|
@@ -30,9 +30,11 @@ class TypingSection(str, Enum):
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class MsrestImportType(Enum):
|
|
33
|
-
Module = auto() # import
|
|
34
|
-
Serializer = auto() # from
|
|
35
|
-
SerializerDeserializer =
|
|
33
|
+
Module = auto() # import _utils/serialization.py or msrest.serialization as Module
|
|
34
|
+
Serializer = auto() # from _utils/serialization.py or msrest.serialization import Serializer
|
|
35
|
+
SerializerDeserializer = (
|
|
36
|
+
auto()
|
|
37
|
+
) # from _utils/serialization.py or msrest.serialization import Serializer and Deserializer
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
class ImportModel:
|
|
@@ -261,21 +263,23 @@ class FileImport:
|
|
|
261
263
|
if msrest_import_type == MsrestImportType.SerializerDeserializer:
|
|
262
264
|
self.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY, typing_section)
|
|
263
265
|
else:
|
|
264
|
-
#
|
|
265
|
-
imported_namespace = self.code_model.namespace
|
|
266
|
+
# _utils/serialization.py is always in root namespace
|
|
267
|
+
imported_namespace = f"{self.code_model.namespace}._utils"
|
|
266
268
|
if self.code_model.options["multiapi"]:
|
|
267
|
-
# for multiapi, the namespace is azure.mgmt.xxx.v20XX_XX_XX
|
|
268
|
-
|
|
269
|
+
# for multiapi, the namespace is azure.mgmt.xxx.v20XX_XX_XX
|
|
270
|
+
# while _utils/serialization.py is in azure.mgmt.xxx
|
|
271
|
+
imported_namespace = f"{get_parent_namespace(imported_namespace)}._utils"
|
|
269
272
|
if msrest_import_type == MsrestImportType.Module:
|
|
270
273
|
self.add_submodule_import(
|
|
271
274
|
self.code_model.get_relative_import_path(serialize_namespace, imported_namespace),
|
|
272
|
-
"
|
|
275
|
+
"serialization",
|
|
273
276
|
ImportType.LOCAL,
|
|
274
277
|
typing_section,
|
|
278
|
+
alias="_serialization",
|
|
275
279
|
)
|
|
276
280
|
else:
|
|
277
281
|
relative_path = self.code_model.get_relative_import_path(
|
|
278
|
-
serialize_namespace,
|
|
282
|
+
serialize_namespace, f"{self.code_model.namespace}._utils.serialization"
|
|
279
283
|
)
|
|
280
284
|
self.add_submodule_import(relative_path, "Serializer", ImportType.LOCAL, typing_section)
|
|
281
285
|
if msrest_import_type == MsrestImportType.SerializerDeserializer:
|
|
@@ -134,7 +134,7 @@ class LROOperationBase(OperationBase[LROResponseType]):
|
|
|
134
134
|
# but final call returns a model
|
|
135
135
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
136
136
|
file_import.add_submodule_import(
|
|
137
|
-
self.code_model.get_relative_import_path(serialize_namespace, module_name="
|
|
137
|
+
self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
|
|
138
138
|
"_deserialize",
|
|
139
139
|
ImportType.LOCAL,
|
|
140
140
|
)
|
|
@@ -318,9 +318,10 @@ class GeneratedModelType(ModelType):
|
|
|
318
318
|
)
|
|
319
319
|
if self.is_form_data:
|
|
320
320
|
file_import.add_submodule_import(
|
|
321
|
-
self.code_model.get_relative_import_path(serialize_namespace),
|
|
322
|
-
"
|
|
321
|
+
self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
|
|
322
|
+
"Model",
|
|
323
323
|
ImportType.LOCAL,
|
|
324
|
+
alias="_Model",
|
|
324
325
|
)
|
|
325
326
|
elif serialize_namespace_type == NamespaceType.TYPES_FILE or (
|
|
326
327
|
serialize_namespace_type == NamespaceType.MODEL and called_by_property
|
|
@@ -391,7 +391,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
391
391
|
ImportType.SDKCORE,
|
|
392
392
|
)
|
|
393
393
|
if not async_mode:
|
|
394
|
-
relative_path = self.code_model.get_relative_import_path(
|
|
394
|
+
relative_path = self.code_model.get_relative_import_path(
|
|
395
|
+
serialize_namespace, module_name="_utils.utils"
|
|
396
|
+
)
|
|
395
397
|
file_import.add_submodule_import(
|
|
396
398
|
relative_path,
|
|
397
399
|
"prep_if_match",
|
|
@@ -436,12 +438,17 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
436
438
|
if self.overloads:
|
|
437
439
|
file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
|
|
438
440
|
if self.code_model.options["models_mode"] == "dpg":
|
|
439
|
-
relative_path = self.code_model.get_relative_import_path(
|
|
441
|
+
relative_path = self.code_model.get_relative_import_path(
|
|
442
|
+
serialize_namespace, module_name="_utils.model_base"
|
|
443
|
+
)
|
|
440
444
|
body_param = self.parameters.body_parameter if self.parameters.has_body else None
|
|
441
445
|
if body_param and not isinstance(body_param.type, BinaryType):
|
|
442
446
|
if self.has_form_data_body:
|
|
443
447
|
file_import.add_submodule_import(
|
|
444
|
-
|
|
448
|
+
relative_path,
|
|
449
|
+
"Model",
|
|
450
|
+
ImportType.LOCAL,
|
|
451
|
+
alias="_Model",
|
|
445
452
|
)
|
|
446
453
|
elif xml_serializable(self.parameters.body_parameter.default_content_type):
|
|
447
454
|
file_import.add_submodule_import(
|
|
@@ -63,11 +63,11 @@ class OperationGroup(BaseModel):
|
|
|
63
63
|
operation_group.has_non_abstract_operations for operation_group in self.operation_groups
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
def base_class(self, async_mode: bool) -> str:
|
|
67
|
+
pipeline_client = f"{'Async' if async_mode else ''}PipelineClient"
|
|
68
68
|
base_classes: List[str] = []
|
|
69
69
|
if self.is_mixin:
|
|
70
|
-
base_classes.append(f"{self.client.name}
|
|
70
|
+
base_classes.append(f"ClientMixinABC[{pipeline_client}, {self.client.name}Configuration]")
|
|
71
71
|
return ", ".join(base_classes)
|
|
72
72
|
|
|
73
73
|
def imports_for_multiapi(self, async_mode: bool, **kwargs) -> FileImport:
|
|
@@ -100,8 +100,12 @@ class OperationGroup(BaseModel):
|
|
|
100
100
|
|
|
101
101
|
def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
|
|
102
102
|
file_import = FileImport(self.code_model)
|
|
103
|
-
|
|
104
103
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
104
|
+
utils_path = self.code_model.get_relative_import_path(
|
|
105
|
+
serialize_namespace,
|
|
106
|
+
f"{self.code_model.namespace}._utils.utils",
|
|
107
|
+
)
|
|
108
|
+
|
|
105
109
|
for operation in self.operations:
|
|
106
110
|
file_import.merge(operation.imports(async_mode, **kwargs))
|
|
107
111
|
if not self.code_model.options["combine_operation_files"]:
|
|
@@ -141,32 +145,28 @@ class OperationGroup(BaseModel):
|
|
|
141
145
|
ImportType.LOCAL,
|
|
142
146
|
alias="_models",
|
|
143
147
|
)
|
|
148
|
+
file_import.add_submodule_import(
|
|
149
|
+
self.code_model.get_relative_import_path(
|
|
150
|
+
serialize_namespace,
|
|
151
|
+
self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
|
|
152
|
+
module_name="_configuration",
|
|
153
|
+
),
|
|
154
|
+
f"{self.client.name}Configuration",
|
|
155
|
+
ImportType.LOCAL,
|
|
156
|
+
)
|
|
157
|
+
file_import.add_submodule_import(
|
|
158
|
+
"" if self.code_model.is_azure_flavor else "runtime",
|
|
159
|
+
f"{'Async' if async_mode else ''}PipelineClient",
|
|
160
|
+
ImportType.SDKCORE,
|
|
161
|
+
)
|
|
144
162
|
if self.is_mixin:
|
|
145
163
|
file_import.add_submodule_import(
|
|
146
|
-
# XxxMixinABC is always defined in
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
|
|
150
|
-
module_name="_vendor",
|
|
151
|
-
),
|
|
152
|
-
f"{self.client.name}MixinABC",
|
|
164
|
+
# XxxMixinABC is always defined in _utils of client namespace
|
|
165
|
+
utils_path,
|
|
166
|
+
"ClientMixinABC",
|
|
153
167
|
ImportType.LOCAL,
|
|
154
168
|
)
|
|
155
169
|
else:
|
|
156
|
-
file_import.add_submodule_import(
|
|
157
|
-
"" if self.code_model.is_azure_flavor else "runtime",
|
|
158
|
-
f"{'Async' if async_mode else ''}PipelineClient",
|
|
159
|
-
ImportType.SDKCORE,
|
|
160
|
-
)
|
|
161
|
-
file_import.add_submodule_import(
|
|
162
|
-
self.code_model.get_relative_import_path(
|
|
163
|
-
serialize_namespace,
|
|
164
|
-
self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
|
|
165
|
-
module_name="_configuration",
|
|
166
|
-
),
|
|
167
|
-
f"{self.client.name}Configuration",
|
|
168
|
-
ImportType.LOCAL,
|
|
169
|
-
)
|
|
170
170
|
file_import.add_msrest_import(
|
|
171
171
|
serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
|
|
172
172
|
msrest_import_type=MsrestImportType.Serializer,
|
|
@@ -179,12 +179,8 @@ class OperationGroup(BaseModel):
|
|
|
179
179
|
)
|
|
180
180
|
if self.has_abstract_operations:
|
|
181
181
|
file_import.add_submodule_import(
|
|
182
|
-
# raise_if_not_implemented is always defined in
|
|
183
|
-
|
|
184
|
-
serialize_namespace,
|
|
185
|
-
self.code_model.get_imported_namespace_for_client(self.code_model.namespace, async_mode),
|
|
186
|
-
module_name="_vendor",
|
|
187
|
-
),
|
|
182
|
+
# raise_if_not_implemented is always defined in _utils of top namespace
|
|
183
|
+
utils_path,
|
|
188
184
|
"raise_if_not_implemented",
|
|
189
185
|
ImportType.LOCAL,
|
|
190
186
|
)
|
|
@@ -157,7 +157,9 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
157
157
|
ImportType.SDKCORE,
|
|
158
158
|
)
|
|
159
159
|
if self.code_model.options["models_mode"] == "dpg":
|
|
160
|
-
relative_path = self.code_model.get_relative_import_path(
|
|
160
|
+
relative_path = self.code_model.get_relative_import_path(
|
|
161
|
+
serialize_namespace, module_name="_utils.model_base"
|
|
162
|
+
)
|
|
161
163
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
162
164
|
if self.default_error_deserialization or self.need_deserialize:
|
|
163
165
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
@@ -275,7 +275,7 @@ class BodyParameter(_ParameterBase):
|
|
|
275
275
|
if self.is_form_data:
|
|
276
276
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
277
277
|
file_import.add_submodule_import(
|
|
278
|
-
self.code_model.get_relative_import_path(serialize_namespace, module_name="
|
|
278
|
+
self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.utils"),
|
|
279
279
|
"prepare_multipart_form_data",
|
|
280
280
|
ImportType.LOCAL,
|
|
281
281
|
)
|
|
@@ -618,13 +618,13 @@ class MultiPartFileType(PrimitiveType):
|
|
|
618
618
|
return self.name
|
|
619
619
|
|
|
620
620
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
621
|
-
return f"~{self.code_model.namespace}.
|
|
621
|
+
return f"~{self.code_model.namespace}._utils.utils.{self.name}"
|
|
622
622
|
|
|
623
623
|
def imports(self, **kwargs: Any) -> FileImport:
|
|
624
624
|
file_import = super().imports(**kwargs)
|
|
625
625
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
626
626
|
file_import.add_submodule_import(
|
|
627
|
-
self.code_model.get_relative_import_path(serialize_namespace, module_name="
|
|
627
|
+
self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.utils"),
|
|
628
628
|
self.name,
|
|
629
629
|
ImportType.LOCAL,
|
|
630
630
|
)
|
|
@@ -149,7 +149,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
149
149
|
if self.code_model.options["models_mode"] == "dpg":
|
|
150
150
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
151
151
|
file_import.add_submodule_import(
|
|
152
|
-
self.code_model.get_relative_import_path(serialize_namespace, module_name="
|
|
152
|
+
self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
|
|
153
153
|
"rest_discriminator" if self.is_discriminator else "rest_field",
|
|
154
154
|
ImportType.LOCAL,
|
|
155
155
|
)
|
|
@@ -153,7 +153,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
153
153
|
general_serializer.serialize_pkgutil_init_file(),
|
|
154
154
|
)
|
|
155
155
|
|
|
156
|
-
#
|
|
156
|
+
# _utils/py.typed/_types.py/_validation.py
|
|
157
157
|
# is always put in top level namespace
|
|
158
158
|
if self.code_model.is_top_namespace(client_namespace):
|
|
159
159
|
self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
|
|
@@ -404,25 +404,41 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
404
404
|
general_serializer.serialize_config_file(clients),
|
|
405
405
|
)
|
|
406
406
|
|
|
407
|
-
# sometimes we need define additional Mixin class for client in
|
|
408
|
-
self.
|
|
407
|
+
# sometimes we need define additional Mixin class for client in _utils.py
|
|
408
|
+
self._serialize_and_write_utils_folder(env, namespace)
|
|
409
409
|
|
|
410
|
-
def
|
|
410
|
+
def _serialize_and_write_utils_folder(self, env: Environment, namespace: str) -> None:
|
|
411
411
|
exec_path = self.exec_path(namespace)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
412
|
+
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
413
|
+
utils_folder_path = exec_path / Path("_utils")
|
|
414
|
+
if self.code_model.need_utils_folder(async_mode=False, client_namespace=namespace):
|
|
415
|
+
self.write_file(
|
|
416
|
+
utils_folder_path / Path("__init__.py"),
|
|
417
|
+
self.code_model.license_header,
|
|
418
|
+
)
|
|
419
|
+
if self.code_model.need_utils_utils(async_mode=False, client_namespace=namespace):
|
|
420
|
+
self.write_file(
|
|
421
|
+
utils_folder_path / Path("utils.py"),
|
|
422
|
+
general_serializer.need_utils_utils_file(),
|
|
423
|
+
)
|
|
424
|
+
# write _utils/serialization.py
|
|
425
|
+
if self.code_model.need_utils_serialization:
|
|
426
|
+
self.write_file(
|
|
427
|
+
utils_folder_path / Path("serialization.py"),
|
|
428
|
+
general_serializer.serialize_serialization_file(),
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
# write _model_base.py
|
|
432
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
433
|
+
self.write_file(
|
|
434
|
+
utils_folder_path / Path("model_base.py"),
|
|
435
|
+
general_serializer.serialize_model_base_file(),
|
|
436
|
+
)
|
|
421
437
|
|
|
422
438
|
def _serialize_and_write_top_level_folder(self, env: Environment, namespace: str) -> None:
|
|
423
439
|
exec_path = self.exec_path(namespace)
|
|
424
|
-
# write
|
|
425
|
-
self.
|
|
440
|
+
# write _utils folder
|
|
441
|
+
self._serialize_and_write_utils_folder(env, namespace)
|
|
426
442
|
|
|
427
443
|
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
428
444
|
|
|
@@ -432,20 +448,6 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
432
448
|
# write the empty py.typed file
|
|
433
449
|
self.write_file(exec_path / Path("py.typed"), "# Marker file for PEP 561.")
|
|
434
450
|
|
|
435
|
-
# write _serialization.py
|
|
436
|
-
if not self.code_model.options["client_side_validation"] and not self.code_model.options["multiapi"]:
|
|
437
|
-
self.write_file(
|
|
438
|
-
exec_path / Path("_serialization.py"),
|
|
439
|
-
general_serializer.serialize_serialization_file(),
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
# write _model_base.py
|
|
443
|
-
if self.code_model.options["models_mode"] == "dpg":
|
|
444
|
-
self.write_file(
|
|
445
|
-
exec_path / Path("_model_base.py"),
|
|
446
|
-
general_serializer.serialize_model_base_file(),
|
|
447
|
-
)
|
|
448
|
-
|
|
449
451
|
# write _validation.py
|
|
450
452
|
if any(og for client in self.code_model.clients for og in client.operation_groups if og.need_validation):
|
|
451
453
|
self.write_file(
|
|
@@ -672,7 +672,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
672
672
|
[
|
|
673
673
|
"_body = (",
|
|
674
674
|
f" {body_param.client_name}.as_dict()",
|
|
675
|
-
f" if isinstance({body_param.client_name},
|
|
675
|
+
f" if isinstance({body_param.client_name}, _Model) else",
|
|
676
676
|
f" {body_param.client_name}",
|
|
677
677
|
")",
|
|
678
678
|
f"_file_fields: List[str] = {file_fields}",
|
|
@@ -107,44 +107,33 @@ class GeneralSerializer(BaseSerializer):
|
|
|
107
107
|
serialize_namespace=self.serialize_namespace,
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
-
def
|
|
111
|
-
template = self.env.get_template("
|
|
110
|
+
def need_utils_utils_file(self) -> str:
|
|
111
|
+
template = self.env.get_template("utils.py.jinja2")
|
|
112
112
|
clients = self.code_model.get_clients(self.client_namespace)
|
|
113
113
|
|
|
114
114
|
# configure imports
|
|
115
115
|
file_import = FileImport(self.code_model)
|
|
116
|
-
if self.code_model.
|
|
116
|
+
if self.code_model.need_utils_mixin:
|
|
117
117
|
file_import.add_submodule_import(
|
|
118
118
|
"abc",
|
|
119
119
|
"ABC",
|
|
120
120
|
ImportType.STDLIB,
|
|
121
121
|
)
|
|
122
|
-
file_import.add_submodule_import(
|
|
123
|
-
"" if self.code_model.is_azure_flavor else "runtime",
|
|
124
|
-
f"{'Async' if self.async_mode else ''}PipelineClient",
|
|
125
|
-
ImportType.SDKCORE,
|
|
126
|
-
TypingSection.TYPING,
|
|
127
|
-
)
|
|
128
122
|
file_import.add_msrest_import(
|
|
129
|
-
serialize_namespace=self.serialize_namespace,
|
|
123
|
+
serialize_namespace=f"{self.serialize_namespace}._utils",
|
|
130
124
|
msrest_import_type=MsrestImportType.SerializerDeserializer,
|
|
131
125
|
typing_section=TypingSection.TYPING,
|
|
132
126
|
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"._configuration",
|
|
137
|
-
f"{client.name}Configuration",
|
|
138
|
-
ImportType.LOCAL,
|
|
139
|
-
)
|
|
140
|
-
if self.code_model.need_vendored_etag(self.client_namespace):
|
|
127
|
+
file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB)
|
|
128
|
+
file_import.add_submodule_import("typing", "Generic", ImportType.STDLIB)
|
|
129
|
+
if self.code_model.need_utils_etag(self.client_namespace):
|
|
141
130
|
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
|
|
142
131
|
file_import.add_submodule_import(
|
|
143
132
|
"",
|
|
144
133
|
"MatchConditions",
|
|
145
134
|
ImportType.SDKCORE,
|
|
146
135
|
)
|
|
147
|
-
if self.code_model.
|
|
136
|
+
if self.code_model.need_utils_form_data(self.async_mode, self.client_namespace):
|
|
148
137
|
file_import.add_submodule_import("typing", "IO", ImportType.STDLIB)
|
|
149
138
|
file_import.add_submodule_import("typing", "Tuple", ImportType.STDLIB)
|
|
150
139
|
file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
|
|
@@ -154,12 +143,12 @@ class GeneralSerializer(BaseSerializer):
|
|
|
154
143
|
file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
|
|
155
144
|
file_import.add_submodule_import("typing", "List", ImportType.STDLIB)
|
|
156
145
|
file_import.add_submodule_import(
|
|
157
|
-
".
|
|
146
|
+
".._utils.model_base",
|
|
158
147
|
"SdkJSONEncoder",
|
|
159
148
|
ImportType.LOCAL,
|
|
160
149
|
)
|
|
161
150
|
file_import.add_submodule_import(
|
|
162
|
-
".
|
|
151
|
+
".._utils.model_base",
|
|
163
152
|
"Model",
|
|
164
153
|
ImportType.LOCAL,
|
|
165
154
|
)
|
|
@@ -230,10 +230,11 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
230
230
|
file_import = FileImport(self.code_model)
|
|
231
231
|
if any(not m.parents for m in self.models):
|
|
232
232
|
file_import.add_submodule_import(
|
|
233
|
-
self.code_model.get_relative_import_path(self.serialize_namespace),
|
|
234
|
-
"
|
|
233
|
+
self.code_model.get_relative_import_path(self.serialize_namespace, module_name="_utils.model_base"),
|
|
234
|
+
"Model",
|
|
235
235
|
ImportType.LOCAL,
|
|
236
236
|
TypingSection.REGULAR,
|
|
237
|
+
alias="_Model",
|
|
237
238
|
)
|
|
238
239
|
for model in self.models:
|
|
239
240
|
if model.base == "json":
|
|
@@ -272,7 +273,7 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
272
273
|
return file_import
|
|
273
274
|
|
|
274
275
|
def declare_model(self, model: ModelType) -> str:
|
|
275
|
-
basename = "
|
|
276
|
+
basename = "_Model"
|
|
276
277
|
if model.parents:
|
|
277
278
|
basename = ", ".join([m.name for m in model.parents])
|
|
278
279
|
if model.discriminator_value:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{% set base_class = ("(" + operation_group.base_class + ")") if operation_group.base_class else "" %}
|
|
1
|
+
{% set base_class = ("(" + operation_group.base_class(async_mode) + ")") if operation_group.base_class(async_mode) else "" %}
|
|
2
2
|
{% macro check_abstract_methods() %}
|
|
3
3
|
{% if operation_group.has_abstract_operations %}
|
|
4
4
|
raise_if_not_implemented(self.__class__, [
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
])
|
|
9
9
|
{% endif %}
|
|
10
10
|
{% endmacro %}
|
|
11
|
-
{% if operation_group.base_class %}
|
|
11
|
+
{% if operation_group.base_class(async_mode) %}
|
|
12
12
|
class {{ operation_group.class_name }}( {{ operation_group.pylint_disable() }}
|
|
13
|
-
{{ operation_group.base_class }}
|
|
13
|
+
{{ operation_group.base_class(async_mode) }}
|
|
14
14
|
):
|
|
15
15
|
{% else %}
|
|
16
16
|
class {{ operation_group.class_name }}: {{ operation_group.pylint_disable() }}
|
|
@@ -5,20 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
{{ imports }}
|
|
7
7
|
|
|
8
|
-
{% if code_model.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
):
|
|
8
|
+
{% if code_model.need_utils_mixin %}
|
|
9
|
+
|
|
10
|
+
TClient = TypeVar("TClient")
|
|
11
|
+
TConfig = TypeVar("TConfig")
|
|
12
|
+
|
|
13
|
+
class ClientMixinABC(ABC, Generic[TClient, TConfig]):
|
|
14
14
|
"""DO NOT use this class. It is for internal typing use only."""
|
|
15
|
-
_client:
|
|
16
|
-
_config:
|
|
15
|
+
_client: TClient
|
|
16
|
+
_config: TConfig
|
|
17
17
|
_serialize: "Serializer"
|
|
18
18
|
_deserialize: "Deserializer"
|
|
19
|
-
{% endfor %}
|
|
20
19
|
{% endif %}
|
|
21
|
-
{% if code_model.
|
|
20
|
+
{% if code_model.need_utils_abstract(client_namespace) %}
|
|
22
21
|
|
|
23
22
|
def raise_if_not_implemented(cls, abstract_methods):
|
|
24
23
|
not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))]
|
|
@@ -29,7 +28,7 @@ def raise_if_not_implemented(cls, abstract_methods):
|
|
|
29
28
|
)
|
|
30
29
|
{% endif %}
|
|
31
30
|
|
|
32
|
-
{% if code_model.
|
|
31
|
+
{% if code_model.need_utils_etag(client_namespace) %}
|
|
33
32
|
def quote_etag(etag: Optional[str]) -> Optional[str]:
|
|
34
33
|
if not etag or etag == "*":
|
|
35
34
|
return etag
|
|
@@ -59,7 +58,7 @@ def prep_if_none_match(etag: Optional[str], match_condition: Optional[MatchCondi
|
|
|
59
58
|
return "*"
|
|
60
59
|
return None
|
|
61
60
|
{% endif %}
|
|
62
|
-
{% if code_model.
|
|
61
|
+
{% if code_model.need_utils_form_data(async_mode, client_namespace) %}
|
|
63
62
|
# file-like tuple could be `(filename, IO (or bytes))` or `(filename, IO (or bytes), content_type)`
|
|
64
63
|
FileContent = Union[str, bytes, IO[str], IO[bytes]]
|
|
65
64
|
|
|
Binary file
|
|
@@ -242,16 +242,26 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
242
242
|
"""
|
|
243
243
|
return client_namespace == self.namespace
|
|
244
244
|
|
|
245
|
-
def
|
|
246
|
-
"""Whether we need to vendor code in the _vendor.py in specific namespace"""
|
|
245
|
+
def need_utils_folder(self, async_mode: bool, client_namespace: str) -> bool:
|
|
247
246
|
return (
|
|
248
|
-
self.
|
|
249
|
-
or self.
|
|
250
|
-
or self.
|
|
251
|
-
or self.need_vendored_mixin(client_namespace)
|
|
247
|
+
self.need_utils_utils(async_mode, client_namespace)
|
|
248
|
+
or self.need_utils_serialization
|
|
249
|
+
or self.options["models_mode"] == "dpg"
|
|
252
250
|
)
|
|
253
251
|
|
|
254
|
-
|
|
252
|
+
@property
|
|
253
|
+
def need_utils_serialization(self) -> bool:
|
|
254
|
+
return not self.options["client_side_validation"]
|
|
255
|
+
|
|
256
|
+
def need_utils_utils(self, async_mode: bool, client_namespace: str) -> bool:
|
|
257
|
+
return (
|
|
258
|
+
self.need_utils_form_data(async_mode, client_namespace)
|
|
259
|
+
or self.need_utils_etag(client_namespace)
|
|
260
|
+
or self.need_utils_abstract(client_namespace)
|
|
261
|
+
or self.need_utils_mixin
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def need_utils_form_data(self, async_mode: bool, client_namespace: str) -> bool:
|
|
255
265
|
return (
|
|
256
266
|
(not async_mode)
|
|
257
267
|
and self.is_top_namespace(client_namespace)
|
|
@@ -259,14 +269,15 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
259
269
|
and self.options["models_mode"] == "dpg"
|
|
260
270
|
)
|
|
261
271
|
|
|
262
|
-
def
|
|
272
|
+
def need_utils_etag(self, client_namespace: str) -> bool:
|
|
263
273
|
return self.is_top_namespace(client_namespace) and self.has_etag
|
|
264
274
|
|
|
265
|
-
def
|
|
275
|
+
def need_utils_abstract(self, client_namespace: str) -> bool:
|
|
266
276
|
return self.is_top_namespace(client_namespace) and self.has_abstract_operations
|
|
267
277
|
|
|
268
|
-
|
|
269
|
-
|
|
278
|
+
@property
|
|
279
|
+
def need_utils_mixin(self) -> bool:
|
|
280
|
+
return any(c_n for c_n in self.client_namespace_types if self.has_mixin(c_n))
|
|
270
281
|
|
|
271
282
|
def has_mixin(self, client_namespace: str) -> bool:
|
|
272
283
|
return any(c for c in self.get_clients(client_namespace) if c.has_mixin)
|