@autorest/python 5.15.0 → 5.18.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 (118) hide show
  1. package/ChangeLog.md +98 -4
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +2 -3
  4. package/autorest/black/__init__.py +12 -5
  5. package/autorest/codegen/__init__.py +122 -211
  6. package/autorest/codegen/models/__init__.py +122 -78
  7. package/autorest/codegen/models/base_builder.py +70 -72
  8. package/autorest/codegen/models/base_model.py +7 -5
  9. package/autorest/codegen/models/{base_schema.py → base_type.py} +68 -45
  10. package/autorest/codegen/models/client.py +193 -40
  11. package/autorest/codegen/models/code_model.py +145 -245
  12. package/autorest/codegen/models/combined_type.py +107 -0
  13. package/autorest/codegen/models/constant_type.py +122 -0
  14. package/autorest/codegen/models/credential_types.py +224 -0
  15. package/autorest/codegen/models/dictionary_type.py +131 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +93 -41
  18. package/autorest/codegen/models/list_type.py +149 -0
  19. package/autorest/codegen/models/lro_operation.py +90 -133
  20. package/autorest/codegen/models/lro_paging_operation.py +28 -12
  21. package/autorest/codegen/models/model_type.py +262 -0
  22. package/autorest/codegen/models/operation.py +412 -259
  23. package/autorest/codegen/models/operation_group.py +80 -91
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +302 -341
  26. package/autorest/codegen/models/parameter_list.py +373 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +136 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -86
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +13 -17
  33. package/autorest/codegen/serializers/__init__.py +212 -112
  34. package/autorest/codegen/serializers/builder_serializer.py +931 -1040
  35. package/autorest/codegen/serializers/client_serializer.py +140 -84
  36. package/autorest/codegen/serializers/general_serializer.py +26 -50
  37. package/autorest/codegen/serializers/import_serializer.py +96 -31
  38. package/autorest/codegen/serializers/metadata_serializer.py +39 -79
  39. package/autorest/codegen/serializers/model_base_serializer.py +62 -34
  40. package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
  41. package/autorest/codegen/serializers/model_init_serializer.py +4 -2
  42. package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
  43. package/autorest/codegen/serializers/operation_groups_serializer.py +21 -19
  44. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  45. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  46. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -126
  49. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  50. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  51. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  52. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  53. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  54. package/autorest/codegen/templates/init.py.jinja2 +3 -3
  55. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  56. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  58. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  59. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  60. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  61. package/autorest/codegen/templates/operation.py.jinja2 +10 -14
  62. package/autorest/codegen/templates/operation_group.py.jinja2 +9 -15
  63. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  64. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  65. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  66. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -10
  67. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  68. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  69. package/autorest/jsonrpc/__init__.py +7 -12
  70. package/autorest/jsonrpc/localapi.py +4 -3
  71. package/autorest/jsonrpc/server.py +28 -9
  72. package/autorest/jsonrpc/stdstream.py +13 -6
  73. package/autorest/m2r/__init__.py +5 -8
  74. package/autorest/m4reformatter/__init__.py +1126 -0
  75. package/autorest/multiapi/__init__.py +24 -14
  76. package/autorest/multiapi/models/client.py +21 -11
  77. package/autorest/multiapi/models/code_model.py +23 -10
  78. package/autorest/multiapi/models/config.py +4 -1
  79. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  80. package/autorest/multiapi/models/global_parameter.py +2 -1
  81. package/autorest/multiapi/models/global_parameters.py +14 -8
  82. package/autorest/multiapi/models/imports.py +24 -17
  83. package/autorest/multiapi/models/mixin_operation.py +5 -5
  84. package/autorest/multiapi/models/operation_group.py +2 -1
  85. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  86. package/autorest/multiapi/serializers/__init__.py +20 -25
  87. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  88. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  89. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  90. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  91. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  92. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  93. package/autorest/multiapi/utils.py +3 -3
  94. package/autorest/postprocess/__init__.py +202 -0
  95. package/autorest/postprocess/get_all.py +19 -0
  96. package/autorest/postprocess/venvtools.py +73 -0
  97. package/autorest/preprocess/__init__.py +210 -0
  98. package/autorest/preprocess/helpers.py +54 -0
  99. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  100. package/package.json +3 -3
  101. package/run-python3.js +2 -3
  102. package/venvtools.py +1 -1
  103. package/autorest/codegen/models/constant_schema.py +0 -101
  104. package/autorest/codegen/models/credential_model.py +0 -47
  105. package/autorest/codegen/models/credential_schema.py +0 -91
  106. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  107. package/autorest/codegen/models/dictionary_schema.py +0 -103
  108. package/autorest/codegen/models/enum_schema.py +0 -215
  109. package/autorest/codegen/models/list_schema.py +0 -123
  110. package/autorest/codegen/models/object_schema.py +0 -253
  111. package/autorest/codegen/models/primitive_schemas.py +0 -466
  112. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  113. package/autorest/codegen/models/rest.py +0 -42
  114. package/autorest/codegen/models/schema_request.py +0 -45
  115. package/autorest/codegen/models/schema_response.py +0 -136
  116. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  117. package/autorest/namer/__init__.py +0 -25
  118. package/autorest/namer/name_converter.py +0 -412
@@ -4,11 +4,11 @@
4
4
  # Licensed under the MIT License. See License.txt in the project root for
5
5
  # license information.
6
6
  # --------------------------------------------------------------------------
7
- from itertools import groupby
8
7
  import json
8
+ from abc import abstractmethod
9
9
  from collections import defaultdict
10
- from abc import abstractmethod, ABC
11
- from typing import Any, List, TypeVar, Dict, Union, Optional, cast
10
+ from typing import Any, Generic, List, Type, TypeVar, Dict, Union, Optional, cast
11
+
12
12
 
13
13
  from ..models import (
14
14
  Operation,
@@ -16,514 +16,443 @@ from ..models import (
16
16
  PagingOperation,
17
17
  LROOperation,
18
18
  LROPagingOperation,
19
- ObjectSchema,
20
- DictionarySchema,
21
- ListSchema,
22
- BaseSchema,
19
+ ModelType,
20
+ DictionaryType,
21
+ ListType,
23
22
  Parameter,
24
23
  RequestBuilder,
25
- RequestBuilderParameter,
26
- EnumSchema,
27
- SchemaResponse,
28
- IOSchema,
29
- ParameterStyle,
30
- ParameterLocation
24
+ ParameterLocation,
25
+ Response,
26
+ BinaryType,
27
+ BodyParameter,
28
+ ParameterMethodLocation,
29
+ RequestBuilderBodyParameter,
30
+ OverloadedRequestBuilder,
31
+ ConstantType,
32
+ MultipartBodyParameter,
33
+ Property,
34
+ RequestBuilderType,
31
35
  )
36
+ from .parameter_serializer import ParameterSerializer, PopKwargType
32
37
  from . import utils
33
38
 
34
39
  T = TypeVar("T")
35
40
  OrderedSet = Dict[T, None]
36
41
 
42
+ BuilderType = TypeVar(
43
+ "BuilderType",
44
+ bound=Union[
45
+ RequestBuilder,
46
+ Operation,
47
+ PagingOperation,
48
+ LROOperation,
49
+ LROPagingOperation,
50
+ OverloadedRequestBuilder,
51
+ ],
52
+ )
53
+ OperationType = TypeVar(
54
+ "OperationType",
55
+ bound=Union[Operation, PagingOperation, LROOperation, LROPagingOperation],
56
+ )
57
+
58
+
37
59
  def _escape_str(input_str: str) -> str:
38
60
  replace = input_str.replace("'", "\\'")
39
61
  return f'"{replace}"'
40
62
 
63
+
41
64
  def _improve_json_string(template_representation: str) -> Any:
42
- origin = template_representation.split('\n')
65
+ origin = template_representation.split("\n")
43
66
  final = []
44
67
  for line in origin:
45
- idx0 = line.find('#')
68
+ idx0 = line.find("#")
46
69
  idx1 = line.rfind('"')
47
70
  modified_line = ""
48
71
  if idx0 > -1 and idx1 > -1:
49
- modified_line = line[:idx0] + line[idx1:] + ' ' + line[idx0:idx1] + '\n'
72
+ modified_line = line[:idx0] + line[idx1:] + " " + line[idx0:idx1] + "\n"
50
73
  else:
51
- modified_line = line + '\n'
74
+ modified_line = line + "\n"
52
75
  modified_line = modified_line.replace('"', "").replace("\\", '"')
53
76
  final.append(modified_line)
54
- return ''.join(final)
77
+ return "".join(final)
78
+
55
79
 
56
80
  def _json_dumps_template(template_representation: Any) -> Any:
57
81
  # only for template use, since it wraps everything in strings
58
- return _improve_json_string(json.dumps(template_representation, sort_keys=True, indent=4))
59
-
60
- def _serialize_files_or_data_dict(multipart_parameters: List[Parameter]) -> str:
61
- # only for template use
62
- template = {
63
- f'"{param.serialized_name}"': param.schema.get_files_and_data_template_representation(
64
- optional=not param.required,
65
- description=param.description,
66
- )
67
- for param in multipart_parameters
68
- }
69
- return _json_dumps_template(template)
70
-
71
- def _get_files_example_template(builder) -> List[str]:
72
- multipart_params = builder.parameters.multipart
73
- if multipart_params:
74
- retval = [
75
- "# multipart input template you can fill out and use as your `files` input.",
76
- ]
77
- retval.extend(f"files = {_serialize_files_or_data_dict(multipart_params)}".splitlines())
78
- return retval
79
- raise ValueError(
80
- "You're trying to get a template for your multipart params, but you don't have multipart params"
82
+ return _improve_json_string(
83
+ json.dumps(template_representation, sort_keys=True, indent=4)
81
84
  )
82
85
 
83
- def _get_data_example_template(builder) -> List[str]:
84
- data_inputs = builder.parameters.data_inputs
85
- if data_inputs:
86
- retval = [
87
- "# form-encoded input template you can fill out and use as your `data` input."
88
- ]
89
- retval.extend(f"data = {_serialize_files_or_data_dict(data_inputs)}".splitlines())
90
- return retval
91
- raise ValueError(
92
- "You're trying to get a template for your form-encoded params, but you don't have form-encoded params"
86
+
87
+ def _get_polymorphic_subtype_template(polymorphic_subtype: ModelType) -> List[str]:
88
+ retval: List[str] = []
89
+ retval.append("")
90
+ retval.append(
91
+ f'# JSON input template for discriminator value "{polymorphic_subtype.discriminator_value}":'
92
+ )
93
+ subtype_template = _json_dumps_template(
94
+ polymorphic_subtype.get_json_template_representation(),
93
95
  )
94
96
 
95
- def _content_type_error_check(builder) -> List[str]:
96
- retval = ["else:"]
97
- retval.append(" raise ValueError(")
98
- retval.append(" \"The content_type '{}' is not one of the allowed values: \"")
99
- retval.append(f' "{builder.parameters.content_types}".format(content_type)')
100
- retval.append(" )")
97
+ def _get_polymorphic_parent(
98
+ polymorphic_subtype: Optional[ModelType],
99
+ ) -> Optional[ModelType]:
100
+ if not polymorphic_subtype:
101
+ return None
102
+ try:
103
+ return next(
104
+ p for p in polymorphic_subtype.parents if p.discriminated_subtypes
105
+ )
106
+ except StopIteration:
107
+ return None
108
+
109
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_subtype)
110
+ while _get_polymorphic_parent(polymorphic_parent):
111
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_parent)
112
+ retval.extend(
113
+ f"{cast(ModelType, polymorphic_parent).snake_case_name} = {subtype_template}".splitlines()
114
+ )
101
115
  return retval
102
116
 
103
- def _serialize_files_and_data_body(builder, param_name: str) -> List[str]:
104
- retval: List[str] = []
105
- # we have to construct our form data before passing to the request as well
106
- retval.append("# Construct form data")
107
- retval.append(f"{param_name} = {{")
108
- for param in builder.parameters.body:
109
- retval.append(f' "{param.rest_api_name}": {param.serialized_name},')
110
- retval.append("}")
111
- return retval
112
117
 
113
- def _serialize_grouped_body(builder) -> List[str]:
118
+ def _serialize_grouped_body(builder: BuilderType) -> List[str]:
114
119
  retval: List[str] = []
115
120
  for grouped_parameter in builder.parameters.grouped:
116
- retval.append(f"{grouped_parameter.serialized_name} = None")
117
- for grouper_name, grouped_parameters in groupby(
118
- builder.parameters.grouped, key=lambda a: cast(Parameter, a.grouped_by).serialized_name
119
- ):
120
- retval.append(f"if {grouper_name} is not None:")
121
- for grouped_parameter in grouped_parameters:
122
- retval.append(
123
- f" {grouped_parameter.serialized_name} = "
124
- f"{ grouper_name }.{ grouped_parameter.corresponding_grouped_property.name }"
125
- )
121
+ retval.append(f"{grouped_parameter.client_name} = None")
122
+ groupers = [p for p in builder.parameters if p.grouper]
123
+ for grouper in groupers:
124
+ retval.append(f"if {grouper.client_name} is not None:")
125
+ retval.extend(
126
+ [
127
+ f" {parameter} = {grouper.client_name}.{property}"
128
+ for property, parameter in grouper.property_to_parameter_name.items()
129
+ ]
130
+ )
126
131
  return retval
127
132
 
128
- def _serialize_flattened_body(builder) -> List[str]:
133
+
134
+ def _serialize_flattened_body(body_parameter: BodyParameter) -> List[str]:
129
135
  retval: List[str] = []
130
- if not builder.parameters.is_flattened:
136
+ if not body_parameter.property_to_parameter_name:
131
137
  raise ValueError(
132
138
  "This method can't be called if the operation doesn't need parameter flattening"
133
139
  )
134
140
 
135
- parameters = builder.parameters.get_from_predicate(
136
- lambda parameter: parameter.in_method_code
137
- )
138
141
  parameter_string = ", ".join(
139
- [f"{param.target_property_name}={param.serialized_name}"
140
- for param in parameters if param.target_property_name
141
- ]
142
+ f"{property_name}={parameter_name}"
143
+ for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
142
144
  )
143
- object_schema = cast(ObjectSchema, builder.parameters.body[0].schema)
145
+ model_type = cast(ModelType, body_parameter.type)
144
146
  retval.append(
145
- f"{builder.parameters.body[0].serialized_name} = _models.{object_schema.name}({parameter_string})"
147
+ f"{body_parameter.client_name} = _models.{model_type.name}({parameter_string})"
146
148
  )
147
149
  return retval
148
150
 
149
- def _content_type_docstring(builder) -> str:
150
- content_types = [f'"{c}"' for c in builder.parameters.content_types]
151
- if len(content_types) == 2:
152
- possible_values_str = " or ".join(content_types)
153
- else:
154
- possible_values_str = ", ".join(
155
- content_types[: len(content_types) - 1]
156
- ) + f", and {content_types[-1]}"
157
- default_value = next(
158
- p for p in builder.parameters.method if p.rest_api_name == "Content-Type"
159
- ).default_value_declaration
160
- return (
161
- ":keyword content_type: Media type of the body sent to the API. " +
162
- f"Known values are: {possible_values_str}. " +
163
- f"Default value is {default_value}."
164
- )
165
151
 
166
- class _BuilderSerializerProtocol(ABC):
167
- @property
168
- @abstractmethod
169
- def _is_in_class(self) -> bool:
170
- ...
152
+ def _serialize_multipart_body(builder: BuilderType) -> List[str]:
153
+ retval: List[str] = []
154
+ body_param = cast(MultipartBodyParameter, builder.parameters.body_parameter)
155
+ # we have to construct our form data before passing to the request as well
156
+ retval.append("# Construct form data")
157
+ retval.append(f"_{body_param.client_name} = {{")
158
+ for param in body_param.entries:
159
+ retval.append(f' "{param.rest_api_name}": {param.client_name},')
160
+ retval.append("}")
161
+ return retval
171
162
 
172
- @property
173
- @abstractmethod
174
- def _function_definition(self) -> str:
175
- """The def keyword for the builder we're serializing, i.e. 'def' or 'async def'"""
176
- ...
177
163
 
178
- @property
179
- @abstractmethod
180
- def _def(self) -> str:
181
- """The general definition of a function, i.e. def or async def"""
182
- ...
164
+ def _get_json_response_template_to_status_codes(
165
+ builder: OperationType,
166
+ ) -> Dict[str, List[str]]:
167
+ retval = defaultdict(list)
168
+ for response in builder.responses:
169
+ json_template = response.get_json_template_representation()
170
+ if not json_template:
171
+ continue
172
+ status_codes = [str(status_code) for status_code in response.status_codes]
173
+ response_json = _json_dumps_template(json_template)
174
+ retval[response_json].extend(status_codes)
175
+ return retval
183
176
 
184
- @property
185
- @abstractmethod
186
- def _want_inline_type_hints(self) -> bool:
187
- """Whether you want inline type hints. If false, your type hints will be commented'"""
188
- ...
189
177
 
190
- @abstractmethod
191
- def _response_type_annotation(self, builder, modify_if_head_as_boolean: bool = True) -> str:
192
- """The mypy type annotation for the response"""
193
- ...
178
+ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-method
179
+ def __init__(
180
+ self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
181
+ ) -> None:
182
+ self.code_model = code_model
183
+ self.async_mode = async_mode
184
+ self.is_python3_file = is_python3_file
185
+ self.parameter_serializer = ParameterSerializer()
194
186
 
187
+ @property
195
188
  @abstractmethod
196
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
197
- """Any wrappers that you want to go around the response type annotation"""
189
+ def _need_self_param(self) -> bool:
198
190
  ...
199
191
 
200
- @staticmethod
192
+ @property
201
193
  @abstractmethod
202
- def _method_signature_and_response_type_annotation_template(
203
- method_signature: str, response_type_annotation: str
204
- ) -> str:
205
- """Template for how to combine the method signature + the response type annotation together. Called by
206
- method_signature_and_response_type_annotation"""
194
+ def _function_def(self) -> str:
195
+ """The def keyword for the builder we're serializing, i.e. 'def' or 'async def'"""
207
196
  ...
208
197
 
198
+ @property
209
199
  @abstractmethod
210
- def method_signature_and_response_type_annotation(self, builder) -> str:
211
- """Combines the method signature + the response type annotation together"""
200
+ def _call_method(self) -> str:
201
+ """How to call network calls. Await if we have to await network calls"""
212
202
  ...
213
203
 
204
+ @property
214
205
  @abstractmethod
215
- def description_and_summary(self, builder) -> List[str]:
216
- """Description + summary from the swagger. Will be formatted into the overall operation description"""
206
+ def serializer_name(self) -> str:
217
207
  ...
218
208
 
219
209
  @abstractmethod
220
- def response_docstring(self, builder) -> List[str]:
210
+ def response_docstring(self, builder: BuilderType) -> List[str]:
221
211
  """Response portion of the docstring"""
222
212
  ...
223
213
 
224
- @abstractmethod
225
- def want_example_template(self, builder) -> bool:
226
- ...
227
-
228
- @abstractmethod
229
- def get_example_template(self, builder) -> List[str]:
230
- ...
231
-
232
- @abstractmethod
233
- def _get_json_example_template(self, builder) -> List[str]:
234
- ...
235
-
236
- @abstractmethod
237
- def _has_json_example_template(self, builder) -> bool:
238
- ...
239
-
240
- @abstractmethod
241
- def _has_files_example_template(self, builder) -> bool:
242
- ...
243
- @abstractmethod
244
- def _has_data_example_template(self, builder) -> bool:
245
- ...
246
-
247
- @abstractmethod
248
- def _json_example_param_name(self, builder) -> str:
249
- ...
250
-
251
- @abstractmethod
252
- def _get_json_response_template(self, builder) -> List[str]:
253
- ...
254
-
255
- @abstractmethod
256
- def _get_json_response_template_to_status_codes(self, builder) -> Dict[str, List[str]]:
257
- ...
258
-
259
- @abstractmethod
260
- def _get_kwargs_to_pop(self, builder) -> List[Parameter]:
261
- ...
262
-
263
- class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abstract-method
264
- def __init__(self, code_model: CodeModel) -> None:
265
- self.code_model = code_model
266
-
267
- @property
268
- def _cls_docstring_rtype(self) -> str:
269
- return "" if self.code_model.options["version_tolerant"] else " or the result of cls(response)"
214
+ def decorators(self, builder: BuilderType) -> List[str]:
215
+ """Decorators for the method"""
216
+ retval: List[str] = []
217
+ if builder.is_overload:
218
+ return ["@overload"]
219
+ if self.code_model.options["tracing"] and builder.want_tracing:
220
+ retval.append(f"@distributed_trace{'_async' if self.async_mode else ''}")
221
+ return retval
270
222
 
271
- def _method_signature(self, builder: Operation, response_type_annotation: str) -> str:
272
- return utils.serialize_method(
273
- function_def=self._function_definition,
223
+ def _method_signature(self, builder: BuilderType) -> str:
224
+ return self.parameter_serializer.serialize_method(
225
+ function_def=self._function_def,
274
226
  method_name=builder.name,
275
- is_in_class=self._is_in_class,
276
- method_param_signatures=builder.parameters.method_signature(self._want_inline_type_hints),
277
- ignore_inconsistent_return_statements=(response_type_annotation == "None")
227
+ need_self_param=self._need_self_param,
228
+ method_param_signatures=builder.method_signature(
229
+ self.async_mode or self.is_python3_file, self.async_mode
230
+ ),
231
+ pylint_disable=builder.pylint_disable,
278
232
  )
279
233
 
280
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
281
- return []
282
-
283
- def method_signature_and_response_type_annotation(self, builder) -> str:
284
- response_type_annotation = self._response_type_annotation(builder)
285
- # want pre-wrapped response type. As long as it's None, pylint will get mad about inconsistent return types
286
- method_signature = self._method_signature(builder, response_type_annotation)
287
- for wrapper in self._response_type_annotation_wrapper(builder)[::-1]:
288
- response_type_annotation = f"{wrapper}[{response_type_annotation}]"
289
- return self._method_signature_and_response_type_annotation_template(method_signature, response_type_annotation)
234
+ def method_signature_and_response_type_annotation(
235
+ self, builder: BuilderType, *, want_decorators: Optional[bool] = True
236
+ ) -> str:
237
+ response_type_annotation = builder.response_type_annotation(
238
+ async_mode=self.async_mode
239
+ )
240
+ method_signature = self._method_signature(builder)
241
+ decorators = self.decorators(builder)
242
+ decorators_str = ""
243
+ if decorators and want_decorators:
244
+ decorators_str = "\n".join(decorators) + "\n"
245
+ return (
246
+ decorators_str
247
+ + utils.method_signature_and_response_type_annotation_template(
248
+ is_python3_file=self.is_python3_file,
249
+ method_signature=method_signature,
250
+ response_type_annotation=response_type_annotation,
251
+ )
252
+ )
290
253
 
291
- def description_and_summary(self, builder) -> List[str]:
254
+ def description_and_summary( # pylint: disable=no-self-use
255
+ self, builder: BuilderType
256
+ ) -> List[str]:
292
257
  description_list: List[str] = []
293
- description_list.append(f"{ builder.summary.strip() if builder.summary else builder.description.strip() }")
258
+ description_list.append(
259
+ f"{ builder.summary.strip() if builder.summary else builder.description.strip() }"
260
+ )
294
261
  if builder.summary and builder.description:
295
262
  description_list.append("")
296
263
  description_list.append(builder.description.strip())
297
264
  description_list.append("")
298
265
  return description_list
299
266
 
300
- def param_description(self, builder: Union[RequestBuilder, Operation]) -> List[str]: # pylint: disable=no-self-use
267
+ def example_template(self, builder: BuilderType) -> List[str]:
268
+ template = []
269
+ if builder.abstract:
270
+ return []
271
+ if self._json_input_example_template(builder):
272
+ template.append("")
273
+ template += self._json_input_example_template(builder)
274
+ return template
275
+
276
+ def param_description( # pylint: disable=no-self-use
277
+ self, builder: BuilderType
278
+ ) -> List[str]:
301
279
  description_list: List[str] = []
302
- for param in [m for m in builder.parameters.method if not m.is_hidden]:
280
+ for param in builder.parameters.method:
281
+ if not param.in_docstring:
282
+ continue
303
283
  description_list.extend(
304
- f":{param.description_keyword} { param.serialized_name }: { param.description }".replace(
284
+ f":{param.description_keyword} { param.client_name }: { param.description }".replace(
305
285
  "\n", "\n "
306
- ).split("\n")
286
+ ).split(
287
+ "\n"
288
+ )
307
289
  )
290
+ docstring_type = param.docstring_type(async_mode=self.async_mode)
308
291
  description_list.append(
309
- f":{param.docstring_type_keyword} { param.serialized_name }: { param.docstring_type }"
292
+ f":{param.docstring_type_keyword} {param.client_name}: {docstring_type}"
310
293
  )
311
-
312
- if len(builder.parameters.content_types) > 1:
313
- description_list = [
314
- _content_type_docstring(builder) if l.startswith(":keyword content_type:") else l
315
- for l in description_list
316
- ]
317
- if not any(l for l in description_list if l.startswith(":keyword content_type:")):
318
- description_list.append(_content_type_docstring(builder))
319
294
  return description_list
320
295
 
321
- def param_description_and_response_docstring(self, builder) -> List[str]:
296
+ def param_description_and_response_docstring(
297
+ self, builder: BuilderType
298
+ ) -> List[str]:
299
+ if builder.abstract:
300
+ return []
322
301
  return self.param_description(builder) + self.response_docstring(builder)
323
302
 
324
- def _get_json_response_template_to_status_codes(self, builder) -> Dict[str, List[str]]:
325
- # successful status codes of responses that have bodies
326
- responses = [
327
- response
328
- for response in builder.responses
329
- if any(code in builder.success_status_code for code in response.status_codes)
330
- and isinstance(
331
- response.schema, (
332
- DictionarySchema,
333
- ListSchema,
334
- ObjectSchema,
335
- EnumSchema
336
- ))
337
- ]
338
- retval = defaultdict(list)
339
- for response in responses:
340
- status_codes = [str(status_code) for status_code in response.status_codes]
341
- response_json = _json_dumps_template(cast(BaseSchema, response.schema).get_json_template_representation())
342
- retval[response_json].extend(status_codes)
343
- return retval
344
-
345
- def get_example_template(self, builder) -> List[str]:
346
- template = []
347
- if self._has_json_example_template(builder):
348
- template.append("")
349
- template += self._get_json_example_template(builder)
350
- if self._has_files_example_template(builder):
351
- template.append("")
352
- template += _get_files_example_template(builder)
353
- if self._has_data_example_template(builder):
354
- template.append("")
355
- template += _get_data_example_template(builder)
356
- if self._get_json_response_template_to_status_codes(builder):
357
- template.append("")
358
- template += self._get_json_response_template(builder)
359
- return template
360
-
361
- def _get_json_example_template(self, builder) -> List[str]:
362
- template = []
363
- json_body = builder.parameters.json_body
364
- object_schema = cast(ObjectSchema, json_body)
365
- try:
366
- discriminator_name = object_schema.discriminator_name
367
- subtype_map = object_schema.subtype_map
368
- except AttributeError:
369
- discriminator_name = None
370
- subtype_map = None
371
- if subtype_map:
372
- template.append("{} = '{}'".format(discriminator_name, "' or '".join(subtype_map.values())))
373
- template.append("")
303
+ @property
304
+ @abstractmethod
305
+ def _json_response_template_name(self) -> str:
306
+ ...
374
307
 
375
- try:
376
- property_with_discriminator = object_schema.property_with_discriminator
377
- except AttributeError:
378
- property_with_discriminator = None
379
- if property_with_discriminator:
380
- polymorphic_schemas = [
381
- s
382
- for s in self.code_model.sorted_schemas
383
- if s.name in property_with_discriminator.schema.subtype_map.values()
384
- ]
385
- num_schemas = min(self.code_model.options["polymorphic_examples"], len(polymorphic_schemas))
386
- for i in range(num_schemas):
387
- schema = polymorphic_schemas[i]
388
- polymorphic_property = _json_dumps_template(
389
- schema.get_json_template_representation(),
308
+ def _json_input_example_template(self, builder: BuilderType) -> List[str]:
309
+ template: List[str] = []
310
+ if self.code_model.options["models_mode"]:
311
+ # No input template if we have models
312
+ return template
313
+ if (
314
+ not builder.parameters.has_body
315
+ or builder.parameters.body_parameter.flattened
316
+ ):
317
+ # No input template if now body parameter
318
+ return template
319
+ if builder.overloads:
320
+ # if there's overloads, we do the json input example template on the overload
321
+ return template
322
+
323
+ body_param = builder.parameters.body_parameter
324
+ if not isinstance(body_param.type, (ListType, DictionaryType, ModelType)):
325
+ return template
326
+
327
+ polymorphic_subtypes: List[ModelType] = []
328
+ body_param.type.get_polymorphic_subtypes(polymorphic_subtypes)
329
+ if polymorphic_subtypes:
330
+ # we just assume one kind of polymorphic body for input
331
+ discriminator_name = cast(
332
+ Property, polymorphic_subtypes[0].discriminator
333
+ ).rest_api_name
334
+ template.append(
335
+ "# The input is polymorphic. The following are possible polymorphic "
336
+ f'inputs based off discriminator "{discriminator_name}":'
337
+ )
338
+ for idx in range(
339
+ min(
340
+ self.code_model.options["polymorphic_examples"],
341
+ len(polymorphic_subtypes),
342
+ )
343
+ ):
344
+ template.extend(
345
+ _get_polymorphic_subtype_template(polymorphic_subtypes[idx])
390
346
  )
391
- template.extend(f"{property_with_discriminator.name} = {polymorphic_property}".splitlines())
392
- if i != num_schemas - 1:
393
- template.append("# OR")
394
347
  template.append("")
395
- template.append("# JSON input template you can fill out and use as your body input.")
348
+ template.append(
349
+ "# JSON input template you can fill out and use as your body input."
350
+ )
396
351
  json_template = _json_dumps_template(
397
- builder.parameters.json_body.get_json_template_representation(),
352
+ body_param.type.get_json_template_representation(),
353
+ )
354
+ template.extend(
355
+ f"{builder.parameters.body_parameter.client_name} = {json_template}".splitlines()
398
356
  )
399
- template.extend(f"{self._json_example_param_name(builder)} = {json_template}".splitlines())
400
357
  return template
401
358
 
402
- @property
403
- @abstractmethod
404
- def serializer_name(self) -> str:
405
- ...
406
-
407
- def _serialize_parameter(
408
- self, param: Parameter, kwarg_name: str
409
- ) -> List[str]:
410
- function_name = "header" if kwarg_name == "headers" else "query"
359
+ def _serialize_parameter(self, param: Parameter, kwarg_name: str) -> List[str]:
411
360
  set_parameter = "_{}['{}'] = {}".format(
412
361
  kwarg_name,
413
362
  param.rest_api_name,
414
- utils.build_serialize_data_call(param, function_name, self.serializer_name)
363
+ self.parameter_serializer.serialize_parameter(param, self.serializer_name),
415
364
  )
416
- if param.required:
365
+ if not param.optional:
417
366
  retval = [set_parameter]
418
367
  else:
419
368
  retval = [
420
- f"if {param.full_serialized_name} is not None:",
421
- f" {set_parameter}"
369
+ f"if {param.full_client_name} is not None:",
370
+ f" {set_parameter}",
422
371
  ]
423
372
  return retval
424
373
 
425
- def _get_json_response_template(self, builder) -> List[str]:
426
- template = []
427
- for response_body, status_codes in self._get_json_response_template_to_status_codes(builder).items():
428
- template.append("# response body for status code(s): {}".format(", ".join(status_codes)))
429
- template.extend(f"response.json() == {response_body}".splitlines())
430
- return template
431
-
432
- def serialize_path(self, builder) -> List[str]:
433
- return utils.serialize_path(builder.parameters.path, self.serializer_name)
434
-
435
- @property
436
- def _function_definition(self) -> str:
437
- return self._def
374
+ def serialize_path(self, builder: BuilderType) -> List[str]:
375
+ return self.parameter_serializer.serialize_path(
376
+ builder.parameters.path, self.serializer_name
377
+ )
438
378
 
439
379
 
440
380
  ############################## REQUEST BUILDERS ##############################
441
381
 
442
382
 
443
- class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstract-method
444
- def description_and_summary(self, builder) -> List[str]:
383
+ class RequestBuilderSerializer(
384
+ _BuilderBaseSerializer[RequestBuilderType]
385
+ ): # pylint: disable=abstract-method
386
+ def description_and_summary(self, builder: RequestBuilderType) -> List[str]:
445
387
  retval = super().description_and_summary(builder)
446
388
  retval += [
447
- "See https://aka.ms/azsdk/python/protocol/quickstart for how to incorporate this "
389
+ "See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this "
448
390
  "request builder into your code flow.",
449
391
  "",
450
392
  ]
451
393
  return retval
452
394
 
395
+ @property
396
+ def _call_method(self) -> str:
397
+ return ""
398
+
453
399
  @property
454
400
  def serializer_name(self) -> str:
455
401
  return "_SERIALIZER"
456
402
 
403
+ @property
404
+ def _json_response_template_name(self) -> str:
405
+ return "response.json()"
406
+
457
407
  @staticmethod
458
- def declare_non_inputtable_constants(builder) -> List[str]:
459
- def _get_value(param: Parameter):
460
- if param.location in [ParameterLocation.Header, ParameterLocation.Query]:
461
- kwarg_dict = "headers" if param.location == ParameterLocation.Header else "params"
462
- return f"_{kwarg_dict}.pop('{param.rest_api_name}', {param.constant_declaration})"
463
- return f"{param.constant_declaration}"
408
+ def declare_non_inputtable_constants(builder: RequestBuilderType) -> List[str]:
409
+ def _get_value(param):
410
+ param_type = cast(ConstantType, param.type)
411
+ if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
412
+ kwarg_dict = (
413
+ "headers"
414
+ if param.location == ParameterLocation.HEADER
415
+ else "params"
416
+ )
417
+ return f"_{kwarg_dict}.pop('{param.rest_api_name}', {param_type.get_declaration()})"
418
+ return f"{param_type.get_declaration()}"
419
+
464
420
  return [
465
- f"{p.serialized_name} = {_get_value(p)}"
421
+ f"{p.client_name} = {_get_value(p)}"
466
422
  for p in builder.parameters.constant
467
- if p.original_parameter is None and
468
- p.in_method_code and
469
- not p.in_method_signature
423
+ if not p.in_method_signature
470
424
  ]
471
425
 
472
- def want_example_template(self, builder) -> bool:
473
- if self.code_model.options["builders_visibility"] != "public":
474
- return False # if we're not exposing rest layer, don't need to generate
475
- if builder.parameters.has_body:
476
- body_kwargs = set(builder.parameters.body_kwarg_names.keys())
477
- return bool(body_kwargs.intersection({"json", "files", "data"}))
478
- return bool(self._get_json_response_template_to_status_codes(builder))
479
-
480
426
  @property
481
- def _def(self) -> str:
427
+ def _function_def(self) -> str:
482
428
  return "def"
483
429
 
484
430
  @property
485
- def _is_in_class(self) -> bool:
431
+ def _need_self_param(self) -> bool:
486
432
  return False
487
433
 
488
- def _response_type_annotation(self, builder, modify_if_head_as_boolean: bool = True) -> str:
489
- return "HttpRequest"
490
-
491
- def response_docstring(self, builder) -> List[str]:
434
+ def response_docstring(self, builder: RequestBuilderType) -> List[str]:
492
435
  response_str = (
493
436
  f":return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
494
- + "`send_request` method. See https://aka.ms/azsdk/python/protocol/quickstart for how to "
437
+ + "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
495
438
  + "incorporate this response into your code flow."
496
439
  )
497
440
  rtype_str = f":rtype: ~azure.core.rest.HttpRequest"
498
441
  return [response_str, rtype_str]
499
442
 
500
- def _json_example_param_name(self, builder) -> str:
501
- return "json"
502
-
503
- def _has_json_example_template(self, builder) -> bool:
504
- return "json" in builder.parameters.body_kwarg_names
505
-
506
- def _has_files_example_template(self, builder) -> bool:
507
- return "files" in builder.parameters.body_kwarg_names
508
-
509
- def _has_data_example_template(self, builder) -> bool:
510
- return "data" in builder.parameters.body_kwarg_names
511
-
512
- @abstractmethod
513
- def _body_params_to_pass_to_request_creation(self, builder) -> List[str]:
514
- ...
515
-
516
- def pop_kwargs_from_signature(self, builder) -> List[str]:
517
- return utils.pop_kwargs_from_signature(
518
- self._get_kwargs_to_pop(builder),
443
+ def pop_kwargs_from_signature(self, builder: RequestBuilderType) -> List[str]:
444
+ return self.parameter_serializer.pop_kwargs_from_signature(
445
+ builder.parameters.kwargs_to_pop(is_python3_file=self.is_python3_file),
519
446
  check_kwarg_dict=True,
520
- pop_headers_kwarg=utils.PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.headers)
521
- else utils.PopKwargType.NO,
522
- pop_params_kwarg=utils.PopKwargType.CASE_INSENSITIVE if bool(builder.parameters.query)
523
- else utils.PopKwargType.NO,
447
+ pop_headers_kwarg=PopKwargType.CASE_INSENSITIVE
448
+ if bool(builder.parameters.headers)
449
+ else PopKwargType.NO,
450
+ pop_params_kwarg=PopKwargType.CASE_INSENSITIVE
451
+ if bool(builder.parameters.query)
452
+ else PopKwargType.NO,
524
453
  )
525
454
 
526
- def create_http_request(self, builder) -> List[str]:
455
+ def create_http_request(self, builder: RequestBuilderType) -> List[str]:
527
456
  retval = ["return HttpRequest("]
528
457
  retval.append(f' method="{builder.method}",')
529
458
  retval.append(" url=_url,")
@@ -531,92 +460,65 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
531
460
  retval.append(" params=_params,")
532
461
  if builder.parameters.headers:
533
462
  retval.append(" headers=_headers,")
534
- if builder.parameters.has_body:
535
- retval.extend([
536
- f" {body_kwarg}={body_kwarg},"
537
- for body_kwarg in self._body_params_to_pass_to_request_creation(builder)
538
- ])
463
+ if (
464
+ builder.parameters.has_body
465
+ and builder.parameters.body_parameter.in_method_signature
466
+ ):
467
+ body_param = builder.parameters.body_parameter
468
+ if body_param.constant or (
469
+ self.is_python3_file
470
+ and body_param.method_location != ParameterMethodLocation.KWARG
471
+ ):
472
+ # we only need to pass it through if it's not a kwarg or it's a popped kwarg
473
+ retval.append(
474
+ f" {builder.parameters.body_parameter.client_name}="
475
+ f"{builder.parameters.body_parameter.client_name},"
476
+ )
539
477
  retval.append(" **kwargs")
540
478
  retval.append(")")
541
479
  return retval
542
480
 
543
- def serialize_headers(self, builder) -> List[str]:
481
+ def serialize_headers(self, builder: RequestBuilderType) -> List[str]:
544
482
  retval = ["# Construct headers"]
545
483
  for parameter in builder.parameters.headers:
546
- retval.extend(self._serialize_parameter(
547
- parameter,
548
- kwarg_name="headers",
549
- ))
484
+ retval.extend(
485
+ self._serialize_parameter(
486
+ parameter,
487
+ kwarg_name="headers",
488
+ )
489
+ )
550
490
  return retval
551
491
 
552
- def serialize_query(self, builder) -> List[str]:
492
+ def serialize_query(self, builder: RequestBuilderType) -> List[str]:
553
493
  retval = ["# Construct parameters"]
554
494
  for parameter in builder.parameters.query:
555
- retval.extend(self._serialize_parameter(
556
- parameter,
557
- kwarg_name="params",
558
- ))
495
+ retval.extend(
496
+ self._serialize_parameter(
497
+ parameter,
498
+ kwarg_name="params",
499
+ )
500
+ )
559
501
  return retval
560
502
 
561
- def construct_url(self, builder) -> str:
562
- if any(o for o in ["low_level_client", "version_tolerant"] if self.code_model.options.get(o)):
503
+ def construct_url(self, builder: RequestBuilderType) -> str:
504
+ if any(
505
+ o
506
+ for o in ["low_level_client", "version_tolerant"]
507
+ if self.code_model.options.get(o)
508
+ ):
563
509
  url_value = _escape_str(builder.url)
564
510
  else:
565
511
  url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
566
512
  return f"_url = {url_value}{' # pylint: disable=line-too-long' if len(url_value) > 114 else ''}"
567
513
 
568
- class RequestBuilderGenericSerializer(_RequestBuilderBaseSerializer):
569
- @property
570
- def _want_inline_type_hints(self) -> bool:
571
- return False
572
-
573
- @staticmethod
574
- def _method_signature_and_response_type_annotation_template(method_signature: str, response_type_annotation: str):
575
- return utils.method_signature_and_response_type_annotation_template(
576
- is_python3_file=False, method_signature=method_signature, response_type_annotation=response_type_annotation
577
- )
578
-
579
- def _get_kwargs_to_pop(self, builder):
580
- return builder.parameters.kwargs_to_pop(is_python3_file=False)
581
-
582
- def _body_params_to_pass_to_request_creation(self, builder) -> List[str]:
583
- if builder.parameters.has_body and not builder.parameters.body_kwarg_names:
584
- # this means we have a constant body
585
- # only doing json body in this case
586
- return ["json"]
587
- return []
588
-
589
-
590
- class RequestBuilderPython3Serializer(_RequestBuilderBaseSerializer):
591
- @property
592
- def _want_inline_type_hints(self) -> bool:
593
- return True
594
-
595
- @staticmethod
596
- def _method_signature_and_response_type_annotation_template(method_signature: str, response_type_annotation: str):
597
- return utils.method_signature_and_response_type_annotation_template(
598
- is_python3_file=True, method_signature=method_signature, response_type_annotation=response_type_annotation
599
- )
600
-
601
- def _get_kwargs_to_pop(self, builder):
602
- return builder.parameters.kwargs_to_pop(is_python3_file=True)
603
-
604
- def _body_params_to_pass_to_request_creation(self, builder) -> List[str]:
605
- body_kwargs = list(builder.parameters.body_kwarg_names.keys())
606
- if body_kwargs:
607
- return body_kwargs
608
- if builder.parameters.has_body:
609
- # this means we have a constant body
610
- # only doing json body in this case
611
- return ["json"]
612
- return body_kwargs
613
-
614
514
 
615
515
  ############################## NORMAL OPERATIONS ##############################
616
516
 
617
517
 
618
- class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstract-method
619
- def description_and_summary(self, builder) -> List[str]:
518
+ class _OperationSerializer(
519
+ _BuilderBaseSerializer[OperationType]
520
+ ): # pylint: disable=abstract-method
521
+ def description_and_summary(self, builder: OperationType) -> List[str]:
620
522
  retval = super().description_and_summary(builder)
621
523
  if builder.deprecated:
622
524
  retval.append(".. warning::")
@@ -625,17 +527,84 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
625
527
  return retval
626
528
 
627
529
  @property
628
- def _is_in_class(self) -> bool:
530
+ def _json_response_template_name(self) -> str:
531
+ return "response"
532
+
533
+ def example_template(self, builder: OperationType) -> List[str]:
534
+ retval = super().example_template(builder)
535
+ if self.code_model.options["models_mode"]:
536
+ return retval
537
+ for response in builder.responses:
538
+ polymorphic_subtypes: List[ModelType] = []
539
+ if not response.type:
540
+ continue
541
+ response.type.get_polymorphic_subtypes(polymorphic_subtypes)
542
+ if polymorphic_subtypes:
543
+ # we just assume one kind of polymorphic body for input
544
+ discriminator_name = cast(
545
+ Property, polymorphic_subtypes[0].discriminator
546
+ ).rest_api_name
547
+ retval.append(
548
+ "# The response is polymorphic. The following are possible polymorphic "
549
+ f'responses based off discriminator "{discriminator_name}":'
550
+ )
551
+ for idx in range(
552
+ min(
553
+ self.code_model.options["polymorphic_examples"],
554
+ len(polymorphic_subtypes),
555
+ )
556
+ ):
557
+ retval.extend(
558
+ _get_polymorphic_subtype_template(polymorphic_subtypes[idx])
559
+ )
560
+
561
+ if _get_json_response_template_to_status_codes(builder):
562
+ retval.append("")
563
+ for (
564
+ response_body,
565
+ status_codes,
566
+ ) in _get_json_response_template_to_status_codes(builder).items():
567
+ retval.append(
568
+ "# response body for status code(s): {}".format(
569
+ ", ".join(status_codes)
570
+ )
571
+ )
572
+ retval.extend(
573
+ f"{self._json_response_template_name} == {response_body}".splitlines()
574
+ )
575
+ return retval
576
+
577
+ def make_pipeline_call(self, builder: OperationType) -> List[str]:
578
+ return [
579
+ f"pipeline_response = {self._call_method}self._client._pipeline.run( # type: ignore # pylint: disable=protected-access",
580
+ " request,",
581
+ f" stream={builder.has_stream_response},",
582
+ " **kwargs",
583
+ ")",
584
+ ]
585
+
586
+ @property
587
+ def _function_def(self) -> str:
588
+ return "async def" if self.async_mode else "def"
589
+
590
+ @property
591
+ def _need_self_param(self) -> bool:
629
592
  return True
630
593
 
631
594
  @property
632
595
  def serializer_name(self) -> str:
633
596
  return "self._serialize"
634
597
 
635
- def _response_docstring_type_wrapper(self, builder) -> List[str]: # pylint: disable=unused-argument, no-self-use
636
- return []
598
+ def decorators(self, builder: OperationType) -> List[str]:
599
+ """Decorators for the method"""
600
+ super_decorators = super().decorators(builder)
601
+ if builder.abstract:
602
+ super_decorators.append("@abc.abstractmethod")
603
+ return super_decorators
637
604
 
638
- def param_description(self, builder) -> List[str]: # pylint: disable=no-self-use
605
+ def param_description(
606
+ self, builder: OperationType
607
+ ) -> List[str]: # pylint: disable=no-self-use
639
608
  description_list = super().param_description(builder)
640
609
  if not self.code_model.options["version_tolerant"]:
641
610
  description_list.append(
@@ -643,251 +612,261 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
643
612
  )
644
613
  return description_list
645
614
 
646
- def _response_docstring_type_template(self, builder) -> str:
647
- retval = "{}"
648
- for wrapper in self._response_docstring_type_wrapper(builder)[::-1]:
649
- retval = f"{wrapper}[{retval}]"
650
- return retval
651
-
652
- def _response_type_annotation(self, builder, modify_if_head_as_boolean: bool = True) -> str:
653
- if (
654
- modify_if_head_as_boolean
655
- and builder.request_builder.method.lower() == "head"
656
- and self.code_model.options["head_as_boolean"]
657
- ):
658
- return "bool"
659
- response_body_annotations: OrderedSet[str] = {}
660
- for response in [r for r in builder.responses if r.has_body]:
661
- response_body_annotations[response.type_annotation(is_operation_file=True)] = None
662
- response_str = ", ".join(response_body_annotations.keys()) or "None"
663
- if len(response_body_annotations) > 1:
664
- response_str = f"Union[{response_str}]"
665
- if builder.has_optional_return_type:
666
- response_str = f"Optional[{response_str}]"
667
- return response_str
668
-
669
- def pop_kwargs_from_signature(self, builder) -> List[str]:
670
- kwargs_to_pop = self._get_kwargs_to_pop(builder)
671
- kwargs = utils.pop_kwargs_from_signature(
615
+ def pop_kwargs_from_signature(self, builder: OperationType) -> List[str]:
616
+ kwargs_to_pop = builder.parameters.kwargs_to_pop(
617
+ is_python3_file=self.is_python3_file
618
+ )
619
+ kwargs = self.parameter_serializer.pop_kwargs_from_signature(
672
620
  kwargs_to_pop,
673
621
  check_kwarg_dict=True,
674
- pop_headers_kwarg=utils.PopKwargType.CASE_INSENSITIVE if builder.has_kwargs_to_pop_with_default(
675
- kwargs_to_pop, ParameterLocation.Header) else utils.PopKwargType.SIMPLE,
676
- pop_params_kwarg=utils.PopKwargType.CASE_INSENSITIVE if builder.has_kwargs_to_pop_with_default(
677
- kwargs_to_pop, ParameterLocation.Query) else utils.PopKwargType.SIMPLE,
622
+ pop_headers_kwarg=PopKwargType.CASE_INSENSITIVE
623
+ if builder.has_kwargs_to_pop_with_default(
624
+ kwargs_to_pop, ParameterLocation.HEADER
625
+ )
626
+ else PopKwargType.SIMPLE,
627
+ pop_params_kwarg=PopKwargType.CASE_INSENSITIVE
628
+ if builder.has_kwargs_to_pop_with_default(
629
+ kwargs_to_pop, ParameterLocation.QUERY
630
+ )
631
+ else PopKwargType.SIMPLE,
632
+ check_client_input=not self.code_model.options["multiapi"],
633
+ )
634
+ kwargs.append(
635
+ f"cls = kwargs.pop('cls', None) {self.cls_type_annotation(builder)}"
678
636
  )
679
- kwargs.append(f"cls = kwargs.pop('cls', None) {self.cls_type_annotation(builder)}")
680
637
  return kwargs
681
638
 
682
- def cls_type_annotation(self, builder) -> str:
683
- return f"# type: ClsType[{self._response_type_annotation(builder, modify_if_head_as_boolean=False)}]"
684
-
685
- def _response_docstring_text_template(self, builder) -> str: # pylint: disable=no-self-use, unused-argument
686
- cls_str = f",{self._cls_docstring_rtype}" if self._cls_docstring_rtype else ""
687
- return "{}" + cls_str
688
-
689
- def response_docstring(self, builder) -> List[str]:
690
- responses_with_body = [r for r in builder.responses if r.has_body]
691
- if builder.request_builder.method.lower() == "head" and self.code_model.options["head_as_boolean"]:
692
- response_docstring_text = "bool"
693
- rtype = "bool"
694
- elif responses_with_body:
695
- response_body_docstring_text: OrderedSet[str] = {
696
- response.docstring_text: None for response in responses_with_body
697
- }
698
- response_docstring_text = " or ".join(response_body_docstring_text.keys())
699
- response_body_docstring_type: OrderedSet[str] = {
700
- response.docstring_type: None for response in responses_with_body
701
- }
702
- rtype = " or ".join(response_body_docstring_type.keys())
703
- if builder.has_optional_return_type:
704
- rtype += " or None"
705
- else:
706
- response_docstring_text = "None"
707
- rtype = "None"
708
- response_str = f":return: {self._response_docstring_text_template(builder).format(response_docstring_text)}"
709
- rtype_str = f":rtype: {self._response_docstring_type_template(builder).format(rtype)}"
710
- return [response_str, rtype_str, ":raises: ~azure.core.exceptions.HttpResponseError"]
711
-
712
- def want_example_template(self, builder) -> bool:
713
- if self.code_model.options['models_mode']:
714
- return False
715
- if builder.parameters.has_body:
716
- if builder.parameters.multipart or builder.parameters.data_inputs:
717
- return True
718
- body_params = builder.parameters.body
719
- return any([b for b in body_params if isinstance(b.schema, (DictionarySchema, ListSchema, ObjectSchema))])
720
- return bool(self._get_json_response_template_to_status_codes(builder))
721
-
722
- def _json_example_param_name(self, builder) -> str:
723
- return builder.parameters.body[0].serialized_name
724
-
725
- def _has_json_example_template(self, builder) -> bool:
726
- return (
727
- builder.parameters.has_body and
728
- not (builder.parameters.multipart or builder.parameters.data_inputs)
729
- )
639
+ def cls_type_annotation(self, builder: OperationType) -> str:
640
+ return f"# type: {builder.cls_type_annotation(async_mode=self.async_mode)}"
730
641
 
731
- def _has_files_example_template(self, builder) -> bool:
732
- return bool(builder.parameters.multipart)
642
+ def response_docstring(self, builder: OperationType) -> List[str]:
643
+ response_str = (
644
+ f":return: {builder.response_docstring_text(async_mode=self.async_mode)}"
645
+ )
646
+ rtype_str = (
647
+ f":rtype: {builder.response_docstring_type(async_mode=self.async_mode)}"
648
+ )
649
+ return [
650
+ response_str,
651
+ rtype_str,
652
+ ":raises ~azure.core.exceptions.HttpResponseError:",
653
+ ]
733
654
 
734
- def _has_data_example_template(self, builder) -> bool:
735
- return bool(builder.parameters.data_inputs)
655
+ def _serialize_body_parameter(self, builder: OperationType) -> List[str]:
656
+ """We need to serialize params if they're not meant to be streamed in.
736
657
 
737
- def _serialize_body_call(
738
- self, builder, body_param: Parameter, send_xml: bool, ser_ctxt: Optional[str], ser_ctxt_name: str
739
- ) -> str:
740
- body_is_xml = ", is_xml=True" if send_xml else ""
741
- pass_ser_ctxt = f", {ser_ctxt_name}={ser_ctxt_name}" if ser_ctxt else ""
742
- body_kwarg_to_pass = builder.body_kwargs_to_pass_to_request_builder[0]
658
+ This function serializes the body params that need to be serialized.
659
+ """
660
+ retval: List[str] = []
661
+ body_param = cast(BodyParameter, builder.parameters.body_parameter)
662
+ body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
663
+ send_xml = builder.parameters.body_parameter.type.is_xml
664
+ xml_serialization_ctxt = (
665
+ body_param.type.xml_serialization_ctxt if send_xml else None
666
+ )
667
+ ser_ctxt_name = "serialization_ctxt"
668
+ if xml_serialization_ctxt and self.code_model.options["models_mode"]:
669
+ retval.append(f'{ser_ctxt_name} = {{"xml": {{{xml_serialization_ctxt}}}}}')
743
670
  if self.code_model.options["models_mode"]:
744
- return (
745
- f"_{body_kwarg_to_pass} = self._serialize.body({body_param.serialized_name}, "
746
- f"'{ body_param.serialization_type }'{body_is_xml}{ pass_ser_ctxt })"
671
+ is_xml_cmd = ", is_xml=True" if send_xml else ""
672
+ serialization_ctxt_cmd = (
673
+ f", {ser_ctxt_name}={ser_ctxt_name}" if xml_serialization_ctxt else ""
747
674
  )
748
- return f"_{body_kwarg_to_pass} = {body_param.serialized_name}"
675
+ create_body_call = (
676
+ f"_{body_kwarg_name} = self._serialize.body({body_param.client_name}, "
677
+ f"'{body_param.type.serialization_type}'{is_xml_cmd}{serialization_ctxt_cmd})"
678
+ )
679
+ else:
680
+ create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
681
+ if body_param.optional:
682
+ retval.append(f"if {body_param.client_name} is not None:")
683
+ retval.append(" " + create_body_call)
684
+ retval.append("else:")
685
+ retval.append(f" _{body_kwarg_name} = None")
686
+ else:
687
+ retval.append(create_body_call)
688
+ return retval
749
689
 
750
- def _serialize_body(self, builder, body_param: Parameter, body_kwarg: str) -> List[str]:
690
+ def _create_body_parameter(
691
+ self,
692
+ builder: OperationType,
693
+ ) -> List[str]:
694
+ """Create the body parameter before we pass it as either json or content to the request builder"""
751
695
  retval = []
752
- send_xml = bool(
753
- builder.parameters.has_body and
754
- any(["xml" in ct for ct in builder.parameters.content_types]) and
755
- not isinstance(body_param.schema, IOSchema)
756
- )
757
- ser_ctxt_name = "serialization_ctxt"
758
- ser_ctxt = builder.parameters.body[0].xml_serialization_ctxt if send_xml else None
759
- if ser_ctxt and self.code_model.options["models_mode"]:
760
- retval.append(f'{ser_ctxt_name} = {{"xml": {{{ser_ctxt}}}}}')
761
- serialize_body_call = self._serialize_body_call(
762
- builder,
763
- body_param,
764
- send_xml,
765
- ser_ctxt,
766
- ser_ctxt_name,
767
- )
768
- if body_param.required:
769
- retval.append(serialize_body_call)
696
+ body_param = cast(BodyParameter, builder.parameters.body_parameter)
697
+ if hasattr(body_param, "entries"):
698
+ return _serialize_multipart_body(builder)
699
+ body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
700
+ if isinstance(body_param.type, BinaryType):
701
+ retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
702
+ if (
703
+ not body_param.default_content_type
704
+ and not next(
705
+ p for p in builder.parameters if p.rest_api_name == "Content-Type"
706
+ ).optional
707
+ ):
708
+ content_types = "'" + "', '".join(body_param.content_types) + "'"
709
+ retval.extend(
710
+ [
711
+ "if not content_type:",
712
+ f' raise TypeError("Missing required keyword-only argument: content_type. '
713
+ f'Known values are:" + "{content_types}")',
714
+ ]
715
+ )
770
716
  else:
771
- retval.append(f"if {body_param.serialized_name} is not None:")
772
- retval.append(" " + serialize_body_call)
773
- if len(builder.body_kwargs_to_pass_to_request_builder) == 1:
774
- retval.append("else:")
775
- retval.append(f" _{body_kwarg} = None")
717
+ retval.extend(self._serialize_body_parameter(builder))
776
718
  return retval
777
719
 
778
- def _set_body_content_kwarg(
779
- self, builder, body_param: Parameter, body_kwarg: Parameter
780
- ) -> List[str]:
720
+ def _initialize_overloads(self, builder: OperationType) -> List[str]:
781
721
  retval: List[str] = []
782
- if body_kwarg.serialized_name == "data" or body_kwarg.serialized_name == "files":
783
- return retval
722
+ same_content_type = (
723
+ len(
724
+ set(
725
+ o.parameters.body_parameter.default_content_type
726
+ for o in builder.overloads
727
+ )
728
+ )
729
+ == 1
730
+ )
731
+ if same_content_type:
732
+ default_content_type = builder.overloads[
733
+ 0
734
+ ].parameters.body_parameter.default_content_type
735
+ retval.append(f'content_type = content_type or "{default_content_type}"')
736
+ for overload in builder.overloads:
737
+ retval.append(
738
+ f"_{overload.request_builder.parameters.body_parameter.client_name} = None"
739
+ )
784
740
  try:
785
- if not body_param.style == ParameterStyle.binary:
786
- retval.extend(self._serialize_body(builder, body_param, body_kwarg.serialized_name))
787
- return retval
788
- except AttributeError:
789
- pass
790
- retval.append(f"_{body_kwarg.serialized_name} = {body_param.serialized_name}")
791
- return retval
792
-
793
-
794
- def _serialize_body_parameters(
795
- self, builder,
796
- ) -> List[str]:
797
- retval = []
798
- body_kwargs = [
799
- p for p in builder.request_builder.parameters.body
800
- if p.content_types
801
- ]
802
- builder_params = []
803
- if builder.parameters.has_body:
804
- builder_params += builder.parameters.body
805
- if builder.multiple_content_type_parameters.has_body:
806
- builder_params += builder.multiple_content_type_parameters.body
807
- if len(body_kwargs) == 1:
808
- retval.extend(self._set_body_content_kwarg(builder, builder.parameters.body[0], body_kwargs[0]))
809
- else:
810
- retval.append('content_type = content_type or ""')
811
- for idx, body_kwarg in enumerate(body_kwargs):
812
- body_param = next(
813
- b for b in builder_params
814
- if body_kwarg in b.body_kwargs
741
+ # if there is a binary overload, we do a binary check first.
742
+ binary_overload = cast(
743
+ OperationType,
744
+ next(
745
+ (
746
+ o
747
+ for o in builder.overloads
748
+ if isinstance(o.parameters.body_parameter.type, BinaryType)
749
+ )
750
+ ),
751
+ )
752
+ binary_body_param = binary_overload.parameters.body_parameter
753
+ retval.append(
754
+ f"if {binary_body_param.type.instance_check_template.format(binary_body_param.client_name)}:"
755
+ )
756
+ if binary_body_param.default_content_type and not same_content_type:
757
+ retval.append(
758
+ f' content_type = content_type or "{binary_body_param.default_content_type}"'
759
+ )
760
+ retval.extend(
761
+ f" {l}" for l in self._create_body_parameter(binary_overload)
762
+ )
763
+ retval.append("else:")
764
+ other_overload = cast(
765
+ OperationType,
766
+ next(
767
+ (
768
+ o
769
+ for o in builder.overloads
770
+ if not isinstance(o.parameters.body_parameter.type, BinaryType)
771
+ )
772
+ ),
773
+ )
774
+ retval.extend(
775
+ f" {l}" for l in self._create_body_parameter(other_overload)
776
+ )
777
+ if (
778
+ other_overload.parameters.body_parameter.default_content_type
779
+ and not same_content_type
780
+ ):
781
+ retval.append(
782
+ " content_type = content_type or "
783
+ f'"{other_overload.parameters.body_parameter.default_content_type}"'
815
784
  )
785
+ except StopIteration:
786
+ for idx, overload in enumerate(builder.overloads):
816
787
  if_statement = "if" if idx == 0 else "elif"
788
+ body_param = overload.parameters.body_parameter
817
789
  retval.append(
818
- f'{if_statement} content_type.split(";")[0] in {body_kwarg.pre_semicolon_content_types}:'
790
+ f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
791
+ )
792
+ if body_param.default_content_type and not same_content_type:
793
+ retval.append(
794
+ f' content_type = content_type or "{body_param.default_content_type}"'
795
+ )
796
+ retval.extend(
797
+ f" {l}"
798
+ for l in self._create_body_parameter(cast(OperationType, overload))
819
799
  )
820
- retval.extend([" " + line for line in self._set_body_content_kwarg(builder, body_param, body_kwarg)])
821
- retval.extend(_content_type_error_check(builder))
822
-
823
800
  return retval
824
801
 
825
- def _call_request_builder_helper(
802
+ def _create_request_builder_call(
826
803
  self,
827
- builder,
828
- request_builder: RequestBuilder,
804
+ builder: OperationType,
805
+ request_builder: RequestBuilderType,
829
806
  template_url: Optional[str] = None,
830
807
  is_next_request: bool = False,
831
808
  ) -> List[str]:
832
- retval = []
833
- if len(builder.body_kwargs_to_pass_to_request_builder) > 1:
834
- # special case for files, bc we hardcode body param to be called 'files' for multipart
835
- body_params_to_initialize = builder.body_kwargs_to_pass_to_request_builder
836
- if self.code_model.options["version_tolerant"]:
837
- body_params_to_initialize = [p for p in body_params_to_initialize if p != "files"]
838
- for k in body_params_to_initialize:
839
- retval.append(f"_{k} = None")
840
- if builder.parameters.grouped:
841
- # request builders don't allow grouped parameters, so we group them before making the call
842
- retval.extend(_serialize_grouped_body(builder))
843
-
844
- if builder.parameters.is_flattened:
845
- # unflatten before passing to request builder as well
846
- retval.extend(_serialize_flattened_body(builder))
847
- if request_builder.multipart or request_builder.parameters.data_inputs:
848
- if not self.code_model.options["version_tolerant"]:
849
- param_name = "_files" if request_builder.multipart else "_data"
850
- retval.extend(_serialize_files_and_data_body(builder, param_name))
851
- elif builder.parameters.has_body and not builder.parameters.body[0].constant:
852
- retval.extend(self._serialize_body_parameters(builder))
853
-
809
+ retval: List[str] = []
854
810
  if self.code_model.options["builders_visibility"] == "embedded":
855
811
  request_path_name = request_builder.name
856
812
  else:
857
- builder_group_name = request_builder.builder_group_name
813
+ group_name = request_builder.group_name
858
814
  request_path_name = "rest{}.{}".format(
859
- ("_" + builder_group_name) if builder_group_name else "", request_builder.name
815
+ ("_" + group_name) if group_name else "",
816
+ request_builder.name,
860
817
  )
861
- retval.append("")
862
818
  retval.append(f"request = {request_path_name}(")
863
819
  for parameter in request_builder.parameters.method:
864
- if (
865
- parameter.is_body and
866
- not parameter.constant and
867
- parameter.serialized_name not in builder.body_kwargs_to_pass_to_request_builder
868
- ):
820
+ if parameter.location == ParameterLocation.BODY:
821
+ # going to pass in body later based off of overloads
869
822
  continue
870
823
  if (
871
- is_next_request and
872
- not bool(builder.next_request_builder) and
873
- not self.code_model.options["reformat_next_link"] and
874
- parameter.location == ParameterLocation.Query
824
+ is_next_request
825
+ and builder.operation_type == "paging"
826
+ and not bool(builder.next_request_builder) # type: ignore
827
+ and not self.code_model.options["reformat_next_link"]
828
+ and parameter.location == ParameterLocation.QUERY
875
829
  ):
876
830
  # if we don't want to reformat query parameters for next link calls
877
831
  # in paging operations with a single swagger operation defintion,
878
832
  # we skip passing query params when building the next request
879
833
  continue
880
- high_level_name = cast(RequestBuilderParameter, parameter).name_in_high_level_operation
881
- retval.append(f" {parameter.serialized_name}={high_level_name},")
834
+ retval.append(
835
+ f" {parameter.client_name}={parameter.name_in_high_level_operation},"
836
+ )
837
+ if request_builder.overloads:
838
+ for overload in request_builder.overloads:
839
+ body_param = cast(
840
+ RequestBuilderBodyParameter, overload.parameters.body_parameter
841
+ )
842
+ retval.append(
843
+ f" {body_param.client_name}={body_param.name_in_high_level_operation},"
844
+ )
845
+ elif request_builder.parameters.has_body:
846
+ body_param = cast(
847
+ RequestBuilderBodyParameter, request_builder.parameters.body_parameter
848
+ )
849
+ retval.append(
850
+ f" {body_param.client_name}={body_param.name_in_high_level_operation},"
851
+ )
882
852
  if not self.code_model.options["version_tolerant"]:
883
853
  template_url = template_url or f"self.{builder.name}.metadata['url']"
884
854
  retval.append(f" template_url={template_url},")
885
- retval.append(' headers=_headers,')
886
- retval.append(' params=_params,')
855
+ retval.append(" headers=_headers,")
856
+ retval.append(" params=_params,")
887
857
  retval.append(f")")
858
+ return retval
859
+
860
+ def _postprocess_http_request(
861
+ self, builder: OperationType, template_url: Optional[str] = None
862
+ ) -> List[str]:
863
+ retval: List[str] = []
888
864
  if not self.code_model.options["version_tolerant"]:
889
865
  pass_files = ""
890
- if "files" in builder.body_kwargs_to_pass_to_request_builder:
866
+ if (
867
+ builder.parameters.has_body
868
+ and builder.parameters.body_parameter.client_name == "files"
869
+ ):
891
870
  pass_files = ", _files"
892
871
  retval.append(f"request = _convert_request(request{pass_files})")
893
872
  if builder.parameters.path:
@@ -898,22 +877,51 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
898
877
  retval.append(
899
878
  "request.url = self._client.format_url({}{}) # type: ignore".format(
900
879
  url_to_format,
901
- ", **path_format_arguments" if builder.parameters.path else ""
880
+ ", **path_format_arguments" if builder.parameters.path else "",
902
881
  )
903
882
  )
904
883
  return retval
905
884
 
906
- def call_request_builder(self, builder) -> List[str]:
885
+ def _call_request_builder_helper( # pylint: disable=too-many-statements
886
+ self,
887
+ builder: OperationType,
888
+ request_builder: RequestBuilderType,
889
+ template_url: Optional[str] = None,
890
+ is_next_request: bool = False,
891
+ ) -> List[str]:
892
+ retval = []
893
+ if builder.parameters.grouped:
894
+ # request builders don't allow grouped parameters, so we group them before making the call
895
+ retval.extend(_serialize_grouped_body(builder))
896
+ if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
897
+ # unflatten before passing to request builder as well
898
+ retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
899
+ if builder.overloads:
900
+ # we are only dealing with two overloads. If there are three, we generate an abstract operation
901
+ retval.extend(self._initialize_overloads(builder))
902
+ elif builder.parameters.has_body:
903
+ # non-overloaded body
904
+ retval.extend(self._create_body_parameter(builder))
905
+ retval.append("")
906
+ retval.extend(
907
+ self._create_request_builder_call(
908
+ builder, request_builder, template_url, is_next_request
909
+ )
910
+ )
911
+ retval.extend(self._postprocess_http_request(builder, template_url))
912
+ return retval
913
+
914
+ def call_request_builder(self, builder: OperationType) -> List[str]:
907
915
  return self._call_request_builder_helper(builder, builder.request_builder)
908
916
 
909
917
  def response_headers_and_deserialization(
910
918
  self,
911
- response: SchemaResponse,
919
+ response: Response,
912
920
  ) -> List[str]:
913
921
  retval: List[str] = [
914
922
  (
915
- f"response_headers['{response_header.name}']=self._deserialize('{response_header.serialization_type}', "
916
- f"response.headers.get('{response_header.name}'))"
923
+ f"response_headers['{response_header.rest_api_name}']=self._deserialize("
924
+ f"'{response_header.serialization_type}', response.headers.get('{response_header.rest_api_name}'))"
917
925
  )
918
926
  for response_header in response.headers
919
927
  ]
@@ -922,43 +930,56 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
922
930
  if response.is_stream_response:
923
931
  retval.append(
924
932
  "deserialized = {}".format(
925
- "response" if self.code_model.options["version_tolerant"]
933
+ "response.iter_bytes()"
934
+ if self.code_model.options["version_tolerant"]
926
935
  else "response.stream_download(self._client._pipeline)"
927
936
  )
928
937
  )
929
- elif response.has_body:
938
+ elif response.type:
930
939
  if self.code_model.options["models_mode"]:
931
- retval.append(f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)")
940
+ retval.append(
941
+ f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)"
942
+ )
932
943
  else:
933
- is_xml = any(["xml" in ct for ct in response.content_types])
934
- deserialized_value = "ET.fromstring(response.text())" if is_xml else "response.json()"
944
+ deserialized_value = (
945
+ "ET.fromstring(response.text())"
946
+ if response.type.is_xml
947
+ else "response.json()"
948
+ )
935
949
  retval.append(f"if response.content:")
936
950
  retval.append(f" deserialized = {deserialized_value}")
937
951
  retval.append("else:")
938
952
  retval.append(f" deserialized = None")
939
953
  return retval
940
954
 
941
- @property
942
- @abstractmethod
943
- def _call_method(self) -> str:
944
- ...
945
-
946
- def handle_error_response(self, builder) -> List[str]:
947
- retval = [f"if response.status_code not in {str(builder.success_status_code)}:"]
948
- retval.append(" map_error(status_code=response.status_code, response=response, error_map=error_map)")
955
+ def handle_error_response(self, builder: OperationType) -> List[str]:
956
+ retval = [
957
+ f"if response.status_code not in {str(builder.success_status_codes)}:"
958
+ ]
959
+ retval.append(
960
+ " map_error(status_code=response.status_code, response=response, error_map=error_map)"
961
+ )
949
962
  error_model = ""
950
- if builder.default_exception and self.code_model.options["models_mode"]:
963
+ if (
964
+ builder.default_error_deserialization
965
+ and self.code_model.options["models_mode"]
966
+ ):
951
967
  retval.append(
952
- f" error = self._deserialize.failsafe_deserialize({builder.default_exception}, pipeline_response)"
968
+ f" error = self._deserialize.failsafe_deserialize({builder.default_error_deserialization}, "
969
+ "pipeline_response)"
953
970
  )
954
971
  error_model = ", model=error"
955
- retval.append(" raise HttpResponseError(response=response{}{})".format(
956
- error_model,
957
- ", error_format=ARMErrorFormat" if self.code_model.options['azure_arm'] else ""
958
- ))
972
+ retval.append(
973
+ " raise HttpResponseError(response=response{}{})".format(
974
+ error_model,
975
+ ", error_format=ARMErrorFormat"
976
+ if self.code_model.options["azure_arm"]
977
+ else "",
978
+ )
979
+ )
959
980
  return retval
960
981
 
961
- def handle_response(self, builder) -> List[str]:
982
+ def handle_response(self, builder: OperationType) -> List[str]:
962
983
  retval: List[str] = ["response = pipeline_response.http_response"]
963
984
  retval.append("")
964
985
  retval.extend(self.handle_error_response(builder))
@@ -969,54 +990,66 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
969
990
  retval.append("response_headers = {}")
970
991
  if builder.has_response_body or builder.any_response_has_headers:
971
992
  if len(builder.responses) > 1:
972
- for status_code in builder.success_status_code:
993
+ for status_code in builder.success_status_codes:
973
994
  response = builder.get_response_from_status(status_code)
974
- if response.headers or response.has_body:
995
+ if response.headers or response.type:
975
996
  retval.append(f"if response.status_code == {status_code}:")
976
- retval.extend([
977
- f" {line}"
978
- for line in self.response_headers_and_deserialization(response)
979
- ])
997
+ retval.extend(
998
+ [
999
+ f" {line}"
1000
+ for line in self.response_headers_and_deserialization(
1001
+ response
1002
+ )
1003
+ ]
1004
+ )
980
1005
  retval.append("")
981
1006
  else:
982
- retval.extend(self.response_headers_and_deserialization(
983
- builder.responses[0]
984
- ))
1007
+ retval.extend(
1008
+ self.response_headers_and_deserialization(builder.responses[0])
1009
+ )
985
1010
  retval.append("")
986
1011
  if builder.has_optional_return_type or self.code_model.options["models_mode"]:
987
1012
  deserialized = "deserialized"
988
1013
  else:
989
- deserialized = f"cast({self._response_type_annotation(builder)}, deserialized)"
1014
+ deserialized = f"cast({builder.response_type_annotation(async_mode=self.async_mode)}, deserialized)"
990
1015
  retval.append("if cls:")
991
- retval.append(" return cls(pipeline_response, {}, {})".format(
992
- deserialized if builder.has_response_body else "None",
993
- "response_headers" if builder.any_response_has_headers else '{}'
994
- ))
1016
+ retval.append(
1017
+ " return cls(pipeline_response, {}, {})".format(
1018
+ deserialized if builder.has_response_body else "None",
1019
+ "response_headers" if builder.any_response_has_headers else "{}",
1020
+ )
1021
+ )
995
1022
  if builder.has_response_body:
996
1023
  retval.append("")
997
1024
  retval.append(f"return {deserialized}")
998
- if builder.request_builder.method == 'HEAD' and self.code_model.options['head_as_boolean']:
1025
+ if (
1026
+ builder.request_builder.method == "HEAD"
1027
+ and self.code_model.options["head_as_boolean"]
1028
+ ):
999
1029
  retval.append("return 200 <= response.status_code <= 299")
1000
1030
  return retval
1001
1031
 
1002
- def error_map(self, builder) -> List[str]:
1032
+ def error_map(self, builder: OperationType) -> List[str]:
1003
1033
  retval = ["error_map = {"]
1004
- if builder.status_code_exceptions:
1005
- if not 401 in builder.status_code_exceptions_status_codes:
1034
+ if builder.non_default_errors:
1035
+ if not 401 in builder.non_default_error_status_codes:
1006
1036
  retval.append(" 401: ClientAuthenticationError,")
1007
- if not 404 in builder.status_code_exceptions_status_codes:
1037
+ if not 404 in builder.non_default_error_status_codes:
1008
1038
  retval.append(" 404: ResourceNotFoundError,")
1009
- if not 409 in builder.status_code_exceptions_status_codes:
1039
+ if not 409 in builder.non_default_error_status_codes:
1010
1040
  retval.append(" 409: ResourceExistsError,")
1011
- for excep in builder.status_code_exceptions:
1041
+ for excep in builder.non_default_errors:
1012
1042
  error_model_str = ""
1013
1043
  if (
1014
- isinstance(excep.schema, ObjectSchema)
1015
- and excep.is_exception
1044
+ isinstance(excep.type, ModelType)
1016
1045
  and self.code_model.options["models_mode"]
1017
1046
  ):
1018
- error_model_str = f", model=self._deserialize(_models.{excep.serialization_type}, response)"
1019
- error_format_str = ", error_format=ARMErrorFormat" if self.code_model.options['azure_arm'] else ""
1047
+ error_model_str = f", model=self._deserialize(_models.{excep.type.serialization_type}, response)"
1048
+ error_format_str = (
1049
+ ", error_format=ARMErrorFormat"
1050
+ if self.code_model.options["azure_arm"]
1051
+ else ""
1052
+ )
1020
1053
  for status_code in excep.status_codes:
1021
1054
  if status_code == 401:
1022
1055
  retval.append(
@@ -1041,183 +1074,149 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
1041
1074
  f"{error_model_str}{error_format_str}),"
1042
1075
  )
1043
1076
  else:
1044
- retval.append(" 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError")
1077
+ retval.append(
1078
+ " 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError"
1079
+ )
1045
1080
  retval.append("}")
1046
1081
  retval.append("error_map.update(kwargs.pop('error_map', {}) or {})")
1047
1082
  return retval
1048
1083
 
1049
1084
  @staticmethod
1050
- def get_metadata_url(builder) -> str:
1085
+ def get_metadata_url(builder: OperationType) -> str:
1051
1086
  url = _escape_str(builder.request_builder.url)
1052
- return f"{builder.python_name}.metadata = {{'url': { url }}} # type: ignore"
1053
-
1054
- class _SyncOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=abstract-method
1055
- @property
1056
- def _want_inline_type_hints(self) -> bool:
1057
- return False
1058
-
1059
- @property
1060
- def _def(self) -> str:
1061
- return "def"
1087
+ return f"{builder.name}.metadata = {{'url': { url }}} # type: ignore"
1062
1088
 
1063
1089
  @property
1064
1090
  def _call_method(self) -> str:
1065
- return ""
1066
-
1067
- class SyncOperationGenericSerializer(_SyncOperationBaseSerializer):
1068
- @property
1069
- def _want_inline_type_hints(self) -> bool:
1070
- return False
1091
+ return "await " if self.async_mode else ""
1071
1092
 
1072
- @staticmethod
1073
- def _method_signature_and_response_type_annotation_template(method_signature: str, response_type_annotation: str):
1074
- return utils.method_signature_and_response_type_annotation_template(
1075
- is_python3_file=False, method_signature=method_signature, response_type_annotation=response_type_annotation
1076
- )
1077
1093
 
1078
- def _get_kwargs_to_pop(self, builder):
1079
- return builder.parameters.kwargs_to_pop(is_python3_file=False)
1080
-
1081
-
1082
- class SyncOperationPython3Serializer(_SyncOperationBaseSerializer):
1083
- @property
1084
- def _want_inline_type_hints(self) -> bool:
1085
- return True
1086
-
1087
- @staticmethod
1088
- def _method_signature_and_response_type_annotation_template(method_signature: str, response_type_annotation: str):
1089
- return utils.method_signature_and_response_type_annotation_template(
1090
- is_python3_file=True, method_signature=method_signature, response_type_annotation=response_type_annotation
1091
- )
1094
+ class OperationSerializer(_OperationSerializer[Operation]):
1095
+ ...
1092
1096
 
1093
- def _get_kwargs_to_pop(self, builder):
1094
- return builder.parameters.kwargs_to_pop(is_python3_file=True)
1095
1097
 
1096
- class AsyncOperationSerializer(SyncOperationPython3Serializer):
1097
-
1098
- @property
1099
- def _def(self) -> str:
1100
- return "async def"
1101
-
1102
- @property
1103
- def _function_definition(self) -> str:
1104
- return "async def"
1105
-
1106
- @property
1107
- def _call_method(self) -> str:
1108
- return "await "
1098
+ ############################## PAGING OPERATIONS ##############################
1109
1099
 
1100
+ PagingOperationType = TypeVar(
1101
+ "PagingOperationType", bound=Union[PagingOperation, LROPagingOperation]
1102
+ )
1110
1103
 
1111
- ############################## PAGING OPERATIONS ##############################
1112
1104
 
1105
+ class _PagingOperationSerializer(
1106
+ _OperationSerializer[PagingOperationType]
1107
+ ): # pylint: disable=abstract-method
1108
+ def __init__(
1109
+ self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
1110
+ ) -> None:
1111
+ # for pylint reasons need to redefine init
1112
+ # probably because inheritance is going too deep
1113
+ super().__init__(code_model, async_mode, is_python3_file)
1114
+ self.code_model = code_model
1115
+ self.async_mode = async_mode
1116
+ self.is_python3_file = is_python3_file
1117
+ self.parameter_serializer = ParameterSerializer()
1113
1118
 
1114
- class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=abstract-method
1115
- def _response_docstring_text_template(self, builder) -> str: # pylint: disable=no-self-use, unused-argument
1116
- if self._cls_docstring_rtype:
1117
- return "An iterator like instance of either {}" + self._cls_docstring_rtype
1118
- return "An iterator like instance of {}"
1119
+ def serialize_path(self, builder: PagingOperationType) -> List[str]:
1120
+ return self.parameter_serializer.serialize_path(
1121
+ builder.parameters.path, self.serializer_name
1122
+ )
1119
1123
 
1120
- def cls_type_annotation(self, builder) -> str:
1121
- interior = super()._response_type_annotation(builder, modify_if_head_as_boolean=False)
1122
- return f"# type: ClsType[{interior}]"
1124
+ def decorators(self, builder: PagingOperationType) -> List[str]:
1125
+ """Decorators for the method"""
1126
+ retval: List[str] = []
1127
+ if self.code_model.options["tracing"] and builder.want_tracing:
1128
+ retval.append("@distributed_trace")
1129
+ if builder.abstract:
1130
+ retval.append("@abc.abstractmethod")
1131
+ return retval
1123
1132
 
1124
- def call_next_link_request_builder(self, builder) -> List[str]:
1133
+ def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
1125
1134
  if builder.next_request_builder:
1126
1135
  request_builder = builder.next_request_builder
1127
- template_url = None if self.code_model.options["version_tolerant"] else f"'{request_builder.url}'"
1136
+ template_url = (
1137
+ None
1138
+ if self.code_model.options["version_tolerant"]
1139
+ else f"'{request_builder.url}'"
1140
+ )
1128
1141
  else:
1129
1142
  request_builder = builder.request_builder
1130
1143
  template_url = "next_link"
1131
1144
 
1132
1145
  request_builder = builder.next_request_builder or builder.request_builder
1133
1146
  return self._call_request_builder_helper(
1134
- builder,
1135
- request_builder,
1136
- template_url=template_url,
1137
- is_next_request=True
1147
+ builder, request_builder, template_url=template_url, is_next_request=True
1138
1148
  )
1139
1149
 
1140
- def _prepare_request_callback(self, builder) -> List[str]:
1150
+ def _prepare_request_callback(self, builder: PagingOperationType) -> List[str]:
1141
1151
  retval = ["def prepare_request(next_link=None):"]
1142
1152
  retval.append(" if not next_link:")
1143
- retval.extend([
1144
- f" {line}"
1145
- for line in self.call_request_builder(builder)
1146
- ])
1153
+ retval.extend(
1154
+ [f" {line}" for line in self.call_request_builder(builder)]
1155
+ )
1147
1156
  retval.append("")
1148
1157
  retval.append(" else:")
1149
- retval.extend([
1150
- f" {line}"
1151
- for line in self.call_next_link_request_builder(builder)
1152
- ])
1158
+ retval.extend(
1159
+ [f" {line}" for line in self.call_next_link_request_builder(builder)]
1160
+ )
1153
1161
  if not builder.next_request_builder and builder.parameters.path:
1154
1162
  retval.append("")
1155
- retval.extend([
1156
- f" {line}"
1157
- for line in self.serialize_path(builder)
1158
- ])
1163
+ retval.extend([f" {line}" for line in self.serialize_path(builder)])
1159
1164
  if not builder.next_request_builder:
1160
1165
  retval.append(' request.method = "GET"')
1161
1166
  else:
1162
- retval.append('')
1167
+ retval.append("")
1163
1168
  retval.append(" return request")
1164
1169
  return retval
1165
1170
 
1166
1171
  @property
1167
- @abstractmethod
1168
- def _list_type_returned_to_users(self) -> str:
1169
- ...
1170
-
1171
- @staticmethod
1172
- @abstractmethod
1173
- def _pager(builder) -> str:
1174
- ...
1172
+ def _function_def(self) -> str:
1173
+ return "def"
1175
1174
 
1176
- def _extract_data_callback(self, builder) -> List[str]:
1177
- retval = [f"{self._def} extract_data(pipeline_response):"]
1175
+ def _extract_data_callback(self, builder: PagingOperationType) -> List[str]:
1176
+ retval = [
1177
+ f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"
1178
+ ]
1178
1179
  response = builder.responses[0]
1179
1180
  deserialized = (
1180
1181
  f'self._deserialize("{response.serialization_type}", pipeline_response)'
1181
- if self.code_model.options["models_mode"] else
1182
- "pipeline_response.http_response.json()"
1182
+ if self.code_model.options["models_mode"]
1183
+ else "pipeline_response.http_response.json()"
1183
1184
  )
1184
1185
  retval.append(f" deserialized = {deserialized}")
1185
- item_name = builder.item_name(self.code_model)
1186
- list_of_elem = f".{item_name}" if self.code_model.options["models_mode"] else f'["{item_name}"]'
1186
+ item_name = builder.item_name
1187
+ list_of_elem = (
1188
+ f".{item_name}"
1189
+ if self.code_model.options["models_mode"]
1190
+ else f'["{item_name}"]'
1191
+ )
1187
1192
  retval.append(f" list_of_elem = deserialized{list_of_elem}")
1188
1193
  retval.append(" if cls:")
1189
1194
  retval.append(" list_of_elem = cls(list_of_elem)")
1190
1195
 
1191
- next_link_name = builder.next_link_name
1192
- if not next_link_name:
1193
- next_link_property = "None"
1196
+ continuation_token_name = builder.continuation_token_name
1197
+ if not continuation_token_name:
1198
+ cont_token_property = "None"
1194
1199
  elif self.code_model.options["models_mode"]:
1195
- next_link_property = f"deserialized.{next_link_name} or None"
1200
+ cont_token_property = f"deserialized.{continuation_token_name} or None"
1196
1201
  else:
1197
- next_link_property = f'deserialized.get("{next_link_name}", None)'
1198
- retval.append(f" return {next_link_property}, {self._list_type_returned_to_users}(list_of_elem)")
1202
+ cont_token_property = f'deserialized.get("{continuation_token_name}", None)'
1203
+ list_type = "AsyncList" if self.async_mode else "iter"
1204
+ retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
1199
1205
  return retval
1200
1206
 
1201
- def _get_next_callback(self, builder) -> List[str]:
1202
- retval = [f"{self._def} get_next(next_link=None):"]
1207
+ def _get_next_callback(self, builder: PagingOperationType) -> List[str]:
1208
+ retval = [f"{'async ' if self.async_mode else ''}def get_next(next_link=None):"]
1203
1209
  retval.append(" request = prepare_request(next_link)")
1204
1210
  retval.append("")
1205
- retval.append(f" pipeline_response = {self._call_method}self._client._pipeline.run( # pylint: disable=protected-access")
1206
- retval.append(" request,")
1207
- retval.append(f" stream={builder.is_stream_response},")
1208
- retval.append(" **kwargs")
1209
- retval.append(" )")
1211
+ retval.extend([f" {l}" for l in self.make_pipeline_call(builder)])
1210
1212
  retval.append(" response = pipeline_response.http_response")
1211
1213
  retval.append("")
1212
- retval.extend([
1213
- f" {line}"
1214
- for line in self.handle_error_response(builder)
1215
- ])
1214
+ retval.extend([f" {line}" for line in self.handle_error_response(builder)])
1216
1215
  retval.append("")
1217
1216
  retval.append(" return pipeline_response")
1218
1217
  return retval
1219
1218
 
1220
- def set_up_params_for_pager(self, builder) -> List[str]:
1219
+ def set_up_params_for_pager(self, builder: PagingOperationType) -> List[str]:
1221
1220
  retval = []
1222
1221
  retval.extend(self.error_map(builder))
1223
1222
  retval.extend(self._prepare_request_callback(builder))
@@ -1227,99 +1226,76 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1227
1226
  retval.extend(self._get_next_callback(builder))
1228
1227
  return retval
1229
1228
 
1230
- class _SyncPagingOperationBaseSerializer(_PagingOperationBaseSerializer, _SyncOperationBaseSerializer): # pylint: disable=abstract-method
1231
- def _response_docstring_type_wrapper(self, builder) -> List[str]: # pylint: no-self-use
1232
- return [f"~{builder.get_pager_path(async_mode=False)}"]
1233
1229
 
1234
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
1235
- return ["Iterable"]
1236
-
1237
- @property
1238
- def _list_type_returned_to_users(self) -> str: # pylint: disable=no-self-use
1239
- return "iter"
1240
-
1241
- @staticmethod
1242
- def _pager(builder) -> str:
1243
- return builder.get_pager(async_mode=False)
1244
-
1245
- class SyncPagingOperationGenericSerializer(_SyncPagingOperationBaseSerializer, SyncOperationGenericSerializer):
1246
- pass
1247
-
1248
- class SyncPagingOperationPython3Serializer(_SyncPagingOperationBaseSerializer, SyncOperationPython3Serializer):
1249
- pass
1250
-
1251
- class AsyncPagingOperationSerializer(_PagingOperationBaseSerializer, AsyncOperationSerializer):
1252
- def _response_docstring_type_wrapper(self, builder) -> List[str]: # pylint: no-self-use
1253
- return [f"~{builder.get_pager_path(async_mode=True)}"]
1254
-
1255
- @property
1256
- def _function_definition(self) -> str:
1257
- return "def"
1258
-
1259
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
1260
- return ["AsyncIterable"]
1261
-
1262
- @property
1263
- def _list_type_returned_to_users(self) -> str: # pylint: disable=no-self-use
1264
- return "AsyncList"
1265
-
1266
- @staticmethod
1267
- def _pager(builder) -> str:
1268
- return builder.get_pager(async_mode=True)
1230
+ class PagingOperationSerializer(_PagingOperationSerializer[PagingOperation]):
1231
+ ...
1269
1232
 
1270
1233
 
1271
1234
  ############################## LRO OPERATIONS ##############################
1272
1235
 
1236
+ LROOperationType = TypeVar(
1237
+ "LROOperationType", bound=Union[LROOperation, LROPagingOperation]
1238
+ )
1273
1239
 
1274
- class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=abstract-method
1275
- def cls_type_annotation(self, builder) -> str:
1276
- return f"# type: ClsType[{super()._response_type_annotation(builder, modify_if_head_as_boolean=False)}]"
1277
-
1278
- @abstractmethod
1279
- def _default_polling_method(self, builder) -> str:
1280
- ...
1281
-
1282
- @abstractmethod
1283
- def _default_no_polling_method(self, builder) -> str:
1284
- ...
1285
1240
 
1286
- @abstractmethod
1287
- def _poller(self, builder) -> str:
1288
- ...
1289
-
1290
- @property
1291
- @abstractmethod
1292
- def _polling_method_type(self):
1293
- ...
1241
+ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1242
+ def __init__(
1243
+ self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
1244
+ ) -> None:
1245
+ # for pylint reasons need to redefine init
1246
+ # probably because inheritance is going too deep
1247
+ super().__init__(code_model, async_mode, is_python3_file)
1248
+ self.code_model = code_model
1249
+ self.async_mode = async_mode
1250
+ self.is_python3_file = is_python3_file
1251
+ self.parameter_serializer = ParameterSerializer()
1294
1252
 
1295
- def param_description(self, builder) -> List[str]:
1253
+ def param_description(self, builder: LROOperationType) -> List[str]:
1296
1254
  retval = super().param_description(builder)
1297
- retval.append(":keyword str continuation_token: A continuation token to restart a poller from a saved state.")
1298
1255
  retval.append(
1299
- f":keyword polling: By default, your polling method will be {self._default_polling_method(builder)}. "
1256
+ ":keyword str continuation_token: A continuation token to restart a poller from a saved state."
1257
+ )
1258
+ retval.append(
1259
+ f":keyword polling: By default, your polling method will be {builder.get_polling_method(self.async_mode)}. "
1300
1260
  "Pass in False for this operation to not poll, or pass in your own initialized polling object for a"
1301
1261
  " personal polling strategy."
1302
1262
  )
1303
- retval.append(f":paramtype polling: bool or ~azure.core.polling.{self._polling_method_type}")
1263
+ retval.append(
1264
+ f":paramtype polling: bool or ~{builder.get_base_polling_method_path(self.async_mode)}"
1265
+ )
1304
1266
  retval.append(
1305
1267
  ":keyword int polling_interval: Default waiting time between two polls for LRO operations "
1306
1268
  "if no Retry-After header is present."
1307
1269
  )
1308
1270
  return retval
1309
1271
 
1310
- def initial_call(self, builder) -> List[str]:
1311
- retval = [f"polling = kwargs.pop('polling', True) # type: Union[bool, {self._polling_method_type}]"]
1272
+ def serialize_path(self, builder: LROOperationType) -> List[str]:
1273
+ return self.parameter_serializer.serialize_path(
1274
+ builder.parameters.path, self.serializer_name
1275
+ )
1276
+
1277
+ def initial_call(self, builder: LROOperationType) -> List[str]:
1278
+ retval = [
1279
+ "polling = kwargs.pop('polling', True) # type: Union[bool, "
1280
+ f"{builder.get_base_polling_method(self.async_mode)}]"
1281
+ ]
1312
1282
  retval.append("lro_delay = kwargs.pop(")
1313
1283
  retval.append(" 'polling_interval',")
1314
1284
  retval.append(" self._config.polling_interval")
1315
1285
  retval.append(")")
1316
- retval.append("cont_token = kwargs.pop('continuation_token', None) # type: Optional[str]")
1286
+ retval.append(
1287
+ "cont_token = kwargs.pop('continuation_token', None) # type: Optional[str]"
1288
+ )
1317
1289
  retval.append("if cont_token is None:")
1318
- retval.append(f" raw_result = {self._call_method}self.{builder.initial_operation.name}( # type: ignore")
1319
- retval.extend([
1320
- f" {parameter.serialized_name}={parameter.serialized_name},"
1321
- for parameter in builder.parameters.method
1322
- ])
1290
+ retval.append(
1291
+ f" raw_result = {self._call_method}self.{builder.initial_operation.name}( # type: ignore"
1292
+ )
1293
+ retval.extend(
1294
+ [
1295
+ f" {parameter.client_name}={parameter.client_name},"
1296
+ for parameter in builder.parameters.method
1297
+ ]
1298
+ )
1323
1299
  retval.append(" cls=lambda x,y,z: x,")
1324
1300
  retval.append(" headers=_headers,")
1325
1301
  retval.append(" params=_params,")
@@ -1328,231 +1304,146 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
1328
1304
  retval.append("kwargs.pop('error_map', None)")
1329
1305
  return retval
1330
1306
 
1331
- def return_lro_poller(self, builder) -> List[str]:
1307
+ def return_lro_poller(self, builder: LROOperationType) -> List[str]:
1332
1308
  retval = []
1333
1309
  lro_options_str = (
1334
- "lro_options={'final-state-via': '" + builder.lro_options['final-state-via'] + "'},"
1335
- if builder.lro_options else ""
1310
+ "lro_options={'final-state-via': '"
1311
+ + builder.lro_options["final-state-via"]
1312
+ + "'},"
1313
+ if builder.lro_options
1314
+ else ""
1336
1315
  )
1337
1316
  path_format_arguments_str = ""
1338
1317
  if builder.parameters.path:
1339
1318
  path_format_arguments_str = "path_format_arguments=path_format_arguments,"
1340
1319
  retval.extend(self.serialize_path(builder))
1341
1320
  retval.append("")
1342
- retval.extend([
1343
- "if polling is True:",
1344
- f" polling_method = cast({self._polling_method_type}, {self._default_polling_method(builder)}(",
1345
- " lro_delay,",
1346
- f" {lro_options_str}",
1347
- f" {path_format_arguments_str}",
1348
- " **kwargs",
1349
- f")) # type: {self._polling_method_type}",
1350
- ]
1321
+ retval.extend(
1322
+ [
1323
+ "if polling is True:",
1324
+ f" polling_method = cast({builder.get_base_polling_method(self.async_mode)}, "
1325
+ f"{builder.get_polling_method(self.async_mode)}(",
1326
+ " lro_delay,",
1327
+ f" {lro_options_str}",
1328
+ f" {path_format_arguments_str}",
1329
+ " **kwargs",
1330
+ f")) # type: {builder.get_base_polling_method(self.async_mode)}",
1331
+ ]
1351
1332
  )
1352
1333
  retval.append(
1353
- f"elif polling is False: polling_method = cast({self._polling_method_type}, "
1354
- f"{self._default_no_polling_method(builder)}())"
1334
+ f"elif polling is False: polling_method = cast({builder.get_base_polling_method(self.async_mode)}, "
1335
+ f"{builder.get_no_polling_method(self.async_mode)}())"
1355
1336
  )
1356
1337
  retval.append("else: polling_method = polling")
1357
1338
  retval.append("if cont_token:")
1358
- retval.append(f" return {self._poller(builder)}.from_continuation_token(")
1339
+ retval.append(
1340
+ f" return {builder.get_poller(self.async_mode)}.from_continuation_token("
1341
+ )
1359
1342
  retval.append(" polling_method=polling_method,")
1360
1343
  retval.append(" continuation_token=cont_token,")
1361
1344
  retval.append(" client=self._client,")
1362
1345
  retval.append(" deserialization_callback=get_long_running_output")
1363
1346
  retval.append(" )")
1364
1347
  retval.append(
1365
- f"return {self._poller(builder)}"
1348
+ f"return {builder.get_poller(self.async_mode)}"
1366
1349
  "(self._client, raw_result, get_long_running_output, polling_method)"
1367
1350
  )
1368
1351
  return retval
1369
1352
 
1370
- def get_long_running_output(self, builder) -> List[str]:
1371
- retval = ["def get_long_running_output(pipeline_response):"]
1353
+ def get_long_running_output(self, builder: LROOperationType) -> List[str]:
1354
+ pylint_disable = ""
1355
+ if not builder.lro_response:
1356
+ pylint_disable = " # pylint: disable=inconsistent-return-statements"
1357
+ retval = [f"def get_long_running_output(pipeline_response):{pylint_disable}"]
1372
1358
  if builder.lro_response:
1373
- if builder.lro_response.has_headers:
1359
+ if builder.lro_response.headers:
1374
1360
  retval.append(" response_headers = {}")
1375
- if not self.code_model.options["models_mode"] or builder.lro_response.has_headers:
1361
+ if (
1362
+ not self.code_model.options["models_mode"]
1363
+ or builder.lro_response.headers
1364
+ ):
1376
1365
  retval.append(" response = pipeline_response.http_response")
1377
- retval.extend([
1378
- f" {line}"
1379
- for line in self.response_headers_and_deserialization(builder.lro_response)
1380
- ])
1366
+ retval.extend(
1367
+ [
1368
+ f" {line}"
1369
+ for line in self.response_headers_and_deserialization(
1370
+ builder.lro_response
1371
+ )
1372
+ ]
1373
+ )
1381
1374
  retval.append(" if cls:")
1382
- retval.append(" return cls(pipeline_response, {}, {})".format(
1383
- 'deserialized' if builder.lro_response and builder.lro_response.has_body else 'None',
1384
- 'response_headers' if builder.lro_response and builder.lro_response.has_headers else '{}'
1385
- ))
1386
- if builder.lro_response and builder.lro_response.has_body:
1375
+ retval.append(
1376
+ " return cls(pipeline_response, {}, {})".format(
1377
+ "deserialized"
1378
+ if builder.lro_response and builder.lro_response.type
1379
+ else "None",
1380
+ "response_headers"
1381
+ if builder.lro_response and builder.lro_response.headers
1382
+ else "{}",
1383
+ )
1384
+ )
1385
+ if builder.lro_response and builder.lro_response.type:
1387
1386
  retval.append(" return deserialized")
1388
1387
  return retval
1389
1388
 
1390
1389
 
1391
- class _SyncLROOperationBaseSerializer(_LROOperationBaseSerializer, _SyncOperationBaseSerializer): # pylint: disable=abstract-method
1392
- def _response_docstring_text_template(self, builder) -> str: # pylint: disable=no-self-use
1393
- lro_section = f"An instance of {builder.get_poller(async_mode=False)} "
1394
- if self._cls_docstring_rtype:
1395
- return lro_section + "that returns either {}" + self._cls_docstring_rtype
1396
- return lro_section + "that returns {}"
1397
-
1398
- def _response_docstring_type_wrapper(self, builder) -> List[str]: # pylint: no-self-use
1399
- return [f"~{builder.get_poller_path(async_mode=False)}"]
1390
+ class LROOperationSerializer(_LROOperationSerializer[LROOperation]):
1391
+ ...
1400
1392
 
1401
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
1402
- return [builder.get_poller(async_mode=False)]
1403
1393
 
1404
- def _default_polling_method(self, builder) -> str:
1405
- return builder.get_default_polling_method(async_mode=False, azure_arm=self.code_model.options["azure_arm"])
1394
+ ############################## LRO PAGING OPERATIONS ##############################
1406
1395
 
1407
- def _default_no_polling_method(self, builder) -> str:
1408
- return builder.get_default_no_polling_method(async_mode=False)
1409
1396
 
1397
+ class LROPagingOperationSerializer(
1398
+ _LROOperationSerializer[LROPagingOperation],
1399
+ _PagingOperationSerializer[LROPagingOperation],
1400
+ ): # pylint: disable=abstract-method
1410
1401
  @property
1411
- def _polling_method_type(self):
1412
- return "PollingMethod"
1413
-
1414
- def _poller(self, builder) -> str:
1415
- return builder.get_poller(async_mode=False)
1416
-
1417
- class SyncLROOperationGenericSerializer(_SyncLROOperationBaseSerializer, SyncOperationGenericSerializer):
1418
- pass
1419
-
1420
- class SyncLROOperationPython3Serializer(_SyncLROOperationBaseSerializer, SyncOperationPython3Serializer):
1421
- pass
1422
-
1423
- class AsyncLROOperationSerializer(_LROOperationBaseSerializer, AsyncOperationSerializer):
1424
-
1425
- def _response_docstring_text_template(self, builder) -> str: # pylint: disable=no-self-use
1426
- lro_section = f"An instance of {builder.get_poller(async_mode=True)} "
1427
- if self._cls_docstring_rtype:
1428
- return lro_section + "that returns either {}" + self._cls_docstring_rtype
1429
- return lro_section + "that returns {}"
1430
-
1431
- def _response_docstring_type_wrapper(self, builder) -> List[str]: # pylint: no-self-use
1432
- return [f"~{builder.get_poller_path(async_mode=True)}"]
1433
-
1434
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
1435
- return [builder.get_poller(async_mode=True)]
1436
-
1437
- def _default_polling_method(self, builder) -> str:
1438
- return builder.get_default_polling_method(async_mode=True, azure_arm=self.code_model.options["azure_arm"])
1439
-
1440
- def _default_no_polling_method(self, builder) -> str:
1441
- return builder.get_default_no_polling_method(async_mode=True)
1402
+ def _call_method(self) -> str:
1403
+ return "await " if self.async_mode else ""
1442
1404
 
1443
1405
  @property
1444
- def _polling_method_type(self):
1445
- return "AsyncPollingMethod"
1446
-
1447
- def _poller(self, builder) -> str:
1448
- return builder.get_poller(async_mode=True)
1449
-
1450
-
1451
- ############################## LRO PAGING OPERATIONS ##############################
1406
+ def _function_def(self) -> str:
1407
+ return "async def" if self.async_mode else "def"
1452
1408
 
1453
- class _LROPagingOperationBaseSerializer(_LROOperationBaseSerializer, _PagingOperationBaseSerializer): # pylint: disable=abstract-method
1454
-
1455
- def get_long_running_output(self, builder) -> List[str]:
1409
+ def get_long_running_output(self, builder: LROPagingOperation) -> List[str]:
1456
1410
  retval = ["def get_long_running_output(pipeline_response):"]
1457
- retval.append(f" {self._def} internal_get_next(next_link=None):")
1411
+ retval.append(f" {self._function_def} internal_get_next(next_link=None):")
1458
1412
  retval.append(" if next_link is None:")
1459
1413
  retval.append(" return pipeline_response")
1460
1414
  retval.append(f" return {self._call_method}get_next(next_link)")
1461
1415
  retval.append("")
1462
- retval.append(f" return {self._pager(builder)}(")
1416
+ retval.append(f" return {builder.get_pager(self.async_mode)}(")
1463
1417
  retval.append(" internal_get_next, extract_data")
1464
1418
  retval.append(" )")
1465
1419
  return retval
1466
1420
 
1467
-
1468
- class _SyncLROPagingOperationBaseSerializer( # pylint: disable=abstract-method
1469
- _SyncLROOperationBaseSerializer, _SyncPagingOperationBaseSerializer, _LROPagingOperationBaseSerializer
1470
- ):
1471
-
1472
- def _response_docstring_type_wrapper(self, builder) -> List[str]:
1473
- return _SyncLROOperationBaseSerializer._response_docstring_type_wrapper(
1474
- self, builder
1475
- ) + _SyncPagingOperationBaseSerializer._response_docstring_type_wrapper(self, builder)
1476
-
1477
- def _response_type_annotation_wrapper(self, builder) -> List[str]:
1478
- return _SyncLROOperationBaseSerializer._response_type_annotation_wrapper(self, builder) + [
1479
- builder.get_pager(async_mode=False)
1480
- ]
1481
-
1482
- def _response_docstring_text_template(self, builder) -> str:
1483
- lro_doc = _SyncLROOperationBaseSerializer._response_docstring_text_template(self, builder)
1484
- paging_doc = _SyncPagingOperationBaseSerializer._response_docstring_text_template(self, builder)
1485
- paging_doc = paging_doc.replace(paging_doc[0], paging_doc[0].lower(), 1)
1486
- return lro_doc.format(paging_doc).replace(self._cls_docstring_rtype, "", 1).replace("either ", "", 1)
1487
-
1488
- def cls_type_annotation(self, builder) -> str:
1489
- return f"# type: ClsType[{self._response_type_annotation(builder, modify_if_head_as_boolean=False)}]"
1490
-
1491
- class SyncLROPagingOperationGenericSerializer(_SyncLROPagingOperationBaseSerializer, SyncOperationGenericSerializer):
1492
- pass
1493
-
1494
- class SyncLROPagingOperationPython3Serializer(_SyncLROPagingOperationBaseSerializer, SyncOperationPython3Serializer):
1495
- pass
1496
-
1497
- class AsyncLROPagingOperationSerializer(
1498
- _LROPagingOperationBaseSerializer, AsyncLROOperationSerializer, AsyncPagingOperationSerializer
1499
- ):
1500
- @property
1501
- def _function_definition(self) -> str:
1502
- return "async def"
1503
-
1504
- def _response_docstring_type_wrapper(self, builder) -> List[str]:
1505
- return AsyncLROOperationSerializer._response_docstring_type_wrapper(
1506
- self, builder
1507
- ) + AsyncPagingOperationSerializer._response_docstring_type_wrapper(self, builder)
1508
-
1509
- def _response_type_annotation_wrapper(self, builder: LROPagingOperation) -> List[str]:
1510
- return AsyncLROOperationSerializer._response_type_annotation_wrapper(self, builder) + [
1511
- builder.get_pager(async_mode=True)
1512
- ]
1513
-
1514
- def _response_docstring_text_template(self, builder) -> str:
1515
- lro_doc = AsyncLROOperationSerializer._response_docstring_text_template(self, builder)
1516
- paging_doc = AsyncPagingOperationSerializer._response_docstring_text_template(self, builder)
1517
- paging_doc = paging_doc.replace(paging_doc[0], paging_doc[0].lower(), 1)
1518
- return lro_doc.format(paging_doc).replace(self._cls_docstring_rtype, "", 1).replace("either ", "", 1)
1421
+ def decorators(self, builder: LROPagingOperation) -> List[str]: # type: ignore
1422
+ """Decorators for the method"""
1423
+ return _LROOperationSerializer.decorators(self, builder) # type: ignore
1519
1424
 
1520
1425
 
1521
1426
  def get_operation_serializer(
1522
- builder,
1427
+ builder: Operation,
1523
1428
  code_model,
1524
1429
  async_mode: bool,
1525
1430
  is_python3_file: bool,
1526
- ) -> _OperationBaseSerializer:
1527
- retcls = _OperationBaseSerializer
1528
- if isinstance(builder, LROPagingOperation):
1529
- retcls = (
1530
- AsyncLROPagingOperationSerializer if async_mode
1531
- else (
1532
- SyncLROPagingOperationPython3Serializer if is_python3_file
1533
- else SyncLROPagingOperationGenericSerializer
1534
- )
1535
- )
1536
- return retcls(code_model)
1537
- if isinstance(builder, LROOperation):
1538
- retcls = (
1539
- AsyncLROOperationSerializer if async_mode
1540
- else (SyncLROOperationPython3Serializer if is_python3_file else SyncLROOperationGenericSerializer)
1541
- )
1542
- return retcls(code_model)
1543
- if isinstance(builder, PagingOperation):
1544
- retcls = (
1545
- AsyncPagingOperationSerializer if async_mode
1546
- else (SyncPagingOperationPython3Serializer if is_python3_file else SyncPagingOperationGenericSerializer)
1547
- )
1548
- return retcls(code_model)
1549
- retcls = (
1550
- AsyncOperationSerializer if async_mode
1551
- else (SyncOperationPython3Serializer if is_python3_file else SyncOperationGenericSerializer)
1552
- )
1553
- return retcls(code_model)
1554
-
1555
-
1556
- def get_request_builder_serializer(code_model, is_python3_file: bool) -> _RequestBuilderBaseSerializer:
1557
- retcls = RequestBuilderPython3Serializer if is_python3_file else RequestBuilderGenericSerializer
1558
- return retcls(code_model)
1431
+ ) -> Union[
1432
+ OperationSerializer,
1433
+ PagingOperationSerializer,
1434
+ LROOperationSerializer,
1435
+ LROPagingOperationSerializer,
1436
+ ]:
1437
+ retcls: Union[
1438
+ Type[OperationSerializer],
1439
+ Type[PagingOperationSerializer],
1440
+ Type[LROOperationSerializer],
1441
+ Type[LROPagingOperationSerializer],
1442
+ ] = OperationSerializer
1443
+ if builder.operation_type == "lropaging":
1444
+ retcls = LROPagingOperationSerializer
1445
+ elif builder.operation_type == "lro":
1446
+ retcls = LROOperationSerializer
1447
+ elif builder.operation_type == "paging":
1448
+ retcls = PagingOperationSerializer
1449
+ return retcls(code_model, async_mode, is_python3_file)