@azure-tools/typespec-python 0.24.3 → 0.26.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.
Files changed (137) hide show
  1. package/dist/src/code-model.d.ts.map +1 -1
  2. package/dist/src/code-model.js +3 -6
  3. package/dist/src/code-model.js.map +1 -1
  4. package/dist/src/emitter.d.ts.map +1 -1
  5. package/dist/src/emitter.js +6 -5
  6. package/dist/src/emitter.js.map +1 -1
  7. package/dist/src/external-process.d.ts +0 -9
  8. package/dist/src/external-process.d.ts.map +1 -1
  9. package/dist/src/external-process.js +1 -25
  10. package/dist/src/external-process.js.map +1 -1
  11. package/dist/src/http.d.ts.map +1 -1
  12. package/dist/src/http.js +2 -1
  13. package/dist/src/http.js.map +1 -1
  14. package/dist/src/types.d.ts.map +1 -1
  15. package/dist/src/types.js +2 -0
  16. package/dist/src/types.js.map +1 -1
  17. package/dist/src/utils.js +1 -1
  18. package/dist/src/utils.js.map +1 -1
  19. package/generator/LICENSE +21 -0
  20. package/generator/README.md +1 -0
  21. package/generator/dev_requirements.txt +5 -0
  22. package/generator/pygen/__init__.py +107 -0
  23. package/generator/pygen/_version.py +7 -0
  24. package/generator/pygen/black.py +71 -0
  25. package/generator/pygen/codegen/__init__.py +338 -0
  26. package/generator/pygen/codegen/_utils.py +16 -0
  27. package/generator/pygen/codegen/models/__init__.py +202 -0
  28. package/generator/pygen/codegen/models/base.py +186 -0
  29. package/generator/pygen/codegen/models/base_builder.py +119 -0
  30. package/generator/pygen/codegen/models/client.py +430 -0
  31. package/generator/pygen/codegen/models/code_model.py +239 -0
  32. package/generator/pygen/codegen/models/combined_type.py +149 -0
  33. package/generator/pygen/codegen/models/constant_type.py +129 -0
  34. package/generator/pygen/codegen/models/credential_types.py +221 -0
  35. package/generator/pygen/codegen/models/dictionary_type.py +127 -0
  36. package/generator/pygen/codegen/models/enum_type.py +238 -0
  37. package/generator/pygen/codegen/models/imports.py +291 -0
  38. package/generator/pygen/codegen/models/list_type.py +143 -0
  39. package/generator/pygen/codegen/models/lro_operation.py +143 -0
  40. package/generator/pygen/codegen/models/lro_paging_operation.py +32 -0
  41. package/generator/pygen/codegen/models/model_type.py +361 -0
  42. package/generator/pygen/codegen/models/operation.py +520 -0
  43. package/generator/pygen/codegen/models/operation_group.py +184 -0
  44. package/generator/pygen/codegen/models/paging_operation.py +156 -0
  45. package/generator/pygen/codegen/models/parameter.py +402 -0
  46. package/generator/pygen/codegen/models/parameter_list.py +390 -0
  47. package/generator/pygen/codegen/models/primitive_types.py +626 -0
  48. package/generator/pygen/codegen/models/property.py +175 -0
  49. package/generator/pygen/codegen/models/request_builder.py +189 -0
  50. package/generator/pygen/codegen/models/request_builder_parameter.py +115 -0
  51. package/generator/pygen/codegen/models/response.py +348 -0
  52. package/generator/pygen/codegen/models/utils.py +23 -0
  53. package/generator/pygen/codegen/serializers/__init__.py +574 -0
  54. package/generator/pygen/codegen/serializers/base_serializer.py +21 -0
  55. package/generator/pygen/codegen/serializers/builder_serializer.py +1473 -0
  56. package/generator/pygen/codegen/serializers/client_serializer.py +295 -0
  57. package/generator/pygen/codegen/serializers/enum_serializer.py +15 -0
  58. package/generator/pygen/codegen/serializers/general_serializer.py +212 -0
  59. package/generator/pygen/codegen/serializers/import_serializer.py +127 -0
  60. package/generator/pygen/codegen/serializers/metadata_serializer.py +198 -0
  61. package/generator/pygen/codegen/serializers/model_init_serializer.py +33 -0
  62. package/generator/pygen/codegen/serializers/model_serializer.py +287 -0
  63. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  64. package/generator/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  65. package/generator/pygen/codegen/serializers/parameter_serializer.py +221 -0
  66. package/generator/pygen/codegen/serializers/patch_serializer.py +19 -0
  67. package/generator/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  68. package/generator/pygen/codegen/serializers/sample_serializer.py +163 -0
  69. package/generator/pygen/codegen/serializers/test_serializer.py +287 -0
  70. package/generator/pygen/codegen/serializers/types_serializer.py +31 -0
  71. package/generator/pygen/codegen/serializers/utils.py +68 -0
  72. package/generator/pygen/codegen/templates/client.py.jinja2 +37 -0
  73. package/generator/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  74. package/generator/pygen/codegen/templates/config.py.jinja2 +73 -0
  75. package/generator/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  76. package/generator/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  77. package/generator/pygen/codegen/templates/enum.py.jinja2 +13 -0
  78. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  79. package/generator/pygen/codegen/templates/init.py.jinja2 +24 -0
  80. package/generator/pygen/codegen/templates/keywords.jinja2 +19 -0
  81. package/generator/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  82. package/generator/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  83. package/generator/pygen/codegen/templates/macros.jinja2 +12 -0
  84. package/generator/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  85. package/generator/pygen/codegen/templates/model_base.py.jinja2 +899 -0
  86. package/generator/pygen/codegen/templates/model_container.py.jinja2 +13 -0
  87. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +92 -0
  88. package/generator/pygen/codegen/templates/model_init.py.jinja2 +28 -0
  89. package/generator/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  90. package/generator/pygen/codegen/templates/operation.py.jinja2 +21 -0
  91. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  92. package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +20 -0
  93. package/generator/pygen/codegen/templates/operation_tools.jinja2 +74 -0
  94. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  95. package/generator/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  96. package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  97. package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  98. package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  99. package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  100. package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  101. package/generator/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  102. package/generator/pygen/codegen/templates/patch.py.jinja2 +19 -0
  103. package/generator/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  104. package/generator/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  105. package/generator/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  106. package/generator/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  107. package/generator/pygen/codegen/templates/sample.py.jinja2 +44 -0
  108. package/generator/pygen/codegen/templates/serialization.py.jinja2 +2006 -0
  109. package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
  110. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  111. package/generator/pygen/codegen/templates/types.py.jinja2 +8 -0
  112. package/generator/pygen/codegen/templates/validation.py.jinja2 +38 -0
  113. package/generator/pygen/codegen/templates/vendor.py.jinja2 +98 -0
  114. package/generator/pygen/codegen/templates/version.py.jinja2 +4 -0
  115. package/generator/pygen/m2r.py +65 -0
  116. package/generator/pygen/postprocess/__init__.py +183 -0
  117. package/generator/pygen/postprocess/get_all.py +19 -0
  118. package/generator/pygen/postprocess/venvtools.py +77 -0
  119. package/generator/pygen/preprocess/__init__.py +509 -0
  120. package/generator/pygen/preprocess/helpers.py +27 -0
  121. package/generator/pygen/preprocess/python_mappings.py +224 -0
  122. package/generator/pygen/utils.py +153 -0
  123. package/generator/pygen.egg-info/PKG-INFO +25 -0
  124. package/generator/pygen.egg-info/SOURCES.txt +66 -0
  125. package/generator/pygen.egg-info/dependency_links.txt +1 -0
  126. package/generator/pygen.egg-info/requires.txt +4 -0
  127. package/generator/pygen.egg-info/top_level.txt +1 -0
  128. package/generator/requirements.txt +12 -0
  129. package/generator/setup.py +55 -0
  130. package/package.json +31 -26
  131. package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
  132. package/scripts/install.py +49 -0
  133. package/scripts/prepare.py +38 -0
  134. package/scripts/run-python3.cjs +22 -0
  135. package/scripts/run_tsp.py +40 -0
  136. package/scripts/system-requirements.cjs +180 -0
  137. package/scripts/venvtools.py +81 -0
@@ -0,0 +1,520 @@
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
+ if self.stream_value:
347
+ errors.extend(["StreamConsumedError", "StreamClosedError"])
348
+ for error in errors:
349
+ file_import.add_submodule_import("exceptions", error, ImportType.SDKCORE)
350
+ if self.code_model.options["azure_arm"]:
351
+ file_import.add_submodule_import("azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.SDKCORE)
352
+ file_import.add_submodule_import(
353
+ "typing",
354
+ "Type",
355
+ ImportType.STDLIB,
356
+ )
357
+ file_import.add_mutable_mapping_import()
358
+ if self.non_default_error_status_codes:
359
+ file_import.add_submodule_import(
360
+ "typing",
361
+ "cast",
362
+ ImportType.STDLIB,
363
+ )
364
+
365
+ if self.has_kwargs_to_pop_with_default(
366
+ self.parameters.kwargs_to_pop, ParameterLocation.HEADER # type: ignore
367
+ ) or self.has_kwargs_to_pop_with_default(
368
+ self.parameters.kwargs_to_pop, ParameterLocation.QUERY # type: ignore
369
+ ):
370
+ file_import.add_submodule_import(
371
+ "utils",
372
+ "case_insensitive_dict",
373
+ ImportType.SDKCORE,
374
+ )
375
+ if self.deprecated:
376
+ file_import.add_import("warnings", ImportType.STDLIB)
377
+
378
+ relative_path = "..." if async_mode else ".."
379
+ if self.has_etag:
380
+ file_import.add_submodule_import(
381
+ "exceptions",
382
+ "ResourceModifiedError",
383
+ ImportType.SDKCORE,
384
+ )
385
+ if not async_mode:
386
+ file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_match", ImportType.LOCAL)
387
+ file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_none_match", ImportType.LOCAL)
388
+ if async_mode:
389
+ file_import.add_submodule_import(
390
+ "rest",
391
+ "AsyncHttpResponse",
392
+ ImportType.SDKCORE,
393
+ )
394
+ else:
395
+ file_import.add_submodule_import(
396
+ "rest",
397
+ "HttpResponse",
398
+ ImportType.SDKCORE,
399
+ )
400
+ if self.code_model.options["builders_visibility"] == "embedded" and not async_mode:
401
+ file_import.merge(self.request_builder.imports())
402
+ file_import.add_submodule_import(
403
+ f"{'' if self.code_model.is_azure_flavor else 'runtime.'}pipeline",
404
+ "PipelineResponse",
405
+ ImportType.SDKCORE,
406
+ )
407
+ file_import.add_submodule_import("rest", "HttpRequest", ImportType.SDKCORE)
408
+ file_import.add_submodule_import("typing", "Callable", ImportType.STDLIB, TypingSection.CONDITIONAL)
409
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
410
+ file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL)
411
+ file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL)
412
+ if self.code_model.options["tracing"] and self.want_tracing and not async_mode:
413
+ file_import.add_submodule_import(
414
+ "azure.core.tracing.decorator",
415
+ "distributed_trace",
416
+ ImportType.SDKCORE,
417
+ )
418
+ file_import.merge(self.get_request_builder_import(self.request_builder, async_mode))
419
+ if self.overloads:
420
+ file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
421
+ if self.non_default_errors and self.code_model.options["models_mode"] == "dpg":
422
+ file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
423
+ return file_import
424
+
425
+ def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType:
426
+ try:
427
+ return next(r for r in self.responses if status_code in r.status_codes)
428
+ except StopIteration as exc:
429
+ raise ValueError(f"Incorrect status code {status_code}, operation {self.name}") from exc
430
+
431
+ @property
432
+ def success_status_codes(self) -> Sequence[Union[str, int]]:
433
+ """The list of all successfull status code."""
434
+ return sorted([code for response in self.responses for code in response.status_codes])
435
+
436
+ @property
437
+ def filename(self) -> str:
438
+ basename = self.group_name
439
+ if basename == "":
440
+ # in a mixin
441
+ basename = self.code_model.clients[0].legacy_filename
442
+
443
+ if basename == "operations" or self.code_model.options["combine_operation_files"]:
444
+ return "_operations"
445
+ return f"_{basename}_operations"
446
+
447
+ @property
448
+ def has_stream_response(self) -> bool:
449
+ return any(r.is_stream_response for r in self.responses)
450
+
451
+ @classmethod
452
+ def get_request_builder(cls, yaml_data: Dict[str, Any], client: "Client"):
453
+ return client.lookup_request_builder(id(yaml_data))
454
+
455
+ @classmethod
456
+ def from_yaml(
457
+ cls,
458
+ yaml_data: Dict[str, Any],
459
+ code_model: "CodeModel",
460
+ client: "Client",
461
+ ):
462
+ name = yaml_data["name"]
463
+ request_builder = cls.get_request_builder(yaml_data, client)
464
+ responses = [cast(ResponseType, get_response(r, code_model)) for r in yaml_data["responses"]]
465
+ exceptions = [Response.from_yaml(e, code_model) for e in yaml_data["exceptions"]]
466
+ parameter_list = ParameterList.from_yaml(yaml_data, code_model)
467
+ overloads = [cls.from_yaml(overload, code_model, client) for overload in yaml_data.get("overloads", [])]
468
+
469
+ return cls(
470
+ yaml_data=yaml_data,
471
+ code_model=code_model,
472
+ client=client,
473
+ request_builder=request_builder,
474
+ name=name,
475
+ parameters=parameter_list,
476
+ overloads=overloads,
477
+ responses=responses,
478
+ exceptions=exceptions,
479
+ )
480
+
481
+
482
+ class Operation(OperationBase[Response]):
483
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
484
+ file_import = super().imports(async_mode, **kwargs)
485
+ if self.abstract:
486
+ return file_import
487
+ if async_mode and self.code_model.options["tracing"] and self.want_tracing:
488
+ file_import.add_submodule_import(
489
+ "azure.core.tracing.decorator_async",
490
+ "distributed_trace_async",
491
+ ImportType.SDKCORE,
492
+ )
493
+ if self.has_response_body and not self.has_optional_return_type and not self.code_model.options["models_mode"]:
494
+ file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
495
+ relative_path = "..." if async_mode else ".."
496
+ if self.code_model.options["models_mode"] == "dpg":
497
+ if self.parameters.has_body:
498
+ if not self.has_form_data_body:
499
+ file_import.add_submodule_import(
500
+ f"{relative_path}_model_base",
501
+ "SdkJSONEncoder",
502
+ ImportType.LOCAL,
503
+ )
504
+ file_import.add_import("json", ImportType.STDLIB)
505
+ if self.default_error_deserialization or any(r.type for r in self.responses):
506
+ file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
507
+
508
+ return file_import
509
+
510
+
511
+ def get_operation(yaml_data: Dict[str, Any], code_model: "CodeModel", client: "Client") -> "OperationType":
512
+ if yaml_data["discriminator"] == "lropaging":
513
+ from .lro_paging_operation import LROPagingOperation as OperationCls
514
+ elif yaml_data["discriminator"] == "lro":
515
+ from .lro_operation import LROOperation as OperationCls # type: ignore
516
+ elif yaml_data["discriminator"] == "paging":
517
+ from .paging_operation import PagingOperation as OperationCls # type: ignore
518
+ else:
519
+ from . import Operation as OperationCls # type: ignore
520
+ return OperationCls.from_yaml(yaml_data, code_model, client)