@autorest/python 5.13.0 → 5.16.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 (101) hide show
  1. package/ChangeLog.md +67 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +239 -105
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +21 -24
  9. package/autorest/codegen/models/client.py +70 -20
  10. package/autorest/codegen/models/code_model.py +144 -129
  11. package/autorest/codegen/models/constant_schema.py +32 -16
  12. package/autorest/codegen/models/credential_model.py +55 -0
  13. package/autorest/codegen/models/credential_schema.py +21 -16
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +27 -24
  16. package/autorest/codegen/models/enum_schema.py +41 -62
  17. package/autorest/codegen/models/imports.py +72 -41
  18. package/autorest/codegen/models/list_schema.py +40 -18
  19. package/autorest/codegen/models/lro_operation.py +61 -25
  20. package/autorest/codegen/models/lro_paging_operation.py +5 -6
  21. package/autorest/codegen/models/object_schema.py +113 -59
  22. package/autorest/codegen/models/operation.py +251 -111
  23. package/autorest/codegen/models/operation_group.py +67 -32
  24. package/autorest/codegen/models/paging_operation.py +48 -21
  25. package/autorest/codegen/models/parameter.py +182 -90
  26. package/autorest/codegen/models/parameter_list.py +184 -163
  27. package/autorest/codegen/models/primitive_schemas.py +89 -70
  28. package/autorest/codegen/models/property.py +49 -31
  29. package/autorest/codegen/models/request_builder.py +67 -32
  30. package/autorest/codegen/models/request_builder_parameter.py +54 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +35 -17
  34. package/autorest/codegen/models/utils.py +24 -1
  35. package/autorest/codegen/serializers/__init__.py +273 -89
  36. package/autorest/codegen/serializers/builder_serializer.py +711 -333
  37. package/autorest/codegen/serializers/client_serializer.py +114 -43
  38. package/autorest/codegen/serializers/general_serializer.py +84 -25
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +42 -14
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +9 -8
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +60 -21
  50. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  51. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  52. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  53. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  54. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  55. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  56. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  58. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  59. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  60. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  61. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  62. package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
  63. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  64. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  65. package/autorest/codegen/templates/operation.py.jinja2 +8 -11
  66. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
  67. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  68. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  69. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  70. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  71. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
  72. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  73. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  74. package/autorest/jsonrpc/__init__.py +7 -12
  75. package/autorest/jsonrpc/localapi.py +4 -3
  76. package/autorest/jsonrpc/server.py +13 -6
  77. package/autorest/jsonrpc/stdstream.py +13 -6
  78. package/autorest/m2r/__init__.py +5 -8
  79. package/autorest/multiapi/__init__.py +24 -14
  80. package/autorest/multiapi/models/client.py +21 -11
  81. package/autorest/multiapi/models/code_model.py +23 -10
  82. package/autorest/multiapi/models/config.py +4 -1
  83. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  84. package/autorest/multiapi/models/global_parameter.py +2 -1
  85. package/autorest/multiapi/models/global_parameters.py +14 -8
  86. package/autorest/multiapi/models/imports.py +35 -18
  87. package/autorest/multiapi/models/mixin_operation.py +5 -5
  88. package/autorest/multiapi/models/operation_group.py +2 -1
  89. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  90. package/autorest/multiapi/serializers/__init__.py +18 -23
  91. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  92. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  93. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  94. package/autorest/multiapi/utils.py +3 -3
  95. package/autorest/namer/__init__.py +2 -4
  96. package/autorest/namer/name_converter.py +200 -103
  97. package/autorest/namer/python_mappings.py +10 -22
  98. package/package.json +3 -3
  99. package/run-python3.js +2 -3
  100. package/venvtools.py +1 -1
  101. package/autorest/codegen/models/rest.py +0 -42
@@ -6,7 +6,7 @@
6
6
  import logging
7
7
  from enum import Enum
8
8
 
9
- from typing import Dict, Optional, List, Any, Union, Tuple, cast
9
+ from typing import Dict, Optional, List, Any, Union, Tuple, cast, TYPE_CHECKING
10
10
 
