@autorest/python 6.4.5 → 6.4.7

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.
@@ -194,7 +194,7 @@ class CodeModel: # pylint: disable=too-many-public-methods
194
194
 
195
195
  @property
196
196
  def public_model_types(self) -> List[ModelType]:
197
- return [m for m in self.model_types if m.is_public and not m.base == "json"]
197
+ return [m for m in self.model_types if not m.internal and not m.base == "json"]
198
198
 
199
199
  @property
200
200
  def enums(self) -> List[EnumType]:
@@ -12,13 +12,11 @@ from .constant_type import ConstantType
12
12
  from .property import Property
13
13
  from .imports import FileImport, ImportType, TypingSection
14
14
 
15
-
16
15
  if sys.version_info >= (3, 8):
17
16
  from typing import Literal # pylint: disable=no-name-in-module, ungrouped-imports
18
17
  else:
19
18
  from typing_extensions import Literal # type: ignore # pylint: disable=ungrouped-imports
20
19
 
21
-
22
20
  if TYPE_CHECKING:
23
21
  from .code_model import CodeModel
24
22
 
@@ -74,7 +72,7 @@ class ModelType( # pylint: disable=abstract-method
74
72
  )
75
73
  self._created_json_template_representation = False
76
74
  self._got_polymorphic_subtypes = False
77
- self.is_public: bool = self.yaml_data.get("isPublic", True)
75
+ self.internal: bool = self.yaml_data.get("internal", False)
78
76
  self.snake_case_name: str = self.yaml_data["snakeCaseName"]
79
77
 
80
78
  @property
@@ -284,7 +282,7 @@ class GeneratedModelType(ModelType): # pylint: disable=abstract-method
284
282
  def type_annotation(self, **kwargs: Any) -> str:
285
283
  is_operation_file = kwargs.pop("is_operation_file", False)
286
284
  retval = f"_models.{self.name}"
287
- if not self.is_public:
285
+ if self.internal:
288
286
  retval = f"{self.code_model.models_filename}.{retval}"
289
287
  return retval if is_operation_file else f'"{retval}"'
290
288
 
@@ -321,7 +319,7 @@ class MsrestModelType(GeneratedModelType):
321
319
  @property
322
320
  def serialization_type(self) -> str:
323
321
  private_model_path = f"_models.{self.code_model.models_filename}."
324
- return f"{'' if self.is_public else private_model_path}{self.name}"
322
+ return f"{private_model_path if self.internal else ''}{self.name}"
325
323
 
326
324
  @property
327
325
  def instance_check_template(self) -> str:
@@ -340,7 +338,7 @@ class DPGModelType(GeneratedModelType):
340
338
 
341
339
  @property
342
340
  def serialization_type(self) -> str:
343
- return f"{'' if self.is_public else '_models.'}_models.{self.name}"
341
+ return f"{'_models.' if self.internal else ''}_models.{self.name}"
344
342
 
345
343
  @property
346
344
  def instance_check_template(self) -> str:
@@ -82,6 +82,9 @@ class OperationBase( # pylint: disable=too-many-public-methods
82
82
  "isLroInitialOperation", False
83
83
  )
84
84
  self.include_documentation: bool = not self.is_lro_initial_operation
85
+ self.internal: bool = self.yaml_data.get("internal", False)
86
+ if self.internal:
87
+ self.name = "_" + self.name
85
88
 
86
89
  @property
87
90
  def expose_stream_keyword(self) -> bool:
