@autorest/python 6.13.19 → 6.14.1

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.
@@ -111,7 +111,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
111
111
  )
112
112
  )
113
113
 
114
- queue = self.yaml_data["operationGroups"].copy()
114
+ queue = self.yaml_data.get("operationGroups", []).copy()
115
115
  while queue:
116
116
  now = queue.pop(0)
117
117
  add_og_request_builder(now)
@@ -225,6 +225,13 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
225
225
  f"{async_prefix}ARMAutoResourceProviderRegistrationPolicy",
226
226
  ImportType.SDKCORE,
227
227
  )
228
+
229
+ # import for "Self"
230
+ file_import.add_submodule_import(
231
+ "typing_extensions",
232
+ "Self",
233
+ ImportType.STDLIB,
234
+ )
228
235
  return file_import
229
236
 
230
237
  @property
@@ -253,18 +260,6 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
253
260
  if isinstance(operation, (LROOperation, LROPagingOperation)):
254
261
  operation.initial_operation = self.lookup_operation(id(operation.yaml_data["initialOperation"]))
255
262
 
256
- @property
257
- def need_request_converter(self) -> bool:
258
- """
259
- Whether we need to convert our created azure.core.rest.HttpRequest to
260
- azure.core.pipeline.transport.HttpRequest
261
- """
262
- return (
263
- self.code_model.options["show_operations"]
264
- and bool(self.request_builders)
265
- and not self.code_model.options["version_tolerant"]
266
- )
267
-
268
263
  @property
269
264
  def has_abstract_operations(self) -> bool:
270
265
  """Whether there is abstract operation in any operation group."""
@@ -120,11 +120,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
120
120
  return True
121
121
  if async_mode:
122
122
  return self.need_mixin_abc
123
- return self.need_request_converter or self.need_mixin_abc or self.has_etag or self.has_form_data
124
-
125
- @property
126
- def need_request_converter(self) -> bool:
127
- return any(c for c in self.clients if c.need_request_converter)
123
+ return self.need_mixin_abc or self.has_etag or self.has_form_data
128
124
 
129
125
  @property
130
126
  def need_mixin_abc(self) -> bool:
@@ -241,9 +237,3 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
241
237
  @property
242
238
  def is_legacy(self) -> bool:
243
239
  return _is_legacy(self.options)
244
-
245
- @property
246
- def need_typing_extensions(self) -> bool:
247
- if self.options["models_mode"] == "dpg":
248
- return True
249
- return False
@@ -3,6 +3,7 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
+ from enum import Enum
6
7
  from collections import OrderedDict
7
8
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
8
9
  import sys
@@ -24,6 +25,15 @@ if TYPE_CHECKING:
24
25
  from .code_model import CodeModel
25
26
 
26
27
 
28
+ class UsageFlags(Enum):
29
+ Default = 0
30
+ Input = 2
31
+ Output = 4
32
+ ApiVersionEnum = 8
33
+ JsonMergePatch = 16
34
+ MultipartFormData = 32
35
+
36
+
27
37
  def _get_properties(type: "ModelType", properties: List[Property]) -> List[Property]:
28
38
  for parent in type.parents:
29
39
  # here we're adding the properties from our parents
