@autorest/python 6.4.2 → 6.4.4

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.
@@ -24,7 +24,6 @@ def to_snake_case(name: str) -> str:
24
24
  and len(name) - next_non_upper_case_char_location > 1
25
25
  and name[next_non_upper_case_char_location].isalpha()
26
26
  ):
27
-
28
27
  return (
29
28
  prefix
30
29
  + match_str[: len(match_str) - 1]
@@ -17,7 +17,6 @@ from ._utils import DEFAULT_HEADER_TEXT
17
17
 
18
18
 
19
19
  def _validate_code_model_options(options: Dict[str, Any]) -> None:
20
-
21
20
  if options["builders_visibility"] not in ["public", "hidden", "embedded"]:
22
21
  raise ValueError(
23
22
  "The value of --builders-visibility must be either 'public', 'hidden', "
@@ -163,7 +163,6 @@ class ModelType( # pylint: disable=abstract-method
163
163
  )
164
164
 
165
165
  def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
166
-
167
166
  is_polymorphic_subtype = (
168
167
  self.discriminator_value and not self.discriminated_subtypes
169
168
  )
@@ -83,6 +83,10 @@ class OperationBase( # pylint: disable=too-many-public-methods
83
83
  )
84
84
  self.include_documentation: bool = not self.is_lro_initial_operation
85
85
 
86
+ @property
87
+ def expose_stream_keyword(self) -> bool:
88
+ return self.yaml_data.get("exposeStreamKeyword", False)
89
+
86
90
  @property
87
91
  def operation_type(self) -> str:
88
92
  return "operation"
@@ -84,17 +84,28 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
84
84
  if not rest_api_name:
85
85
  # That's an ok scenario, it just means no next page possible
86
86
  return None
87
- if self.code_model.options["models_mode"]:
87
+ if self.code_model.options["models_mode"] == "msrest":
88
88
  return self._get_attr_name(rest_api_name)
89
89
  return rest_api_name
90
90
 
91
91
  @property
92
92
  def item_name(self) -> str:
93
93
  rest_api_name = self.yaml_data["itemName"]
94
- if self.code_model.options["models_mode"]:
94
+ if self.code_model.options["models_mode"] == "msrest":
95
+ # we don't use the paging model for dpg
95
96
  return self._get_attr_name(rest_api_name)
96
97
  return rest_api_name
97
98
 
99
+ @property
100
+ def item_type(self) -> ModelType:
101
+ try:
102
+ item_type_yaml = self.yaml_data["itemType"]
103
+ except KeyError as e:
104
+ raise ValueError(
105
+ "Only call this for DPG paging model deserialization"
106
+ ) from e
107
+ return cast(ModelType, self.code_model.types_map[id(item_type_yaml)])
108
+
98
109
  @property
99
110
  def operation_type(self) -> str:
100
111
  return "paging"
@@ -144,6 +155,8 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
144
155
  file_import.add_submodule_import(
145
156
  "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
146
157
  )
158
+ if self.code_model.options["models_mode"] == "dpg":
159
+ file_import.merge(self.item_type.imports(**kwargs))
147
160
  return file_import
148
161
 
149
162
 
@@ -118,9 +118,9 @@ class _ParameterListBase(
118
118
 
119
119
  @staticmethod
120
120
  @abstractmethod
121
- def body_parameter_creator() -> Callable[
122
- [Dict[str, Any], "CodeModel"], BodyParameterType
123
- ]:
121
+ def body_parameter_creator() -> (
122
+ Callable[[Dict[str, Any], "CodeModel"], BodyParameterType]
123
+ ):
124
124
  """Callable for creating body parameters"""
125
125
 
126
126
  @property
@@ -317,9 +317,11 @@ class _ParameterList(
317
317
  return Parameter.from_yaml
318
318
 
319
319
  @staticmethod
320
- def body_parameter_creator() -> Callable[
321
- [Dict[str, Any], "CodeModel"], Union[MultipartBodyParameter, BodyParameter]
322
- ]:
320
+ def body_parameter_creator() -> (
321
+ Callable[
322
+ [Dict[str, Any], "CodeModel"], Union[MultipartBodyParameter, BodyParameter]
323
+ ]
324
+ ):
323
325
  return get_body_parameter
324
326
 
325
327
  @property
@@ -345,15 +347,15 @@ class _RequestBuilderParameterList(
345
347
  """_RequestBuilderParameterList is base parameter list for RequestBuilder classes"""
346
348
 
347
349
  @staticmethod
348
- def parameter_creator() -> Callable[
349
- [Dict[str, Any], "CodeModel"], RequestBuilderParameter
350
- ]:
350
+ def parameter_creator() -> (
351
+ Callable[[Dict[str, Any], "CodeModel"], RequestBuilderParameter]
352
+ ):
351
353
  return RequestBuilderParameter.from_yaml
352
354
 
353
355
  @staticmethod
354
- def body_parameter_creator() -> Callable[
355
- [Dict[str, Any], "CodeModel"], RequestBuilderBodyParameterType
356
- ]:
356
+ def body_parameter_creator() -> (
357
+ Callable[[Dict[str, Any], "CodeModel"], RequestBuilderBodyParameterType]
358
+ ):
357
359
  return get_request_body_parameter
358
360
 
359
361
  @property
@@ -422,9 +424,9 @@ class _ClientGlobalParameterList( # pylint: disable=abstract-method
422
424
  """Base parameter list for client and config classes"""
423
425
 
424
426
  @staticmethod
425
- def body_parameter_creator() -> Callable[
426
- [Dict[str, Any], "CodeModel"], BodyParameter
427
- ]:
427
+ def body_parameter_creator() -> (
428
+ Callable[[Dict[str, Any], "CodeModel"], BodyParameter]
429
+ ):
428
430
  return BodyParameter.from_yaml
429
431
 
430
432
  @property
@@ -121,9 +121,9 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
121
121
 
122
122
  @staticmethod
123
123
  @abstractmethod
124
- def parameter_list_type() -> Callable[
125
- [Dict[str, Any], "CodeModel"], ParameterListType
126
- ]:
124
+ def parameter_list_type() -> (
125
+ Callable[[Dict[str, Any], "CodeModel"], ParameterListType]
126
+ ):
127
127
  ...
128
128
 
129
129
  @classmethod
@@ -178,9 +178,9 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
178
178
 
179
179
  class RequestBuilder(RequestBuilderBase[RequestBuilderParameterList]):
180
180
  @staticmethod
181
- def parameter_list_type() -> Callable[
182
- [Dict[str, Any], "CodeModel"], RequestBuilderParameterList
183
- ]:
181
+ def parameter_list_type() -> (
182
+ Callable[[Dict[str, Any], "CodeModel"], RequestBuilderParameterList]
183
+ ):
184
184
  return RequestBuilderParameterList.from_yaml
185
185
 
186
186
 
@@ -188,9 +188,9 @@ class OverloadedRequestBuilder(
188
188
  RequestBuilderBase[OverloadedRequestBuilderParameterList]
189
189
  ):
190
190
  @staticmethod
191
- def parameter_list_type() -> Callable[
192
- [Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList
193
- ]:
191
+ def parameter_list_type() -> (
192
+ Callable[[Dict[str, Any], "CodeModel"], OverloadedRequestBuilderParameterList]
193
+ ):
194
194
  return OverloadedRequestBuilderParameterList.from_yaml
195
195
 
196
196
 
@@ -639,11 +639,17 @@ class _OperationSerializer(
639
639
 
640
640
  def make_pipeline_call(self, builder: OperationType) -> List[str]:
641
641
  type_ignore = self.async_mode and builder.group_name == "" # is in a mixin
642
+ stream_value = (
643
+ 'kwargs.pop("stream", False)'
644
+ if builder.expose_stream_keyword
645
+ else builder.has_stream_response
646
+ )
642
647
  return [
648
+ f"_stream = {stream_value}",
643
649
  f"pipeline_response: PipelineResponse = {self._call_method}self._client._pipeline.run( "
644
650
  + f"{'# type: ignore' if type_ignore else ''} # pylint: disable=protected-access",
645
651
  " request,",
646
- f" stream={builder.has_stream_response},",
652
+ " stream=_stream,",
647
653
  " **kwargs",
648
654
  ")",
649
655
  ]
@@ -669,6 +675,11 @@ class _OperationSerializer(
669
675
 
670
676
  def param_description(self, builder: OperationType) -> List[str]:
671
677
  description_list = super().param_description(builder)
678
+ if builder.expose_stream_keyword:
679
+ description_list.append(
680
+ ":keyword bool stream: Whether to stream the response of this operation. "
681
+ "Defaults to False. You will have to context manage the returned stream."
682
+ )
672
683
  if not self.code_model.options["version_tolerant"]:
673
684
  description_list.append(
674
685
  ":keyword callable cls: A custom type or function that will be passed the direct response"
@@ -1014,6 +1025,7 @@ class _OperationSerializer(
1014
1025
 
1015
1026
  def response_headers_and_deserialization(
1016
1027
  self,
1028
+ builder: OperationType,
1017
1029
  response: Response,
1018
1030
  ) -> List[str]:
1019
1031
  retval: List[str] = [
@@ -1025,8 +1037,9 @@ class _OperationSerializer(
1025
1037
  ]
1026
1038
  if response.headers:
1027
1039
  retval.append("")
1040
+ deserialize_code: List[str] = []
1028
1041
  if response.is_stream_response:
1029
- retval.append(
1042
+ deserialize_code.append(
1030
1043
  "deserialized = {}".format(
1031
1044
  "response.iter_bytes()"
1032
1045
  if self.code_model.options["version_tolerant"]
@@ -1035,11 +1048,11 @@ class _OperationSerializer(
1035
1048
  )
1036
1049
  elif response.type:
1037
1050
  if self.code_model.options["models_mode"] == "msrest":
1038
- retval.append(
1051
+ deserialize_code.append(
1039
1052
  f"deserialized = self._deserialize('{response.serialization_type}', pipeline_response)"
1040
1053
  )
1041
1054
  elif self.code_model.options["models_mode"] == "dpg":
1042
- retval.append(
1055
+ deserialize_code.append(
1043
1056
  f"deserialized = _deserialize({response.type.type_annotation(is_operation_file=True)}"
1044
1057
  ", response.json())"
1045
1058
  )
@@ -1049,10 +1062,18 @@ class _OperationSerializer(
1049
1062
  if response.type.is_xml
1050
1063
  else "response.json()"
1051
1064
  )
1052
- retval.append("if response.content:")
1053
- retval.append(f" deserialized = {deserialized_value}")
1065
+ deserialize_code.append("if response.content:")
1066
+ deserialize_code.append(f" deserialized = {deserialized_value}")
1067
+ deserialize_code.append("else:")
1068
+ deserialize_code.append(" deserialized = None")
1069
+ if len(deserialize_code) > 0:
1070
+ if builder.expose_stream_keyword:
1071
+ retval.append("if _stream:")
1072
+ retval.append(" deserialized = response.iter_bytes()")
1054
1073
  retval.append("else:")
1055
- retval.append(" deserialized = None")
1074
+ retval.extend([f" {dc}" for dc in deserialize_code])
1075
+ else:
1076
+ retval.extend(deserialize_code)
1056
1077
  return retval
1057
1078
 
1058
1079
  def handle_error_response(self, builder: OperationType) -> List[str]:
@@ -1106,14 +1127,16 @@ class _OperationSerializer(
1106
1127
  [
1107
1128
  f" {line}"
1108
1129
  for line in self.response_headers_and_deserialization(
1109
- response
1130
+ builder, response
1110
1131
  )
1111
1132
  ]
1112
1133
  )
1113
1134
  retval.append("")
1114
1135
  else:
1115
1136
  retval.extend(
1116
- self.response_headers_and_deserialization(builder.responses[0])
1137
+ self.response_headers_and_deserialization(
1138
+ builder, builder.responses[0]
1139
+ )
1117
1140
  )
1118
1141
  retval.append("")
1119
1142
  type_ignore = (
@@ -1362,32 +1385,32 @@ class _PagingOperationSerializer(
1362
1385
  deserialized = f"self._deserialize(\n {deserialize_type}, pipeline_response{pylint_disable}\n)"
1363
1386
  retval.append(f" deserialized = {deserialized}")
1364
1387
  elif self.code_model.options["models_mode"] == "dpg":
1365
- pylint_disable = (
1366
- " # pylint: disable=protected-access\n"
1367
- if isinstance(response.type, ModelType) and not response.type.is_public
1368
- else ""
1369
- )
1370
- deserialized = f"_deserialize({response.serialization_type}{pylint_disable}, pipeline_response)"
1371
- retval.append(
1372
- f" deserialized: {response.serialization_type} = ({pylint_disable}"
1373
- )
1374
- retval.append(f" {deserialized})")
1388
+ # we don't want to generate paging models for DPG
1389
+ retval.append(f" deserialized = {deserialized}")
1375
1390
  else:
1376
1391
  retval.append(f" deserialized = {deserialized}")
1377
1392
  item_name = builder.item_name
1378
- list_of_elem = (
1393
+ access = (
1379
1394
  f".{item_name}"
1380
- if self.code_model.options["models_mode"]
1395
+ if self.code_model.options["models_mode"] == "msrest"
1381
1396
  else f'["{item_name}"]'
1382
1397
  )
1383
- retval.append(f" list_of_elem = deserialized{list_of_elem}")
1398
+ list_of_elem_deserialized = ""
1399
+ if self.code_model.options["models_mode"] == "dpg":
1400
+ item_type = builder.item_type.type_annotation(is_operation_file=True)
1401
+ list_of_elem_deserialized = (
1402
+ f"_deserialize({item_type}, deserialized{access})"
1403
+ )
1404
+ else:
1405
+ list_of_elem_deserialized = f"deserialized{access}"
1406
+ retval.append(f" list_of_elem = {list_of_elem_deserialized}")
1384
1407
  retval.append(" if cls:")
1385
1408
  retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
1386
1409
 
1387
1410
  continuation_token_name = builder.continuation_token_name
1388
1411
  if not continuation_token_name:
1389
1412
  cont_token_property = "None"
1390
- elif self.code_model.options["models_mode"]:
1413
+ elif self.code_model.options["models_mode"] == "msrest":
1391
1414
  cont_token_property = f"deserialized.{continuation_token_name} or None"
1392
1415
  else:
1393
1416
  cont_token_property = (
@@ -1559,7 +1582,7 @@ class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1559
1582
  [
1560
1583
  f" {line}"
1561
1584
  for line in self.response_headers_and_deserialization(
1562
- builder.lro_response
1585
+ builder, builder.lro_response
1563
1586
  )
1564
1587
  ]
1565
1588
  )
@@ -83,7 +83,6 @@ class GeneralSerializer:
83
83
  )
84
84
 
85
85
  def serialize_service_client_file(self, clients: List[Client]) -> str:
86
-
87
86
  template = self.env.get_template("client_container.py.jinja2")
88
87
 
89
88
  imports = FileImport()
@@ -108,8 +108,8 @@ class FileImportSerializer:
108
108
  "typing", "TYPE_CHECKING", ImportType.STDLIB
109
109
  )
110
110
 
111
- def _get_typing_definitions(self) -> str:
112
- def declare_defintion(
111
+ def get_typing_definitions(self) -> str:
112
+ def declare_definition(
113
113
  type_name: str, type_definition: TypeDefinition
114
114
  ) -> List[str]:
115
115
  ret: List[str] = []
@@ -125,7 +125,7 @@ class FileImportSerializer:
125
125
  return ""
126
126
  declarations: List[str] = [""]
127
127
  for type_name, value in self.file_import.type_definitions.items():
128
- declarations.extend(declare_defintion(type_name, value))
128
+ declarations.extend(declare_definition(type_name, value))
129
129
  return "\n".join(declarations)
130
130
 
131
131
  def __str__(self) -> str:
@@ -151,4 +151,4 @@ class FileImportSerializer:
151
151
  typing_imports += "\n\n ".join(
152
152
  _get_import_clauses(typing_imports_list, "\n ")
153
153
  )
154
- return regular_imports + typing_imports + self._get_typing_definitions()
154
+ return regular_imports + typing_imports + self.get_typing_definitions()
@@ -16,6 +16,7 @@ from ..models import (
16
16
  CodeModel,
17
17
  )
18
18
  from .builder_serializer import get_operation_serializer
19
+ from .import_serializer import FileImportSerializer
19
20
 
20
21
 
21
22
  def _to_string(data: Union[Tuple[Any], List[Any], str]) -> str:
@@ -91,6 +92,24 @@ def _mixin_imports(
91
92
  ), _json_serialize_imports(async_mixin_imports.to_dict())
92
93
 
93
94
 
95
+ def _mixin_typing_definitions(
96
+ mixin_operation_group: Optional[OperationGroup],
97
+ ) -> Tuple[Optional[str], Optional[str]]:
98
+ if not mixin_operation_group:
99
+ return None, None
100
+
101
+ sync_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=False)
102
+ async_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=True)
103
+ sync_mixin_typing_definitions = FileImportSerializer(
104
+ sync_mixin_imports, False
105
+ ).get_typing_definitions()
106
+ async_mixin_typing_definitions = FileImportSerializer(
107
+ async_mixin_imports, True
108
+ ).get_typing_definitions()
109
+
110
+ return sync_mixin_typing_definitions, async_mixin_typing_definitions
111
+
112
+
94
113
  class MetadataSerializer:
95
114
  def __init__(self, code_model: CodeModel, env: Environment) -> None:
96
115
  self.code_model = code_model
@@ -141,6 +160,10 @@ class MetadataSerializer:
141
160
  mixin_operation_group.operations if mixin_operation_group else []
142
161
  )
143
162
  sync_mixin_imports, async_mixin_imports = _mixin_imports(mixin_operation_group)
163
+ (
164
+ sync_mixin_typing_definitions,
165
+ async_mixin_typing_definitions,
166
+ ) = _mixin_typing_definitions(mixin_operation_group)
144
167
 
145
168
  chosen_version, total_api_version_list = self._choose_api_version()
146
169
 
@@ -161,6 +184,8 @@ class MetadataSerializer:
161
184
  str=str,
162
185
  sync_mixin_imports=sync_mixin_imports,
163
186
  async_mixin_imports=async_mixin_imports,
187
+ sync_mixin_typing_definitions=sync_mixin_typing_definitions,
188
+ async_mixin_typing_definitions=async_mixin_typing_definitions,
164
189
  sync_client_imports=_json_serialize_imports(
165
190
  self.client.imports_for_multiapi(async_mode=False).to_dict()
166
191
  ),
@@ -115,6 +115,8 @@
115
115
  "operation_mixins": {
116
116
  "sync_imports": {{ str(sync_mixin_imports) | tojson }},
117
117
  "async_imports": {{ str(async_mixin_imports) | tojson }},
118
+ "sync_mixin_typing_definitions": {{ str(sync_mixin_typing_definitions) | tojson }},
119
+ "async_mixin_typing_definitions": {{ str(async_mixin_typing_definitions) | tojson }},
118
120
  "operations": {
119
121
  {% for operation in mixin_operations %}
120
122
  {{ operation.name | tojson }} : {
@@ -37,7 +37,6 @@ def Process(plugin_name: str, session_id: str) -> bool:
37
37
  from .stdstream import StdStreamAutorestAPI
38
38
 
39
39
  with contextlib.closing(StdStreamAutorestAPI(session_id)) as stdstream_connection:
40
-
41
40
  _LOGGER.debug(
42
41
  "Autorest called process with plugin_name '%s' and session_id: '%s'",
43
42
  plugin_name,
@@ -595,6 +595,19 @@ class M4Reformatter(
595
595
  operation["continuationTokenName"] = yaml_data["extensions"][
596
596
  "x-ms-pageable"
597
597
  ].get("nextLinkName")
598
+ returned_response_object = (
599
+ operation["nextOperation"]["responses"][0]
600
+ if operation.get("nextOperation")
601
+ else operation["responses"][0]
602
+ )
603
+ if self.version_tolerant:
604
+ # if we're in version tolerant, hide the paging model
605
+ returned_response_object["type"]["isPublic"] = False
606
+ operation["itemType"] = next(
607
+ p["type"]
608
+ for p in returned_response_object["type"]["properties"]
609
+ if p["restApiName"] == operation["itemName"]
610
+ )
598
611
  if yaml_data["language"]["default"]["paging"].get("nextLinkOperation"):
599
612
  operation["nextOperation"] = self.update_operation(
600
613
  group_name=group_name,
@@ -31,6 +31,20 @@ class OperationMixinGroup:
31
31
  imports.merge(current_version_imports)
32
32
  return imports
33
33
 
34
+ def typing_definitions(self, async_mode: bool) -> str:
35
+ key = (
36
+ "sync_mixin_typing_definitions"
37
+ if async_mode
38
+ else "async_mixin_typing_definitions"
39
+ )
40
+ origin = "".join(
41
+ [
42
+ metadata_json.get("operation_mixins", {}).get(key, "")
43
+ for metadata_json in self.version_path_to_metadata.values()
44
+ ]
45
+ )
46
+ return "\n".join(set(origin.split("\n")))
47
+
34
48
  def _use_metadata_of_default_api_version(
35
49
  self, mixin_operations: List[MixinOperation]
36
50
  ) -> List[MixinOperation]:
@@ -101,7 +101,8 @@ class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
101
101
  # serialize mixins
102
102
  if code_model.operation_mixin_group.mixin_operations:
103
103
  imports = FileImportSerializer(
104
- code_model.operation_mixin_group.imports(async_mode)
104
+ code_model.operation_mixin_group.imports(async_mode),
105
+ code_model.operation_mixin_group.typing_definitions(async_mode),
105
106
  )
106
107
  self.write_file(
107
108
  _get_file_path("_operations_mixin", async_mode),
@@ -135,8 +135,9 @@ def _get_import_clauses(
135
135
 
136
136
 
137
137
  class FileImportSerializer:
138
- def __init__(self, file_import: FileImport) -> None:
138
+ def __init__(self, file_import: FileImport, typing_definitions: str = "") -> None:
139
139
  self._file_import = file_import
140
+ self._typing_definitions = typing_definitions
140
141
 
141
142
  def _switch_typing_section_key(self, new_key: TypingSection):
142
143
  switched_dictionary = {}
@@ -193,4 +194,4 @@ class FileImportSerializer:
193
194
  _get_import_clauses(typing_imports_dict, "\n ")
194
195
  )
195
196
 
196
- return regular_imports + typing_imports
197
+ return regular_imports + typing_imports + self._typing_definitions
@@ -10,11 +10,11 @@ from typing import Callable, Dict, Any, List, Optional
10
10
 
11
11
  from .._utils import to_snake_case
12
12
  from .helpers import (
13
- pad_reserved_words,
14
13
  add_redefined_builtin_info,
15
14
  pad_builtin_namespaces,
15
+ pad_special_chars,
16
16
  )
17
- from .python_mappings import PadType
17
+ from .python_mappings import CADL_RESERVED_WORDS, RESERVED_WORDS, PadType
18
18
 
19
19
  from .. import YamlUpdatePlugin, YamlUpdatePluginAutorest
20
20
  from .._utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNOWN_TYPES
@@ -168,51 +168,6 @@ def update_operation_group_class_name(
168
168
  return class_name + "Operations"
169
169
 
170
170
 
171
- def update_parameter(yaml_data: Dict[str, Any]) -> None:
172
- yaml_data["description"] = update_description(yaml_data["description"])
173
- if not (
174
- yaml_data["location"] == "header"
175
- and yaml_data["clientName"] in ("content_type", "accept")
176
- ):
177
- yaml_data["clientName"] = pad_reserved_words(
178
- yaml_data["clientName"].lower(), PadType.PARAMETER
179
- )
180
- if yaml_data.get("propertyToParameterName"):
181
- # need to create a new one with padded keys and values
182
- yaml_data["propertyToParameterName"] = {
183
- pad_reserved_words(prop, PadType.PROPERTY)
184
- .lower(): pad_reserved_words(param_name, PadType.PARAMETER)
185
- .lower()
186
- for prop, param_name in yaml_data["propertyToParameterName"].items()
187
- }
188
-
189
-
190
- def update_types(yaml_data: List[Dict[str, Any]]) -> None:
191
- for type in yaml_data:
192
- for property in type.get("properties", []):
193
- property["description"] = update_description(property["description"])
194
- property["clientName"] = pad_reserved_words(
195
- property["clientName"].lower(), PadType.PROPERTY
196
- )
197
- add_redefined_builtin_info(property["clientName"], property)
198
- if type.get("name"):
199
- type["description"] = update_description(type["description"], type["name"])
200
- type["snakeCaseName"] = to_snake_case(type["name"])
201
-
202
-
203
- def update_client(yaml_data: Dict[str, Any]) -> None:
204
- yaml_data["description"] = update_description(
205
- yaml_data["description"], default_description=yaml_data["name"]
206
- )
207
- yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
208
- for parameter in yaml_data["parameters"]:
209
- update_parameter(parameter)
210
- prop_name = yaml_data["name"]
211
- if prop_name.endswith("Client"):
212
- prop_name = prop_name[: len(prop_name) - len("Client")]
213
- yaml_data["builderPadName"] = to_snake_case(prop_name)
214
-
215
-
216
171
  def update_paging_response(yaml_data: Dict[str, Any]) -> None:
217
172
  yaml_data["discriminator"] = "paging"
218
173
  yaml_data["pagerSync"] = yaml_data.get("pagerSync") or "azure.core.paging.ItemPaged"
@@ -230,9 +185,55 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
230
185
 
231
186
  @property
232
187
  def models_mode(self) -> Optional[str]:
233
- return self.options.get(
234
- "models-mode", "dpg" if self.options.get("cadl_file") else None
188
+ return self.options.get("models-mode", "dpg" if self.is_cadl else None)
189
+
190
+ @property
191
+ def is_cadl(self) -> bool:
192
+ return self.options.get("cadl_file", False)
193
+
194
+ def pad_reserved_words(self, name: str, pad_type: PadType):
195
+ # we want to pad hidden variables as well
196
+ if not name:
197
+ # we'll pass in empty operation groups sometime etc.
198
+ return name
199
+
200
+ if self.is_cadl:
201
+ reserved_words = copy.copy(CADL_RESERVED_WORDS)
202
+ reserved_words.update(RESERVED_WORDS)
203
+ else:
204
+ reserved_words = RESERVED_WORDS
205
+ name = pad_special_chars(name)
206
+ name_prefix = "_" if name[0] == "_" else ""
207
+ name = name[1:] if name[0] == "_" else name
208
+ if name.lower() in reserved_words[pad_type]:
209
+ return name_prefix + name + pad_type
210
+ return name_prefix + name
211
+
212
+ def update_types(self, yaml_data: List[Dict[str, Any]]) -> None:
213
+ for type in yaml_data:
214
+ for property in type.get("properties", []):
215
+ property["description"] = update_description(property["description"])
216
+ property["clientName"] = self.pad_reserved_words(
217
+ property["clientName"].lower(), PadType.PROPERTY
218
+ )
219
+ add_redefined_builtin_info(property["clientName"], property)
220
+ if type.get("name"):
221
+ type["description"] = update_description(
222
+ type["description"], type["name"]
223
+ )
224
+ type["snakeCaseName"] = to_snake_case(type["name"])
225
+
226
+ def update_client(self, yaml_data: Dict[str, Any]) -> None:
227
+ yaml_data["description"] = update_description(
228
+ yaml_data["description"], default_description=yaml_data["name"]
235
229
  )
230
+ yaml_data["legacyFilename"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
231
+ for parameter in yaml_data["parameters"]:
232
+ self.update_parameter(parameter)
233
+ prop_name = yaml_data["name"]
234
+ if prop_name.endswith("Client"):
235
+ prop_name = prop_name[: len(prop_name) - len("Client")]
236
+ yaml_data["builderPadName"] = to_snake_case(prop_name)
236
237
 
237
238
  def get_operation_updater(
238
239
  self, yaml_data: Dict[str, Any]
@@ -245,6 +246,24 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
245
246
  return self.update_paging_operation
246
247
  return self.update_operation
247
248
 
249
+ def update_parameter(self, yaml_data: Dict[str, Any]) -> None:
250
+ yaml_data["description"] = update_description(yaml_data["description"])
251
+ if not (
252
+ yaml_data["location"] == "header"
253
+ and yaml_data["clientName"] in ("content_type", "accept")
254
+ ):
255
+ yaml_data["clientName"] = self.pad_reserved_words(
256
+ yaml_data["clientName"].lower(), PadType.PARAMETER
257
+ )
258
+ if yaml_data.get("propertyToParameterName"):
259
+ # need to create a new one with padded keys and values
260
+ yaml_data["propertyToParameterName"] = {
261
+ self.pad_reserved_words(prop, PadType.PROPERTY)
262
+ .lower(): self.pad_reserved_words(param_name, PadType.PARAMETER)
263
+ .lower()
264
+ for prop, param_name in yaml_data["propertyToParameterName"].items()
265
+ }
266
+
248
267
  def update_operation(
249
268
  self,
250
269
  code_model: Dict[str, Any],
@@ -252,23 +271,23 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
252
271
  *,
253
272
  is_overload: bool = False,
254
273
  ) -> None:
255
- yaml_data["groupName"] = pad_reserved_words(
274
+ yaml_data["groupName"] = self.pad_reserved_words(
256
275
  yaml_data["groupName"], PadType.OPERATION_GROUP
257
276
  )
258
277
  yaml_data["groupName"] = to_snake_case(yaml_data["groupName"])
259
278
  yaml_data["name"] = yaml_data["name"].lower()
260
- yaml_data["name"] = pad_reserved_words(yaml_data["name"], PadType.METHOD)
279
+ yaml_data["name"] = self.pad_reserved_words(yaml_data["name"], PadType.METHOD)
261
280
  yaml_data["description"] = update_description(
262
281
  yaml_data["description"], yaml_data["name"]
263
282
  )
264
283
  yaml_data["summary"] = update_description(yaml_data.get("summary", ""))
265
284
  body_parameter = yaml_data.get("bodyParameter")
266
285
  for parameter in yaml_data["parameters"]:
267
- update_parameter(parameter)
286
+ self.update_parameter(parameter)
268
287
  if yaml_data.get("bodyParameter"):
269
- update_parameter(yaml_data["bodyParameter"])
288
+ self.update_parameter(yaml_data["bodyParameter"])
270
289
  for entry in yaml_data["bodyParameter"].get("entries", []):
271
- update_parameter(entry)
290
+ self.update_parameter(entry)
272
291
  for overload in yaml_data.get("overloads", []):
273
292
  self.update_operation(code_model, overload, is_overload=True)
274
293
  for response in yaml_data.get("responses", []):
@@ -337,30 +356,21 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
337
356
  code_model: Dict[str, Any],
338
357
  yaml_data: Dict[str, Any],
339
358
  is_overload: bool = False,
359
+ item_type: Optional[Dict[str, Any]] = None,
340
360
  ) -> None:
341
361
  self.update_operation(code_model, yaml_data, is_overload=is_overload)
342
362
  if not yaml_data.get("pagerSync"):
343
363
  yaml_data["pagerSync"] = "azure.core.paging.ItemPaged"
344
364
  if not yaml_data.get("pagerAsync"):
345
365
  yaml_data["pagerAsync"] = "azure.core.async_paging.AsyncItemPaged"
346
- returned_response_object = (
347
- yaml_data["nextOperation"]["responses"][0]
348
- if yaml_data.get("nextOperation")
349
- else yaml_data["responses"][0]
350
- )
351
366
  if self.version_tolerant:
352
367
  # if we're in version tolerant, hide the paging model
353
- returned_response_object["type"]["isPublic"] = False
354
368
  _remove_paging_maxpagesize(yaml_data)
355
- item_type = next(
356
- p["type"]["elementType"]
357
- for p in returned_response_object["type"]["properties"]
358
- if p["restApiName"] == (yaml_data.get("itemName") or "value")
359
- )
369
+ item_type = item_type or yaml_data["itemType"]["elementType"]
360
370
  if yaml_data.get("nextOperation"):
361
371
  if self.version_tolerant:
362
372
  _remove_paging_maxpagesize(yaml_data["nextOperation"])
363
- yaml_data["nextOperation"]["groupName"] = pad_reserved_words(
373
+ yaml_data["nextOperation"]["groupName"] = self.pad_reserved_words(
364
374
  yaml_data["nextOperation"]["groupName"], PadType.OPERATION_GROUP
365
375
  )
366
376
  yaml_data["nextOperation"]["groupName"] = to_snake_case(
@@ -373,7 +383,9 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
373
383
  update_paging_response(response)
374
384
  response["itemType"] = item_type
375
385
  for overload in yaml_data.get("overloads", []):
376
- self.update_paging_operation(code_model, overload, is_overload=True)
386
+ self.update_paging_operation(
387
+ code_model, overload, is_overload=True, item_type=item_type
388
+ )
377
389
 
378
390
  def update_operation_groups(
379
391
  self, code_model: Dict[str, Any], client: Dict[str, Any]
@@ -381,7 +393,7 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
381
393
  operation_groups_yaml_data = client["operationGroups"]
382
394
  for operation_group in operation_groups_yaml_data:
383
395
  operation_group["clientName"] = client["name"]
384
- operation_group["propertyName"] = pad_reserved_words(
396
+ operation_group["propertyName"] = self.pad_reserved_words(
385
397
  operation_group["propertyName"], PadType.OPERATION_GROUP
386
398
  )
387
399
  operation_group["propertyName"] = to_snake_case(
@@ -395,13 +407,13 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
395
407
 
396
408
  def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
397
409
  """Convert in place the YAML str."""
398
- update_types(yaml_data["types"])
410
+ self.update_types(yaml_data["types"])
399
411
  for client in yaml_data["clients"]:
400
- update_client(client)
412
+ self.update_client(client)
401
413
  self.update_operation_groups(yaml_data, client)
402
414
  for clients in yaml_data["subnamespaceToClients"].values():
403
415
  for client in clients:
404
- update_client(client)
416
+ self.update_client(client)
405
417
  self.update_operation_groups(yaml_data, client)
406
418
  if yaml_data.get("namespace"):
407
419
  yaml_data["namespace"] = pad_builtin_namespaces(yaml_data["namespace"])
@@ -6,26 +6,11 @@
6
6
  import re
7
7
  from typing import Any, Dict
8
8
  from .python_mappings import (
9
- PadType,
10
- RESERVED_WORDS,
11
9
  REDEFINED_BUILTINS,
12
10
  BUILTIN_PACKAGES,
13
11
  )
14
12
 
15
13
 
16
- def pad_reserved_words(name: str, pad_type: PadType):
17
- # we want to pad hidden variables as well
18
- if not name:
19
- # we'll pass in empty operation groups sometime etc.
20
- return name
21
- name = pad_special_chars(name)
22
- name_prefix = "_" if name[0] == "_" else ""
23
- name = name[1:] if name[0] == "_" else name
24
- if name.lower() in RESERVED_WORDS[pad_type]:
25
- return name_prefix + name + pad_type
26
- return name_prefix + name
27
-
28
-
29
14
  def add_redefined_builtin_info(name: str, yaml_data: Dict[str, Any]) -> None:
30
15
  if name in REDEFINED_BUILTINS:
31
16
  yaml_data["pylintDisable"] = "redefined-builtin"
@@ -168,6 +168,8 @@ RESERVED_WORDS = {
168
168
  PadType.OPERATION_GROUP: [*_always_reserved],
169
169
  }
170
170
 
171
+ CADL_RESERVED_WORDS = {PadType.PARAMETER: ["stream"]}
172
+
171
173
  REDEFINED_BUILTINS = [ # we don't pad, but we need to do lint ignores
172
174
  "id",
173
175
  "min",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.4.2",
3
+ "version": "6.4.4",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {
package/requirements.txt CHANGED
@@ -7,6 +7,6 @@ m2r2==0.3.3
7
7
  MarkupSafe==2.1.2
8
8
  mistune==0.8.4
9
9
  pathspec==0.11.0
10
- platformdirs==2.6.2
10
+ platformdirs==3.1.0
11
11
  PyYAML==6.0
12
12
  tomli==2.0.1