@@ -140,7 +140,11 @@ class _ParameterBase(
140
140
 
141
141
  def type_annotation(self, **kwargs: Any) -> str:
142
142
  kwargs["is_operation_file"] = True
143
- type_annot = self.type.type_annotation(**kwargs)
143
+ # special logic for api-version parameter
144
+ if self.is_api_version:
145
+ type_annot = "str"
146
+ else:
147
+ type_annot = self.type.type_annotation(**kwargs)
144
148
  if self.optional and self.client_default_value is None:
145
149
  return f"Optional[{type_annot}]"
146
150
  return type_annot
@@ -176,9 +180,13 @@ class _ParameterBase(
176
180
 
177
181
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
178
182
  file_import = self._imports_shared(async_mode, **kwargs)
179
- file_import.merge(
180
- self.type.imports(is_operation_file=True, async_mode=async_mode, **kwargs)
181
- )
183
+ # special logic for api-version parameter
184
+ if not self.is_api_version:
185
+ file_import.merge(
186
+ self.type.imports(
187
+ is_operation_file=True, async_mode=async_mode, **kwargs
188
+ )
189
+ )
182
190
  if self.default_to_unset_sentinel:
183
191
  file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
184
192
  file_import.define_mypy_type(
@@ -305,7 +305,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
305
305
  def description_and_summary(self, builder: BuilderType) -> List[str]:
306
306
  description_list: List[str] = []
307
307
  description_list.append(
308
- f"{ builder.summary.strip() if builder.summary else builder.description.strip() }"
308
+ f"{builder.summary.strip() if builder.summary else builder.description.strip()}"
309
309
  )
310
310
  if builder.summary and builder.description:
311
311
  description_list.append("")
@@ -328,7 +328,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
328
328
  if not param.in_docstring:
329
329
  continue
330
330
  description_list.extend(
331
- f":{param.description_keyword} { param.client_name }: { param.description }".replace(
331
+ f":{param.description_keyword} {param.client_name}: {param.description}".replace(
332
332
  "\n", "\n "
333
333
  ).split(
334
334
  "\n"
@@ -704,9 +704,12 @@ class _OperationSerializer(
704
704
  check_client_input=not self.code_model.options["multiapi"],
705
705
  )
706
706
  cls_annotation = builder.cls_type_annotation(async_mode=self.async_mode)
707
- kwargs.append(f"cls: {cls_annotation} = kwargs.pop('cls', None)")
707
+ pylint_disable = ""
708
708
  if any(x.startswith("_") for x in cls_annotation.split(".")):
709
- kwargs[-1] += " # pylint: disable=protected-access"
709
+ pylint_disable = " # pylint: disable=protected-access"
710
+ kwargs.append(
711
+ f"cls: {cls_annotation} = kwargs.pop({pylint_disable}\n 'cls', None\n)"
712
+ )
710
713
  return kwargs
711
714
 
712
715
  def response_docstring(self, builder: OperationType) -> List[str]:
@@ -1047,15 +1050,23 @@ class _OperationSerializer(
1047
1050
  )
1048
1051
  )
1049
1052
  elif response.type:
1053
+ pylint_disable = ""
1054
+ if isinstance(response.type, ModelType) and response.type.internal:
1055
+ pylint_disable = " # pylint: disable=protected-access"
1050
1056
  if self.code_model.options["models_mode"] == "msrest":
1057
+ deserialize_code.append("deserialized = self._deserialize(")
1051
1058
  deserialize_code.append(
1052
- f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)"
1059
+ f" '{response.serialization_type}',{pylint_disable}"
1053
1060
  )
1061
+ deserialize_code.append(" pipeline_response")
1062
+ deserialize_code.append(")")
1054
1063
  elif self.code_model.options["models_mode"] == "dpg":
1064
+ deserialize_code.append("deserialized = _deserialize(")
1055
1065
  deserialize_code.append(
1056
- f"deserialized = _deserialize({response.type.type_annotation(is_operation_file=True)}"
1057
- ", response.json())"
1066
+ f" {response.type.type_annotation(is_operation_file=True)},{pylint_disable}"
1058
1067
  )
1068
+ deserialize_code.append(" response.json()")
1069
+ deserialize_code.append(")")
1059
1070
  else:
1060
1071
  deserialized_value = (
1061
1072
  "ET.fromstring(response.text())"
@@ -1247,7 +1258,7 @@ class _OperationSerializer(
1247
1258
  @staticmethod
1248
1259
  def get_metadata_url(builder: OperationType) -> str:
1249
1260
  url = _escape_str(builder.request_builder.url)
1250
- return f"{builder.name}.metadata = {{'url': { url }}}"
1261
+ return f"{builder.name}.metadata = {{'url': {url}}}"
1251
1262
 
1252
1263
  @property
1253
1264
  def _call_method(self) -> str:
@@ -1379,10 +1390,10 @@ class _PagingOperationSerializer(
1379
1390
  if self.code_model.options["models_mode"] == "msrest":
1380
1391
  deserialize_type = response.serialization_type
1381
1392
  pylint_disable = " # pylint: disable=protected-access"
1382
- if isinstance(response.type, ModelType) and response.type.is_public:
1393
+ if isinstance(response.type, ModelType) and not response.type.internal:
1383
1394
  deserialize_type = f'"{response.serialization_type}"'
1384
1395
  pylint_disable = ""
1385
- deserialized = f"self._deserialize(\n {deserialize_type}, pipeline_response{pylint_disable}\n)"
1396
+ deserialized = f"self._deserialize(\n {deserialize_type},{pylint_disable}\n pipeline_response\n)"
1386
1397
  retval.append(f" deserialized = {deserialized}")
1387
1398
  elif self.code_model.options["models_mode"] == "dpg":
1388
1399
  # we don't want to generate paging models for DPG
@@ -1501,7 +1512,7 @@ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1501
1512
  retval.append("if cont_token is None:")
1502
1513
  retval.append(
1503
1514
  f" raw_result = {self._call_method}self.{builder.initial_operation.name}("
1504
- f"{'' if builder.lro_response and builder.lro_response.type else ' # type: ignore'}"
1515
+ f"{'' if builder.lro_response and builder.lro_response.type else ' # type: ignore'}"
1505
1516
  )
1506
1517
  retval.extend(
1507
1518
  [
@@ -215,7 +215,7 @@ class DpgModelSerializer(_ModelSerializer):
215
215
  file_import.merge(prop.imports())
216
216
  if model.is_polymorphic:
217
217
  file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB)
218
- if model.is_public and self.init_line(model):
218
+ if not model.internal and self.init_line(model):
219
219
  file_import.add_submodule_import(
220
220
  "typing", "overload", ImportType.STDLIB
221
221
  )
@@ -251,7 +251,7 @@ class DpgModelSerializer(_ModelSerializer):
251
251
  return properties_to_declare
252
252
 
253
253
  @staticmethod
254
- def declare_property(prop: Property) -> List[str]:
254
+ def declare_property(prop: Property) -> str:
255
255
  args = []
256
256
  if prop.client_name != prop.rest_api_name or prop.is_discriminator:
257
257
  args.append(f'name="{prop.rest_api_name}"')
@@ -266,14 +266,10 @@ class DpgModelSerializer(_ModelSerializer):
266
266
  and prop.is_discriminator
267
267
  and cast(ConstantType, prop.type).value
268
268
  )
269
- ret = [
269
+ return (
270
270
  f"{prop.client_name}: {prop.type_annotation()} ="
271
271
  f' {field}({", ".join(args)}){" # type: ignore" if type_ignore else ""}'
272
- ]
273
- comment = prop.description(is_operation_file=False).replace('"', '\\"')
274
- if comment:
275
- ret.append(f'"""{comment}"""')
276
- return ret
272
+ )
277
273
 
278
274
  def initialize_properties(self, model: ModelType) -> List[str]:
279
275
  init_args = []
@@ -127,6 +127,7 @@ class ParameterSerializer:
127
127
  if pop_headers_kwarg != PopKwargType.NO or pop_params_kwarg != PopKwargType.NO:
128
128
  retval.append("")
129
129
  for kwarg in parameters:
130
+ type_annot = kwarg.type_annotation()
130
131
  if kwarg.client_default_value is not None or kwarg.optional:
131
132
  if check_client_input and kwarg.check_client_input:
132
133
  default_value = f"self._config.{kwarg.client_name}"
@@ -145,11 +146,10 @@ class ParameterSerializer:
145
146
  f"_{kwarg_dict}.pop('{kwarg.rest_api_name}', {default_value})"
146
147
  )
147
148
  retval.append(
148
- f"{kwarg.client_name}: {kwarg.type_annotation()} = kwargs.pop('{kwarg.client_name}', "
149
+ f"{kwarg.client_name}: {type_annot} = kwargs.pop('{kwarg.client_name}', "
149
150
  + f"{default_value})"
150
151
  )
151
152
  else:
152
- type_annot = kwarg.type_annotation()
153
153
  retval.append(
154
154
  f"{kwarg.client_name}: {type_annot} = kwargs.pop('{kwarg.client_name}')"
155
155
  )
@@ -1,7 +1,5 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools %}
2
2
  {% import 'keywords.jinja2' as keywords %}
3
- {% set only_path = client.code_model.options["only_path_and_body_params_positional"] %}
4
- {% set method_location = "keywordOnly" if only_path else "positional" %}
5
3
  {
6
4
  "chosen_version": {{ chosen_version | tojson }},
7
5
  "total_api_version_list": {{ total_api_version_list | tojson }},
@@ -52,15 +50,15 @@
52
50
  "description": "API version to use if no profile is provided, or if missing in profile.",
53
51
  "docstring_type": "str",
54
52
  "required": false,
55
- "method_location": {{ method_location | tojson }}
53
+ "method_location": "positional"
56
54
  },
57
55
  {% if not client.has_parameterized_host %}
58
- "{{ "endpoint" if only_path else "base_url" }}": {
56
+ "base_url": {
59
57
  "signature": {{ client.parameters.host.method_signature(async_mode=False) | tojson }},
60
58
  "description": "Service URL",
61
59
  "docstring_type": "str",
62
60
  "required": false,
63
- "method_location": {{ method_location | tojson }}
61
+ "method_location": "positional"
64
62
  },
65
63
  {% endif %}
66
64
  "profile": {
@@ -68,7 +66,7 @@
68
66
  "description": "A profile definition, from KnownProfiles to dict.",
69
67
  "docstring_type": "azure.profiles.KnownProfiles",
70
68
  "required": false,
71
- "method_location": {{ method_location | tojson }}
69
+ "method_location": "positional"
72
70
  }
73
71
  },
74
72
  "async": {
@@ -77,15 +75,15 @@
77
75
  "description": "API version to use if no profile is provided, or if missing in profile.",
78
76
  "docstring_type": "str",
79
77
  "required": false,
80
- "method_location": {{ method_location | tojson }}
78
+ "method_location": "positional"
81
79
  },
82
80
  {% if not client.has_parameterized_host %}
83
- "{{ "endpoint" if only_path else "base_url" }}": {
81
+ "base_url": {
84
82
  "signature": {{ client.parameters.host.method_signature(async_mode=True) | tojson }},
85
83
  "description": "Service URL",
86
84
  "docstring_type": "str",
87
85
  "required": false,
88
- "method_location": {{ method_location | tojson }}
86
+ "method_location": "positional"
89
87
  },
90
88
  {% endif %}
91
89
  "profile": {
@@ -93,7 +91,7 @@
93
91
  "description": "A profile definition, from KnownProfiles to dict.",
94
92
  "docstring_type": "azure.profiles.KnownProfiles",
95
93
  "required": false,
96
- "method_location": {{ method_location | tojson }}
94
+ "method_location": "positional"
97
95
  }
98
96
  }
99
97
  }
@@ -421,7 +421,10 @@ class Model(_MyMutableMapping):
421
421
  if non_attr_kwargs:
422
422
  # actual type errors only throw the first wrong keyword arg they see, so following that.
423
423
  raise TypeError(f"{class_name}.__init__() got an unexpected keyword argument '{non_attr_kwargs[0]}'")
424
- dict_to_pass.update({self._attr_to_rest_field[k]._rest_name: _serialize(v) for k, v in kwargs.items()})
424
+ dict_to_pass.update({
425
+ self._attr_to_rest_field[k]._rest_name: _serialize(v)
426
+ for k, v in kwargs.items() if v is not None
427
+ })
425
428
  super().__init__(dict_to_pass)
426
429
 
427
430
  def copy(self) -> "Model":
@@ -31,12 +31,14 @@
31
31
  __mapping__: Dict[str, _model_base.Model] = {}
32
32
  {% endif %}
33
33
  {% for p in serializer.get_properties_to_declare(model)%}
34
- {% for line in serializer.declare_property(p) %}
35
- {{ line }}
36
- {% endfor %}
34
+ {{ serializer.declare_property(p) }}
35
+ {% set prop_description = p.description(is_operation_file=False).replace('"', '\\"') %}
36
+ {% if prop_description %}
37
+ """{{ prop_description | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n ') }}"""
38
+ {% endif %}
37
39
  {% endfor %}
38
40
 
39
- {% if model.is_public and serializer.init_line(model) %}
41
+ {% if not model.internal and serializer.init_line(model) %}
40
42
  @overload
41
43
  def __init__(
42
44
  self,
@@ -55,7 +57,7 @@
55
57
 
56
58
  {% endif %}
57
59
  {% set initialize_properties = serializer.initialize_properties(model) %}
58
- {% if model.is_public and serializer.init_line(model) or initialize_properties %}
60
+ {% if not model.internal and serializer.init_line(model) or initialize_properties %}
59
61
  def __init__(self, *args: Any, **kwargs: Any) -> None:{{ '# pylint: disable=useless-super-delegation' if not initialize_properties else '' }}
60
62
  super().__init__(*args, **kwargs)
61
63
  {% for initialize_property in initialize_properties %}
@@ -62,5 +62,9 @@ _SERIALIZER.client_side_validation = False
62
62
  {% macro generate_overloads(operation_serializer, operation) %}
63
63
  {% for overload in operation.overloads %}
64
64
  {{ operation_serializer.method_signature_and_response_type_annotation(overload) }}
65
+ {% if not operation.internal %}
65
66
  {{ description(overload, operation_serializer) | indent }}
67
+ {% else %}
68
+ ...
69
+ {% endif %}
66
70
  {% endfor %}{% endmacro %}
@@ -602,7 +602,7 @@ class M4Reformatter(
602
602
  )
603
603
  if self.version_tolerant:
604
604
  # if we're in version tolerant, hide the paging model
605
- returned_response_object["type"]["isPublic"] = False
605
+ returned_response_object["type"]["internal"] = True
606
606
  operation["itemType"] = next(
607
607
  p["type"]
608
608
  for p in returned_response_object["type"]["properties"]
@@ -994,11 +994,7 @@ class M4Reformatter(
994
994
  if name == "$host":
995
995
  # I am the non-parameterized endpoint. Modify name based off of flag
996
996
 
997
- client_name = (
998
- "endpoint"
999
- if self.only_path_and_body_parameters_positional
1000
- else "base_url"
1001
- )
997
+ client_name = "endpoint" if self.version_tolerant else "base_url"
1002
998
  global_parameter["language"]["default"]["description"] = "Service URL."
1003
999
  elif (
1004
1000
  global_parameter.get("origin") == "modelerfour:synthesized/api-version"
@@ -1129,7 +1125,7 @@ class M4Reformatter(
1129
1125
  "skipUrlEncoding": True,
1130
1126
  "inOverload": False,
1131
1127
  }
1132
- if self.only_path_and_body_parameters_positional:
1128
+ if self.version_tolerant:
1133
1129
  parameters.append(credential)
1134
1130
  else:
1135
1131
  parameters.insert(0, credential)
@@ -218,10 +218,27 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
218
218
  )
219
219
  add_redefined_builtin_info(property["clientName"], property)
220
220
  if type.get("name"):
221
+ type["name"] = self.pad_reserved_words(type["name"], PadType.MODEL)
221
222
  type["description"] = update_description(
222
223
  type["description"], type["name"]
223
224
  )
224
225
  type["snakeCaseName"] = to_snake_case(type["name"])
226
+ if type.get("values") and not self.version_tolerant:
227
+ # we're enums
228
+ values_to_add = []
229
+ for value in type["values"]:
230
+ padded_name = self.pad_reserved_words(
231
+ value["name"].lower(), PadType.ENUM
232
+ ).upper()
233
+ if value["name"] != padded_name:
234
+ values_to_add.append(
235
+ {
236
+ "description": value["description"],
237
+ "name": padded_name,
238
+ "value": value["value"],
239
+ }
240
+ )
241
+ type["values"].extend(values_to_add)
225
242
 
226
243
  def update_client(self, yaml_data: Dict[str, Any]) -> None:
227
244
  yaml_data["description"] = update_description(
@@ -325,14 +342,22 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
325
342
  code_model: Dict[str, Any],
326
343
  yaml_data: Dict[str, Any],
327
344
  is_overload: bool = False,
345
+ item_type: Optional[Dict[str, Any]] = None,
328
346
  ) -> None:
329
347
  self.update_lro_operation(code_model, yaml_data, is_overload=is_overload)
330
- self.update_paging_operation(code_model, yaml_data, is_overload=is_overload)
348
+ self.update_paging_operation(
349
+ code_model, yaml_data, is_overload=is_overload, item_type=item_type
350
+ )
331
351
  yaml_data["discriminator"] = "lropaging"
332
352
  for response in yaml_data.get("responses", []):
333
353
  response["discriminator"] = "lropaging"
334
354
  for overload in yaml_data.get("overloads", []):
335
- self.update_lro_paging_operation(code_model, overload, is_overload=True)
355
+ self.update_lro_paging_operation(
356
+ code_model,
357
+ overload,
358
+ is_overload=True,
359
+ item_type=yaml_data["responses"][0]["itemType"],
360
+ )
336
361
 
337
362
  def update_lro_operation(
338
363
  self,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.4.5",
3
+ "version": "6.4.7",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "@autorest/system-requirements": "~1.0.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@microsoft.azure/autorest.testserver": "^3.3.45",
25
+ "@microsoft.azure/autorest.testserver": "^3.3.46",
26
26
  "typescript": "^4.8.3"
27
27
  },
28
28
  "files": [
package/requirements.txt CHANGED
@@ -6,7 +6,7 @@ json-rpc==1.14.0
6
6
  m2r2==0.3.3
7
7
  MarkupSafe==2.1.2
8
8
  mistune==0.8.4
9
- pathspec==0.11.0
10
- platformdirs==3.1.0
9
+ pathspec==0.11.1
10
+ platformdirs==3.2.0
11
11
  PyYAML==6.0
12
12
  tomli==2.0.1