11
11
  from .imports import FileImport, ImportType, TypingSection
12
12
  from .base_model import BaseModel
@@ -15,6 +15,10 @@ from .constant_schema import ConstantSchema
15
15
  from .object_schema import ObjectSchema
16
16
  from .property import Property
17
17
  from .primitive_schemas import IOSchema
18
+ from .utils import get_schema
19
+
20
+ if TYPE_CHECKING:
21
+ from .code_model import CodeModel
18
22
 
19
23
 
20
24
  _LOGGER = logging.getLogger(__name__)
@@ -22,6 +26,13 @@ _LOGGER = logging.getLogger(__name__)
22
26
  _HIDDEN_KWARGS = ["content_type"]
23
27
 
24
28
 
29
+ class ParameterMethodLocation(str, Enum):
30
+ POSITIONAL = "positional"
31
+ KEYWORD_ONLY = "keyword_only"
32
+ KWARG = "kwarg"
33
+ HIDDEN_KWARG = "hidden_kwarg"
34
+
35
+
25
36
  class ParameterLocation(Enum):
26
37
  Path = "path"
27
38
  Body = "body"
@@ -46,11 +57,21 @@ class ParameterStyle(Enum):
46
57
  multipart = "multipart"
47
58
 
48
59
 
49
- class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too-many-public-methods
60
+ def get_target_property_name(code_model: "CodeModel", target_property_id: int) -> str:
61
+ for obj in code_model.schemas.values():
62
+ for prop in obj.properties:
63
+ if prop.id == target_property_id:
64
+ return prop.name
65
+ raise KeyError("Didn't find the target property")
66
+
67
+
68
+ class Parameter(
69
+ BaseModel
70
+ ): # pylint: disable=too-many-instance-attributes, too-many-public-methods
50
71
  def __init__(
51
72
  self,
52
- code_model,
53
73
  yaml_data: Dict[str, Any],
74
+ code_model: "CodeModel",
54
75
  schema: BaseSchema,
55
76
  rest_api_name: str,
56
77
  serialized_name: str,
@@ -60,7 +81,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
60
81
  location: ParameterLocation,
61
82
  skip_url_encoding: bool,
62
83
  constraints: List[Any],
63
- target_property_name: Optional[Union[int, str]] = None, # first uses id as placeholder
84
+ target_property_name: Optional[
85
+ Union[int, str]
86
+ ] = None, # first uses id as placeholder
64
87
  style: Optional[ParameterStyle] = None,
65
88
  explode: Optional[bool] = False,
66
89
  *,
@@ -68,10 +91,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
68
91
  grouped_by: Optional["Parameter"] = None,
69
92
  original_parameter: Optional["Parameter"] = None,
70
93
  client_default_value: Optional[Any] = None,
71
- keyword_only: Optional[bool] = None,
72
94
  content_types: Optional[List[str]] = None,
73
95
  ) -> None:
74
- super().__init__(yaml_data)
96
+ super().__init__(yaml_data, code_model)
75
97
  self.code_model = code_model
76
98
  self.schema = schema
77
99
  self.rest_api_name = rest_api_name
@@ -92,14 +114,17 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
92
114
  self.has_multiple_content_types: bool = False
93
115
  self.multiple_content_types_type_annot: Optional[str] = None
94
116
  self.multiple_content_types_docstring_type: Optional[str] = None
95
- self._keyword_only = keyword_only
96
- self.is_multipart = yaml_data.get("language", {}).get("python", {}).get("multipart", False)
97
- self.is_data_input = yaml_data.get("isPartialBody", False) and not self.is_multipart
117
+ self.is_multipart = (
118
+ yaml_data.get("language", {}).get("python", {}).get("multipart", False)
119
+ )
120
+ self.is_data_input = (
121
+ yaml_data.get("isPartialBody", False) and not self.is_multipart
122
+ )
98
123
  self.content_types = content_types or []
99
124
  self.body_kwargs: List[Parameter] = []
100
125
  self.is_body_kwarg = False
101
126
  self.need_import = True
102
- self.is_kwarg = (self.rest_api_name == "Content-Type" or (self.constant and self.rest_api_name != "Accept"))
127
+ self._method_location: Optional[ParameterMethodLocation] = None
103
128
 
104
129
  def __hash__(self) -> int:
105
130
  return hash(self.serialized_name)
@@ -115,9 +140,11 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
115
140
  if isinstance(self.schema, ConstantSchema) and not self.constant:
116
141
  if description:
117
142
  description += " "
118
- description += f"Possible values are {self.schema.get_declaration(self.schema.value)} or {None}."
143
+ description += f"Known values are {self.schema.get_declaration(self.schema.value)} or {None}."
119
144
  if self.has_default_value and not any(
120
- l for l in ["default value is", "default is"] if l in description.lower()
145
+ l
146
+ for l in ["default value is", "default is"]
147
+ if l in description.lower()
121
148
  ):
122
149
  description += f" Default value is {self.default_value_declaration}."
123
150
  if self.constant:
@@ -160,12 +187,12 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
160
187
  return self.schema.get_declaration(self.schema.value)
161
188
  raise ValueError(
162
189
  "Trying to get constant declaration for a schema that is not ConstantSchema"
163
- )
190
+ )
164
191
  raise ValueError("Trying to get a declaration for a schema that doesn't exist")
165
192
 
166
193
  @property
167
194
  def serialization_formats(self) -> List[str]:
168
- return self.yaml_data.get('serializationFormats', [])
195
+ return self.yaml_data.get("serializationFormats", [])
169
196
 
170
197
  @property
171
198
  def xml_serialization_ctxt(self) -> str:
@@ -175,6 +202,10 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
175
202
  def is_body(self) -> bool:
176
203
  return self.location == ParameterLocation.Body
177
204
 
205
+ @property
206
+ def inputtable_by_user(self) -> bool:
207
+ return self.rest_api_name != "Accept"
208
+
178
209
  @property
179
210
  def pre_semicolon_content_types(self) -> List[str]:
180
211
  """Splits on semicolon of media types and returns the first half.
@@ -184,9 +215,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
184
215
 
185
216
  @property
186
217
  def in_method_signature(self) -> bool:
187
- return not(
188
- # don't put accept in signature
189
- self.rest_api_name == "Accept"
218
+ return not (
219
+ # if not inputtable, don't put in signature
220
+ not self.inputtable_by_user
190
221
  # If i'm not in the method code, no point in being in signature
191
222
  or not self.in_method_code
192
223
  # If I'm grouped, my grouper will be on signature, not me
@@ -201,15 +232,20 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
201
232
  raise ValueError("Should only be calling if your parameter is grouped")
202
233
  try:
203
234
  return next(
204
- p for p in cast(ObjectSchema, self.grouped_by.schema).properties
205
- if any(op for op in p.yaml_data['originalParameter'] if id(op) == self.id)
235
+ p
236
+ for p in cast(ObjectSchema, self.grouped_by.schema).properties
237
+ if any(
238
+ op for op in p.yaml_data["originalParameter"] if id(op) == self.id
239
+ )
206
240
  )
207
241
  except StopIteration:
208
- raise ValueError("There is not a corresponding grouped property for your parameter.")
242
+ raise ValueError(
243
+ "There is not a corresponding grouped property for your parameter."
244
+ )
209
245
 
210
246
  @property
211
247
  def in_method_code(self) -> bool:
212
- return self.rest_api_name != '$host'
248
+ return self.rest_api_name != "$host"
213
249
 
214
250
  @property
215
251
  def implementation(self) -> str:
@@ -225,15 +261,21 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
225
261
  ) and isinstance(self.schema, IOSchema)
226
262
 
227
263
  def _default_value(self) -> Tuple[Optional[Any], str, str]:
228
- type_annot = self.multiple_content_types_type_annot or self.schema.operation_type_annotation
264
+ type_annot = (
265
+ self.multiple_content_types_type_annot
266
+ or self.schema.type_annotation(is_operation_file=True)
267
+ )
229
268
  if self._is_io_json:
230
- type_annot = f"Union[{type_annot}, JSONType]"
231
- any_types = ["Any", "JSONType"]
232
- if not self.required and type_annot not in any_types and not self._is_io_json:
269
+ type_annot = f"Union[{type_annot}, Any]"
270
+ if not self.required and type_annot != "Any" and not self._is_io_json:
233
271
  type_annot = f"Optional[{type_annot}]"
234
272
 
235
273
  if self.client_default_value is not None:
236
- return self.client_default_value, self.schema.get_declaration(self.client_default_value), type_annot
274
+ return (
275
+ self.client_default_value,
276
+ self.schema.get_declaration(self.client_default_value),
277
+ type_annot,
278
+ )
237
279
 
238
280
  if self.multiple_content_types_type_annot:
239
281
  # means this parameter has multiple media types. We force default value to be None.
@@ -241,9 +283,11 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
241
283
  default_value_declaration = "None"
242
284
  else:
243
285
  if isinstance(self.schema, ConstantSchema):
244
- if (self.required or
245
- self.is_content_type or
246
- not self.code_model.options["default_optional_constants_to_none"]):
286
+ if (
287
+ self.required
288
+ or self.is_content_type
289
+ or not self.code_model.options["default_optional_constants_to_none"]
290
+ ):
247
291
  default_value = self.schema.get_declaration(self.schema.value)
248
292
  else:
249
293
  default_value = None
@@ -254,18 +298,36 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
254
298
  if default_value is not None and self.required:
255
299
  _LOGGER.warning(
256
300
  "Parameter '%s' is required and has a default value, this combination is not recommended",
257
- self.rest_api_name
301
+ self.rest_api_name,
258
302
  )
259
303
 
260
304
  return default_value, default_value_declaration, type_annot
261
305
 
262
306
  @property
263
307
  def description_keyword(self) -> str:
264
- return "keyword" if self.is_kwarg or self.is_keyword_only else "param"
308
+ return (
309
+ "keyword"
310
+ if self.method_location
311
+ in (
312
+ ParameterMethodLocation.KWARG,
313
+ ParameterMethodLocation.HIDDEN_KWARG,
314
+ ParameterMethodLocation.KEYWORD_ONLY,
315
+ )
316
+ else "param"
317
+ )
265
318
 
266
319
  @property
267
320
  def docstring_type_keyword(self) -> str:
268
- return "paramtype" if self.is_kwarg or self.is_keyword_only else "type"
321
+ return (
322
+ "paramtype"
323
+ if self.method_location
324
+ in (
325
+ ParameterMethodLocation.KWARG,
326
+ ParameterMethodLocation.HIDDEN_KWARG,
327
+ ParameterMethodLocation.KEYWORD_ONLY,
328
+ )
329
+ else "type"
330
+ )
269
331
 
270
332
  @property
271
333
  def default_value(self) -> Optional[Any]:
@@ -277,8 +339,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
277
339
  def default_value_declaration(self) -> Optional[Any]:
278
340
  return self._default_value()[1]
279
341
 
280
- @property
281
- def type_annotation(self) -> str:
342
+ def type_annotation(
343
+ self, *, is_operation_file: bool = False # pylint: disable=unused-argument
344
+ ) -> str:
282
345
  return self._default_value()[2]
283
346
 
284
347
  @property
@@ -287,9 +350,11 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
287
350
 
288
351
  @property
289
352
  def docstring_type(self) -> str:
290
- retval = self.multiple_content_types_docstring_type or self.schema.docstring_type
353
+ retval = (
354
+ self.multiple_content_types_docstring_type or self.schema.docstring_type
355
+ )
291
356
  if self._is_io_json:
292
- retval += " or JSONType"
357
+ retval += " or Any"
293
358
  return retval
294
359
 
295
360
  @property
@@ -297,13 +362,14 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
297
362
  return self.default_value is not None or not self.required
298
363
 
299
364
  def method_signature(self, is_python3_file: bool) -> str:
365
+ type_annot = self.type_annotation(is_operation_file=True)
300
366
  if is_python3_file:
301
367
  if self.has_default_value:
302
- return f"{self.serialized_name}: {self.type_annotation} = {self.default_value_declaration},"
303
- return f"{self.serialized_name}: {self.type_annotation},"
368
+ return f"{self.serialized_name}: {type_annot} = {self.default_value_declaration},"
369
+ return f"{self.serialized_name}: {type_annot},"
304
370
  if self.has_default_value:
305
- return f"{self.serialized_name}={self.default_value_declaration}, # type: {self.type_annotation}"
306
- return f"{self.serialized_name}, # type: {self.type_annotation}"
371
+ return f"{self.serialized_name}={self.default_value_declaration}, # type: {type_annot}"
372
+ return f"{self.serialized_name}, # type: {type_annot}"
307
373
 
308
374
  @property
309
375
  def full_serialized_name(self) -> str:
@@ -312,91 +378,117 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
312
378
  origin_name = f"self._config.{self.serialized_name}"
313
379
  return origin_name
314
380
 
315
- @property
316
- def is_keyword_only(self) -> bool:
317
- # this means in async mode, I am documented like def hello(positional_1, *, me!)
318
- return self._keyword_only or False
319
-
320
- @is_keyword_only.setter
321
- def is_keyword_only(self, val: bool) -> None:
322
- self._keyword_only = val
323
- self.is_kwarg = False
324
-
325
- @property
326
- def is_hidden(self) -> bool:
327
- return self.serialized_name in _HIDDEN_KWARGS and self.is_kwarg or (
328
- self.yaml_data["implementation"] == "Client" and self.constant
329
- )
330
-
331
381
  @property
332
382
  def is_content_type(self) -> bool:
333
- return self.rest_api_name == "Content-Type" and self.location == ParameterLocation.Header
383
+ return (
384
+ self.rest_api_name == "Content-Type"
385
+ and self.location == ParameterLocation.Header
386
+ )
334
387
 
335
388
  @property
336
- def is_positional(self) -> bool:
337
- return self.in_method_signature and not (self.is_keyword_only or self.is_kwarg)
389
+ def method_location(self) -> ParameterMethodLocation:
390
+ if self._method_location:
391
+ return self._method_location
392
+ if self.serialized_name in _HIDDEN_KWARGS or (
393
+ self._implementation == "Client" and self.constant
394
+ ):
395
+ return ParameterMethodLocation.HIDDEN_KWARG
396
+ if self.constant and self.inputtable_by_user:
397
+ return ParameterMethodLocation.KWARG
398
+ return ParameterMethodLocation.POSITIONAL
399
+
400
+ @method_location.setter
401
+ def method_location(self, val: ParameterMethodLocation) -> None:
402
+ self._method_location = val
338
403
 
339
404
  @classmethod
340
405
  def from_yaml(
341
406
  cls,
342
407
  yaml_data: Dict[str, Any],
408
+ code_model: "CodeModel",
343
409
  *,
344
- code_model,
345
- content_types: Optional[List[str]] = None
410
+ content_types: Optional[List[str]] = None,
346
411
  ) -> "Parameter":
347
- http_protocol = yaml_data["protocol"].get("http", {"in": ParameterLocation.Other})
412
+ http_protocol = yaml_data["protocol"].get(
413
+ "http", {"in": ParameterLocation.Other}
414
+ )
415
+ serialized_name = yaml_data["language"]["python"]["name"]
416
+ schema = get_schema(code_model, yaml_data.get("schema"), serialized_name)
417
+ target_property = yaml_data.get("targetProperty")
418
+ target_property_name = (
419
+ get_target_property_name(code_model, id(target_property))
420
+ if target_property
421
+ else None
422
+ )
423
+
348
424
  return cls(
349
- code_model=code_model,
350
425
  yaml_data=yaml_data,
351
- schema=yaml_data.get("schema", None), # FIXME replace by operation model
426
+ code_model=code_model,
427
+ schema=schema, # FIXME replace by operation model
352
428
  # See also https://github.com/Azure/autorest.modelerfour/issues/80
353
429
  rest_api_name=yaml_data["language"]["default"].get(
354
430
  "serializedName", yaml_data["language"]["default"]["name"]
355
431
  ),
356
- serialized_name=yaml_data["language"]["python"]["name"],
432
+ serialized_name=serialized_name,
357
433
  description=yaml_data["language"]["python"]["description"],
358
434
  implementation=yaml_data["implementation"],
359
435
  required=yaml_data.get("required", False),
360
436
  location=ParameterLocation(http_protocol["in"]),
361
- skip_url_encoding=yaml_data.get("extensions", {}).get("x-ms-skip-url-encoding", False),
437
+ skip_url_encoding=yaml_data.get("extensions", {}).get(
438
+ "x-ms-skip-url-encoding", False
439
+ ),
362
440
  constraints=[], # FIXME constraints
363
- target_property_name=id(yaml_data["targetProperty"]) if yaml_data.get("targetProperty") else None,
364
- style=ParameterStyle(http_protocol["style"]) if "style" in http_protocol else None,
441
+ target_property_name=target_property_name,
442
+ style=ParameterStyle(http_protocol["style"])
443
+ if "style" in http_protocol
444
+ else None,
365
445
  explode=http_protocol.get("explode", False),
366
446
  grouped_by=yaml_data.get("groupedBy", None),
367
447
  original_parameter=yaml_data.get("originalParameter", None),
368
448
  flattened=yaml_data.get("flattened", False),
369
449
  client_default_value=yaml_data.get("clientDefaultValue"),
370
- content_types=content_types
450
+ content_types=content_types,
371
451
  )
372
452
 
373
453
  def imports(self) -> FileImport:
374
- file_import = self.schema.imports()
375
- if not self.required:
376
- file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
377
- if self.has_multiple_content_types or self._is_io_json:
378
- file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
454
+ if self.need_import:
455
+ file_import = self.schema.imports()
456
+ if not self.required:
457
+ file_import.add_submodule_import(
458
+ "typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
459
+ )
460
+ if self.has_multiple_content_types or self._is_io_json:
461
+ file_import.add_submodule_import(
462
+ "typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
463
+ )
379
464
 
380
- return file_import
465
+ return file_import
466
+ return FileImport()
381
467
 
382
- class ParameterOnlyPathAndBodyPositional(Parameter):
383
468
 
469
+ class ParameterOnlyPathAndBodyPositional(Parameter):
384
470
  @property
385
- def is_keyword_only(self) -> bool:
386
- if self._keyword_only is not None:
387
- return self._keyword_only
388
- return self.in_method_signature and not (
389
- self.is_hidden or
390
- self.location == ParameterLocation.Path or
391
- self.location == ParameterLocation.Uri or
392
- self.location == ParameterLocation.Body or
393
- self.is_kwarg
394
- )
471
+ def method_location(self) -> ParameterMethodLocation:
472
+ super_method_location = super().method_location
473
+ if super_method_location in (
474
+ ParameterMethodLocation.KWARG,
475
+ ParameterMethodLocation.HIDDEN_KWARG,
476
+ ):
477
+ return super_method_location
478
+ if self._method_location:
479
+ return self._method_location
480
+ if self.location not in (
481
+ ParameterLocation.Path,
482
+ ParameterLocation.Uri,
483
+ ParameterLocation.Body,
484
+ ):
485
+ return ParameterMethodLocation.KEYWORD_ONLY
486
+ return super_method_location
487
+
488
+ @method_location.setter
489
+ def method_location(self, val: ParameterMethodLocation) -> None:
490
+ self._method_location = val
395
491
 
396
- @is_keyword_only.setter
397
- def is_keyword_only(self, val: bool) -> None:
398
- self._keyword_only = val
399
- self.is_kwarg = False
400
492
 
401
493
  def get_parameter(code_model):
402
494
  if code_model.options["only_path_and_body_params_positional"]: