@autorest/python 5.16.0 → 5.17.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 (92) hide show
  1. package/ChangeLog.md +43 -3
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +1 -1
  4. package/autorest/codegen/__init__.py +48 -209
  5. package/autorest/codegen/models/__init__.py +116 -83
  6. package/autorest/codegen/models/base_builder.py +49 -88
  7. package/autorest/codegen/models/base_model.py +1 -1
  8. package/autorest/codegen/models/{base_schema.py → base_type.py} +56 -40
  9. package/autorest/codegen/models/client.py +157 -48
  10. package/autorest/codegen/models/code_model.py +108 -254
  11. package/autorest/codegen/models/combined_type.py +107 -0
  12. package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
  13. package/autorest/codegen/models/credential_types.py +224 -0
  14. package/autorest/codegen/models/{dictionary_schema.py → dictionary_type.py} +41 -31
  15. package/autorest/codegen/models/enum_type.py +195 -0
  16. package/autorest/codegen/models/imports.py +23 -0
  17. package/autorest/codegen/models/list_type.py +134 -0
  18. package/autorest/codegen/models/lro_operation.py +77 -156
  19. package/autorest/codegen/models/lro_paging_operation.py +28 -11
  20. package/autorest/codegen/models/model_type.py +239 -0
  21. package/autorest/codegen/models/operation.py +303 -269
  22. package/autorest/codegen/models/operation_group.py +48 -89
  23. package/autorest/codegen/models/paging_operation.py +80 -123
  24. package/autorest/codegen/models/parameter.py +289 -396
  25. package/autorest/codegen/models/parameter_list.py +348 -360
  26. package/autorest/codegen/models/primitive_types.py +544 -0
  27. package/autorest/codegen/models/property.py +109 -139
  28. package/autorest/codegen/models/request_builder.py +105 -88
  29. package/autorest/codegen/models/request_builder_parameter.py +112 -100
  30. package/autorest/codegen/models/response.py +325 -0
  31. package/autorest/codegen/models/utils.py +12 -19
  32. package/autorest/codegen/serializers/__init__.py +46 -37
  33. package/autorest/codegen/serializers/builder_serializer.py +604 -1146
  34. package/autorest/codegen/serializers/client_serializer.py +83 -88
  35. package/autorest/codegen/serializers/general_serializer.py +5 -64
  36. package/autorest/codegen/serializers/import_serializer.py +7 -4
  37. package/autorest/codegen/serializers/metadata_serializer.py +15 -104
  38. package/autorest/codegen/serializers/model_base_serializer.py +40 -32
  39. package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
  40. package/autorest/codegen/serializers/model_init_serializer.py +2 -4
  41. package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
  42. package/autorest/codegen/serializers/operation_groups_serializer.py +4 -13
  43. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  44. package/autorest/codegen/serializers/request_builders_serializer.py +12 -29
  45. package/autorest/codegen/serializers/utils.py +0 -142
  46. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  47. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  48. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  49. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  50. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  51. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  52. package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
  53. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
  54. package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
  55. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  56. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  57. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  58. package/autorest/codegen/templates/operation.py.jinja2 +6 -8
  59. package/autorest/codegen/templates/operation_group.py.jinja2 +7 -7
  60. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  61. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  62. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  63. package/autorest/codegen/templates/request_builder.py.jinja2 +13 -11
  64. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  65. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  66. package/autorest/jsonrpc/server.py +15 -3
  67. package/autorest/m4reformatter/__init__.py +1108 -0
  68. package/autorest/multiapi/models/code_model.py +1 -1
  69. package/autorest/multiapi/serializers/__init__.py +4 -4
  70. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  71. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  72. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +3 -3
  73. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  74. package/autorest/postprocess/__init__.py +202 -0
  75. package/autorest/postprocess/get_all.py +19 -0
  76. package/autorest/postprocess/venvtools.py +73 -0
  77. package/autorest/preprocess/__init__.py +209 -0
  78. package/autorest/preprocess/helpers.py +54 -0
  79. package/autorest/{namer → preprocess}/python_mappings.py +21 -16
  80. package/package.json +2 -2
  81. package/autorest/codegen/models/credential_model.py +0 -55
  82. package/autorest/codegen/models/credential_schema.py +0 -95
  83. package/autorest/codegen/models/credential_schema_policy.py +0 -73
  84. package/autorest/codegen/models/enum_schema.py +0 -225
  85. package/autorest/codegen/models/list_schema.py +0 -135
  86. package/autorest/codegen/models/object_schema.py +0 -303
  87. package/autorest/codegen/models/primitive_schemas.py +0 -495
  88. package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
  89. package/autorest/codegen/models/schema_request.py +0 -55
  90. package/autorest/codegen/models/schema_response.py +0 -141
  91. package/autorest/namer/__init__.py +0 -23
  92. package/autorest/namer/name_converter.py +0 -509
@@ -3,43 +3,92 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from collections.abc import MutableSequence
7
6
  import logging
8
- from typing import cast, List, Callable, Optional, TypeVar, Dict, TYPE_CHECKING
7
+ from typing import (
8
+ Any,
9
+ Callable,
10
+ Dict,
11
+ List,
12
+ Optional,
13
+ TYPE_CHECKING,
14
+ Union,
15
+ Generic,
16
+ TypeVar,
17
+ cast,
18
+ )
19
+ from abc import abstractmethod
20
+ from collections.abc import MutableSequence
21
+ from enum import Enum
22
+
23
+ from .request_builder_parameter import (
24
+ RequestBuilderBodyParameter,
25
+ RequestBuilderMultipartBodyParameter,
26
+ RequestBuilderParameter,
27
+ get_request_body_parameter,
28
+ )
29
+ from .parameter import (
30
+ MultipartBodyParameter,
31
+ ParameterLocation,
32
+ BodyParameter,
33
+ Parameter,
34
+ ParameterMethodLocation,
35
+ ClientParameter,
36
+ ConfigParameter,
37
+ get_body_parameter,
38
+ )
39
+
40
+ ParameterType = TypeVar(
41
+ "ParameterType", bound=Union[Parameter, RequestBuilderParameter]
42
+ )
43
+ BodyParameterType = TypeVar(
44
+ "BodyParameterType", bound=Union[BodyParameter, RequestBuilderBodyParameter]
45
+ )
46
+ RequestBuilderBodyParameterType = Union[
47
+ RequestBuilderBodyParameter, RequestBuilderMultipartBodyParameter
48
+ ]
9
49
 
10
- from .parameter import Parameter, ParameterLocation, ParameterMethodLocation
11
- from .base_schema import BaseSchema
12
- from .primitive_schemas import StringSchema
13
- from .utils import JSON_REGEXP
14
50
 
15
51
  if TYPE_CHECKING:
16
- from .schema_request import SchemaRequest
17
52
  from .code_model import CodeModel
18
53
 
19
- T = TypeVar("T")
20
- OrderedSet = Dict[T, None]
54
+
55
+ class ParameterImplementation(Enum):
56
+ METHOD = "method"
57
+ CLIENT = "client"
58
+
21
59
 
22
60
  _LOGGER = logging.getLogger(__name__)
23
61
 
24
62
 
25
- def _method_signature_helper(
63
+ def method_signature_helper(
26
64
  positional: List[str], keyword_only: Optional[List[str]], kwarg_params: List[str]
27
65
  ):
28
66
  keyword_only = keyword_only or []
29
67
  return positional + keyword_only + kwarg_params
30
68
 
31
69
 
32
- class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
70
+ def _sort(params):
71
+ return sorted(
72
+ params, key=lambda x: not (x.client_default_value or x.optional), reverse=True
73
+ )
74
+
75
+
76
+ class _ParameterListBase(
77
+ MutableSequence, Generic[ParameterType, BodyParameterType]
78
+ ): # pylint: disable=too-many-public-methods
79
+ """Base class for all of our different ParameterList classes"""
80
+
33
81
  def __init__(
34
82
  self,
83
+ yaml_data: Dict[str, Any],
35
84
  code_model: "CodeModel",
36
- parameters: Optional[List[Parameter]] = None,
37
- schema_requests: Optional[List["SchemaRequest"]] = None,
85
+ parameters: List[ParameterType],
86
+ body_parameter: Optional[BodyParameterType] = None,
38
87
  ) -> None:
88
+ self.yaml_data = yaml_data
39
89
  self.code_model = code_model
40
- self.schema_requests = schema_requests or []
41
90
  self.parameters = parameters or []
42
- self._json_body: Optional[BaseSchema] = None
91
+ self._body_parameter = body_parameter
43
92
 
44
93
  # MutableSequence
45
94
 
@@ -57,450 +106,389 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
57
106
  def __delitem__(self, index):
58
107
  del self.parameters[index]
59
108
 
60
- def insert(self, index: int, value: Parameter) -> None:
109
+ def insert(self, index: int, value: ParameterType) -> None:
61
110
  self.parameters.insert(index, value)
62
111
 
63
112
  # Parameter helpers
64
113
 
65
- def has_any_location(self, location: ParameterLocation) -> bool:
66
- return bool(
67
- [
68
- parameter
69
- for parameter in self.parameters
70
- if parameter.location == location
71
- ]
72
- )
73
-
74
- def get_from_predicate(
75
- self, predicate: Callable[[Parameter], bool]
76
- ) -> List[Parameter]:
77
- return [parameter for parameter in self.parameters if predicate(parameter)]
78
-
79
- def get_from_location(self, location: ParameterLocation) -> List[Parameter]:
80
- return self.get_from_predicate(lambda parameter: parameter.location == location)
81
-
82
- @property
83
- def content_types(self) -> List[str]:
84
- ordered_set = {
85
- m: None for request in self.schema_requests for m in request.content_types
86
- }
87
- return list(ordered_set.keys())
114
+ @staticmethod
115
+ @abstractmethod
116
+ def parameter_creator() -> Callable[[Dict[str, Any], "CodeModel"], ParameterType]:
117
+ """Callable for creating parameters"""
118
+ ...
88
119
 
89
- @property
90
- def default_content_type(self) -> str:
91
- json_content_types = [c for c in self.content_types if JSON_REGEXP.match(c)]
92
- if json_content_types:
93
- if "application/json" in json_content_types:
94
- return "application/json"
95
- return json_content_types[0]
96
-
97
- xml_content_types = [c for c in self.content_types if "xml" in c]
98
- if xml_content_types:
99
- if "application/xml" in xml_content_types:
100
- return "application/xml"
101
- return xml_content_types[0]
102
- return self.content_types[0]
120
+ @staticmethod
121
+ @abstractmethod
122
+ def body_parameter_creator() -> Callable[
123
+ [Dict[str, Any], "CodeModel"], BodyParameterType
124
+ ]:
125
+ """Callable for creating body parameters"""
126
+ ...
103
127
 
104
128
  @property
105
- def json_body(self) -> BaseSchema:
106
- if not self._json_body:
107
- self._json_body = self.body[0].schema
108
- return self._json_body
129
+ def grouped(self) -> List[Union[ParameterType, BodyParameterType]]:
130
+ """All parameters that are inside a parameter group"""
131
+ params: List[Union[ParameterType, BodyParameterType]] = [
132
+ p for p in self.parameters if p.grouped_by
133
+ ]
134
+ if self.has_body and self.body_parameter.grouped_by:
135
+ params.append(self.body_parameter)
136
+ return params
109
137
 
110
138
  @property
111
139
  def has_body(self) -> bool:
112
- return self.has_any_location(ParameterLocation.Body)
140
+ """Whether there is a body parameter in the parameter list"""
141
+ return bool(self._body_parameter)
113
142
 
114
143
  @property
115
- def body(self) -> List[Parameter]:
116
- if not self.has_body:
117
- raise ValueError(f"Can't get body parameter")
118
- # Should we check if there is two body? Modeler role right?
119
- body_params = self.get_from_location(ParameterLocation.Body)
120
- return body_params
121
-
122
- @staticmethod
123
- def _wanted_path_parameter(parameter: Parameter):
124
- # TODO add 'and parameter.location == "Method"' as requirement to this check once
125
- # I can use send_request on operations.
126
- # Don't want to duplicate code from send_request.
127
- return (
128
- parameter.location == ParameterLocation.Uri
129
- and parameter.rest_api_name != "$host"
130
- )
131
-
132
- @property
133
- def implementation(self) -> str:
134
- return "Method"
135
-
136
- @property
137
- def path(self) -> List[Parameter]:
144
+ def path(self) -> List[ParameterType]:
145
+ """All path parameters"""
138
146
  return [
139
- parameter
140
- for parameter in self.parameters
141
- if self._wanted_path_parameter(parameter)
147
+ p
148
+ for p in self.parameters
149
+ if p.location in (ParameterLocation.PATH, ParameterLocation.ENDPOINT_PATH)
142
150
  ]
143
151
 
144
152
  @property
145
- def query(self) -> List[Parameter]:
146
- return self.get_from_location(ParameterLocation.Query)
153
+ def query(self) -> List[ParameterType]:
154
+ """All query parameters"""
155
+ return [p for p in self.parameters if p.location == ParameterLocation.QUERY]
147
156
 
148
157
  @property
149
- def headers(self) -> List[Parameter]:
150
- headers = self.get_from_location(ParameterLocation.Header)
151
- if not headers:
152
- return headers
153
- return list({header.serialized_name: header for header in headers}.values())
154
-
155
- @property
156
- def grouped(self) -> List[Parameter]:
157
- return self.get_from_predicate(
158
- lambda parameter: cast(bool, parameter.grouped_by)
159
- )
158
+ def headers(self) -> List[ParameterType]:
159
+ """All header parameters"""
160
+ return [p for p in self.parameters if p.location == ParameterLocation.HEADER]
160
161
 
161
162
  @property
162
- def groupers(self) -> List[Parameter]:
163
- groupers: List[Parameter] = []
164
- for parameter in self.parameters:
165
- if any(
166
- [
167
- p
168
- for p in self.grouped
169
- if p.grouped_by
170
- and id(p.grouped_by.yaml_data) == id(parameter.yaml_data)
171
- ]
172
- ):
173
- groupers.append(parameter)
174
- return groupers
163
+ def constant(self) -> List[Union[ParameterType, BodyParameterType]]:
164
+ """All constant parameters"""
165
+ return [p for p in self.parameters if p.constant]
175
166
 
176
167
  @property
177
- def constant(self) -> List[Parameter]:
178
- """Return the constants of this parameter list.
179
-
180
- This excludes the constant from flatening on purpose, since technically they are not
181
- constant from this set of parameters, they are constants on the models and hence they do
182
- not have impact on any generation at this level
183
- """
184
- return self.get_from_predicate(lambda parameter: parameter.constant)
185
-
186
- @property
187
- def multipart(self) -> List[Parameter]:
188
- return self.get_from_predicate(lambda parameter: parameter.is_multipart)
189
-
190
- @property
191
- def data_inputs(self) -> List[Parameter]:
192
- return self.get_from_predicate(lambda parameter: parameter.is_data_input)
193
-
194
- def _filter_out_multiple_content_type(self, kwarg_params):
195
- """We don't want multiple content type kwargs in the method signature"""
196
- content_type_params = [
197
- k for k in kwarg_params if k.rest_api_name == "Content-Type"
198
- ]
199
- if len(content_type_params) > 1:
200
- # we don't want multiple content type params in the method, just one
201
- # we'll pick the one with the default content type
202
- seen_content_type = False
203
- new_kwarg_params = []
204
- for k in kwarg_params:
205
- if k.rest_api_name == "Content-Type":
206
- if (
207
- not seen_content_type
208
- and k.default_value_declaration
209
- == f'"{self.default_content_type}"'
210
- ):
211
- new_kwarg_params.append(k)
212
- seen_content_type = True
213
- else:
214
- continue
215
- else:
216
- new_kwarg_params.append(k)
217
- kwarg_params = new_kwarg_params
218
- return kwarg_params
168
+ def positional(self) -> List[Union[ParameterType, BodyParameterType]]:
169
+ """All positional parameters"""
170
+ return _sort(
171
+ [
172
+ p
173
+ for p in self.unsorted_method_params
174
+ if p.method_location == ParameterMethodLocation.POSITIONAL
175
+ ]
176
+ )
219
177
 
220
178
  @property
221
- def method(self) -> List[Parameter]:
222
- """The list of parameter used in method signature."""
223
- # Client level should not be on Method, etc.
224
- parameters_of_this_implementation = self.get_from_predicate(
225
- lambda parameter: parameter.implementation == self.implementation
226
- and parameter.in_method_signature
227
- )
228
- positional = [
229
- p
230
- for p in parameters_of_this_implementation
231
- if p.method_location == ParameterMethodLocation.POSITIONAL
232
- ]
233
- keyword_only = self._filter_out_multiple_content_type(
179
+ def keyword_only(self) -> List[Union[ParameterType, BodyParameterType]]:
180
+ """All keyword only parameters"""
181
+ return _sort(
234
182
  [
235
183
  p
236
- for p in parameters_of_this_implementation
184
+ for p in self.unsorted_method_params
237
185
  if p.method_location == ParameterMethodLocation.KEYWORD_ONLY
238
186
  ]
239
187
  )
240
- kwargs = self._filter_out_multiple_content_type(
188
+
189
+ @property
190
+ def kwarg(self) -> List[Union[ParameterType, BodyParameterType]]:
191
+ """All kwargs"""
192
+ return _sort(
241
193
  [
242
194
  p
243
- for p in parameters_of_this_implementation
244
- if p.method_location
245
- in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
195
+ for p in self.unsorted_method_params
196
+ if p.method_location == ParameterMethodLocation.KWARG
246
197
  ]
247
198
  )
248
199
 
249
- def _sort(params):
250
- return sorted(
251
- params, key=lambda x: not x.default_value and x.required, reverse=True
252
- )
200
+ @property
201
+ def body_parameter(self) -> BodyParameterType:
202
+ """The body parameter of the parameter list. Will only ever be at most one."""
203
+ if not self._body_parameter:
204
+ raise ValueError("There is no body parameter")
205
+ return self._body_parameter
253
206
 
254
- signature_parameters = _sort(positional) + _sort(keyword_only) + _sort(kwargs)
255
- return signature_parameters
207
+ @property
208
+ @abstractmethod
209
+ def implementation(self) -> str:
210
+ """Whether this is a client or a method parameter"""
211
+ ...
256
212
 
257
- def method_signature(self, is_python3_file: bool) -> List[str]:
258
- return _method_signature_helper(
259
- positional=self.method_signature_positional(is_python3_file),
260
- keyword_only=self.method_signature_keyword_only(is_python3_file),
213
+ @property
214
+ def unsorted_method_params(self) -> List[Union[ParameterType, BodyParameterType]]:
215
+ """Method params before sorting"""
216
+ method_params: List[Union[ParameterType, BodyParameterType]] = [
217
+ p
218
+ for p in self.parameters
219
+ if p.in_method_signature and p.implementation == self.implementation
220
+ ]
221
+ if self._body_parameter:
222
+ if self._body_parameter.in_method_signature:
223
+ method_params.append(self._body_parameter)
224
+ try:
225
+ # i am a multipart body parameter
226
+ # Only legacy generates operations with me, so I will follow the legacy rules
227
+ # I will splat out my entries as individual entries
228
+ method_params.extend(self._body_parameter.entries) # type: ignore
229
+ except AttributeError:
230
+ pass
231
+ return method_params
232
+
233
+ @property
234
+ def method(self) -> List[Union[ParameterType, BodyParameterType]]:
235
+ """Sorted method params. First positional, then keyword only, then kwarg"""
236
+ return self.positional + self.keyword_only + self.kwarg
237
+
238
+ def method_signature(self, is_python3_file: bool, async_mode: bool) -> List[str]:
239
+ """Method signature for this parameter list."""
240
+ return method_signature_helper(
241
+ positional=self.method_signature_positional(is_python3_file, async_mode),
242
+ keyword_only=self.method_signature_keyword_only(
243
+ is_python3_file, async_mode
244
+ ),
261
245
  kwarg_params=self.method_signature_kwargs(is_python3_file),
262
246
  )
263
247
 
264
- def method_signature_positional(self, is_python3_file: bool) -> List[str]:
248
+ def method_signature_positional(
249
+ self, is_python3_file: bool, async_mode: bool
250
+ ) -> List[str]:
251
+ """Signature for positional parameters"""
265
252
  return [
266
- parameter.method_signature(is_python3_file) for parameter in self.positional
253
+ parameter.method_signature(is_python3_file, async_mode)
254
+ for parameter in self.positional
267
255
  ]
268
256
 
269
- def method_signature_keyword_only(self, is_python3_file: bool) -> List[str]:
257
+ def method_signature_keyword_only(
258
+ self, is_python3_file: bool, async_mode: bool
259
+ ) -> List[str]:
260
+ """Signature for keyword only parameters"""
270
261
  if not (self.keyword_only and is_python3_file):
271
262
  return []
272
263
  return ["*,"] + [
273
- parameter.method_signature(is_python3_file)
264
+ parameter.method_signature(is_python3_file, async_mode)
274
265
  for parameter in self.keyword_only
275
266
  ]
276
267
 
277
268
  @staticmethod
278
269
  def method_signature_kwargs(is_python3_file: bool) -> List[str]:
270
+ """Signature for kwargs"""
279
271
  return ["**kwargs: Any"] if is_python3_file else ["**kwargs # type: Any"]
280
272
 
281
- @property
282
- def positional(self) -> List[Parameter]:
273
+ def kwargs_to_pop(
274
+ self, is_python3_file: bool
275
+ ) -> List[Union[ParameterType, BodyParameterType]]:
276
+ """Method kwargs we want to pop"""
277
+ # don't want to pop bodies unless it's a constant
278
+ kwargs_to_pop = self.kwarg
279
+ if not is_python3_file:
280
+ kwargs_to_pop += self.keyword_only
283
281
  return [
284
- p
285
- for p in self.method
286
- if p.method_location == ParameterMethodLocation.POSITIONAL
282
+ k
283
+ for k in kwargs_to_pop
284
+ if k.location != ParameterLocation.BODY or k.constant
287
285
  ]
288
286
 
289
287
  @property
290
- def keyword_only(self) -> List[Parameter]:
291
- return [
292
- p
288
+ def call(self) -> List[str]:
289
+ """How to pass in parameters to call the operation"""
290
+ retval = [
291
+ p.client_name
293
292
  for p in self.method
294
- if p.method_location == ParameterMethodLocation.KEYWORD_ONLY
293
+ if p.method_location == ParameterMethodLocation.POSITIONAL
295
294
  ]
295
+ retval.extend(
296
+ [
297
+ f"{p.client_name}={p.client_name}"
298
+ for p in self.method
299
+ if p.method_location == ParameterMethodLocation.KEYWORD_ONLY
300
+ ]
301
+ )
302
+ retval.append("**kwargs")
303
+ return retval
304
+
305
+ @classmethod
306
+ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"):
307
+ parameters = [
308
+ cls.parameter_creator()(parameter, code_model)
309
+ for parameter in yaml_data["parameters"]
310
+ ]
311
+ body_parameter = None
312
+ if yaml_data.get("bodyParameter"):
313
+ body_parameter = cls.body_parameter_creator()(
314
+ yaml_data["bodyParameter"], code_model
315
+ )
316
+ return cls(
317
+ yaml_data,
318
+ code_model,
319
+ parameters=parameters,
320
+ body_parameter=body_parameter,
321
+ )
322
+
323
+
324
+ class _ParameterList(
325
+ _ParameterListBase[ # pylint: disable=unsubscriptable-object
326
+ Parameter, Union[MultipartBodyParameter, BodyParameter]
327
+ ]
328
+ ):
329
+ """Base Parameter class for the two operation ParameterLists"""
330
+
331
+ @staticmethod
332
+ def parameter_creator() -> Callable[[Dict[str, Any], "CodeModel"], Parameter]:
333
+ return Parameter.from_yaml
334
+
335
+ @staticmethod
336
+ def body_parameter_creator() -> Callable[
337
+ [Dict[str, Any], "CodeModel"], Union[MultipartBodyParameter, BodyParameter]
338
+ ]:
339
+ return get_body_parameter
340
+
341
+ @property
342
+ def implementation(self) -> str:
343
+ return "Method"
296
344
 
297
345
  @property
298
- def kwargs(self) -> List[Parameter]:
346
+ def path(self) -> List[Parameter]:
299
347
  return [
300
- p
301
- for p in self.method
302
- if p.method_location
303
- in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
348
+ k for k in super().path if k.location == ParameterLocation.ENDPOINT_PATH
304
349
  ]
305
350
 
306
- def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
307
- kwargs_to_pop = self.kwargs
308
- if not is_python3_file:
309
- kwargs_to_pop += self.keyword_only
310
- return kwargs_to_pop
311
351
 
312
- def call(self, is_python3_file: bool) -> List[str]:
313
- retval = [p.serialized_name for p in self.positional]
314
- if is_python3_file:
315
- retval.extend(
316
- [f"{p.serialized_name}={p.serialized_name}" for p in self.keyword_only]
317
- )
318
- retval.append("**kwargs")
319
- return retval
352
+ class ParameterList(_ParameterList):
353
+ """ParameterList is the parameter list for Operation classes"""
354
+
355
+ ...
320
356
 
321
- @property
322
- def is_flattened(self) -> bool:
323
- return cast(
324
- bool, self.get_from_predicate(lambda parameter: parameter.flattened)
325
- )
326
357
 
358
+ class _RequestBuilderParameterList(
359
+ _ParameterListBase[ # pylint: disable=unsubscriptable-object
360
+ RequestBuilderParameter, RequestBuilderBodyParameterType
361
+ ]
362
+ ):
363
+ """_RequestBuilderParameterList is base parameter list for RequestBuilder classes"""
364
+
365
+ @staticmethod
366
+ def parameter_creator() -> Callable[
367
+ [Dict[str, Any], "CodeModel"], RequestBuilderParameter
368
+ ]:
369
+ return RequestBuilderParameter.from_yaml
370
+
371
+ @staticmethod
372
+ def body_parameter_creator() -> Callable[
373
+ [Dict[str, Any], "CodeModel"], RequestBuilderBodyParameterType
374
+ ]:
375
+ return get_request_body_parameter
327
376
 
328
- class GlobalParameterList(ParameterList):
329
377
  @property
330
378
  def implementation(self) -> str:
331
- return "Client"
379
+ return "Method"
332
380
 
333
381
  @property
334
- def method(self) -> List[Parameter]:
335
- """The list of parameter used in method signature."""
336
- # Client level should not be on Method, etc.
337
- positional = [
382
+ def unsorted_method_params(
383
+ self,
384
+ ) -> List[Union[RequestBuilderParameter, RequestBuilderBodyParameterType]]:
385
+ # don't have access to client params in request builder
386
+ retval = [
338
387
  p
339
- for p in self.parameters
340
- if p.method_location == ParameterMethodLocation.POSITIONAL
388
+ for p in super().unsorted_method_params
389
+ if not (
390
+ p.location == ParameterLocation.BODY
391
+ and cast(RequestBuilderBodyParameterType, p).is_partial_body
392
+ )
341
393
  ]
342
- keyword_only = self._filter_out_multiple_content_type(
394
+ retval.extend(
343
395
  [
344
396
  p
345
397
  for p in self.parameters
346
- if p.method_location == ParameterMethodLocation.KEYWORD_ONLY
347
- ]
348
- )
349
- kwargs = self._filter_out_multiple_content_type(
350
- [
351
- p
352
- for p in self.parameters
353
- if p.method_location
354
- in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
398
+ if p.implementation == "Client" and p.in_method_signature
355
399
  ]
356
400
  )
401
+ return retval
357
402
 
358
- def _sort(params):
359
- return sorted(
360
- params, key=lambda x: not x.default_value and x.required, reverse=True
361
- )
403
+ @property
404
+ def path(self) -> List[RequestBuilderParameter]:
405
+ return [
406
+ p for p in super().path if p.location != ParameterLocation.ENDPOINT_PATH
407
+ ]
362
408
 
363
- signature_parameters = _sort(positional) + _sort(keyword_only) + _sort(kwargs)
364
- return signature_parameters
365
409
 
366
- @property
367
- def host_variable_name(self) -> str:
368
- return (
369
- "endpoint"
370
- if self.code_model.options["version_tolerant"]
371
- or self.code_model.options["low_level_client"]
372
- else "base_url"
373
- )
410
+ class RequestBuilderParameterList(_RequestBuilderParameterList):
411
+ """Parameter list for Request Builder"""
412
+
413
+ ...
414
+
415
+
416
+ class OverloadedRequestBuilderParameterList(_RequestBuilderParameterList):
417
+ """Parameter list for OverloadedRequestBuilder"""
418
+
419
+ def method_signature(self, is_python3_file: bool, async_mode: bool) -> List[str]:
420
+ return self.method_signature_positional(
421
+ is_python3_file, async_mode
422
+ ) + self.method_signature_kwargs(is_python3_file)
423
+
424
+
425
+ class _ClientGlobalParameterList(
426
+ # pylint: disable=unsubscriptable-object
427
+ _ParameterListBase[ParameterType, BodyParameter]
428
+ ):
429
+ """Base parameter list for client and config classes"""
374
430
 
375
431
  @staticmethod
376
- def _wanted_path_parameter(parameter: Parameter) -> bool:
377
- return (
378
- parameter.location == ParameterLocation.Uri
379
- and parameter.implementation == "Client"
380
- and parameter.rest_api_name != "$host"
381
- )
432
+ def body_parameter_creator() -> Callable[
433
+ [Dict[str, Any], "CodeModel"], BodyParameter
434
+ ]:
435
+ return BodyParameter.from_yaml
382
436
 
383
- def add_host(self, host_value: Optional[str]) -> None:
384
- # only adds if we don't have a parameterized host
385
- host_param = Parameter(
386
- yaml_data={},
387
- code_model=self.code_model,
388
- schema=StringSchema(yaml_data={"type": "str"}, code_model=self.code_model),
389
- rest_api_name=self.host_variable_name,
390
- serialized_name=self.host_variable_name,
391
- description=f"Service URL.",
392
- implementation="Client",
393
- required=True,
394
- location=ParameterLocation.Other,
395
- skip_url_encoding=False,
396
- constraints=[],
397
- client_default_value=host_value,
398
- )
399
- if (
400
- self.code_model.options["version_tolerant"]
401
- or self.code_model.options["low_level_client"]
402
- ):
403
- host_param.method_location = ParameterMethodLocation.KEYWORD_ONLY
404
- self.parameters.append(host_param)
405
-
406
- def add_credential_global_parameter(self) -> None:
407
- credential_parameter = Parameter(
408
- yaml_data={},
409
- code_model=self.code_model,
410
- schema=self.code_model.credential_model.credential_schema_policy.credential,
411
- serialized_name="credential",
412
- rest_api_name="credential",
413
- implementation="Client",
414
- description="Credential needed for the client to connect to Azure.",
415
- required=True,
416
- location=ParameterLocation.Other,
417
- skip_url_encoding=True,
418
- constraints=[],
419
- )
420
- if (
421
- self.code_model.options["version_tolerant"]
422
- or self.code_model.options["low_level_client"]
423
- ):
424
- self.parameters.append(credential_parameter)
425
- else:
426
- self.parameters.insert(0, credential_parameter)
437
+ @property
438
+ def implementation(self) -> str:
439
+ return "Client"
427
440
 
428
441
  @property
429
- def host(self) -> Optional[Parameter]:
442
+ def credential(self) -> Optional[ParameterType]:
430
443
  try:
431
- return next(
432
- p
433
- for p in self.parameters
434
- if p.serialized_name == self.host_variable_name
435
- )
444
+ return next(p for p in self.parameters if p.client_name == "credential")
436
445
  except StopIteration:
437
446
  return None
438
447
 
439
448
  @property
440
- def host_value(self) -> Optional[str]:
441
- if self.code_model.service_client.has_parameterized_host:
442
- return None
443
- return next(
444
- p for p in self.parameters if p.serialized_name == self.host_variable_name
445
- ).default_value_declaration
449
+ def path(self) -> List[ParameterType]:
450
+ return [
451
+ p for p in super().path if p.location == ParameterLocation.ENDPOINT_PATH
452
+ ]
446
453
 
447
- @property
448
- def client_method(self) -> List[Parameter]:
449
- return self.method
450
454
 
451
- def _param_is_in_config_method(self, serialized_name):
452
- if self.code_model.service_client.has_parameterized_host:
453
- return True
454
- return serialized_name != self.host_variable_name
455
+ class ClientGlobalParameterList(_ClientGlobalParameterList[ClientParameter]):
456
+ """Parameter list for Client class"""
455
457
 
456
- def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
457
- return [
458
- k
459
- for k in super().kwargs_to_pop(is_python3_file)
460
- if not self._param_is_in_config_method(k.serialized_name)
461
- ]
458
+ @staticmethod
459
+ def parameter_creator() -> Callable[[Dict[str, Any], "CodeModel"], ClientParameter]:
460
+ return ClientParameter.from_yaml
462
461
 
463
- def config_kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
464
- current_kwargs_to_pop = super().kwargs_to_pop(is_python3_file)
465
- return [
466
- k
467
- for k in current_kwargs_to_pop
468
- if self._param_is_in_config_method(k.serialized_name)
469
- ]
462
+ @property
463
+ def path(self) -> List[ClientParameter]:
464
+ return [p for p in super().path if not p.is_host]
470
465
 
471
466
  @property
472
- def config_method(self) -> List[Parameter]:
467
+ def host(self) -> Optional[ClientParameter]:
468
+ """Get the host parameter"""
469
+ try:
470
+ return next(p for p in self.parameters if p.is_host)
471
+ except StopIteration:
472
+ return None
473
+
474
+ def kwargs_to_pop(
475
+ self, is_python3_file: bool
476
+ ) -> List[Union[ClientParameter, BodyParameter]]:
477
+ """We only want to pass base url path parameters in the client"""
473
478
  return [
474
- p for p in self.method if self._param_is_in_config_method(p.serialized_name)
479
+ k
480
+ for k in super().kwargs_to_pop(is_python3_file=is_python3_file)
481
+ if k.location == ParameterLocation.ENDPOINT_PATH
475
482
  ]
476
483
 
477
- def client_method_signature(self, is_python3_file: bool) -> List[str]:
478
- return self.method_signature(is_python3_file)
479
484
 
480
- def config_method_signature(self, is_python3_file: bool) -> List[str]:
485
+ class ConfigGlobalParameterList(_ClientGlobalParameterList[ConfigParameter]):
486
+ """Parameter list for config"""
481
487
 
482
- positional = [
483
- p.method_signature(is_python3_file)
484
- for p in self.positional
485
- if self._param_is_in_config_method(p.serialized_name)
486
- ]
487
- keyword_only_params = [
488
- p
489
- for p in self.keyword_only
490
- if self._param_is_in_config_method(p.serialized_name)
491
- ]
492
- keyword_only_method_signature = []
493
- if is_python3_file:
494
- keyword_only_method_signature = (
495
- (
496
- ["*,"]
497
- + [p.method_signature(is_python3_file) for p in keyword_only_params]
498
- )
499
- if keyword_only_params
500
- else []
501
- )
502
- return _method_signature_helper(
503
- positional=positional,
504
- keyword_only=keyword_only_method_signature,
505
- kwarg_params=self.method_signature_kwargs(is_python3_file),
506
- )
488
+ @staticmethod
489
+ def parameter_creator() -> Callable[[Dict[str, Any], "CodeModel"], ConfigParameter]:
490
+ return ConfigParameter.from_yaml
491
+
492
+ @property
493
+ def implementation(self) -> str:
494
+ return "Client"