@@ -72,6 +82,11 @@ class ModelType( # pylint: disable=abstract-method
72
82
  self.snake_case_name: str = self.yaml_data["snakeCaseName"]
73
83
  self.page_result_model: bool = self.yaml_data.get("pageResultModel", False)
74
84
  self.cross_language_definition_id: Optional[str] = self.yaml_data.get("crossLanguageDefinitionId")
85
+ self.usage: int = self.yaml_data.get("usage", 0)
86
+
87
+ @property
88
+ def is_usage_output(self) -> bool:
89
+ return self.usage == UsageFlags.Output.value
75
90
 
76
91
  @property
77
92
  def flattened_property(self) -> Optional[Property]:
@@ -91,6 +91,14 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
91
91
  self.has_etag: bool = self.yaml_data.get("hasEtag", False)
92
92
  self.cross_language_definition_id: Optional[str] = self.yaml_data.get("crossLanguageDefinitionId")
93
93
 
94
+ @property
95
+ def stream_value(self) -> Union[str, bool]:
96
+ return (
97
+ f'kwargs.pop("stream", {self.has_stream_response})'
98
+ if self.expose_stream_keyword and self.has_response_body
99
+ else self.has_stream_response
100
+ )
101
+
94
102
  @property
95
103
  def has_form_data_body(self):
96
104
  return self.parameters.has_form_data_body
@@ -366,8 +374,6 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
366
374
  file_import.add_import("warnings", ImportType.STDLIB)
367
375
 
368
376
  relative_path = "..." if async_mode else ".."
369
- if self.code_model.need_request_converter:
370
- file_import.add_submodule_import(f"{relative_path}_vendor", "_convert_request", ImportType.LOCAL)
371
377
  if self.has_etag:
372
378
  file_import.add_submodule_import(
373
379
  "exceptions",
@@ -377,32 +383,18 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
377
383
  if not async_mode:
378
384
  file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_match", ImportType.LOCAL)
379
385
  file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_none_match", ImportType.LOCAL)
380
- if self.code_model.need_request_converter:
381
- if async_mode:
382
- file_import.add_submodule_import(
383
- "azure.core.pipeline.transport",
384
- "AsyncHttpResponse",
385
- ImportType.SDKCORE,
386
- )
387
- else:
388
- file_import.add_submodule_import(
389
- "azure.core.pipeline.transport",
390
- "HttpResponse",
391
- ImportType.SDKCORE,
392
- )
386
+ if async_mode:
387
+ file_import.add_submodule_import(
388
+ "rest",
389
+ "AsyncHttpResponse",
390
+ ImportType.SDKCORE,
391
+ )
393
392
  else:
394
- if async_mode:
395
- file_import.add_submodule_import(
396
- "rest",
397
- "AsyncHttpResponse",
398
- ImportType.SDKCORE,
399
- )
400
- else:
401
- file_import.add_submodule_import(
402
- "rest",
403
- "HttpResponse",
404
- ImportType.SDKCORE,
405
- )
393
+ file_import.add_submodule_import(
394
+ "rest",
395
+ "HttpResponse",
396
+ ImportType.SDKCORE,
397
+ )
406
398
  if self.code_model.options["builders_visibility"] == "embedded" and not async_mode:
407
399
  file_import.merge(self.request_builder.imports())
408
400
  file_import.add_submodule_import(
@@ -189,6 +189,8 @@ def _get_json_response_template_to_status_codes(
189
189
 
190
190
 
191
191
  def _api_version_validation(builder: OperationType) -> str:
192
+ if builder.is_overload:
193
+ return ""
192
194
  retval: List[str] = []
193
195
  if builder.added_on:
194
196
  retval.append(f' method_added_on="{builder.added_on}",')
@@ -560,13 +562,8 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
560
562
 
561
563
  def make_pipeline_call(self, builder: OperationType) -> List[str]:
562
564
  type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
563
- stream_value = (
564
- f'kwargs.pop("stream", {builder.has_stream_response})'
565
- if builder.expose_stream_keyword and builder.has_response_body
566
- else builder.has_stream_response
567
- )
568
565
  return [
569
- f"_stream = {stream_value}",
566
+ f"_stream = {builder.stream_value}",
570
567
  f"pipeline_response: PipelineResponse = {self._call_method}self._client.{self.pipeline_name}.run( "
571
568
  + f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
572
569
  " _request,",
@@ -846,11 +843,6 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
846
843
 
847
844
  def _postprocess_http_request(self, builder: OperationType, template_url: Optional[str] = None) -> List[str]:
848
845
  retval: List[str] = []
849
- if not self.code_model.options["version_tolerant"]:
850
- pass_files = ""
851
- if builder.parameters.has_body and builder.parameters.body_parameter.client_name == "files":
852
- pass_files = ", _files"
853
- retval.append(f"_request = _convert_request(_request{pass_files})")
854
846
  if builder.parameters.path:
855
847
  retval.extend(self.serialize_path(builder))
856
848
  url_to_format = "_request.url"
@@ -930,7 +922,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
930
922
  if self.code_model.options["models_mode"] == "msrest":
931
923
  deserialize_code.append("deserialized = self._deserialize(")
932
924
  deserialize_code.append(f" '{response.serialization_type}',{pylint_disable}")
933
- deserialize_code.append(" pipeline_response")
925
+ deserialize_code.append(" pipeline_response.http_response")
934
926
  deserialize_code.append(")")
935
927
  elif self.code_model.options["models_mode"] == "dpg":
936
928
  if builder.has_stream_response:
@@ -969,13 +961,11 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]): # pylint: di
969
961
  def handle_error_response(self, builder: OperationType) -> List[str]:
970
962
  async_await = "await " if self.async_mode else ""
971
963
  retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
972
- if not self.code_model.need_request_converter:
973
- retval.extend(
974
- [
975
- " if _stream:",
976
- f" {async_await} response.read() # Load the body in memory and close the socket",
977
- ]
978
- )
964
+ response_read = f" {async_await}response.read() # Load the body in memory and close the socket"
965
+ if builder.stream_value is True: # _stream is True so no need to judge it
966
+ retval.append(response_read)
967
+ elif isinstance(builder.stream_value, str): # _stream is not sure, so we need to judge it
968
+ retval.extend([" if _stream:", f" {response_read}"])
979
969
  type_ignore = " # type: ignore" if _need_type_ignore(builder) else ""
980
970
  retval.append(
981
971
  f" map_error(status_code=response.status_code, response=response, error_map=error_map){type_ignore}"
@@ -1224,12 +1214,15 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]): #
1224
1214
  response = builder.responses[0]
1225
1215
  deserialized = "pipeline_response.http_response.json()"
1226
1216
  if self.code_model.options["models_mode"] == "msrest":
1217
+ suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
1227
1218
  deserialize_type = response.serialization_type
1228
1219
  pylint_disable = " # pylint: disable=protected-access"
1229
1220
  if isinstance(response.type, ModelType) and not response.type.internal:
1230
1221
  deserialize_type = f'"{response.serialization_type}"'
1231
1222
  pylint_disable = ""
1232
- deserialized = f"self._deserialize(\n {deserialize_type},{pylint_disable}\n pipeline_response\n)"
1223
+ deserialized = (
1224
+ f"self._deserialize(\n {deserialize_type},{pylint_disable}\n pipeline_response{suffix}\n)"
1225
+ )
1233
1226
  retval.append(f" deserialized = {deserialized}")
1234
1227
  elif self.code_model.options["models_mode"] == "dpg":
1235
1228
  # we don't want to generate paging models for DPG
@@ -1324,6 +1317,8 @@ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1324
1317
  retval.append(" params=_params,")
1325
1318
  retval.append(" **kwargs")
1326
1319
  retval.append(" )")
1320
+ retval.append(f" {'await ' if self.async_mode else ''}raw_result.http_response.read() # type: ignore")
1321
+
1327
1322
  retval.append("kwargs.pop('error_map', None)")
1328
1323
  return retval
1329
1324
 
@@ -87,13 +87,6 @@ class GeneralSerializer(BaseSerializer):
87
87
 
88
88
  # configure imports
89
89
  file_import = FileImport(self.code_model)
90
- if self.code_model.need_request_converter:
91
- file_import.add_submodule_import(
92
- "azure.core.pipeline.transport",
93
- "HttpRequest",
94
- ImportType.SDKCORE,
95
- )
96
-
97
90
  if self.code_model.need_mixin_abc:
98
91
  file_import.add_submodule_import(
99
92
  "abc",
@@ -29,7 +29,7 @@
29
29
  {{ keywords.def }} close(self) -> None:
30
30
  {{ keywords.await }}self._client.close()
31
31
 
32
- {{ keywords.def }} __{{ keywords.async_prefix }}enter__(self){{ " -> \"" + client.name + "\"" }}:
32
+ {{ keywords.def }} __{{ keywords.async_prefix }}enter__(self) -> Self:
33
33
  {{ keywords.await }}self._client.__{{ keywords.async_prefix }}enter__()
34
34
  return self
35
35
 
@@ -894,5 +894,6 @@ def rest_discriminator(
894
894
  *,
895
895
  name: typing.Optional[str] = None,
896
896
  type: typing.Optional[typing.Callable] = None, # pylint: disable=redefined-builtin
897
+ visibility: typing.Optional[typing.List[str]] = None,
897
898
  ) -> typing.Any:
898
- return _RestField(name=name, type=type, is_discriminator=True)
899
+ return _RestField(name=name, type=type, is_discriminator=True, visibility=visibility)
@@ -14,8 +14,10 @@
14
14
  {% endif %}
15
15
  {% if (model.properties | selectattr('optional', "equalto", false) | first) is defined %}
16
16
 
17
+ {% if not model.is_usage_output %}
17
18
  All required parameters must be populated in order to send to server.
18
19
  {% endif %}
20
+ {% endif %}
19
21
 
20
22
  {% if model.properties != None %}
21
23
  {% for p in model.properties %}
@@ -96,9 +96,7 @@ setup(
96
96
  {% else %}
97
97
  "corehttp[requests]",
98
98
  {% endif %}
99
- {% if code_model.need_typing_extensions %}
100
99
  "typing-extensions>=4.6.0",
101
- {% endif %}
102
100
  ],
103
101
  {% if package_mode %}
104
102
  python_requires=">=3.8",
@@ -3,14 +3,6 @@
3
3
 
4
4
  {{ imports }}
5
5
 
6
- {% if code_model.need_request_converter and not async_mode %}
7
- def _convert_request(request, files=None):
8
- data = request.content if not files else None
9
- request = HttpRequest(method=request.method, url=request.url, headers=request.headers, data=data)
10
- if files:
11
- request.set_formdata_body(files)
12
- return request
13
- {% endif %}
14
6
  {% if code_model.need_mixin_abc %}
15
7
  {% for client in clients | selectattr("has_mixin") %}
16
8
  {% set pylint_disable = "# pylint: disable=name-too-long" if (client.name | length) + ("MixinABC" | length) > 40 else "" %}
@@ -17,7 +17,7 @@ from .helpers import (
17
17
  from .python_mappings import CADL_RESERVED_WORDS, RESERVED_WORDS, PadType
18
18
 
19
19
  from .. import YamlUpdatePlugin, YamlUpdatePluginAutorest
20
- from .._utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNOWN_TYPES
20
+ from .._utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNOWN_TYPES, update_enum_value
21
21
 
22
22
 
23
23
  def update_overload_section(
@@ -241,11 +241,24 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
241
241
  type["snakeCaseName"] = to_snake_case(type["name"])
242
242
  if type.get("values"):
243
243
  # we're enums
244
+ values_to_add = []
244
245
  for value in type["values"]:
245
246
  padded_name = self.pad_reserved_words(value["name"].lower(), PadType.ENUM).upper()
246
- if padded_name[0] in "0123456789":
247
- padded_name = "ENUM_" + padded_name
248
- value["name"] = padded_name
247
+ if self.version_tolerant:
248
+ if padded_name[0] in "0123456789":
249
+ padded_name = "ENUM_" + padded_name
250
+ value["name"] = padded_name
251
+ else:
252
+ if value["name"] != padded_name:
253
+ values_to_add.append(
254
+ update_enum_value(
255
+ name=padded_name,
256
+ value=value["value"],
257
+ description=value["description"],
258
+ enum_type=value["enumType"],
259
+ )
260
+ )
261
+ type["values"].extend(values_to_add)
249
262
 
250
263
  # add type for reference
251
264
  for v in HEADERS_CONVERT_IN_METHOD.values():
@@ -274,7 +287,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
274
287
  if prop_name.endswith("Client"):
275
288
  prop_name = prop_name[: len(prop_name) - len("Client")]
276
289
  yaml_data["builderPadName"] = to_snake_case(prop_name)
277
- for og in yaml_data["operationGroups"]:
290
+ for og in yaml_data.get("operationGroups", []):
278
291
  for o in og["operations"]:
279
292
  property_if_match = None
280
293
  property_if_none_match = None
@@ -412,12 +425,18 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
412
425
  yaml_data: Dict[str, Any],
413
426
  is_overload: bool = False,
414
427
  ) -> None:
428
+ def convert_initial_operation_response_type(data: Dict[str, Any]) -> None:
429
+ for response in data.get("responses", []):
430
+ response["type"] = KNOWN_TYPES["binary"]
431
+
415
432
  self.update_operation(code_model, yaml_data, is_overload=is_overload)
416
433
  self.update_operation(code_model, yaml_data["initialOperation"], is_overload=is_overload)
434
+ convert_initial_operation_response_type(yaml_data["initialOperation"])
417
435
  self._update_lro_operation_helper(yaml_data)
418
436
  for overload in yaml_data.get("overloads", []):
419
437
  self._update_lro_operation_helper(overload)
420
438
  self.update_operation(code_model, overload["initialOperation"], is_overload=True)
439
+ convert_initial_operation_response_type(overload["initialOperation"])
421
440
 
422
441
  def update_paging_operation(
423
442
  self,
@@ -443,7 +462,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
443
462
  self.update_paging_operation(code_model, overload, is_overload=True, item_type=item_type)
444
463
 
445
464
  def update_operation_groups(self, code_model: Dict[str, Any], client: Dict[str, Any]) -> None:
446
- operation_groups_yaml_data = client["operationGroups"]
465
+ operation_groups_yaml_data = client.get("operationGroups", [])
447
466
  for operation_group in operation_groups_yaml_data:
448
467
  operation_group["identifyName"] = self.pad_reserved_words(
449
468
  operation_group.get("name", operation_group["propertyName"]),
@@ -466,6 +485,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
466
485
  def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
467
486
  """Convert in place the YAML str."""
468
487
  self.update_types(yaml_data["types"])
488
+ yaml_data["types"] += KNOWN_TYPES.values()
469
489
  for client in yaml_data["clients"]:
470
490
  self.update_client(client)
471
491
  self.update_operation_groups(yaml_data, client)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.13.19",
3
+ "version": "6.14.1",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {