@azure-tools/typespec-python 0.24.2 → 0.25.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/dist/src/code-model.d.ts.map +1 -1
- package/dist/src/code-model.js +1 -4
- package/dist/src/code-model.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +5 -4
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/external-process.d.ts +0 -9
- package/dist/src/external-process.d.ts.map +1 -1
- package/dist/src/external-process.js +1 -25
- package/dist/src/external-process.js.map +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -1
- package/generator/LICENSE +21 -0
- package/generator/README.md +1 -0
- package/generator/dev_requirements.txt +5 -0
- package/generator/pygen/__init__.py +107 -0
- package/generator/pygen/_version.py +7 -0
- package/generator/pygen/black.py +71 -0
- package/generator/pygen/codegen/__init__.py +334 -0
- package/generator/pygen/codegen/_utils.py +16 -0
- package/generator/pygen/codegen/models/__init__.py +202 -0
- package/generator/pygen/codegen/models/base.py +186 -0
- package/generator/pygen/codegen/models/base_builder.py +119 -0
- package/generator/pygen/codegen/models/client.py +429 -0
- package/generator/pygen/codegen/models/code_model.py +239 -0
- package/generator/pygen/codegen/models/combined_type.py +149 -0
- package/generator/pygen/codegen/models/constant_type.py +129 -0
- package/generator/pygen/codegen/models/credential_types.py +221 -0
- package/generator/pygen/codegen/models/dictionary_type.py +127 -0
- package/generator/pygen/codegen/models/enum_type.py +238 -0
- package/generator/pygen/codegen/models/imports.py +291 -0
- package/generator/pygen/codegen/models/list_type.py +143 -0
- package/generator/pygen/codegen/models/lro_operation.py +143 -0
- package/generator/pygen/codegen/models/lro_paging_operation.py +32 -0
- package/generator/pygen/codegen/models/model_type.py +361 -0
- package/generator/pygen/codegen/models/operation.py +518 -0
- package/generator/pygen/codegen/models/operation_group.py +184 -0
- package/generator/pygen/codegen/models/paging_operation.py +156 -0
- package/generator/pygen/codegen/models/parameter.py +402 -0
- package/generator/pygen/codegen/models/parameter_list.py +390 -0
- package/generator/pygen/codegen/models/primitive_types.py +626 -0
- package/generator/pygen/codegen/models/property.py +175 -0
- package/generator/pygen/codegen/models/request_builder.py +189 -0
- package/generator/pygen/codegen/models/request_builder_parameter.py +115 -0
- package/generator/pygen/codegen/models/response.py +348 -0
- package/generator/pygen/codegen/models/utils.py +23 -0
- package/generator/pygen/codegen/serializers/__init__.py +570 -0
- package/generator/pygen/codegen/serializers/base_serializer.py +21 -0
- package/generator/pygen/codegen/serializers/builder_serializer.py +1454 -0
- package/generator/pygen/codegen/serializers/client_serializer.py +295 -0
- package/generator/pygen/codegen/serializers/enum_serializer.py +15 -0
- package/generator/pygen/codegen/serializers/general_serializer.py +212 -0
- package/generator/pygen/codegen/serializers/import_serializer.py +127 -0
- package/generator/pygen/codegen/serializers/metadata_serializer.py +198 -0
- package/generator/pygen/codegen/serializers/model_init_serializer.py +33 -0
- package/generator/pygen/codegen/serializers/model_serializer.py +287 -0
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +44 -0
- package/generator/pygen/codegen/serializers/parameter_serializer.py +221 -0
- package/generator/pygen/codegen/serializers/patch_serializer.py +19 -0
- package/generator/pygen/codegen/serializers/request_builders_serializer.py +52 -0
- package/generator/pygen/codegen/serializers/sample_serializer.py +163 -0
- package/generator/pygen/codegen/serializers/test_serializer.py +287 -0
- package/generator/pygen/codegen/serializers/types_serializer.py +31 -0
- package/generator/pygen/codegen/serializers/utils.py +68 -0
- package/generator/pygen/codegen/templates/client.py.jinja2 +37 -0
- package/generator/pygen/codegen/templates/client_container.py.jinja2 +12 -0
- package/generator/pygen/codegen/templates/config.py.jinja2 +73 -0
- package/generator/pygen/codegen/templates/config_container.py.jinja2 +16 -0
- package/generator/pygen/codegen/templates/conftest.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/enum.py.jinja2 +13 -0
- package/generator/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
- package/generator/pygen/codegen/templates/init.py.jinja2 +24 -0
- package/generator/pygen/codegen/templates/keywords.jinja2 +19 -0
- package/generator/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
- package/generator/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
- package/generator/pygen/codegen/templates/macros.jinja2 +12 -0
- package/generator/pygen/codegen/templates/metadata.json.jinja2 +167 -0
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +899 -0
- package/generator/pygen/codegen/templates/model_container.py.jinja2 +13 -0
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +92 -0
- package/generator/pygen/codegen/templates/model_init.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
- package/generator/pygen/codegen/templates/operation.py.jinja2 +21 -0
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +20 -0
- package/generator/pygen/codegen/templates/operation_tools.jinja2 +74 -0
- package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
- package/generator/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
- package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
- package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
- package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
- package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
- package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
- package/generator/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
- package/generator/pygen/codegen/templates/patch.py.jinja2 +19 -0
- package/generator/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
- package/generator/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
- package/generator/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
- package/generator/pygen/codegen/templates/sample.py.jinja2 +44 -0
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +2006 -0
- package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
- package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
- package/generator/pygen/codegen/templates/types.py.jinja2 +8 -0
- package/generator/pygen/codegen/templates/validation.py.jinja2 +38 -0
- package/generator/pygen/codegen/templates/vendor.py.jinja2 +98 -0
- package/generator/pygen/codegen/templates/version.py.jinja2 +4 -0
- package/generator/pygen/m2r.py +65 -0
- package/generator/pygen/postprocess/__init__.py +183 -0
- package/generator/pygen/postprocess/get_all.py +19 -0
- package/generator/pygen/postprocess/venvtools.py +77 -0
- package/generator/pygen/preprocess/__init__.py +503 -0
- package/generator/pygen/preprocess/helpers.py +27 -0
- package/generator/pygen/preprocess/python_mappings.py +222 -0
- package/generator/pygen/utils.py +149 -0
- package/generator/pygen.egg-info/PKG-INFO +25 -0
- package/generator/pygen.egg-info/SOURCES.txt +66 -0
- package/generator/pygen.egg-info/dependency_links.txt +1 -0
- package/generator/pygen.egg-info/requires.txt +4 -0
- package/generator/pygen.egg-info/top_level.txt +1 -0
- package/generator/requirements.txt +12 -0
- package/generator/setup.py +55 -0
- package/package.json +10 -7
- package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/scripts/install.py +49 -0
- package/scripts/prepare.py +38 -0
- package/scripts/run-python3.cjs +22 -0
- package/scripts/run_tsp.py +40 -0
- package/scripts/system-requirements.cjs +180 -0
- package/scripts/venvtools.py +81 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from itertools import chain
|
|
7
|
+
from typing import (
|
|
8
|
+
Dict,
|
|
9
|
+
List,
|
|
10
|
+
Any,
|
|
11
|
+
Optional,
|
|
12
|
+
Union,
|
|
13
|
+
TYPE_CHECKING,
|
|
14
|
+
Generic,
|
|
15
|
+
TypeVar,
|
|
16
|
+
cast,
|
|
17
|
+
Sequence,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .request_builder_parameter import RequestBuilderParameter
|
|
21
|
+
|
|
22
|
+
from .utils import OrderedSet, add_to_pylint_disable, NAME_LENGTH_LIMIT
|
|
23
|
+
from .base_builder import BaseBuilder
|
|
24
|
+
from .imports import FileImport, ImportType, TypingSection
|
|
25
|
+
from .response import (
|
|
26
|
+
Response,
|
|
27
|
+
PagingResponse,
|
|
28
|
+
LROResponse,
|
|
29
|
+
LROPagingResponse,
|
|
30
|
+
get_response,
|
|
31
|
+
)
|
|
32
|
+
from .parameter import (
|
|
33
|
+
BodyParameter,
|
|
34
|
+
Parameter,
|
|
35
|
+
ParameterLocation,
|
|
36
|
+
)
|
|
37
|
+
from .parameter_list import ParameterList
|
|
38
|
+
from .model_type import ModelType
|
|
39
|
+
from .base import BaseType
|
|
40
|
+
from .request_builder import OverloadedRequestBuilder, RequestBuilder
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from .code_model import CodeModel
|
|
44
|
+
from .client import Client
|
|
45
|
+
from . import OperationType
|
|
46
|
+
|
|
47
|
+
ResponseType = TypeVar(
|
|
48
|
+
"ResponseType",
|
|
49
|
+
bound=Union[Response, PagingResponse, LROResponse, LROPagingResponse],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def is_internal(target: Optional[BaseType]) -> bool:
|
|
54
|
+
return isinstance(target, ModelType) and target.base == "dpg" and target.internal
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class OperationBase( # pylint: disable=too-many-public-methods,too-many-instance-attributes
|
|
58
|
+
Generic[ResponseType], BaseBuilder[ParameterList, List["Operation"]]
|
|
59
|
+
):
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
yaml_data: Dict[str, Any],
|
|
63
|
+
code_model: "CodeModel",
|
|
64
|
+
client: "Client",
|
|
65
|
+
name: str,
|
|
66
|
+
request_builder: Union[RequestBuilder, OverloadedRequestBuilder],
|
|
67
|
+
parameters: ParameterList,
|
|
68
|
+
responses: List[ResponseType],
|
|
69
|
+
exceptions: List[Response],
|
|
70
|
+
*,
|
|
71
|
+
overloads: Optional[List["Operation"]] = None,
|
|
72
|
+
) -> None:
|
|
73
|
+
super().__init__(
|
|
74
|
+
code_model=code_model,
|
|
75
|
+
client=client,
|
|
76
|
+
yaml_data=yaml_data,
|
|
77
|
+
name=name,
|
|
78
|
+
parameters=parameters,
|
|
79
|
+
overloads=overloads,
|
|
80
|
+
)
|
|
81
|
+
self.overloads: List["Operation"] = overloads or []
|
|
82
|
+
self.responses = responses
|
|
83
|
+
self.request_builder = request_builder
|
|
84
|
+
self.deprecated = False
|
|
85
|
+
self.exceptions = exceptions
|
|
86
|
+
self.is_lro_initial_operation: bool = self.yaml_data.get("isLroInitialOperation", False)
|
|
87
|
+
self.include_documentation: bool = not self.is_lro_initial_operation
|
|
88
|
+
self.internal: bool = self.yaml_data.get("internal", False)
|
|
89
|
+
if self.internal:
|
|
90
|
+
self.name = "_" + self.name
|
|
91
|
+
self.has_etag: bool = self.yaml_data.get("hasEtag", False)
|
|
92
|
+
self.cross_language_definition_id: Optional[str] = self.yaml_data.get("crossLanguageDefinitionId")
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def stream_value(self) -> Union[str, bool]:
|
|
96
|
+
return (
|
|
97
|
+
f'kwargs.pop("stream", {self.has_stream_response})'
|
|
98
|
+
if self.expose_stream_keyword and self.has_response_body
|
|
99
|
+
else self.has_stream_response
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def has_form_data_body(self):
|
|
104
|
+
return self.parameters.has_form_data_body
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def expose_stream_keyword(self) -> bool:
|
|
108
|
+
return self.yaml_data.get("exposeStreamKeyword", False)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def operation_type(self) -> str:
|
|
112
|
+
return "operation"
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def has_optional_return_type(self) -> bool:
|
|
116
|
+
"""Has optional return type if there are multiple successful response types where some have
|
|
117
|
+
bodies and some are None
|
|
118
|
+
"""
|
|
119
|
+
# means if we have at least one successful response with a body and one without
|
|
120
|
+
successful_response_with_body = any(r for r in self.responses if r.type)
|
|
121
|
+
successful_response_without_body = any(r for r in self.responses if not r.type)
|
|
122
|
+
return successful_response_with_body and successful_response_without_body
|
|
123
|
+
|
|
124
|
+
def response_type_annotation(self, **kwargs) -> str:
|
|
125
|
+
if self.code_model.options["head_as_boolean"] and self.request_builder.method.lower() == "head":
|
|
126
|
+
return "bool"
|
|
127
|
+
response_type_annotations: OrderedSet[str] = {
|
|
128
|
+
response.type_annotation(**kwargs): None for response in self.responses if response.type
|
|
129
|
+
}
|
|
130
|
+
response_str = ", ".join(response_type_annotations.keys())
|
|
131
|
+
if len(response_type_annotations) > 1:
|
|
132
|
+
return f"Union[{response_str}]"
|
|
133
|
+
if self.has_optional_return_type:
|
|
134
|
+
return f"Optional[{response_str}]"
|
|
135
|
+
if self.responses:
|
|
136
|
+
return self.responses[0].type_annotation(**kwargs)
|
|
137
|
+
return "None"
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def pylint_disable(self) -> str:
|
|
141
|
+
retval: str = ""
|
|
142
|
+
if self.response_type_annotation(async_mode=False) == "None":
|
|
143
|
+
# doesn't matter if it's async or not
|
|
144
|
+
retval = add_to_pylint_disable(retval, "inconsistent-return-statements")
|
|
145
|
+
try:
|
|
146
|
+
if any(is_internal(r.type) for r in self.responses) or is_internal(self.parameters.body_parameter.type):
|
|
147
|
+
retval = add_to_pylint_disable(retval, "protected-access")
|
|
148
|
+
except ValueError:
|
|
149
|
+
pass
|
|
150
|
+
if len(self.name) > NAME_LENGTH_LIMIT:
|
|
151
|
+
retval = add_to_pylint_disable(retval, "name-too-long")
|
|
152
|
+
return retval
|
|
153
|
+
|
|
154
|
+
def cls_type_annotation(self, *, async_mode: bool) -> str:
|
|
155
|
+
if self.request_builder.method.lower() == "head" and self.code_model.options["head_as_boolean"]:
|
|
156
|
+
return "ClsType[None]"
|
|
157
|
+
return f"ClsType[{self.response_type_annotation(async_mode=async_mode)}]"
|
|
158
|
+
|
|
159
|
+
def _response_docstring_helper(self, attr_name: str, **kwargs: Any) -> str:
|
|
160
|
+
responses_with_body = [r for r in self.responses if r.type]
|
|
161
|
+
if self.request_builder.method.lower() == "head" and self.code_model.options["head_as_boolean"]:
|
|
162
|
+
return "bool"
|
|
163
|
+
if responses_with_body:
|
|
164
|
+
response_docstring_values: OrderedSet[str] = {
|
|
165
|
+
getattr(response, attr_name)(**kwargs): None for response in responses_with_body
|
|
166
|
+
}
|
|
167
|
+
retval = " or ".join(response_docstring_values.keys())
|
|
168
|
+
if self.has_optional_return_type:
|
|
169
|
+
retval += " or None"
|
|
170
|
+
return retval
|
|
171
|
+
if self.responses:
|
|
172
|
+
return getattr(self.responses[0], attr_name)(**kwargs)
|
|
173
|
+
return "None"
|
|
174
|
+
|
|
175
|
+
def response_docstring_text(self, **kwargs) -> str:
|
|
176
|
+
retval = self._response_docstring_helper("docstring_text", **kwargs)
|
|
177
|
+
if not self.code_model.options["version_tolerant"]:
|
|
178
|
+
retval += " or the result of cls(response)"
|
|
179
|
+
if self.code_model.options["models_mode"] == "dpg" and any(
|
|
180
|
+
isinstance(r.type, ModelType) for r in self.responses
|
|
181
|
+
):
|
|
182
|
+
r = next(r for r in self.responses if isinstance(r.type, ModelType))
|
|
183
|
+
item_type = getattr(r, "item_type", getattr(r, "type"))
|
|
184
|
+
if item_type:
|
|
185
|
+
type_name = item_type.docstring_text(**kwargs)
|
|
186
|
+
retval += f". The {type_name} is compatible with MutableMapping"
|
|
187
|
+
return retval
|
|
188
|
+
|
|
189
|
+
def response_docstring_type(self, **kwargs) -> str:
|
|
190
|
+
return self._response_docstring_helper("docstring_type", **kwargs)
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def has_response_body(self) -> bool:
|
|
194
|
+
"""Tell if at least one response has a body."""
|
|
195
|
+
return any(response.type for response in self.responses)
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def any_response_has_headers(self) -> bool:
|
|
199
|
+
return any(response.headers for response in self.responses)
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def default_error_deserialization(self) -> Optional[str]:
|
|
203
|
+
default_exceptions = [e for e in self.exceptions if "default" in e.status_codes and e.type]
|
|
204
|
+
if not default_exceptions:
|
|
205
|
+
return None
|
|
206
|
+
excep_schema = default_exceptions[0].type
|
|
207
|
+
if isinstance(excep_schema, ModelType):
|
|
208
|
+
return excep_schema.type_annotation(skip_quote=True)
|
|
209
|
+
# in this case, it's just an AnyType
|
|
210
|
+
return "'object'"
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def non_default_errors(self) -> List[Response]:
|
|
214
|
+
return [e for e in self.exceptions if "default" not in e.status_codes]
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def non_default_error_status_codes(self) -> List[Union[str, int]]:
|
|
218
|
+
"""Actually returns all of the status codes from exceptions (besides default)"""
|
|
219
|
+
return list(chain.from_iterable([error.status_codes for error in self.non_default_errors]))
|
|
220
|
+
|
|
221
|
+
def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport: # pylint: disable=unused-argument
|
|
222
|
+
file_import = FileImport(self.code_model)
|
|
223
|
+
file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
224
|
+
|
|
225
|
+
response_types = [r.type_annotation(async_mode=async_mode, operation=self) for r in self.responses if r.type]
|
|
226
|
+
if len(set(response_types)) > 1:
|
|
227
|
+
file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
228
|
+
if self.added_on:
|
|
229
|
+
file_import.add_submodule_import(
|
|
230
|
+
f"{'.' if async_mode else ''}.._validation",
|
|
231
|
+
"api_version_validation",
|
|
232
|
+
ImportType.LOCAL,
|
|
233
|
+
)
|
|
234
|
+
return file_import
|
|
235
|
+
|
|
236
|
+
def imports_for_multiapi(self, async_mode: bool, **kwargs: Any) -> FileImport:
|
|
237
|
+
if self.abstract:
|
|
238
|
+
return FileImport(self.code_model)
|
|
239
|
+
file_import = self._imports_shared(async_mode, **kwargs)
|
|
240
|
+
for param in self.parameters.method:
|
|
241
|
+
file_import.merge(
|
|
242
|
+
param.imports_for_multiapi(
|
|
243
|
+
async_mode,
|
|
244
|
+
operation=self,
|
|
245
|
+
**kwargs,
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
for response in self.responses:
|
|
249
|
+
file_import.merge(response.imports_for_multiapi(async_mode=async_mode, operation=self, **kwargs))
|
|
250
|
+
if self.code_model.options["models_mode"]:
|
|
251
|
+
for exception in self.exceptions:
|
|
252
|
+
file_import.merge(exception.imports_for_multiapi(async_mode=async_mode, operation=self, **kwargs))
|
|
253
|
+
return file_import
|
|
254
|
+
|
|
255
|
+
@staticmethod
|
|
256
|
+
def has_kwargs_to_pop_with_default(
|
|
257
|
+
kwargs_to_pop: List[
|
|
258
|
+
Union[
|
|
259
|
+
Parameter,
|
|
260
|
+
RequestBuilderParameter,
|
|
261
|
+
BodyParameter,
|
|
262
|
+
]
|
|
263
|
+
],
|
|
264
|
+
location: ParameterLocation,
|
|
265
|
+
) -> bool:
|
|
266
|
+
return any(
|
|
267
|
+
(kwarg.client_default_value or kwarg.optional) and kwarg.location == location for kwarg in kwargs_to_pop
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def need_validation(self) -> bool:
|
|
272
|
+
"""Whether we need parameter / operation validation. For API version."""
|
|
273
|
+
return bool(self.added_on) or any(p for p in self.parameters if p.added_on)
|
|
274
|
+
|
|
275
|
+
def get_request_builder_import(
|
|
276
|
+
self,
|
|
277
|
+
request_builder: Union[RequestBuilder, OverloadedRequestBuilder],
|
|
278
|
+
async_mode: bool,
|
|
279
|
+
) -> FileImport:
|
|
280
|
+
"""Helper method to get a request builder import."""
|
|
281
|
+
file_import = FileImport(self.code_model)
|
|
282
|
+
if self.code_model.options["builders_visibility"] != "embedded":
|
|
283
|
+
group_name = request_builder.group_name
|
|
284
|
+
rest_import_path = "..." if async_mode else ".."
|
|
285
|
+
if group_name:
|
|
286
|
+
file_import.add_submodule_import(
|
|
287
|
+
f"{rest_import_path}{self.code_model.rest_layer_name}",
|
|
288
|
+
group_name,
|
|
289
|
+
import_type=ImportType.LOCAL,
|
|
290
|
+
alias=f"rest_{group_name}",
|
|
291
|
+
)
|
|
292
|
+
else:
|
|
293
|
+
file_import.add_submodule_import(
|
|
294
|
+
rest_import_path,
|
|
295
|
+
self.code_model.rest_layer_name,
|
|
296
|
+
import_type=ImportType.LOCAL,
|
|
297
|
+
alias="rest",
|
|
298
|
+
)
|
|
299
|
+
if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
|
|
300
|
+
file_import.add_submodule_import(
|
|
301
|
+
f"...{self.code_model.operations_folder_name}.{self.filename}",
|
|
302
|
+
request_builder.name,
|
|
303
|
+
import_type=ImportType.LOCAL,
|
|
304
|
+
)
|
|
305
|
+
return file_import
|
|
306
|
+
|
|
307
|
+
def imports( # pylint: disable=too-many-branches, disable=too-many-statements
|
|
308
|
+
self, async_mode: bool, **kwargs: Any
|
|
309
|
+
) -> FileImport:
|
|
310
|
+
if self.abstract:
|
|
311
|
+
return FileImport(self.code_model)
|
|
312
|
+
file_import = self._imports_shared(async_mode, **kwargs)
|
|
313
|
+
|
|
314
|
+
for param in self.parameters.method:
|
|
315
|
+
file_import.merge(
|
|
316
|
+
param.imports(
|
|
317
|
+
async_mode,
|
|
318
|
+
operation=self,
|
|
319
|
+
**kwargs,
|
|
320
|
+
)
|
|
321
|
+
)
|
|
322
|
+
for response in self.responses:
|
|
323
|
+
file_import.merge(response.imports(async_mode=async_mode, operation=self, **kwargs))
|
|
324
|
+
if self.code_model.options["models_mode"]:
|
|
325
|
+
for exception in self.exceptions:
|
|
326
|
+
file_import.merge(exception.imports(async_mode=async_mode, **kwargs))
|
|
327
|
+
|
|
328
|
+
if self.parameters.has_body and self.parameters.body_parameter.flattened:
|
|
329
|
+
file_import.merge(self.parameters.body_parameter.type.imports(operation=self, **kwargs))
|
|
330
|
+
if not async_mode:
|
|
331
|
+
for param in self.parameters.headers:
|
|
332
|
+
if param.wire_name.lower() == "repeatability-request-id":
|
|
333
|
+
file_import.add_import("uuid", ImportType.STDLIB)
|
|
334
|
+
elif param.wire_name.lower() == "repeatability-first-sent":
|
|
335
|
+
file_import.add_import("datetime", ImportType.STDLIB)
|
|
336
|
+
|
|
337
|
+
# Exceptions
|
|
338
|
+
errors = [
|
|
339
|
+
"map_error",
|
|
340
|
+
"HttpResponseError",
|
|
341
|
+
"ClientAuthenticationError",
|
|
342
|
+
"ResourceNotFoundError",
|
|
343
|
+
"ResourceExistsError",
|
|
344
|
+
"ResourceNotModifiedError",
|
|
345
|
+
]
|
|
346
|
+
for error in errors:
|
|
347
|
+
file_import.add_submodule_import("exceptions", error, ImportType.SDKCORE)
|
|
348
|
+
if self.code_model.options["azure_arm"]:
|
|
349
|
+
file_import.add_submodule_import("azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.SDKCORE)
|
|
350
|
+
file_import.add_submodule_import(
|
|
351
|
+
"typing",
|
|
352
|
+
"Type",
|
|
353
|
+
ImportType.STDLIB,
|
|
354
|
+
)
|
|
355
|
+
file_import.add_mutable_mapping_import()
|
|
356
|
+
if self.non_default_error_status_codes:
|
|
357
|
+
file_import.add_submodule_import(
|
|
358
|
+
"typing",
|
|
359
|
+
"cast",
|
|
360
|
+
ImportType.STDLIB,
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
if self.has_kwargs_to_pop_with_default(
|
|
364
|
+
self.parameters.kwargs_to_pop, ParameterLocation.HEADER # type: ignore
|
|
365
|
+
) or self.has_kwargs_to_pop_with_default(
|
|
366
|
+
self.parameters.kwargs_to_pop, ParameterLocation.QUERY # type: ignore
|
|
367
|
+
):
|
|
368
|
+
file_import.add_submodule_import(
|
|
369
|
+
"utils",
|
|
370
|
+
"case_insensitive_dict",
|
|
371
|
+
ImportType.SDKCORE,
|
|
372
|
+
)
|
|
373
|
+
if self.deprecated:
|
|
374
|
+
file_import.add_import("warnings", ImportType.STDLIB)
|
|
375
|
+
|
|
376
|
+
relative_path = "..." if async_mode else ".."
|
|
377
|
+
if self.has_etag:
|
|
378
|
+
file_import.add_submodule_import(
|
|
379
|
+
"exceptions",
|
|
380
|
+
"ResourceModifiedError",
|
|
381
|
+
ImportType.SDKCORE,
|
|
382
|
+
)
|
|
383
|
+
if not async_mode:
|
|
384
|
+
file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_match", ImportType.LOCAL)
|
|
385
|
+
file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_none_match", ImportType.LOCAL)
|
|
386
|
+
if async_mode:
|
|
387
|
+
file_import.add_submodule_import(
|
|
388
|
+
"rest",
|
|
389
|
+
"AsyncHttpResponse",
|
|
390
|
+
ImportType.SDKCORE,
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
file_import.add_submodule_import(
|
|
394
|
+
"rest",
|
|
395
|
+
"HttpResponse",
|
|
396
|
+
ImportType.SDKCORE,
|
|
397
|
+
)
|
|
398
|
+
if self.code_model.options["builders_visibility"] == "embedded" and not async_mode:
|
|
399
|
+
file_import.merge(self.request_builder.imports())
|
|
400
|
+
file_import.add_submodule_import(
|
|
401
|
+
f"{'' if self.code_model.is_azure_flavor else 'runtime.'}pipeline",
|
|
402
|
+
"PipelineResponse",
|
|
403
|
+
ImportType.SDKCORE,
|
|
404
|
+
)
|
|
405
|
+
file_import.add_submodule_import("rest", "HttpRequest", ImportType.SDKCORE)
|
|
406
|
+
file_import.add_submodule_import("typing", "Callable", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
407
|
+
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
408
|
+
file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
409
|
+
file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
410
|
+
if self.code_model.options["tracing"] and self.want_tracing and not async_mode:
|
|
411
|
+
file_import.add_submodule_import(
|
|
412
|
+
"azure.core.tracing.decorator",
|
|
413
|
+
"distributed_trace",
|
|
414
|
+
ImportType.SDKCORE,
|
|
415
|
+
)
|
|
416
|
+
file_import.merge(self.get_request_builder_import(self.request_builder, async_mode))
|
|
417
|
+
if self.overloads:
|
|
418
|
+
file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
|
|
419
|
+
if self.non_default_errors and self.code_model.options["models_mode"] == "dpg":
|
|
420
|
+
file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
|
|
421
|
+
return file_import
|
|
422
|
+
|
|
423
|
+
def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType:
|
|
424
|
+
try:
|
|
425
|
+
return next(r for r in self.responses if status_code in r.status_codes)
|
|
426
|
+
except StopIteration as exc:
|
|
427
|
+
raise ValueError(f"Incorrect status code {status_code}, operation {self.name}") from exc
|
|
428
|
+
|
|
429
|
+
@property
|
|
430
|
+
def success_status_codes(self) -> Sequence[Union[str, int]]:
|
|
431
|
+
"""The list of all successfull status code."""
|
|
432
|
+
return sorted([code for response in self.responses for code in response.status_codes])
|
|
433
|
+
|
|
434
|
+
@property
|
|
435
|
+
def filename(self) -> str:
|
|
436
|
+
basename = self.group_name
|
|
437
|
+
if basename == "":
|
|
438
|
+
# in a mixin
|
|
439
|
+
basename = self.code_model.clients[0].legacy_filename
|
|
440
|
+
|
|
441
|
+
if basename == "operations" or self.code_model.options["combine_operation_files"]:
|
|
442
|
+
return "_operations"
|
|
443
|
+
return f"_{basename}_operations"
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def has_stream_response(self) -> bool:
|
|
447
|
+
return any(r.is_stream_response for r in self.responses)
|
|
448
|
+
|
|
449
|
+
@classmethod
|
|
450
|
+
def get_request_builder(cls, yaml_data: Dict[str, Any], client: "Client"):
|
|
451
|
+
return client.lookup_request_builder(id(yaml_data))
|
|
452
|
+
|
|
453
|
+
@classmethod
|
|
454
|
+
def from_yaml(
|
|
455
|
+
cls,
|
|
456
|
+
yaml_data: Dict[str, Any],
|
|
457
|
+
code_model: "CodeModel",
|
|
458
|
+
client: "Client",
|
|
459
|
+
):
|
|
460
|
+
name = yaml_data["name"]
|
|
461
|
+
request_builder = cls.get_request_builder(yaml_data, client)
|
|
462
|
+
responses = [cast(ResponseType, get_response(r, code_model)) for r in yaml_data["responses"]]
|
|
463
|
+
exceptions = [Response.from_yaml(e, code_model) for e in yaml_data["exceptions"]]
|
|
464
|
+
parameter_list = ParameterList.from_yaml(yaml_data, code_model)
|
|
465
|
+
overloads = [cls.from_yaml(overload, code_model, client) for overload in yaml_data.get("overloads", [])]
|
|
466
|
+
|
|
467
|
+
return cls(
|
|
468
|
+
yaml_data=yaml_data,
|
|
469
|
+
code_model=code_model,
|
|
470
|
+
client=client,
|
|
471
|
+
request_builder=request_builder,
|
|
472
|
+
name=name,
|
|
473
|
+
parameters=parameter_list,
|
|
474
|
+
overloads=overloads,
|
|
475
|
+
responses=responses,
|
|
476
|
+
exceptions=exceptions,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
class Operation(OperationBase[Response]):
|
|
481
|
+
def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
|
|
482
|
+
file_import = super().imports(async_mode, **kwargs)
|
|
483
|
+
if self.abstract:
|
|
484
|
+
return file_import
|
|
485
|
+
if async_mode and self.code_model.options["tracing"] and self.want_tracing:
|
|
486
|
+
file_import.add_submodule_import(
|
|
487
|
+
"azure.core.tracing.decorator_async",
|
|
488
|
+
"distributed_trace_async",
|
|
489
|
+
ImportType.SDKCORE,
|
|
490
|
+
)
|
|
491
|
+
if self.has_response_body and not self.has_optional_return_type and not self.code_model.options["models_mode"]:
|
|
492
|
+
file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
|
|
493
|
+
relative_path = "..." if async_mode else ".."
|
|
494
|
+
if self.code_model.options["models_mode"] == "dpg":
|
|
495
|
+
if self.parameters.has_body:
|
|
496
|
+
if not self.has_form_data_body:
|
|
497
|
+
file_import.add_submodule_import(
|
|
498
|
+
f"{relative_path}_model_base",
|
|
499
|
+
"SdkJSONEncoder",
|
|
500
|
+
ImportType.LOCAL,
|
|
501
|
+
)
|
|
502
|
+
file_import.add_import("json", ImportType.STDLIB)
|
|
503
|
+
if self.default_error_deserialization or any(r.type for r in self.responses):
|
|
504
|
+
file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
|
|
505
|
+
|
|
506
|
+
return file_import
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def get_operation(yaml_data: Dict[str, Any], code_model: "CodeModel", client: "Client") -> "OperationType":
|
|
510
|
+
if yaml_data["discriminator"] == "lropaging":
|
|
511
|
+
from .lro_paging_operation import LROPagingOperation as OperationCls
|
|
512
|
+
elif yaml_data["discriminator"] == "lro":
|
|
513
|
+
from .lro_operation import LROOperation as OperationCls # type: ignore
|
|
514
|
+
elif yaml_data["discriminator"] == "paging":
|
|
515
|
+
from .paging_operation import PagingOperation as OperationCls # type: ignore
|
|
516
|
+
else:
|
|
517
|
+
from . import Operation as OperationCls # type: ignore
|
|
518
|
+
return OperationCls.from_yaml(yaml_data, code_model, client)
|