@autorest/python 6.32.3 → 6.34.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/autorest/m2r.py +1 -2
- package/autorest/m4reformatter/__init__.py +1 -2
- package/autorest/multiapi/models/imports.py +7 -2
- package/autorest/multiapi/serializers/__init__.py +5 -1
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +13 -2
- package/autorest/multiapi/templates/multiapi_utils_init.py.jinja2 +10 -0
- package/autorest/preprocess.py +1 -2
- package/generator/build/lib/pygen/codegen/models/client.py +39 -2
- package/generator/build/lib/pygen/codegen/models/code_model.py +22 -11
- package/generator/build/lib/pygen/codegen/models/enum_type.py +2 -2
- 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 +4 -3
- 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 +4 -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/client_serializer.py +32 -6
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +57 -35
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +4 -3
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +6 -1
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +2 -2
- package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +2 -8
- 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/packaging_templates/setup.py.jinja2 +12 -11
- package/generator/build/lib/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
- package/generator/component-detection-pip-report.json +4 -5
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/client.py +39 -2
- package/generator/pygen/codegen/models/code_model.py +22 -11
- package/generator/pygen/codegen/models/enum_type.py +2 -2
- 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 +4 -3
- 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 +4 -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/client_serializer.py +32 -6
- package/generator/pygen/codegen/serializers/general_serializer.py +57 -35
- package/generator/pygen/codegen/serializers/model_serializer.py +4 -3
- package/generator/pygen/codegen/serializers/parameter_serializer.py +6 -1
- package/generator/pygen/codegen/serializers/sample_serializer.py +2 -2
- package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/config.py.jinja2 +2 -8
- 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/packaging_templates/setup.py.jinja2 +12 -11
- package/generator/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
- package/generator/pygen.egg-info/SOURCES.txt +1 -1
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
package/autorest/m2r.py
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
"""An autorest MD to RST plugin.
|
|
7
|
-
"""
|
|
6
|
+
"""An autorest MD to RST plugin."""
|
|
8
7
|
import logging
|
|
9
8
|
from typing import Any, Dict, Set, Union
|
|
10
9
|
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
5
5
|
# license information.
|
|
6
6
|
# --------------------------------------------------------------------------
|
|
7
|
-
"""The modelerfour reformatter autorest plugin.
|
|
8
|
-
"""
|
|
7
|
+
"""The modelerfour reformatter autorest plugin."""
|
|
9
8
|
import re
|
|
10
9
|
import copy
|
|
11
10
|
import logging
|
|
@@ -123,9 +123,14 @@ class FileImport:
|
|
|
123
123
|
],
|
|
124
124
|
convert_list_to_tuple(name_import),
|
|
125
125
|
)
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
target_values = (
|
|
127
|
+
self._imports.setdefault(typing_section, {}).setdefault(import_type, {}).setdefault(from_section, set())
|
|
128
128
|
)
|
|
129
|
+
if isinstance(target_values, list):
|
|
130
|
+
if name_input not in target_values:
|
|
131
|
+
target_values.append(name_input)
|
|
132
|
+
else:
|
|
133
|
+
target_values.add(name_input)
|
|
129
134
|
|
|
130
135
|
def add_submodule_import(
|
|
131
136
|
self,
|
|
@@ -133,7 +133,11 @@ class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
|
133
133
|
lstrip_blocks=True,
|
|
134
134
|
)
|
|
135
135
|
self.write_file(
|
|
136
|
-
Path("
|
|
136
|
+
Path("_utils/__init__.py"),
|
|
137
|
+
self.env.get_template("multiapi_utils_init.py.jinja2").render(),
|
|
138
|
+
)
|
|
139
|
+
self.write_file(
|
|
140
|
+
Path("_utils/serialization.py"),
|
|
137
141
|
codegen_env.get_template("serialization.py.jinja2").render(
|
|
138
142
|
code_model=code_model,
|
|
139
143
|
),
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# Changes may cause incorrect behavior and will be lost if the code is
|
|
9
9
|
# regenerated.
|
|
10
10
|
# --------------------------------------------------------------------------
|
|
11
|
-
from {{ ".." if async_mode else "." }}
|
|
11
|
+
from {{ ".." if async_mode else "." }}_utils.serialization import Serializer, Deserializer
|
|
12
12
|
{% if imports %}
|
|
13
13
|
{{ imports }}
|
|
14
14
|
{% endif %}
|
|
@@ -18,6 +18,7 @@ def __init__(
|
|
|
18
18
|
{% set async_prefix = "Async" if async_mode else "" %}
|
|
19
19
|
{% set a_prefix = "a" if async_mode else "" %}
|
|
20
20
|
{% set await = "await " if async_mode else "" %}
|
|
21
|
+
{% set credential_scopes = "credential_scopes=credential_scopes, " if code_model.config.credential_scopes is not none and code_model.azure_arm else "" %}
|
|
21
22
|
# coding=utf-8
|
|
22
23
|
# --------------------------------------------------------------------------
|
|
23
24
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -77,6 +78,7 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
|
|
|
77
78
|
)
|
|
78
79
|
|
|
79
80
|
{{ method_signature()|indent }}
|
|
81
|
+
{% if not code_model.azure_arm %}
|
|
80
82
|
{% if not code_model.client.host_value %}
|
|
81
83
|
{% for parameterized_host_template, api_versions in code_model.client.parameterized_host_template_to_api_version|dictsort %}
|
|
82
84
|
{% set if_statement = "if" if loop.first else "elif" %}
|
|
@@ -86,9 +88,17 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
|
|
|
86
88
|
else:
|
|
87
89
|
raise ValueError("API version {} is not available".format(api_version))
|
|
88
90
|
{% endif %}
|
|
91
|
+
{% endif %}
|
|
89
92
|
if api_version:
|
|
90
93
|
kwargs.setdefault('api_version', api_version)
|
|
91
|
-
|
|
94
|
+
{% if credential_scopes %}
|
|
95
|
+
_cloud = kwargs.pop("cloud_setting", None) or settings.current.azure_cloud # type: ignore
|
|
96
|
+
_endpoints = get_arm_endpoints(_cloud)
|
|
97
|
+
if not base_url:
|
|
98
|
+
base_url = _endpoints["resource_manager"]
|
|
99
|
+
credential_scopes = kwargs.pop("credential_scopes", _endpoints["credential_scopes"])
|
|
100
|
+
{% endif %}
|
|
101
|
+
self._config = {{ code_model.client.name }}Configuration({{ code_model.global_parameters.call }}{{ ", " if code_model.global_parameters.call }}{{ credential_scopes }}**kwargs)
|
|
92
102
|
_policies = kwargs.pop("policies", None)
|
|
93
103
|
if _policies is None:
|
|
94
104
|
_policies = [
|
|
@@ -96,7 +106,8 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
|
|
|
96
106
|
{{ p }},
|
|
97
107
|
{% endfor %}
|
|
98
108
|
]
|
|
99
|
-
|
|
109
|
+
{% set host_variable_name = "cast(str, " + code_model.host_variable_name + ")" if credential_scopes else code_model.host_variable_name %}
|
|
110
|
+
self._client: {{ async_prefix }}{{ code_model.client.pipeline_client }} = {{ async_prefix }}{{ code_model.client.pipeline_client }}(base_url={{ host_variable_name }}, policies=_policies, **kwargs)
|
|
100
111
|
super({{ code_model.client.name }}, self).__init__(
|
|
101
112
|
api_version=api_version,
|
|
102
113
|
profile=profile
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# --------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
5
|
+
# license information.
|
|
6
|
+
#
|
|
7
|
+
# Code generated by Microsoft (R) AutoRest Code Generator.
|
|
8
|
+
# Changes may cause incorrect behavior and will be lost if the code is
|
|
9
|
+
# regenerated.
|
|
10
|
+
# --------------------------------------------------------------------------
|
package/autorest/preprocess.py
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
"""The preprocessing autorest plugin.
|
|
7
|
-
"""
|
|
6
|
+
"""The preprocessing autorest plugin."""
|
|
8
7
|
from typing import Dict, Any
|
|
9
8
|
from pygen.preprocess import PreProcessPlugin
|
|
10
9
|
from . import YamlUpdatePluginAutorest
|
|
@@ -15,7 +15,7 @@ from .request_builder import (
|
|
|
15
15
|
OverloadedRequestBuilder,
|
|
16
16
|
get_request_builder,
|
|
17
17
|
)
|
|
18
|
-
from .parameter import Parameter, ParameterMethodLocation
|
|
18
|
+
from .parameter import Parameter, ParameterMethodLocation, ParameterLocation
|
|
19
19
|
from .lro_operation import LROOperation
|
|
20
20
|
from .lro_paging_operation import LROPagingOperation
|
|
21
21
|
from ...utils import extract_original_name, NAME_LENGTH_LIMIT
|
|
@@ -54,7 +54,7 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
|
|
|
54
54
|
return self.yaml_data["name"]
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
57
|
+
class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=too-many-public-methods
|
|
58
58
|
"""Model representing our service client"""
|
|
59
59
|
|
|
60
60
|
def __init__(
|
|
@@ -79,6 +79,27 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
79
79
|
self.request_id_header_name = self.yaml_data.get("requestIdHeaderName", None)
|
|
80
80
|
self.has_etag: bool = yaml_data.get("hasEtag", False)
|
|
81
81
|
|
|
82
|
+
# update the host parameter value. In later logic, SDK will overwrite it
|
|
83
|
+
# with value from cloud_setting if users don't provide it.
|
|
84
|
+
if self.need_cloud_setting:
|
|
85
|
+
for p in self.parameters.parameters:
|
|
86
|
+
if p.location == ParameterLocation.ENDPOINT_PATH:
|
|
87
|
+
p.client_default_value = None
|
|
88
|
+
p.optional = True
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def need_cloud_setting(self) -> bool:
|
|
93
|
+
return bool(
|
|
94
|
+
self.code_model.options.get("azure_arm", False)
|
|
95
|
+
and self.credential_scopes is not None
|
|
96
|
+
and self.endpoint_parameter is not None
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def endpoint_parameter(self) -> Optional[Parameter]:
|
|
101
|
+
return next((p for p in self.parameters.parameters if p.location == ParameterLocation.ENDPOINT_PATH), None)
|
|
102
|
+
|
|
82
103
|
def _build_request_builders(
|
|
83
104
|
self,
|
|
84
105
|
) -> List[Union[RequestBuilder, OverloadedRequestBuilder]]:
|
|
@@ -233,6 +254,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
233
254
|
"Self",
|
|
234
255
|
ImportType.STDLIB,
|
|
235
256
|
)
|
|
257
|
+
if self.need_cloud_setting:
|
|
258
|
+
file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
|
|
259
|
+
file_import.add_submodule_import("azure.core.settings", "settings", ImportType.SDKCORE)
|
|
260
|
+
file_import.add_submodule_import("azure.mgmt.core.tools", "get_arm_endpoints", ImportType.SDKCORE)
|
|
236
261
|
return file_import
|
|
237
262
|
|
|
238
263
|
@property
|
|
@@ -332,6 +357,18 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
332
357
|
)
|
|
333
358
|
return file_import
|
|
334
359
|
|
|
360
|
+
@property
|
|
361
|
+
def credential_scopes(self) -> Optional[List[str]]:
|
|
362
|
+
"""Credential scopes for this client"""
|
|
363
|
+
|
|
364
|
+
if self.credential:
|
|
365
|
+
if hasattr(getattr(self.credential.type, "policy", None), "credential_scopes"):
|
|
366
|
+
return self.credential.type.policy.credential_scopes # type: ignore
|
|
367
|
+
for t in getattr(self.credential.type, "types", []):
|
|
368
|
+
if hasattr(getattr(t, "policy", None), "credential_scopes"):
|
|
369
|
+
return t.policy.credential_scopes
|
|
370
|
+
return None
|
|
371
|
+
|
|
335
372
|
@classmethod
|
|
336
373
|
def from_yaml(
|
|
337
374
|
cls,
|
|
@@ -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)
|
|
@@ -52,7 +52,7 @@ class EnumValue(BaseType):
|
|
|
52
52
|
"""The python type used for RST syntax input and type annotation."""
|
|
53
53
|
|
|
54
54
|
type_annotation = self.value_type.type_annotation(**kwargs)
|
|
55
|
-
enum_type_annotation = f"{self.
|
|
55
|
+
enum_type_annotation = f"{self.enum_type.client_namespace}.models.{self.name}"
|
|
56
56
|
return f"{type_annotation} or ~{enum_type_annotation}"
|
|
57
57
|
|
|
58
58
|
def get_json_template_representation(
|
|
@@ -198,7 +198,7 @@ class EnumType(BaseType):
|
|
|
198
198
|
"""The python type used for RST syntax input and type annotation."""
|
|
199
199
|
if self.code_model.options["models_mode"]:
|
|
200
200
|
type_annotation = self.value_type.type_annotation(**kwargs)
|
|
201
|
-
enum_type_annotation = f"{self.
|
|
201
|
+
enum_type_annotation = f"{self.client_namespace}.models.{self.name}"
|
|
202
202
|
return f"{type_annotation} or ~{enum_type_annotation}"
|
|
203
203
|
return self.value_type.type_annotation(**kwargs)
|
|
204
204
|
|
|
@@ -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
|
)
|
|
@@ -292,7 +292,7 @@ class GeneratedModelType(ModelType):
|
|
|
292
292
|
|
|
293
293
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
294
294
|
type_annotation = self.type_annotation(need_model_alias=False, skip_quote=True, **kwargs)
|
|
295
|
-
return f"~{self.
|
|
295
|
+
return f"~{self.client_namespace}.models.{type_annotation}"
|
|
296
296
|
|
|
297
297
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
298
298
|
return self.name
|
|
@@ -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
|
)
|
|
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
|
|
|
357
357
|
)
|
|
358
358
|
if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
|
|
359
359
|
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
|
+
# for optional path parameter, we need to use keyword only
|
|
361
|
+
if self.location == ParameterLocation.PATH and self.optional:
|
|
362
|
+
return ParameterMethodLocation.KEYWORD_ONLY
|
|
360
363
|
return ParameterMethodLocation.POSITIONAL
|
|
361
364
|
|
|
362
365
|
@classmethod
|
|
@@ -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}",
|