@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.
Files changed (132) hide show
  1. package/dist/src/code-model.d.ts.map +1 -1
  2. package/dist/src/code-model.js +1 -4
  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 +5 -4
  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/types.d.ts.map +1 -1
  12. package/dist/src/types.js +2 -0
  13. package/dist/src/types.js.map +1 -1
  14. package/generator/LICENSE +21 -0
  15. package/generator/README.md +1 -0
  16. package/generator/dev_requirements.txt +5 -0
  17. package/generator/pygen/__init__.py +107 -0
  18. package/generator/pygen/_version.py +7 -0
  19. package/generator/pygen/black.py +71 -0
  20. package/generator/pygen/codegen/__init__.py +334 -0
  21. package/generator/pygen/codegen/_utils.py +16 -0
  22. package/generator/pygen/codegen/models/__init__.py +202 -0
  23. package/generator/pygen/codegen/models/base.py +186 -0
  24. package/generator/pygen/codegen/models/base_builder.py +119 -0
  25. package/generator/pygen/codegen/models/client.py +429 -0
  26. package/generator/pygen/codegen/models/code_model.py +239 -0
  27. package/generator/pygen/codegen/models/combined_type.py +149 -0
  28. package/generator/pygen/codegen/models/constant_type.py +129 -0
  29. package/generator/pygen/codegen/models/credential_types.py +221 -0
  30. package/generator/pygen/codegen/models/dictionary_type.py +127 -0
  31. package/generator/pygen/codegen/models/enum_type.py +238 -0
  32. package/generator/pygen/codegen/models/imports.py +291 -0
  33. package/generator/pygen/codegen/models/list_type.py +143 -0
  34. package/generator/pygen/codegen/models/lro_operation.py +143 -0
  35. package/generator/pygen/codegen/models/lro_paging_operation.py +32 -0
  36. package/generator/pygen/codegen/models/model_type.py +361 -0
  37. package/generator/pygen/codegen/models/operation.py +518 -0
  38. package/generator/pygen/codegen/models/operation_group.py +184 -0
  39. package/generator/pygen/codegen/models/paging_operation.py +156 -0
  40. package/generator/pygen/codegen/models/parameter.py +402 -0
  41. package/generator/pygen/codegen/models/parameter_list.py +390 -0
  42. package/generator/pygen/codegen/models/primitive_types.py +626 -0
  43. package/generator/pygen/codegen/models/property.py +175 -0
  44. package/generator/pygen/codegen/models/request_builder.py +189 -0
  45. package/generator/pygen/codegen/models/request_builder_parameter.py +115 -0
  46. package/generator/pygen/codegen/models/response.py +348 -0
  47. package/generator/pygen/codegen/models/utils.py +23 -0
  48. package/generator/pygen/codegen/serializers/__init__.py +570 -0
  49. package/generator/pygen/codegen/serializers/base_serializer.py +21 -0
  50. package/generator/pygen/codegen/serializers/builder_serializer.py +1454 -0
  51. package/generator/pygen/codegen/serializers/client_serializer.py +295 -0
  52. package/generator/pygen/codegen/serializers/enum_serializer.py +15 -0
  53. package/generator/pygen/codegen/serializers/general_serializer.py +212 -0
  54. package/generator/pygen/codegen/serializers/import_serializer.py +127 -0
  55. package/generator/pygen/codegen/serializers/metadata_serializer.py +198 -0
  56. package/generator/pygen/codegen/serializers/model_init_serializer.py +33 -0
  57. package/generator/pygen/codegen/serializers/model_serializer.py +287 -0
  58. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  59. package/generator/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  60. package/generator/pygen/codegen/serializers/parameter_serializer.py +221 -0
  61. package/generator/pygen/codegen/serializers/patch_serializer.py +19 -0
  62. package/generator/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  63. package/generator/pygen/codegen/serializers/sample_serializer.py +163 -0
  64. package/generator/pygen/codegen/serializers/test_serializer.py +287 -0
  65. package/generator/pygen/codegen/serializers/types_serializer.py +31 -0
  66. package/generator/pygen/codegen/serializers/utils.py +68 -0
  67. package/generator/pygen/codegen/templates/client.py.jinja2 +37 -0
  68. package/generator/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  69. package/generator/pygen/codegen/templates/config.py.jinja2 +73 -0
  70. package/generator/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  71. package/generator/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  72. package/generator/pygen/codegen/templates/enum.py.jinja2 +13 -0
  73. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  74. package/generator/pygen/codegen/templates/init.py.jinja2 +24 -0
  75. package/generator/pygen/codegen/templates/keywords.jinja2 +19 -0
  76. package/generator/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  77. package/generator/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  78. package/generator/pygen/codegen/templates/macros.jinja2 +12 -0
  79. package/generator/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  80. package/generator/pygen/codegen/templates/model_base.py.jinja2 +899 -0
  81. package/generator/pygen/codegen/templates/model_container.py.jinja2 +13 -0
  82. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +92 -0
  83. package/generator/pygen/codegen/templates/model_init.py.jinja2 +28 -0
  84. package/generator/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  85. package/generator/pygen/codegen/templates/operation.py.jinja2 +21 -0
  86. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  87. package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +20 -0
  88. package/generator/pygen/codegen/templates/operation_tools.jinja2 +74 -0
  89. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  90. package/generator/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  91. package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  92. package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  93. package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  94. package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  95. package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  96. package/generator/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  97. package/generator/pygen/codegen/templates/patch.py.jinja2 +19 -0
  98. package/generator/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  99. package/generator/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  100. package/generator/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  101. package/generator/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  102. package/generator/pygen/codegen/templates/sample.py.jinja2 +44 -0
  103. package/generator/pygen/codegen/templates/serialization.py.jinja2 +2006 -0
  104. package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
  105. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  106. package/generator/pygen/codegen/templates/types.py.jinja2 +8 -0
  107. package/generator/pygen/codegen/templates/validation.py.jinja2 +38 -0
  108. package/generator/pygen/codegen/templates/vendor.py.jinja2 +98 -0
  109. package/generator/pygen/codegen/templates/version.py.jinja2 +4 -0
  110. package/generator/pygen/m2r.py +65 -0
  111. package/generator/pygen/postprocess/__init__.py +183 -0
  112. package/generator/pygen/postprocess/get_all.py +19 -0
  113. package/generator/pygen/postprocess/venvtools.py +77 -0
  114. package/generator/pygen/preprocess/__init__.py +503 -0
  115. package/generator/pygen/preprocess/helpers.py +27 -0
  116. package/generator/pygen/preprocess/python_mappings.py +222 -0
  117. package/generator/pygen/utils.py +149 -0
  118. package/generator/pygen.egg-info/PKG-INFO +25 -0
  119. package/generator/pygen.egg-info/SOURCES.txt +66 -0
  120. package/generator/pygen.egg-info/dependency_links.txt +1 -0
  121. package/generator/pygen.egg-info/requires.txt +4 -0
  122. package/generator/pygen.egg-info/top_level.txt +1 -0
  123. package/generator/requirements.txt +12 -0
  124. package/generator/setup.py +55 -0
  125. package/package.json +10 -7
  126. package/scripts/__pycache__/venvtools.cpython-38.pyc +0 -0
  127. package/scripts/install.py +49 -0
  128. package/scripts/prepare.py +38 -0
  129. package/scripts/run-python3.cjs +22 -0
  130. package/scripts/run_tsp.py +40 -0
  131. package/scripts/system-requirements.cjs +180 -0
  132. package/scripts/venvtools.py +81 -0
@@ -0,0 +1,1454 @@
1
+ # pylint: disable=too-many-lines,multiple-statements
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
+ from abc import abstractmethod
8
+ from collections import defaultdict
9
+ from typing import Generic, List, Type, TypeVar, Dict, Union, Optional, cast
10
+
11
+ from ..models import (
12
+ Operation,
13
+ PagingOperation,
14
+ CodeModel,
15
+ LROOperation,
16
+ LROPagingOperation,
17
+ ModelType,
18
+ DictionaryType,
19
+ ListType,
20
+ RequestBuilder,
21
+ ParameterLocation,
22
+ Response,
23
+ BinaryType,
24
+ BodyParameter,
25
+ ParameterMethodLocation,
26
+ RequestBuilderBodyParameter,
27
+ OverloadedRequestBuilder,
28
+ Property,
29
+ RequestBuilderType,
30
+ CombinedType,
31
+ JSONModelType,
32
+ DPGModelType,
33
+ ParameterListType,
34
+ ByteArraySchema,
35
+ )
36
+ from .parameter_serializer import ParameterSerializer, PopKwargType
37
+ from ..models.parameter_list import ParameterType
38
+ from . import utils
39
+ from ...utils import JSON_REGEXP
40
+
41
+ T = TypeVar("T")
42
+ OrderedSet = Dict[T, None]
43
+
44
+ BuilderType = TypeVar(
45
+ "BuilderType",
46
+ bound=Union[
47
+ RequestBuilder,
48
+ Operation,
49
+ PagingOperation,
50
+ LROOperation,
51
+ LROPagingOperation,
52
+ OverloadedRequestBuilder,
53
+ ],
54
+ )
55
+ OperationType = TypeVar(
56
+ "OperationType",
57
+ bound=Union[Operation, PagingOperation, LROOperation, LROPagingOperation],
58
+ )
59
+
60
+
61
+ def _json_serializable(content_type: str) -> bool:
62
+ return bool(JSON_REGEXP.match(content_type.split(";")[0].strip().lower()))
63
+
64
+
65
+ def _need_type_ignore(builder: OperationType) -> bool:
66
+ for excep in builder.non_default_errors:
67
+ for status_code in excep.status_codes:
68
+ if status_code in (401, 404, 409, 304):
69
+ return True
70
+ return False
71
+
72
+
73
+ def _xml_config(send_xml: bool, content_types: List[str]) -> str:
74
+ if not (send_xml and "xml" in str(content_types)):
75
+ return ""
76
+ if len(content_types) == 1:
77
+ return ", is_xml=True"
78
+ return ", is_xml='xml' in str(content_type)"
79
+
80
+
81
+ def _escape_str(input_str: str) -> str:
82
+ replace = input_str.replace("'", "\\'")
83
+ return f'"{replace}"'
84
+
85
+
86
+ def _get_polymorphic_subtype_template(polymorphic_subtype: ModelType) -> List[str]:
87
+ retval: List[str] = []
88
+ retval.append("")
89
+ retval.append(f'# JSON input template for discriminator value "{polymorphic_subtype.discriminator_value}":')
90
+ subtype_template = utils.json_dumps_template(
91
+ polymorphic_subtype.get_json_template_representation(),
92
+ )
93
+
94
+ def _get_polymorphic_parent(
95
+ polymorphic_subtype: Optional[ModelType],
96
+ ) -> Optional[ModelType]:
97
+ if not polymorphic_subtype:
98
+ return None
99
+ try:
100
+ return next(p for p in polymorphic_subtype.parents if p.discriminated_subtypes)
101
+ except StopIteration:
102
+ return None
103
+
104
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_subtype)
105
+ while _get_polymorphic_parent(polymorphic_parent):
106
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_parent)
107
+ retval.extend(f"{cast(ModelType, polymorphic_parent).snake_case_name} = {subtype_template}".splitlines())
108
+ return retval
109
+
110
+
111
+ def _serialize_grouped_body(builder: BuilderType) -> List[str]:
112
+ retval: List[str] = []
113
+ for grouped_parameter in builder.parameters.grouped:
114
+ retval.append(f"{grouped_parameter.client_name} = None")
115
+ groupers = [p for p in builder.parameters if p.grouper]
116
+ for grouper in groupers:
117
+ retval.append(f"if {grouper.client_name} is not None:")
118
+ retval.extend(
119
+ [
120
+ f" {parameter} = {grouper.client_name}.{property}"
121
+ for property, parameter in grouper.property_to_parameter_name.items()
122
+ ]
123
+ )
124
+ return retval
125
+
126
+
127
+ def _serialize_flattened_body(body_parameter: BodyParameter) -> List[str]:
128
+ retval: List[str] = []
129
+ if not body_parameter.property_to_parameter_name:
130
+ raise ValueError("This method can't be called if the operation doesn't need parameter flattening")
131
+
132
+ parameter_string = ", ".join(
133
+ f"{property_name}={parameter_name}"
134
+ for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
135
+ )
136
+ model_type = cast(ModelType, body_parameter.type)
137
+ retval.append(f"{body_parameter.client_name} = _models.{model_type.name}({parameter_string})")
138
+ return retval
139
+
140
+
141
+ def _serialize_json_model_body(body_parameter: BodyParameter, parameters: List[ParameterType]) -> List[str]:
142
+ retval: List[str] = []
143
+ if not body_parameter.property_to_parameter_name:
144
+ raise ValueError("This method can't be called if the operation doesn't need parameter flattening")
145
+
146
+ retval.append(f"if {body_parameter.client_name} is _Unset:")
147
+ for p in parameters:
148
+ if p.client_default_value is None and not p.optional and p.default_to_unset_sentinel:
149
+ retval.append(f" if {p.client_name} is _Unset:")
150
+ retval.append(f" raise TypeError('missing required argument: {p.client_name}')")
151
+ parameter_string = ", \n".join(
152
+ f'"{property_name}": {parameter_name}'
153
+ for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
154
+ )
155
+ model_type = cast(ModelType, body_parameter.type)
156
+ if isinstance(model_type, CombinedType) and model_type.target_model_subtype((JSONModelType,)):
157
+ model_type = model_type.target_model_subtype((JSONModelType,))
158
+ retval.append(f" {body_parameter.client_name} = {{{parameter_string}}}")
159
+ retval.append(f" {body_parameter.client_name} = {{")
160
+ retval.append(f" k: v for k, v in {body_parameter.client_name}.items() if v is not None")
161
+ retval.append(" }")
162
+ return retval
163
+
164
+
165
+ def _serialize_multipart_body(builder: BuilderType) -> List[str]:
166
+ retval: List[str] = []
167
+ body_param = builder.parameters.body_parameter
168
+ # we have to construct our form data before passing to the request as well
169
+ retval.append("# Construct form data")
170
+ retval.append(f"_{body_param.client_name} = {{")
171
+ for param in body_param.entries:
172
+ retval.append(f' "{param.wire_name}": {param.client_name},')
173
+ retval.append("}")
174
+ return retval
175
+
176
+
177
+ def _get_json_response_template_to_status_codes(
178
+ builder: OperationType,
179
+ ) -> Dict[str, List[str]]:
180
+ retval = defaultdict(list)
181
+ for response in builder.responses:
182
+ json_template = response.get_json_template_representation()
183
+ if not json_template:
184
+ continue
185
+ status_codes = [str(status_code) for status_code in response.status_codes]
186
+ response_json = utils.json_dumps_template(json_template)
187
+ retval[response_json].extend(status_codes)
188
+ return retval
189
+
190
+
191
+ def _api_version_validation(builder: OperationType) -> str:
192
+ if builder.is_overload:
193
+ return ""
194
+ retval: List[str] = []
195
+ if builder.added_on:
196
+ retval.append(f' method_added_on="{builder.added_on}",')
197
+ params_added_on = defaultdict(list)
198
+ for parameter in builder.parameters:
199
+ if parameter.added_on:
200
+ params_added_on[parameter.added_on].append(parameter.client_name)
201
+ if params_added_on:
202
+ retval.append(f" params_added_on={dict(params_added_on)},")
203
+ if retval:
204
+ retval_str = "\n".join(retval)
205
+ return f"@api_version_validation(\n{retval_str}\n){builder.pylint_disable}"
206
+ return ""
207
+
208
+
209
+ def is_json_model_type(parameters: ParameterListType) -> bool:
210
+ return (
211
+ parameters.has_body
212
+ and parameters.body_parameter.has_json_model_type
213
+ and any(p.in_flattened_body for p in parameters.parameters)
214
+ )
215
+
216
+
217
+ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-method
218
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
219
+ self.code_model = code_model
220
+ self.async_mode = async_mode
221
+ self.parameter_serializer = ParameterSerializer()
222
+
223
+ @property
224
+ @abstractmethod
225
+ def _need_self_param(self) -> bool: ...
226
+
227
+ @property
228
+ @abstractmethod
229
+ def _function_def(self) -> str:
230
+ """The def keyword for the builder we're serializing, i.e. 'def' or 'async def'"""
231
+
232
+ @property
233
+ @abstractmethod
234
+ def _call_method(self) -> str:
235
+ """How to call network calls. Await if we have to await network calls"""
236
+
237
+ @property
238
+ @abstractmethod
239
+ def serializer_name(self) -> str:
240
+ """Name of serializer"""
241
+
242
+ @abstractmethod
243
+ def response_docstring(self, builder: BuilderType) -> List[str]:
244
+ """Response portion of the docstring"""
245
+
246
+ def decorators(self, builder: BuilderType) -> List[str]:
247
+ """Decorators for the method"""
248
+ retval: List[str] = []
249
+ if builder.is_overload:
250
+ return ["@overload"]
251
+ if self.code_model.options["tracing"] and builder.want_tracing:
252
+ retval.append(f"@distributed_trace{'_async' if self.async_mode else ''}")
253
+ return retval
254
+
255
+ def _method_signature(self, builder: BuilderType) -> str:
256
+ return self.parameter_serializer.serialize_method(
257
+ function_def=self._function_def,
258
+ method_name=builder.name,
259
+ need_self_param=self._need_self_param,
260
+ method_param_signatures=builder.method_signature(self.async_mode),
261
+ pylint_disable=builder.pylint_disable,
262
+ )
263
+
264
+ def method_signature_and_response_type_annotation(
265
+ self, builder: BuilderType, *, want_decorators: Optional[bool] = True
266
+ ) -> str:
267
+ response_type_annotation = builder.response_type_annotation(async_mode=self.async_mode)
268
+ method_signature = self._method_signature(builder)
269
+ decorators = self.decorators(builder)
270
+ decorators_str = ""
271
+ if decorators and want_decorators:
272
+ decorators_str = "\n".join(decorators) + "\n"
273
+ return decorators_str + utils.method_signature_and_response_type_annotation_template(
274
+ method_signature=method_signature,
275
+ response_type_annotation=response_type_annotation,
276
+ )
277
+
278
+ def description_and_summary(self, builder: BuilderType) -> List[str]:
279
+ description_list: List[str] = []
280
+ description_list.append(f"{builder.summary.strip() if builder.summary else builder.description.strip()}")
281
+ if builder.summary and builder.description:
282
+ description_list.append("")
283
+ description_list.append(builder.description.strip())
284
+ description_list.append("")
285
+ return description_list
286
+
287
+ @staticmethod
288
+ def line_too_long(docs: List[str]) -> bool:
289
+ return any(len(line) > 120 for line in docs)
290
+
291
+ def example_template(self, builder: BuilderType) -> List[str]:
292
+ template = []
293
+ if builder.abstract:
294
+ return []
295
+ if self._json_input_example_template(builder):
296
+ template.append("")
297
+ template += self._json_input_example_template(builder)
298
+ return template
299
+
300
+ def param_description(self, builder: BuilderType) -> List[str]:
301
+ description_list: List[str] = []
302
+ for param in builder.parameters.method:
303
+ if (
304
+ not param.in_docstring
305
+ or param.hide_in_operation_signature
306
+ or param.method_location == ParameterMethodLocation.KWARG
307
+ ):
308
+ continue
309
+ description_list.extend(
310
+ f":{param.description_keyword} {param.client_name}: {param.description}".replace("\n", "\n ").split(
311
+ "\n"
312
+ )
313
+ )
314
+ docstring_type = param.docstring_type(
315
+ async_mode=self.async_mode,
316
+ )
317
+ description_list.append(f":{param.docstring_type_keyword} {param.client_name}: {docstring_type}")
318
+ return description_list
319
+
320
+ def param_description_and_response_docstring(self, builder: BuilderType) -> List[str]:
321
+ if builder.abstract:
322
+ return []
323
+ return self.param_description(builder) + self.response_docstring(builder)
324
+
325
+ @property
326
+ @abstractmethod
327
+ def _json_response_template_name(self) -> str: ...
328
+
329
+ def _json_input_example_template(self, builder: BuilderType) -> List[str]:
330
+ template: List[str] = []
331
+ if not builder.parameters.has_body or builder.parameters.body_parameter.flattened:
332
+ # No input template if now body parameter
333
+ return template
334
+
335
+ body_param = builder.parameters.body_parameter
336
+ if not isinstance(body_param.type, (ListType, DictionaryType, ModelType, CombinedType)):
337
+ return template
338
+
339
+ if (
340
+ isinstance(body_param.type, (ListType, DictionaryType))
341
+ and self.code_model.options["models_mode"] == "msrest"
342
+ ):
343
+ return template
344
+
345
+ if isinstance(body_param.type, ModelType) and body_param.type.base == "msrest":
346
+ return template
347
+
348
+ json_type = body_param.type
349
+ if isinstance(body_param.type, CombinedType):
350
+ target_model_type = body_param.type.target_model_subtype((JSONModelType, DPGModelType))
351
+ if target_model_type is None:
352
+ return template
353
+ json_type = target_model_type
354
+
355
+ polymorphic_subtypes: List[ModelType] = []
356
+ json_type.get_polymorphic_subtypes(polymorphic_subtypes)
357
+ if polymorphic_subtypes:
358
+ # we just assume one kind of polymorphic body for input
359
+ discriminator_name = cast(Property, polymorphic_subtypes[0].discriminator).wire_name
360
+ template.append(
361
+ "# The input is polymorphic. The following are possible polymorphic "
362
+ f'inputs based off discriminator "{discriminator_name}":'
363
+ )
364
+ for idx in range(
365
+ min(
366
+ self.code_model.options["polymorphic_examples"],
367
+ len(polymorphic_subtypes),
368
+ )
369
+ ):
370
+ template.extend(_get_polymorphic_subtype_template(polymorphic_subtypes[idx]))
371
+ template.append("")
372
+ template.append("# JSON input template you can fill out and use as your body input.")
373
+ json_template = utils.json_dumps_template(
374
+ json_type.get_json_template_representation(),
375
+ )
376
+ template.extend(f"{builder.parameters.body_parameter.client_name} = {json_template}".splitlines())
377
+ return template
378
+
379
+ def serialize_path(self, builder: BuilderType) -> List[str]:
380
+ return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
381
+
382
+ @property
383
+ def pipeline_name(self) -> str:
384
+ return f"{'_' if self.code_model.is_azure_flavor else ''}pipeline"
385
+
386
+
387
+ ############################## REQUEST BUILDERS ##############################
388
+
389
+
390
+ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]): # pylint: disable=abstract-method
391
+ def description_and_summary(self, builder: RequestBuilderType) -> List[str]:
392
+ retval = super().description_and_summary(builder)
393
+ retval += [
394
+ "See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this "
395
+ "request builder into your code flow.",
396
+ "",
397
+ ]
398
+ return retval
399
+
400
+ @property
401
+ def _call_method(self) -> str:
402
+ return ""
403
+
404
+ @property
405
+ def serializer_name(self) -> str:
406
+ return "_SERIALIZER"
407
+
408
+ @property
409
+ def _json_response_template_name(self) -> str:
410
+ return "response.json()"
411
+
412
+ @staticmethod
413
+ def declare_non_inputtable_constants(builder: RequestBuilderType) -> List[str]:
414
+ def _get_value(param):
415
+ if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
416
+ kwarg_dict = "headers" if param.location == ParameterLocation.HEADER else "params"
417
+ return f"_{kwarg_dict}.pop('{param.wire_name}', {param.get_declaration()})"
418
+ return f"{param.get_declaration()}"
419
+
420
+ return [f"{p.client_name} = {_get_value(p)}" for p in builder.parameters.constant if not p.in_method_signature]
421
+
422
+ @property
423
+ def _function_def(self) -> str:
424
+ return "def"
425
+
426
+ @property
427
+ def _need_self_param(self) -> bool:
428
+ return False
429
+
430
+ def response_docstring(self, builder: RequestBuilderType) -> List[str]:
431
+ request_full_path = f"{self.code_model.core_library}.rest.HttpRequest"
432
+ response_str = (
433
+ f":return: Returns an :class:`~{request_full_path}` that you will pass to the client's "
434
+ + "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
435
+ + "incorporate this response into your code flow."
436
+ )
437
+ rtype_str = f":rtype: ~{request_full_path}"
438
+ return [response_str, rtype_str]
439
+
440
+ def pop_kwargs_from_signature(self, builder: RequestBuilderType) -> List[str]:
441
+ return self.parameter_serializer.pop_kwargs_from_signature(
442
+ builder.parameters.kwargs_to_pop,
443
+ check_kwarg_dict=True,
444
+ pop_headers_kwarg=(PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.headers) else PopKwargType.NO),
445
+ pop_params_kwarg=(PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.query) else PopKwargType.NO),
446
+ )
447
+
448
+ @staticmethod
449
+ def create_http_request(builder: RequestBuilderType) -> List[str]:
450
+ retval = ["return HttpRequest("]
451
+ retval.append(f' method="{builder.method}",')
452
+ retval.append(" url=_url,")
453
+ if builder.parameters.query:
454
+ retval.append(" params=_params,")
455
+ if builder.parameters.headers:
456
+ retval.append(" headers=_headers,")
457
+ if builder.parameters.has_body and builder.parameters.body_parameter.in_method_signature:
458
+ body_param = builder.parameters.body_parameter
459
+ if body_param.constant or body_param.method_location != ParameterMethodLocation.KWARG:
460
+ # we only need to pass it through if it's not a kwarg or it's a popped kwarg
461
+ retval.append(
462
+ f" {builder.parameters.body_parameter.client_name}="
463
+ f"{builder.parameters.body_parameter.client_name},"
464
+ )
465
+ retval.append(" **kwargs")
466
+ retval.append(")")
467
+ return retval
468
+
469
+ def serialize_headers(self, builder: RequestBuilderType) -> List[str]:
470
+ headers = [
471
+ h
472
+ for h in builder.parameters.headers
473
+ if not builder.has_form_data_body or h.wire_name.lower() != "content-type"
474
+ ]
475
+ retval = ["# Construct headers"] if headers else []
476
+ for header in headers:
477
+ retval.extend(
478
+ self.parameter_serializer.serialize_query_header(
479
+ header,
480
+ "headers",
481
+ self.serializer_name,
482
+ self.code_model.is_legacy,
483
+ )
484
+ )
485
+ return retval
486
+
487
+ def serialize_query(self, builder: RequestBuilderType) -> List[str]:
488
+ retval = ["# Construct parameters"]
489
+ for parameter in builder.parameters.query:
490
+ retval.extend(
491
+ self.parameter_serializer.serialize_query_header(
492
+ parameter,
493
+ "params",
494
+ self.serializer_name,
495
+ self.code_model.is_legacy,
496
+ )
497
+ )
498
+ return retval
499
+
500
+ def construct_url(self, builder: RequestBuilderType) -> str:
501
+ if any(o for o in ["low_level_client", "version_tolerant"] if self.code_model.options.get(o)):
502
+ url_value = _escape_str(builder.url)
503
+ else:
504
+ url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
505
+ return f"_url = {url_value}{' # pylint: disable=line-too-long' if len(url_value) > 114 else ''}"
506
+
507
+
508
+ ############################## NORMAL OPERATIONS ##############################
509
+
510
+
511
+ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: disable=abstract-method
512
+ def description_and_summary(self, builder: OperationType) -> List[str]:
513
+ retval = super().description_and_summary(builder)
514
+ if builder.deprecated:
515
+ retval.append(".. warning::")
516
+ retval.append(" This method is deprecated")
517
+ retval.append("")
518
+ if builder.external_docs and builder.external_docs.get("url"):
519
+ retval.append(".. seealso::")
520
+ retval.append(f" - {builder.external_docs['url']}")
521
+ retval.append("")
522
+ return retval
523
+
524
+ @property
525
+ def _json_response_template_name(self) -> str:
526
+ return "response"
527
+
528
+ def example_template(self, builder: OperationType) -> List[str]:
529
+ retval = super().example_template(builder)
530
+ if self.code_model.options["models_mode"] == "msrest":
531
+ return retval
532
+ for response in builder.responses:
533
+ polymorphic_subtypes: List[ModelType] = []
534
+ if not response.type:
535
+ continue
536
+ response.get_polymorphic_subtypes(polymorphic_subtypes)
537
+ if polymorphic_subtypes:
538
+ # we just assume one kind of polymorphic body for input
539
+ discriminator_name = cast(Property, polymorphic_subtypes[0].discriminator).wire_name
540
+ retval.append("")
541
+ retval.append(
542
+ "# The response is polymorphic. The following are possible polymorphic "
543
+ f'responses based off discriminator "{discriminator_name}":'
544
+ )
545
+ for idx in range(
546
+ min(
547
+ self.code_model.options["polymorphic_examples"],
548
+ len(polymorphic_subtypes),
549
+ )
550
+ ):
551
+ retval.extend(_get_polymorphic_subtype_template(polymorphic_subtypes[idx]))
552
+
553
+ if _get_json_response_template_to_status_codes(builder):
554
+ retval.append("")
555
+ for (
556
+ response_body,
557
+ status_codes,
558
+ ) in _get_json_response_template_to_status_codes(builder).items():
559
+ retval.append("# response body for status code(s): {}".format(", ".join(status_codes)))
560
+ retval.extend(f"{self._json_response_template_name} == {response_body}".splitlines())
561
+ return retval
562
+
563
+ def make_pipeline_call(self, builder: OperationType) -> List[str]:
564
+ type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
565
+ return [
566
+ f"_stream = {builder.stream_value}",
567
+ f"pipeline_response: PipelineResponse = {self._call_method}self._client.{self.pipeline_name}.run( "
568
+ + f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
569
+ " _request,",
570
+ " stream=_stream,",
571
+ " **kwargs",
572
+ ")",
573
+ ]
574
+
575
+ @property
576
+ def _function_def(self) -> str:
577
+ return "async def" if self.async_mode else "def"
578
+
579
+ @property
580
+ def _need_self_param(self) -> bool:
581
+ return True
582
+
583
+ @property
584
+ def serializer_name(self) -> str:
585
+ return "self._serialize"
586
+
587
+ def decorators(self, builder: OperationType) -> List[str]:
588
+ """Decorators for the method"""
589
+ retval = super().decorators(builder)
590
+ if _api_version_validation(builder):
591
+ retval.append(_api_version_validation(builder))
592
+ return retval
593
+
594
+ def pop_kwargs_from_signature(self, builder: OperationType) -> List[str]:
595
+ kwargs_to_pop = builder.parameters.kwargs_to_pop
596
+ kwargs = self.parameter_serializer.pop_kwargs_from_signature(
597
+ kwargs_to_pop,
598
+ check_kwarg_dict=True,
599
+ pop_headers_kwarg=(
600
+ PopKwargType.CASE_INSENSITIVE
601
+ if builder.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.HEADER) # type: ignore
602
+ else PopKwargType.SIMPLE
603
+ ),
604
+ pop_params_kwarg=(
605
+ PopKwargType.CASE_INSENSITIVE
606
+ if builder.has_kwargs_to_pop_with_default(kwargs_to_pop, ParameterLocation.QUERY) # type: ignore
607
+ else PopKwargType.SIMPLE
608
+ ),
609
+ check_client_input=not self.code_model.options["multiapi"],
610
+ operation_name=f"('{builder.name}')" if builder.group_name == "" else "",
611
+ )
612
+ for p in builder.parameters.parameters:
613
+ if p.hide_in_operation_signature:
614
+ kwargs.append(f'{p.client_name} = kwargs.pop("{p.client_name}", None)')
615
+ cls_annotation = builder.cls_type_annotation(async_mode=self.async_mode)
616
+ pylint_disable = ""
617
+ if any(x.startswith("_") for x in cls_annotation.split(".")):
618
+ pylint_disable = " # pylint: disable=protected-access"
619
+ kwargs.append(f"cls: {cls_annotation} = kwargs.pop({pylint_disable}\n 'cls', None\n)")
620
+ return kwargs
621
+
622
+ def response_docstring(self, builder: OperationType) -> List[str]:
623
+ response_str = f":return: {builder.response_docstring_text(async_mode=self.async_mode)}"
624
+ rtype_str = f":rtype: {builder.response_docstring_type(async_mode=self.async_mode)}"
625
+ return [
626
+ response_str,
627
+ rtype_str,
628
+ f":raises ~{self.code_model.core_library}.exceptions.HttpResponseError:",
629
+ ]
630
+
631
+ def _serialize_body_parameter(self, builder: OperationType) -> List[str]:
632
+ """We need to serialize params if they're not meant to be streamed in.
633
+
634
+ This function serializes the body params that need to be serialized.
635
+ """
636
+ retval: List[str] = []
637
+ body_param = builder.parameters.body_parameter
638
+ if body_param.is_form_data:
639
+ model_type = cast(
640
+ ModelType,
641
+ (
642
+ body_param.type.target_model_subtype((JSONModelType, DPGModelType))
643
+ if isinstance(body_param.type, CombinedType)
644
+ else body_param.type
645
+ ),
646
+ )
647
+ file_fields = [p.wire_name for p in model_type.properties if p.is_multipart_file_input]
648
+ data_fields = [p.wire_name for p in model_type.properties if not p.is_multipart_file_input]
649
+ retval.extend(
650
+ [
651
+ "_body = (",
652
+ f" {body_param.client_name}.as_dict()",
653
+ f" if isinstance({body_param.client_name}, _model_base.Model) else",
654
+ f" {body_param.client_name}",
655
+ ")",
656
+ f"_file_fields: List[str] = {file_fields}",
657
+ f"_data_fields: List[str] = {data_fields}",
658
+ "_files, _data = prepare_multipart_form_data(_body, _file_fields, _data_fields)",
659
+ ]
660
+ )
661
+ return retval
662
+
663
+ body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
664
+ send_xml = builder.parameters.body_parameter.type.is_xml
665
+ xml_serialization_ctxt = body_param.type.xml_serialization_ctxt if send_xml else None
666
+ ser_ctxt_name = "serialization_ctxt"
667
+ if xml_serialization_ctxt and self.code_model.options["models_mode"]:
668
+ retval.append(f'{ser_ctxt_name} = {{"xml": {{{xml_serialization_ctxt}}}}}')
669
+ if self.code_model.options["models_mode"] == "msrest":
670
+ is_xml_cmd = _xml_config(send_xml, builder.parameters.body_parameter.content_types)
671
+ serialization_ctxt_cmd = f", {ser_ctxt_name}={ser_ctxt_name}" if xml_serialization_ctxt else ""
672
+ create_body_call = (
673
+ f"_{body_kwarg_name} = self._serialize.body({body_param.client_name}, "
674
+ f"'{body_param.type.serialization_type}'{is_xml_cmd}{serialization_ctxt_cmd})"
675
+ )
676
+ elif self.code_model.options["models_mode"] == "dpg":
677
+ if _json_serializable(body_param.default_content_type):
678
+ if hasattr(body_param.type, "encode") and body_param.type.encode: # type: ignore
679
+ create_body_call = (
680
+ f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
681
+ "cls=SdkJSONEncoder, exclude_readonly=True, "
682
+ f"format='{body_param.type.encode}') # type: ignore" # type: ignore
683
+ )
684
+ else:
685
+ create_body_call = (
686
+ f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
687
+ "cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore"
688
+ )
689
+ else:
690
+ create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
691
+ else:
692
+ create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
693
+ if body_param.optional:
694
+ retval.append(f"if {body_param.client_name} is not None:")
695
+ retval.append(" " + create_body_call)
696
+ retval.append("else:")
697
+ retval.append(f" _{body_kwarg_name} = None")
698
+ else:
699
+ retval.append(create_body_call)
700
+ return retval
701
+
702
+ def _create_body_parameter(
703
+ self,
704
+ builder: OperationType,
705
+ ) -> List[str]:
706
+ """Create the body parameter before we pass it as either json or content to the request builder"""
707
+ retval = []
708
+ body_param = builder.parameters.body_parameter
709
+ if body_param.entries:
710
+ return _serialize_multipart_body(builder)
711
+ body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
712
+ body_param_type = body_param.type
713
+ if isinstance(body_param_type, BinaryType) or (
714
+ isinstance(body_param.type, ByteArraySchema) and body_param.default_content_type != "application/json"
715
+ ):
716
+ retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
717
+ if (
718
+ not body_param.default_content_type
719
+ and not next(p for p in builder.parameters if p.wire_name.lower() == "content-type").optional
720
+ ):
721
+ content_types = "'" + "', '".join(body_param.content_types) + "'"
722
+ retval.extend(
723
+ [
724
+ "if not content_type:",
725
+ f' raise TypeError("Missing required keyword-only argument: content_type. '
726
+ f'Known values are:" + "{content_types}")',
727
+ ]
728
+ )
729
+ else:
730
+ retval.extend(self._serialize_body_parameter(builder))
731
+ return retval
732
+
733
+ def _initialize_overloads(self, builder: OperationType, is_paging: bool = False) -> List[str]:
734
+ retval: List[str] = []
735
+ # For paging, we put body parameter in local place outside `prepare_request`
736
+ if is_paging:
737
+ return retval
738
+ same_content_type = len(set(o.parameters.body_parameter.default_content_type for o in builder.overloads)) == 1
739
+ if same_content_type:
740
+ default_content_type = builder.overloads[0].parameters.body_parameter.default_content_type
741
+ retval.append(f'content_type = content_type or "{default_content_type}"')
742
+ client_names = [
743
+ overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
744
+ ]
745
+ for v in sorted(set(client_names), key=client_names.index):
746
+ retval.append(f"_{v} = None")
747
+ try:
748
+ # if there is a binary overload, we do a binary check first.
749
+ binary_overload = cast(
750
+ OperationType,
751
+ next((o for o in builder.overloads if isinstance(o.parameters.body_parameter.type, BinaryType))),
752
+ )
753
+ binary_body_param = binary_overload.parameters.body_parameter
754
+ retval.append(f"if {binary_body_param.type.instance_check_template.format(binary_body_param.client_name)}:")
755
+ if binary_body_param.default_content_type and not same_content_type:
756
+ retval.append(f' content_type = content_type or "{binary_body_param.default_content_type}"')
757
+ retval.extend(f" {l}" for l in self._create_body_parameter(binary_overload))
758
+ retval.append("else:")
759
+ other_overload = cast(
760
+ OperationType,
761
+ next((o for o in builder.overloads if not isinstance(o.parameters.body_parameter.type, BinaryType))),
762
+ )
763
+ retval.extend(f" {l}" for l in self._create_body_parameter(other_overload))
764
+ if other_overload.parameters.body_parameter.default_content_type and not same_content_type:
765
+ retval.append(
766
+ " content_type = content_type or "
767
+ f'"{other_overload.parameters.body_parameter.default_content_type}"'
768
+ )
769
+ except StopIteration:
770
+ for idx, overload in enumerate(builder.overloads):
771
+ if_statement = "if" if idx == 0 else "elif"
772
+ body_param = overload.parameters.body_parameter
773
+ retval.append(
774
+ f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
775
+ )
776
+ if body_param.default_content_type and not same_content_type:
777
+ retval.append(f' content_type = content_type or "{body_param.default_content_type}"')
778
+ retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
779
+ return retval
780
+
781
+ def _create_request_builder_call(
782
+ self,
783
+ builder: OperationType,
784
+ request_builder: RequestBuilderType,
785
+ is_next_request: bool = False,
786
+ ) -> List[str]:
787
+ retval: List[str] = []
788
+ if self.code_model.options["builders_visibility"] == "embedded":
789
+ request_path_name = request_builder.name
790
+ else:
791
+ group_name = request_builder.group_name
792
+ request_path_name = "rest{}.{}".format(
793
+ ("_" + group_name) if group_name else "",
794
+ request_builder.name,
795
+ )
796
+ retval.append(f"_request = {request_path_name}(")
797
+ for parameter in request_builder.parameters.method:
798
+ if parameter.location == ParameterLocation.BODY:
799
+ # going to pass in body later based off of overloads
800
+ continue
801
+ if (
802
+ is_next_request
803
+ and builder.operation_type == "paging"
804
+ and not bool(builder.next_request_builder) # type: ignore
805
+ and parameter.location == ParameterLocation.QUERY
806
+ ):
807
+ # if we don't want to reformat query parameters for next link calls
808
+ # in paging operations with a single swagger operation defintion,
809
+ # we skip passing query params when building the next request
810
+ continue
811
+ type_ignore = (
812
+ parameter.grouped_by
813
+ and parameter.client_default_value is not None
814
+ and next(p for p in builder.parameters if p.grouper and p.client_name == parameter.grouped_by).optional
815
+ )
816
+ retval.append(
817
+ f" {parameter.client_name}={parameter.name_in_high_level_operation},"
818
+ f"{' # type: ignore' if type_ignore else ''}"
819
+ )
820
+ if builder.parameters.has_body and builder.parameters.body_parameter.entries:
821
+ # this is for legacy
822
+ client_name = builder.parameters.body_parameter.client_name
823
+ retval.append(f" {client_name}=_{client_name},")
824
+ elif request_builder.has_form_data_body:
825
+ retval.append(" files=_files,")
826
+ retval.append(" data=_data,")
827
+ elif request_builder.overloads:
828
+ seen_body_params = set()
829
+ for overload in request_builder.overloads:
830
+ body_param = cast(RequestBuilderBodyParameter, overload.parameters.body_parameter)
831
+ if body_param.client_name in seen_body_params:
832
+ continue
833
+ seen_body_params.add(body_param.client_name)
834
+
835
+ retval.append(f" {body_param.client_name}={body_param.name_in_high_level_operation},")
836
+ elif request_builder.parameters.has_body:
837
+ body_param = cast(RequestBuilderBodyParameter, request_builder.parameters.body_parameter)
838
+ retval.append(f" {body_param.client_name}={body_param.name_in_high_level_operation},")
839
+ retval.append(" headers=_headers,")
840
+ retval.append(" params=_params,")
841
+ retval.append(")")
842
+ return retval
843
+
844
+ def _postprocess_http_request(self, builder: OperationType, template_url: Optional[str] = None) -> List[str]:
845
+ retval: List[str] = []
846
+ if builder.parameters.path:
847
+ retval.extend(self.serialize_path(builder))
848
+ url_to_format = "_request.url"
849
+ if self.code_model.options["version_tolerant"] and template_url:
850
+ url_to_format = template_url
851
+ retval.append(
852
+ "_request.url = self._client.format_url({}{})".format(
853
+ url_to_format,
854
+ ", **path_format_arguments" if builder.parameters.path else "",
855
+ )
856
+ )
857
+ return retval
858
+
859
+ def _call_request_builder_helper( # pylint: disable=too-many-statements
860
+ self,
861
+ builder: OperationType,
862
+ request_builder: RequestBuilderType,
863
+ template_url: Optional[str] = None,
864
+ is_next_request: bool = False,
865
+ is_paging: bool = False,
866
+ ) -> List[str]:
867
+ retval = []
868
+ if builder.parameters.grouped:
869
+ # request builders don't allow grouped parameters, so we group them before making the call
870
+ retval.extend(_serialize_grouped_body(builder))
871
+ if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
872
+ # unflatten before passing to request builder as well
873
+ retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
874
+ if is_json_model_type(builder.parameters):
875
+ retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters))
876
+ if builder.has_form_data_body:
877
+ retval.extend(self._create_body_parameter(builder))
878
+ elif builder.overloads:
879
+ # we are only dealing with two overloads. If there are three, we generate an abstract operation
880
+ retval.extend(self._initialize_overloads(builder, is_paging=is_paging))
881
+ elif builder.parameters.has_body:
882
+ # non-overloaded body
883
+ retval.extend(self._create_body_parameter(builder))
884
+ retval.append("")
885
+ retval.extend(self._create_request_builder_call(builder, request_builder, is_next_request))
886
+ retval.extend(self._postprocess_http_request(builder, template_url))
887
+ return retval
888
+
889
+ def call_request_builder(self, builder: OperationType, is_paging: bool = False) -> List[str]:
890
+ return self._call_request_builder_helper(builder, builder.request_builder, is_paging=is_paging)
891
+
892
+ def response_headers_and_deserialization(
893
+ self,
894
+ builder: OperationType,
895
+ response: Response,
896
+ ) -> List[str]:
897
+ retval: List[str] = [
898
+ (
899
+ f"response_headers['{response_header.wire_name}']=self._deserialize("
900
+ f"'{response_header.serialization_type}', response.headers.get('{response_header.wire_name}'))"
901
+ )
902
+ for response_header in response.headers
903
+ ]
904
+ if response.headers:
905
+ retval.append("")
906
+ deserialize_code: List[str] = []
907
+ stream_logic = True
908
+ if builder.has_stream_response:
909
+ if isinstance(response.type, ByteArraySchema):
910
+ deserialized = f"{'await ' if self.async_mode else ''}response.read()"
911
+ else:
912
+ stream_logic = False
913
+ if self.code_model.options["version_tolerant"]:
914
+ deserialized = "response.iter_bytes()"
915
+ else:
916
+ deserialized = f"response.stream_download(self._client.{self.pipeline_name})"
917
+ deserialize_code.append(f"deserialized = {deserialized}")
918
+ elif response.type:
919
+ pylint_disable = ""
920
+ if isinstance(response.type, ModelType) and response.type.internal:
921
+ pylint_disable = " # pylint: disable=protected-access"
922
+ if self.code_model.options["models_mode"] == "msrest":
923
+ deserialize_code.append("deserialized = self._deserialize(")
924
+ deserialize_code.append(f" '{response.serialization_type}',{pylint_disable}")
925
+ deserialize_code.append(" pipeline_response.http_response")
926
+ deserialize_code.append(")")
927
+ elif self.code_model.options["models_mode"] == "dpg":
928
+ if builder.has_stream_response:
929
+ deserialize_code.append("deserialized = response.content")
930
+ else:
931
+ format_filed = (
932
+ f', format="{response.type.encode}"'
933
+ if isinstance(response.type, ByteArraySchema)
934
+ and response.default_content_type == "application/json"
935
+ else ""
936
+ )
937
+ response_attr = "json" if _json_serializable(str(response.default_content_type)) else "text"
938
+ deserialize_code.append("deserialized = _deserialize(")
939
+ deserialize_code.append(
940
+ f" {response.type.type_annotation(is_operation_file=True)},{pylint_disable}"
941
+ )
942
+ deserialize_code.append(f" response.{response_attr}(){response.result_property}{format_filed}")
943
+ deserialize_code.append(")")
944
+
945
+ else:
946
+ deserialized_value = "ET.fromstring(response.text())" if response.type.is_xml else "response.json()"
947
+ deserialize_code.append("if response.content:")
948
+ deserialize_code.append(f" deserialized = {deserialized_value}")
949
+ deserialize_code.append("else:")
950
+ deserialize_code.append(" deserialized = None")
951
+ if len(deserialize_code) > 0:
952
+ if builder.expose_stream_keyword and stream_logic:
953
+ retval.append("if _stream:")
954
+ retval.append(" deserialized = response.iter_bytes()")
955
+ retval.append("else:")
956
+ retval.extend([f" {dc}" for dc in deserialize_code])
957
+ else:
958
+ retval.extend(deserialize_code)
959
+ return retval
960
+
961
+ def handle_error_response(self, builder: OperationType) -> List[str]:
962
+ async_await = "await " if self.async_mode else ""
963
+ retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
964
+ response_read = f" {async_await}response.read() # Load the body in memory and close the socket"
965
+ if builder.stream_value is True: # _stream is True so no need to judge it
966
+ retval.append(response_read)
967
+ elif isinstance(builder.stream_value, str): # _stream is not sure, so we need to judge it
968
+ retval.extend([" if _stream:", f" {response_read}"])
969
+ type_ignore = " # type: ignore" if _need_type_ignore(builder) else ""
970
+ retval.append(
971
+ f" map_error(status_code=response.status_code, response=response, error_map=error_map){type_ignore}"
972
+ )
973
+ error_model = ""
974
+ if builder.default_error_deserialization and self.code_model.options["models_mode"]:
975
+ if self.code_model.options["models_mode"] == "dpg":
976
+ retval.append(f" error = _deserialize({builder.default_error_deserialization}, response.json())")
977
+ else:
978
+ retval.append(
979
+ f" error = self._deserialize.failsafe_deserialize({builder.default_error_deserialization}, "
980
+ "pipeline_response)"
981
+ )
982
+ error_model = ", model=error"
983
+ retval.append(
984
+ " raise HttpResponseError(response=response{}{})".format(
985
+ error_model,
986
+ (", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
987
+ )
988
+ )
989
+ return retval
990
+
991
+ def handle_response(self, builder: OperationType) -> List[str]:
992
+ retval: List[str] = ["response = pipeline_response.http_response"]
993
+ retval.append("")
994
+ retval.extend(self.handle_error_response(builder))
995
+ retval.append("")
996
+ if builder.has_optional_return_type:
997
+ retval.append("deserialized = None")
998
+ if builder.any_response_has_headers:
999
+ retval.append("response_headers = {}")
1000
+ if builder.has_response_body or builder.any_response_has_headers:
1001
+ if len(builder.responses) > 1:
1002
+ for status_code in builder.success_status_codes:
1003
+ response = builder.get_response_from_status(status_code)
1004
+ if response.headers or response.type:
1005
+ retval.append(f"if response.status_code == {status_code}:")
1006
+ retval.extend(
1007
+ [f" {line}" for line in self.response_headers_and_deserialization(builder, response)]
1008
+ )
1009
+ retval.append("")
1010
+ else:
1011
+ retval.extend(self.response_headers_and_deserialization(builder, builder.responses[0]))
1012
+ retval.append("")
1013
+ if builder.has_optional_return_type or self.code_model.options["models_mode"]:
1014
+ deserialized = "deserialized"
1015
+ else:
1016
+ deserialized = f"cast({builder.response_type_annotation(async_mode=self.async_mode)}, deserialized)"
1017
+ retval.append("if cls:")
1018
+ retval.append(
1019
+ " return cls(pipeline_response, {}, {}){}".format(
1020
+ deserialized if builder.has_response_body else "None",
1021
+ "response_headers" if builder.any_response_has_headers else "{}",
1022
+ " # type: ignore",
1023
+ )
1024
+ )
1025
+ if builder.has_response_body and any(
1026
+ response.is_stream_response or response.type for response in builder.responses
1027
+ ):
1028
+ retval.append("")
1029
+ retval.append(f"return {deserialized} # type: ignore")
1030
+ if builder.request_builder.method == "HEAD" and self.code_model.options["head_as_boolean"]:
1031
+ retval.append("return 200 <= response.status_code <= 299")
1032
+ return retval
1033
+
1034
+ def error_map(self, builder: OperationType) -> List[str]:
1035
+ retval = ["error_map: MutableMapping[int, Type[HttpResponseError]] = {"]
1036
+ if builder.non_default_errors:
1037
+ if not 401 in builder.non_default_error_status_codes:
1038
+ retval.append(" 401: ClientAuthenticationError,")
1039
+ if not 404 in builder.non_default_error_status_codes:
1040
+ retval.append(" 404: ResourceNotFoundError,")
1041
+ if not 409 in builder.non_default_error_status_codes:
1042
+ retval.append(" 409: ResourceExistsError,")
1043
+ if not 304 in builder.non_default_error_status_codes:
1044
+ retval.append(" 304: ResourceNotModifiedError,")
1045
+ for excep in builder.non_default_errors:
1046
+ error_model_str = ""
1047
+ if isinstance(excep.type, ModelType):
1048
+ if self.code_model.options["models_mode"] == "msrest":
1049
+ error_model_str = (
1050
+ f", model=self._deserialize(" f"_models.{excep.type.serialization_type}, response)"
1051
+ )
1052
+ elif self.code_model.options["models_mode"] == "dpg":
1053
+ error_model_str = f", model=_deserialize(_models.{excep.type.name}, response.json())"
1054
+ error_format_str = ", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""
1055
+ for status_code in excep.status_codes:
1056
+ if status_code == 401:
1057
+ retval.append(
1058
+ " 401: cast(Type[HttpResponseError], "
1059
+ "lambda response: ClientAuthenticationError(response=response"
1060
+ f"{error_model_str}{error_format_str})),"
1061
+ )
1062
+ elif status_code == 404:
1063
+ retval.append(
1064
+ " 404: cast(Type[HttpResponseError], "
1065
+ "lambda response: ResourceNotFoundError(response=response"
1066
+ f"{error_model_str}{error_format_str})),"
1067
+ )
1068
+ elif status_code == 409:
1069
+ retval.append(
1070
+ " 409: cast(Type[HttpResponseError], "
1071
+ "lambda response: ResourceExistsError(response=response"
1072
+ f"{error_model_str}{error_format_str})),"
1073
+ )
1074
+ elif status_code == 304:
1075
+ retval.append(
1076
+ " 304: cast(Type[HttpResponseError], "
1077
+ "lambda response: ResourceNotModifiedError(response=response"
1078
+ f"{error_model_str}{error_format_str})),"
1079
+ )
1080
+ elif not error_model_str and not error_format_str:
1081
+ retval.append(f" {status_code}: HttpResponseError,")
1082
+ else:
1083
+ retval.append(
1084
+ f" {status_code}: cast(Type[HttpResponseError], "
1085
+ "lambda response: HttpResponseError(response=response"
1086
+ f"{error_model_str}{error_format_str})),"
1087
+ )
1088
+ else:
1089
+ retval.append(
1090
+ " 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError, "
1091
+ "304: ResourceNotModifiedError"
1092
+ )
1093
+ retval.append("}")
1094
+ if builder.has_etag:
1095
+ retval.extend(
1096
+ [
1097
+ "if match_condition == MatchConditions.IfNotModified:",
1098
+ " error_map[412] = ResourceModifiedError",
1099
+ "elif match_condition == MatchConditions.IfPresent:",
1100
+ " error_map[412] = ResourceNotFoundError",
1101
+ "elif match_condition == MatchConditions.IfMissing:",
1102
+ " error_map[412] = ResourceExistsError",
1103
+ ]
1104
+ )
1105
+ retval.append("error_map.update(kwargs.pop('error_map', {}) or {})")
1106
+ return retval
1107
+
1108
+ @property
1109
+ def _call_method(self) -> str:
1110
+ return "await " if self.async_mode else ""
1111
+
1112
+
1113
+ class OperationSerializer(_OperationSerializer[Operation]): ...
1114
+
1115
+
1116
+ ############################## PAGING OPERATIONS ##############################
1117
+
1118
+ PagingOperationType = TypeVar("PagingOperationType", bound=Union[PagingOperation, LROPagingOperation])
1119
+
1120
+
1121
+ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]): # pylint: disable=abstract-method
1122
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
1123
+ # for pylint reasons need to redefine init
1124
+ # probably because inheritance is going too deep
1125
+ super().__init__(code_model, async_mode)
1126
+ self.code_model = code_model
1127
+ self.async_mode = async_mode
1128
+ self.parameter_serializer = ParameterSerializer()
1129
+
1130
+ def serialize_path(self, builder: PagingOperationType) -> List[str]:
1131
+ return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
1132
+
1133
+ def decorators(self, builder: PagingOperationType) -> List[str]:
1134
+ """Decorators for the method"""
1135
+ retval: List[str] = []
1136
+ if builder.is_overload:
1137
+ return ["@overload"]
1138
+ if self.code_model.options["tracing"] and builder.want_tracing:
1139
+ retval.append("@distributed_trace")
1140
+ if _api_version_validation(builder):
1141
+ retval.append(_api_version_validation(builder))
1142
+ return retval
1143
+
1144
+ def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
1145
+ if builder.next_request_builder:
1146
+ request_builder = builder.next_request_builder
1147
+ template_url = None
1148
+ else:
1149
+ request_builder = builder.request_builder
1150
+ template_url = "next_link"
1151
+
1152
+ request_builder = builder.next_request_builder or builder.request_builder
1153
+ if builder.next_request_builder:
1154
+ return self._call_request_builder_helper(
1155
+ builder,
1156
+ request_builder,
1157
+ template_url=template_url,
1158
+ is_next_request=True,
1159
+ )
1160
+ retval: List[str] = []
1161
+ query_str = ""
1162
+ next_link_str = "next_link"
1163
+ try:
1164
+ api_version_param = next(
1165
+ p for p in builder.client.parameters if p.is_api_version and p.location == ParameterLocation.QUERY
1166
+ )
1167
+ retval.append("# make call to next link with the client's api-version")
1168
+ retval.append("_parsed_next_link = urllib.parse.urlparse(next_link)")
1169
+ retval.extend(
1170
+ [
1171
+ "_next_request_params = case_insensitive_dict({",
1172
+ " key: [urllib.parse.quote(v) for v in value]"
1173
+ " for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()"
1174
+ "})",
1175
+ ]
1176
+ )
1177
+ api_version = (
1178
+ "self._api_version"
1179
+ if self.code_model.options["multiapi"] and builder.group_name
1180
+ else api_version_param.full_client_name
1181
+ )
1182
+ retval.append(f'_next_request_params["api-version"] = {api_version}')
1183
+ query_str = ", params=_next_request_params"
1184
+ next_link_str = "urllib.parse.urljoin(next_link, _parsed_next_link.path)"
1185
+ except StopIteration:
1186
+ pass
1187
+
1188
+ retval.append(f'_request = HttpRequest("GET", {next_link_str}{query_str})')
1189
+ retval.extend(self._postprocess_http_request(builder, "_request.url"))
1190
+
1191
+ return retval
1192
+
1193
+ def _prepare_request_callback(self, builder: PagingOperationType) -> List[str]:
1194
+ retval = self._initialize_overloads(builder)
1195
+ retval.append("def prepare_request(next_link=None):")
1196
+ retval.append(" if not next_link:")
1197
+ retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
1198
+ retval.append("")
1199
+ retval.append(" else:")
1200
+ retval.extend([f" {line}" for line in self.call_next_link_request_builder(builder)])
1201
+ if not builder.next_request_builder and self.code_model.is_legacy:
1202
+ retval.append(' _request.method = "GET"')
1203
+ else:
1204
+ retval.append("")
1205
+ retval.append(" return _request")
1206
+ return retval
1207
+
1208
+ @property
1209
+ def _function_def(self) -> str:
1210
+ return "def"
1211
+
1212
+ def _extract_data_callback(self, builder: PagingOperationType) -> List[str]:
1213
+ retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
1214
+ response = builder.responses[0]
1215
+ deserialized = "pipeline_response.http_response.json()"
1216
+ if self.code_model.options["models_mode"] == "msrest":
1217
+ suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
1218
+ deserialize_type = response.serialization_type
1219
+ pylint_disable = " # pylint: disable=protected-access"
1220
+ if isinstance(response.type, ModelType) and not response.type.internal:
1221
+ deserialize_type = f'"{response.serialization_type}"'
1222
+ pylint_disable = ""
1223
+ deserialized = (
1224
+ f"self._deserialize(\n {deserialize_type},{pylint_disable}\n pipeline_response{suffix}\n)"
1225
+ )
1226
+ retval.append(f" deserialized = {deserialized}")
1227
+ elif self.code_model.options["models_mode"] == "dpg":
1228
+ # we don't want to generate paging models for DPG
1229
+ retval.append(f" deserialized = {deserialized}")
1230
+ else:
1231
+ retval.append(f" deserialized = {deserialized}")
1232
+ item_name = builder.item_name
1233
+ access = f".{item_name}" if self.code_model.options["models_mode"] == "msrest" else f'["{item_name}"]'
1234
+ list_of_elem_deserialized = ""
1235
+ if self.code_model.options["models_mode"] == "dpg":
1236
+ item_type = builder.item_type.type_annotation(is_operation_file=True)
1237
+ list_of_elem_deserialized = f"_deserialize({item_type}, deserialized{access})"
1238
+ else:
1239
+ list_of_elem_deserialized = f"deserialized{access}"
1240
+ retval.append(f" list_of_elem = {list_of_elem_deserialized}")
1241
+ retval.append(" if cls:")
1242
+ retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
1243
+
1244
+ continuation_token_name = builder.continuation_token_name
1245
+ if not continuation_token_name:
1246
+ cont_token_property = "None"
1247
+ elif self.code_model.options["models_mode"] == "msrest":
1248
+ cont_token_property = f"deserialized.{continuation_token_name} or None"
1249
+ else:
1250
+ cont_token_property = f'deserialized.get("{continuation_token_name}") or None'
1251
+ list_type = "AsyncList" if self.async_mode else "iter"
1252
+ retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
1253
+ return retval
1254
+
1255
+ def _get_next_callback(self, builder: PagingOperationType) -> List[str]:
1256
+ retval = [f"{'async ' if self.async_mode else ''}def get_next(next_link=None):"]
1257
+ retval.append(" _request = prepare_request(next_link)")
1258
+ retval.append("")
1259
+ retval.extend([f" {l}" for l in self.make_pipeline_call(builder)])
1260
+ retval.append(" response = pipeline_response.http_response")
1261
+ retval.append("")
1262
+ retval.extend([f" {line}" for line in self.handle_error_response(builder)])
1263
+ retval.append("")
1264
+ retval.append(" return pipeline_response")
1265
+ return retval
1266
+
1267
+ def set_up_params_for_pager(self, builder: PagingOperationType) -> List[str]:
1268
+ retval = []
1269
+ retval.extend(self.error_map(builder))
1270
+ retval.extend(self._prepare_request_callback(builder))
1271
+ retval.append("")
1272
+ retval.extend(self._extract_data_callback(builder))
1273
+ retval.append("")
1274
+ retval.extend(self._get_next_callback(builder))
1275
+ return retval
1276
+
1277
+
1278
+ class PagingOperationSerializer(_PagingOperationSerializer[PagingOperation]): ...
1279
+
1280
+
1281
+ ############################## LRO OPERATIONS ##############################
1282
+
1283
+ LROOperationType = TypeVar("LROOperationType", bound=Union[LROOperation, LROPagingOperation])
1284
+
1285
+
1286
+ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1287
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
1288
+ # for pylint reasons need to redefine init
1289
+ # probably because inheritance is going too deep
1290
+ super().__init__(code_model, async_mode)
1291
+ self.code_model = code_model
1292
+ self.async_mode = async_mode
1293
+ self.parameter_serializer = ParameterSerializer()
1294
+
1295
+ def serialize_path(self, builder: LROOperationType) -> List[str]:
1296
+ return self.parameter_serializer.serialize_path(builder.parameters.path, self.serializer_name)
1297
+
1298
+ def initial_call(self, builder: LROOperationType) -> List[str]:
1299
+ retval = [
1300
+ f"polling: Union[bool, {builder.get_base_polling_method(self.async_mode)}] = kwargs.pop('polling', True)",
1301
+ ]
1302
+ retval.append("lro_delay = kwargs.pop(")
1303
+ retval.append(" 'polling_interval',")
1304
+ retval.append(" self._config.polling_interval")
1305
+ retval.append(")")
1306
+ retval.append("cont_token: Optional[str] = kwargs.pop('continuation_token', None)")
1307
+ retval.append("if cont_token is None:")
1308
+ retval.append(
1309
+ f" raw_result = {self._call_method}self.{builder.initial_operation.name}("
1310
+ f"{'' if any(rsp.type for rsp in builder.initial_operation.responses) else ' # type: ignore'}"
1311
+ )
1312
+ retval.extend(
1313
+ [f" {parameter.client_name}={parameter.client_name}," for parameter in builder.parameters.method]
1314
+ )
1315
+ retval.append(" cls=lambda x,y,z: x,")
1316
+ retval.append(" headers=_headers,")
1317
+ retval.append(" params=_params,")
1318
+ retval.append(" **kwargs")
1319
+ retval.append(" )")
1320
+ retval.append(f" {'await ' if self.async_mode else ''}raw_result.http_response.read() # type: ignore")
1321
+
1322
+ retval.append("kwargs.pop('error_map', None)")
1323
+ return retval
1324
+
1325
+ def return_lro_poller(self, builder: LROOperationType) -> List[str]:
1326
+ retval = []
1327
+ lro_options_str = (
1328
+ "lro_options={'final-state-via': '" + builder.lro_options["final-state-via"] + "'},"
1329
+ if builder.lro_options
1330
+ else ""
1331
+ )
1332
+ path_format_arguments_str = ""
1333
+ if builder.parameters.path:
1334
+ path_format_arguments_str = "path_format_arguments=path_format_arguments,"
1335
+ retval.extend(self.serialize_path(builder))
1336
+ retval.append("")
1337
+ retval.extend(
1338
+ [
1339
+ "if polling is True:",
1340
+ f" polling_method: {builder.get_base_polling_method(self.async_mode)} "
1341
+ + f"= cast({builder.get_base_polling_method(self.async_mode)}, "
1342
+ f"{builder.get_polling_method(self.async_mode)}(",
1343
+ " lro_delay,",
1344
+ f" {lro_options_str}",
1345
+ f" {path_format_arguments_str}",
1346
+ " **kwargs",
1347
+ "))",
1348
+ ]
1349
+ )
1350
+ retval.append(
1351
+ f"elif polling is False: polling_method = cast({builder.get_base_polling_method(self.async_mode)}, "
1352
+ f"{builder.get_no_polling_method(self.async_mode)}())"
1353
+ )
1354
+ retval.append("else: polling_method = polling")
1355
+ retval.append("if cont_token:")
1356
+ retval.append(f" return {builder.get_poller_with_response_type(self.async_mode)}.from_continuation_token(")
1357
+ retval.append(" polling_method=polling_method,")
1358
+ retval.append(" continuation_token=cont_token,")
1359
+ retval.append(" client=self._client,")
1360
+ retval.append(" deserialization_callback=get_long_running_output")
1361
+ retval.append(" )")
1362
+ retval.append(f"return {builder.get_poller_with_response_type(self.async_mode)}(")
1363
+ retval.append(" self._client, raw_result, get_long_running_output, polling_method # type: ignore")
1364
+ retval.append(" )")
1365
+ return retval
1366
+
1367
+ def get_long_running_output(self, builder: LROOperationType) -> List[str]:
1368
+ pylint_disable = ""
1369
+ if not builder.lro_response:
1370
+ pylint_disable = " # pylint: disable=inconsistent-return-statements"
1371
+ retval = [f"def get_long_running_output(pipeline_response):{pylint_disable}"]
1372
+ if builder.lro_response:
1373
+ if builder.lro_response.headers:
1374
+ retval.append(" response_headers = {}")
1375
+ if (
1376
+ not self.code_model.options["models_mode"]
1377
+ or self.code_model.options["models_mode"] == "dpg"
1378
+ or builder.lro_response.headers
1379
+ ):
1380
+ retval.append(" response = pipeline_response.http_response")
1381
+ retval.extend(
1382
+ [f" {line}" for line in self.response_headers_and_deserialization(builder, builder.lro_response)]
1383
+ )
1384
+ retval.append(" if cls:")
1385
+ retval.append(
1386
+ " return cls(pipeline_response, {}, {}){}".format(
1387
+ ("deserialized" if builder.lro_response and builder.lro_response.type else "None"),
1388
+ ("response_headers" if builder.lro_response and builder.lro_response.headers else "{}"),
1389
+ " # type: ignore",
1390
+ )
1391
+ )
1392
+ if builder.lro_response and builder.lro_response.type:
1393
+ retval.append(" return deserialized")
1394
+ return retval
1395
+
1396
+
1397
+ class LROOperationSerializer(_LROOperationSerializer[LROOperation]): ...
1398
+
1399
+
1400
+ ############################## LRO PAGING OPERATIONS ##############################
1401
+
1402
+
1403
+ class LROPagingOperationSerializer(
1404
+ _LROOperationSerializer[LROPagingOperation],
1405
+ _PagingOperationSerializer[LROPagingOperation],
1406
+ ): # pylint: disable=abstract-method
1407
+ @property
1408
+ def _call_method(self) -> str:
1409
+ return "await " if self.async_mode else ""
1410
+
1411
+ @property
1412
+ def _function_def(self) -> str:
1413
+ return "async def" if self.async_mode else "def"
1414
+
1415
+ def get_long_running_output(self, builder: LROPagingOperation) -> List[str]:
1416
+ retval = ["def get_long_running_output(pipeline_response):"]
1417
+ retval.append(f" {self._function_def} internal_get_next(next_link=None):")
1418
+ retval.append(" if next_link is None:")
1419
+ retval.append(" return pipeline_response")
1420
+ retval.append(f" return {self._call_method}get_next(next_link)")
1421
+ retval.append("")
1422
+ retval.append(f" return {builder.get_pager(self.async_mode)}(")
1423
+ retval.append(" internal_get_next, extract_data")
1424
+ retval.append(" )")
1425
+ return retval
1426
+
1427
+ def decorators(self, builder: LROPagingOperation) -> List[str]:
1428
+ """Decorators for the method"""
1429
+ return _LROOperationSerializer.decorators(self, builder) # type: ignore
1430
+
1431
+
1432
+ def get_operation_serializer(
1433
+ builder: Operation,
1434
+ code_model,
1435
+ async_mode: bool,
1436
+ ) -> Union[
1437
+ OperationSerializer,
1438
+ PagingOperationSerializer,
1439
+ LROOperationSerializer,
1440
+ LROPagingOperationSerializer,
1441
+ ]:
1442
+ retcls: Union[
1443
+ Type[OperationSerializer],
1444
+ Type[PagingOperationSerializer],
1445
+ Type[LROOperationSerializer],
1446
+ Type[LROPagingOperationSerializer],
1447
+ ] = OperationSerializer
1448
+ if builder.operation_type == "lropaging":
1449
+ retcls = LROPagingOperationSerializer
1450
+ elif builder.operation_type == "lro":
1451
+ retcls = LROOperationSerializer
1452
+ elif builder.operation_type == "paging":
1453
+ retcls = PagingOperationSerializer
1454
+ return retcls(code_model, async_mode)