@autorest/python 5.15.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 (86) hide show
  1. package/ChangeLog.md +20 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +145 -73
  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 +19 -18
  9. package/autorest/codegen/models/client.py +65 -21
  10. package/autorest/codegen/models/code_model.py +107 -61
  11. package/autorest/codegen/models/constant_schema.py +25 -13
  12. package/autorest/codegen/models/credential_model.py +23 -15
  13. package/autorest/codegen/models/credential_schema.py +18 -14
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +20 -17
  16. package/autorest/codegen/models/enum_schema.py +35 -25
  17. package/autorest/codegen/models/imports.py +70 -41
  18. package/autorest/codegen/models/list_schema.py +25 -13
  19. package/autorest/codegen/models/lro_operation.py +58 -22
  20. package/autorest/codegen/models/lro_paging_operation.py +2 -3
  21. package/autorest/codegen/models/object_schema.py +99 -49
  22. package/autorest/codegen/models/operation.py +236 -117
  23. package/autorest/codegen/models/operation_group.py +64 -34
  24. package/autorest/codegen/models/paging_operation.py +45 -18
  25. package/autorest/codegen/models/parameter.py +151 -83
  26. package/autorest/codegen/models/parameter_list.py +183 -162
  27. package/autorest/codegen/models/primitive_schemas.py +84 -55
  28. package/autorest/codegen/models/property.py +44 -26
  29. package/autorest/codegen/models/request_builder.py +65 -30
  30. package/autorest/codegen/models/request_builder_parameter.py +47 -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 +18 -13
  34. package/autorest/codegen/models/utils.py +5 -2
  35. package/autorest/codegen/serializers/__init__.py +182 -91
  36. package/autorest/codegen/serializers/builder_serializer.py +667 -331
  37. package/autorest/codegen/serializers/client_serializer.py +98 -37
  38. package/autorest/codegen/serializers/general_serializer.py +61 -26
  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 +35 -15
  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 +7 -6
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +35 -21
  50. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  51. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  52. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  53. package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
  54. package/autorest/codegen/templates/operation.py.jinja2 +7 -9
  55. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
  56. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  58. package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
  59. package/autorest/jsonrpc/__init__.py +7 -12
  60. package/autorest/jsonrpc/localapi.py +4 -3
  61. package/autorest/jsonrpc/server.py +13 -6
  62. package/autorest/jsonrpc/stdstream.py +13 -6
  63. package/autorest/m2r/__init__.py +5 -8
  64. package/autorest/multiapi/__init__.py +24 -14
  65. package/autorest/multiapi/models/client.py +21 -11
  66. package/autorest/multiapi/models/code_model.py +23 -10
  67. package/autorest/multiapi/models/config.py +4 -1
  68. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  69. package/autorest/multiapi/models/global_parameter.py +2 -1
  70. package/autorest/multiapi/models/global_parameters.py +14 -8
  71. package/autorest/multiapi/models/imports.py +24 -17
  72. package/autorest/multiapi/models/mixin_operation.py +5 -5
  73. package/autorest/multiapi/models/operation_group.py +2 -1
  74. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  75. package/autorest/multiapi/serializers/__init__.py +18 -23
  76. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  77. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  78. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  79. package/autorest/multiapi/utils.py +3 -3
  80. package/autorest/namer/__init__.py +2 -4
  81. package/autorest/namer/name_converter.py +200 -103
  82. package/autorest/namer/python_mappings.py +10 -22
  83. package/package.json +2 -2
  84. package/run-python3.js +2 -3
  85. package/venvtools.py +1 -1
  86. package/autorest/codegen/models/rest.py +0 -42
@@ -9,21 +9,21 @@ from typing import cast, Any, Dict, List, Match, Optional
9
9
  from .python_mappings import basic_latin_chars, reserved_words, PadType
10
10
  from ..codegen.models.utils import JSON_REGEXP
11
11
 
12
+
12
13
  def _get_all_values(all_headers: List[Dict[str, Any]]) -> List[str]:
13
14
  content_types: List[str] = []
14
15
  for h in all_headers:
15
- if h['schema']['type'] == 'constant':
16
- content_types.append(h['schema']['value']['value'])
16
+ if h["schema"]["type"] == "constant":
17
+ content_types.append(h["schema"]["value"]["value"])
17
18
  elif any(
18
- choice_type for choice_type in ['sealed-choice', 'choice']
19
- if h['schema']['type'] == choice_type
19
+ choice_type
20
+ for choice_type in ["sealed-choice", "choice"]
21
+ if h["schema"]["type"] == choice_type
20
22
  ):
21
- content_types.extend([
22
- choice['value']
23
- for choice in h['schema']['choices']
24
- ])
23
+ content_types.extend([choice["value"] for choice in h["schema"]["choices"]])
25
24
  return content_types
26
25
 
26
+
27
27
  def _get_default_value(all_values: List[str]) -> str:
28
28
  json_values = [v for v in all_values if JSON_REGEXP.match(v)]
29
29
  if json_values:
@@ -38,7 +38,10 @@ def _get_default_value(all_values: List[str]) -> str:
38
38
  return xml_values[0]
39
39
  return all_values[0]
40
40
 
41
+
41
42
  _M4_HEADER_PARAMETERS = ["content_type", "accept"]
43
+
44
+
42
45
  class NameConverter:
43
46
  @staticmethod
44
47
  def convert_yaml_names(yaml_data: Dict[str, Any]) -> None:
@@ -46,16 +49,22 @@ class NameConverter:
46
49
  yaml_data["info"]["python_title"] = NameConverter._to_valid_python_name(
47
50
  name=yaml_data["info"]["title"].replace(" ", ""), convert_name=True
48
51
  )
49
- yaml_data['info']['pascal_case_title'] = yaml_data["language"]["default"]["name"]
50
- if yaml_data['info'].get("description"):
52
+ yaml_data["info"]["pascal_case_title"] = yaml_data["language"]["default"][
53
+ "name"
54
+ ]
55
+ if yaml_data["info"].get("description"):
51
56
  if yaml_data["info"]["description"][-1] != ".":
52
57
  yaml_data["info"]["description"] += "."
53
58
  else:
54
- yaml_data["info"]["description"] = yaml_data['info']['pascal_case_title'] + "."
55
- NameConverter._convert_schemas(yaml_data['schemas'])
56
- NameConverter._convert_operation_groups(yaml_data['operationGroups'], yaml_data['info']['pascal_case_title'])
57
- if yaml_data.get('globalParameters'):
58
- NameConverter._convert_global_parameters(yaml_data['globalParameters'])
59
+ yaml_data["info"]["description"] = (
60
+ yaml_data["info"]["pascal_case_title"] + "."
61
+ )
62
+ NameConverter._convert_schemas(yaml_data["schemas"])
63
+ NameConverter._convert_operation_groups(
64
+ yaml_data["operationGroups"], yaml_data["info"]["pascal_case_title"]
65
+ )
66
+ if yaml_data.get("globalParameters"):
67
+ NameConverter._convert_global_parameters(yaml_data["globalParameters"])
59
68
 
60
69
  @staticmethod
61
70
  def _convert_global_parameters(global_parameters: List[Dict[str, Any]]) -> None:
@@ -63,48 +72,69 @@ class NameConverter:
63
72
  NameConverter._convert_language_default_python_case(global_parameter)
64
73
 
65
74
  @staticmethod
66
- def _convert_operation_groups(operation_groups: List[Dict[str, Any]], code_model_title: str) -> None:
75
+ def _convert_operation_groups(
76
+ operation_groups: List[Dict[str, Any]], code_model_title: str
77
+ ) -> None:
67
78
  for operation_group in operation_groups:
68
79
  builder_group = copy.deepcopy(operation_group)
69
80
  NameConverter._convert_language_default_python_case(
70
81
  operation_group, pad_string=PadType.OperationGroup, convert_name=True
71
82
  )
72
- operation_group_name = operation_group['language']['default']['name']
83
+ operation_group_name = operation_group["language"]["default"]["name"]
73
84
  if not operation_group_name:
74
- operation_group['language']['python']['className'] = code_model_title + "OperationsMixin"
75
- operation_group['language']['python']['name'] = ""
76
- elif operation_group_name == 'Operations':
77
- operation_group['language']['python']['className'] = operation_group_name
85
+ operation_group["language"]["python"]["className"] = (
86
+ code_model_title + "OperationsMixin"
87
+ )
88
+ operation_group["language"]["python"]["name"] = ""
89
+ elif operation_group_name == "Operations":
90
+ operation_group["language"]["python"][
91
+ "className"
92
+ ] = operation_group_name
78
93
  else:
79
- operation_group['language']['python']['className'] = operation_group_name + "Operations"
80
- for operation in operation_group['operations']:
81
- NameConverter._convert_language_default_python_case(operation, pad_string=PadType.Method)
94
+ operation_group["language"]["python"]["className"] = (
95
+ operation_group_name + "Operations"
96
+ )
97
+ for operation in operation_group["operations"]:
98
+ NameConverter._convert_language_default_python_case(
99
+ operation, pad_string=PadType.Method
100
+ )
82
101
  if operation_group_name:
83
- operation['language']['python']['operationGroupName'] = (
84
- operation_group['language']['python']['name'].lower()
85
- )
102
+ operation["language"]["python"][
103
+ "operationGroupName"
104
+ ] = operation_group["language"]["python"]["name"].lower()
86
105
  NameConverter._convert_language_default_python_case(
87
- builder_group, pad_string=PadType.BuilderGroup, convert_name=True
88
- )
89
- operation['language']['python']['builderGroupName'] = (
90
- builder_group['language']['python']['name'].lower()
106
+ builder_group,
107
+ pad_string=PadType.BuilderGroup,
108
+ convert_name=True,
91
109
  )
110
+ operation["language"]["python"]["builderGroupName"] = builder_group[
111
+ "language"
112
+ ]["python"]["name"].lower()
92
113
  else:
93
- operation['language']['python']['operationGroupName'] = ""
94
- operation['language']['python']['builderGroupName'] = ""
95
- for exception in operation.get('exceptions', []):
114
+ operation["language"]["python"]["operationGroupName"] = ""
115
+ operation["language"]["python"]["builderGroupName"] = ""
116
+ for exception in operation.get("exceptions", []):
96
117
  NameConverter._convert_language_default_python_case(exception)
97
118
  for parameter in operation.get("parameters", []):
98
119
  NameConverter._add_multipart_information(parameter, operation)
99
- NameConverter._convert_language_default_python_case(parameter, pad_string=PadType.Parameter)
120
+ NameConverter._convert_language_default_python_case(
121
+ parameter, pad_string=PadType.Parameter
122
+ )
100
123
  for request in operation.get("requests", []):
101
124
  NameConverter._convert_language_default_python_case(request)
102
125
  for parameter in request.get("parameters", []):
103
126
  NameConverter._add_multipart_information(parameter, request)
104
- NameConverter._convert_language_default_python_case(parameter, pad_string=PadType.Parameter)
105
- if parameter.get("origin", "") == "modelerfour:synthesized/content-type":
127
+ NameConverter._convert_language_default_python_case(
128
+ parameter, pad_string=PadType.Parameter
129
+ )
130
+ if (
131
+ parameter.get("origin", "")
132
+ == "modelerfour:synthesized/content-type"
133
+ ):
106
134
  parameter["required"] = False
107
- NameConverter._handle_m4_header_parameters(operation.get("requests", []))
135
+ NameConverter._handle_m4_header_parameters(
136
+ operation.get("requests", [])
137
+ )
108
138
  for response in operation.get("responses", []):
109
139
  NameConverter._convert_language_default_python_case(response)
110
140
  if operation.get("extensions"):
@@ -114,64 +144,82 @@ class NameConverter:
114
144
  def _handle_m4_header_parameters(requests):
115
145
  m4_header_params = []
116
146
  for request in requests:
117
- m4_header_params.extend([
118
- p for p in request.get('parameters', [])
119
- if NameConverter._is_schema_an_m4_header_parameter(p['language']['default']['name'], p)
120
- ])
147
+ m4_header_params.extend(
148
+ [
149
+ p
150
+ for p in request.get("parameters", [])
151
+ if NameConverter._is_schema_an_m4_header_parameter(
152
+ p["language"]["default"]["name"], p
153
+ )
154
+ ]
155
+ )
121
156
  m4_header_params_to_remove = []
122
157
  for m4_header in _M4_HEADER_PARAMETERS:
123
158
  params_of_header = [
124
- p for p in m4_header_params
125
- if p['language']['default']['name'] == m4_header
159
+ p
160
+ for p in m4_header_params
161
+ if p["language"]["default"]["name"] == m4_header
126
162
  ]
127
163
  if len(params_of_header) < 2:
128
164
  continue
129
165
  param_schema_to_param = { # if they share the same schema, we don't need to keep both of them in this case
130
- id(param['schema']): param
131
- for param in params_of_header
166
+ id(param["schema"]): param for param in params_of_header
132
167
  }
133
168
  if len(param_schema_to_param) == 1:
134
169
  # we'll remove the ones that aren't the first
135
- m4_header_params_to_remove.extend([
136
- id(p) for p in params_of_header[1:]
137
- ])
170
+ m4_header_params_to_remove.extend([id(p) for p in params_of_header[1:]])
138
171
  else:
139
172
  all_values = _get_all_values(params_of_header)
140
173
  # if one of them is an enum schema, set the default value to constant
141
- param_with_constant_schema = next(p for p in params_of_header if p['schema']['type'] == 'constant')
174
+ param_with_constant_schema = next(
175
+ p for p in params_of_header if p["schema"]["type"] == "constant"
176
+ )
142
177
  try:
143
178
  param_with_enum_schema = next(
144
- p for p in params_of_header
145
- if p['schema']['type'] == 'sealed-choice' or p['schema']['type'] == 'choice'
179
+ p
180
+ for p in params_of_header
181
+ if p["schema"]["type"] == "sealed-choice"
182
+ or p["schema"]["type"] == "choice"
146
183
  )
147
184
  except StopIteration:
148
185
  # this means there's no enum schema
149
186
  pass
150
187
  else:
151
- param_with_enum_schema['clientDefaultValue'] = _get_default_value(all_values)
188
+ param_with_enum_schema["clientDefaultValue"] = _get_default_value(
189
+ all_values
190
+ )
152
191
  # add constant enum schema value into list of possible schema values
153
- constant_schema = param_with_constant_schema['schema']
192
+ constant_schema = param_with_constant_schema["schema"]
154
193
  constant_choice = {
155
194
  "language": {
156
195
  "default": {
157
- "description": constant_schema['language']['default']['description'],
158
- "name": constant_schema['language']['default']['name'],
196
+ "description": constant_schema["language"]["default"][
197
+ "description"
198
+ ],
199
+ "name": constant_schema["language"]["default"]["name"],
159
200
  },
160
201
  "python": {
161
- "description": constant_schema['language']['python']['description'],
162
- "name": constant_schema['language']['python']['name'].upper(),
163
- }
202
+ "description": constant_schema["language"]["python"][
203
+ "description"
204
+ ],
205
+ "name": constant_schema["language"]["python"][
206
+ "name"
207
+ ].upper(),
208
+ },
164
209
  },
165
- "value": constant_schema['value']['value']
210
+ "value": constant_schema["value"]["value"],
166
211
  }
167
- param_with_enum_schema['schema']['choices'].append(constant_choice)
212
+ param_with_enum_schema["schema"]["choices"].append(constant_choice)
168
213
  m4_header_params_to_remove.append(id(param_with_constant_schema))
169
214
 
170
215
  for request in requests:
171
- if not request.get('parameters'):
216
+ if not request.get("parameters"):
172
217
  continue
173
- request['parameters'] = [p for p in request['parameters'] if id(p) not in m4_header_params_to_remove]
174
-
218
+ request["parameters"] = [
219
+ p
220
+ for p in request["parameters"]
221
+ if id(p) not in m4_header_params_to_remove
222
+ ]
175
223
 
176
224
  @staticmethod
177
225
  def _add_multipart_information(parameter: Dict[str, Any], request: Dict[str, Any]):
@@ -180,13 +228,12 @@ class NameConverter:
180
228
  if parameter["protocol"]["http"]["in"] == "body":
181
229
  parameter["language"]["default"]["multipart"] = True
182
230
  if parameter["language"]["default"]["serializedName"] == "Content-Type":
183
- parameter['schema']['value']['value'] = None
184
-
231
+ parameter["schema"]["value"]["value"] = None
185
232
 
186
233
  @staticmethod
187
234
  def _convert_extensions(operation: Dict[str, Any]) -> None:
188
235
  operation_extensions = operation["extensions"]
189
- if operation_extensions.get('x-ms-pageable'):
236
+ if operation_extensions.get("x-ms-pageable"):
190
237
  operation["extensions"]["pager-sync"] = operation_extensions.get(
191
238
  "x-python-custom-pager-sync", "azure.core.paging.ItemPaged"
192
239
  )
@@ -203,29 +250,45 @@ class NameConverter:
203
250
  )
204
251
 
205
252
  # polling methods
206
- sync_polling_method_directive = "x-python-custom-default-polling-method-sync"
253
+ sync_polling_method_directive = (
254
+ "x-python-custom-default-polling-method-sync"
255
+ )
207
256
  operation["extensions"]["default-polling-method-sync"] = {
208
257
  "azure-arm": operation_extensions.get(
209
- sync_polling_method_directive, "azure.mgmt.core.polling.arm_polling.ARMPolling"
258
+ sync_polling_method_directive,
259
+ "azure.mgmt.core.polling.arm_polling.ARMPolling",
210
260
  ),
211
261
  "data-plane": operation_extensions.get(
212
- sync_polling_method_directive, "azure.core.polling.base_polling.LROBasePolling"
262
+ sync_polling_method_directive,
263
+ "azure.core.polling.base_polling.LROBasePolling",
213
264
  ),
214
265
  }
215
- async_polling_method_directive = "x-python-custom-default-polling-method-async"
266
+ async_polling_method_directive = (
267
+ "x-python-custom-default-polling-method-async"
268
+ )
216
269
  operation["extensions"]["default-polling-method-async"] = {
217
270
  "azure-arm": operation_extensions.get(
218
- async_polling_method_directive, "azure.mgmt.core.polling.async_arm_polling.AsyncARMPolling"
271
+ async_polling_method_directive,
272
+ "azure.mgmt.core.polling.async_arm_polling.AsyncARMPolling",
219
273
  ),
220
274
  "data-plane": operation_extensions.get(
221
- async_polling_method_directive, "azure.core.polling.async_base_polling.AsyncLROBasePolling"
275
+ async_polling_method_directive,
276
+ "azure.core.polling.async_base_polling.AsyncLROBasePolling",
222
277
  ),
223
278
  }
224
279
 
225
- operation["extensions"]["default-no-polling-method-sync"] = "azure.core.polling.NoPolling"
226
- operation["extensions"]["default-no-polling-method-async"] = "azure.core.polling.AsyncNoPolling"
227
- operation["extensions"]["base-polling-method-sync"] = "azure.core.polling.PollingMethod"
228
- operation["extensions"]["base-polling-method-async"] = "azure.core.polling.AsyncPollingMethod"
280
+ operation["extensions"][
281
+ "default-no-polling-method-sync"
282
+ ] = "azure.core.polling.NoPolling"
283
+ operation["extensions"][
284
+ "default-no-polling-method-async"
285
+ ] = "azure.core.polling.AsyncNoPolling"
286
+ operation["extensions"][
287
+ "base-polling-method-sync"
288
+ ] = "azure.core.polling.PollingMethod"
289
+ operation["extensions"][
290
+ "base-polling-method-async"
291
+ ] = "azure.core.polling.AsyncPollingMethod"
229
292
 
230
293
  @staticmethod
231
294
  def _convert_schemas(schemas: Dict[str, Any]) -> None:
@@ -239,11 +302,15 @@ class NameConverter:
239
302
  continue
240
303
  if type_list in ["arrays", "dictionaries"]:
241
304
  NameConverter._convert_language_default_python_case(schema)
242
- NameConverter._convert_language_default_python_case(schema["elementType"])
305
+ NameConverter._convert_language_default_python_case(
306
+ schema["elementType"]
307
+ )
243
308
  elif type_list == "constants":
244
309
  NameConverter._convert_language_default_python_case(schema)
245
310
  NameConverter._convert_language_default_python_case(schema["value"])
246
- NameConverter._convert_language_default_python_case(schema["valueType"])
311
+ NameConverter._convert_language_default_python_case(
312
+ schema["valueType"]
313
+ )
247
314
  else:
248
315
  NameConverter._convert_language_default_python_case(schema)
249
316
 
@@ -251,7 +318,9 @@ class NameConverter:
251
318
  def _convert_enum_schema(schema: Dict[str, Any]) -> None:
252
319
  NameConverter._convert_language_default_pascal_case(schema)
253
320
  for choice in schema["choices"]:
254
- NameConverter._convert_language_default_python_case(choice, pad_string=PadType.Enum, all_upper=True)
321
+ NameConverter._convert_language_default_python_case(
322
+ choice, pad_string=PadType.Enum, all_upper=True
323
+ )
255
324
 
256
325
  @staticmethod
257
326
  def _convert_object_schema(schema: Dict[str, Any]) -> None:
@@ -264,13 +333,17 @@ class NameConverter:
264
333
  schema_description += "."
265
334
  schema["language"]["python"]["description"] = schema_description
266
335
  for prop in schema.get("properties", []):
267
- NameConverter._convert_language_default_python_case(schema=prop, pad_string=PadType.Property)
336
+ NameConverter._convert_language_default_python_case(
337
+ schema=prop, pad_string=PadType.Property
338
+ )
268
339
 
269
340
  @staticmethod
270
- def _is_schema_an_m4_header_parameter(schema_name: str, schema: Dict[str, Any]) -> bool:
341
+ def _is_schema_an_m4_header_parameter(
342
+ schema_name: str, schema: Dict[str, Any]
343
+ ) -> bool:
271
344
  return (
272
- schema_name in _M4_HEADER_PARAMETERS and
273
- schema.get('protocol', {}).get('http', {}).get('in', {}) == 'header'
345
+ schema_name in _M4_HEADER_PARAMETERS
346
+ and schema.get("protocol", {}).get("http", {}).get("in", {}) == "header"
274
347
  )
275
348
 
276
349
  @staticmethod
@@ -279,17 +352,15 @@ class NameConverter:
279
352
  *,
280
353
  pad_string: Optional[PadType] = None,
281
354
  convert_name: bool = False,
282
- all_upper: bool = False
355
+ all_upper: bool = False,
283
356
  ) -> None:
284
357
  if not schema.get("language") or schema["language"].get("python"):
285
358
  return
286
- schema['language']['python'] = dict(schema['language']['default'])
287
- schema_name = schema['language']['default']['name']
288
- schema_python_name = schema['language']['python']['name']
359
+ schema["language"]["python"] = dict(schema["language"]["default"])
360
+ schema_name = schema["language"]["default"]["name"]
361
+ schema_python_name = schema["language"]["python"]["name"]
289
362
 
290
- if not NameConverter._is_schema_an_m4_header_parameter(
291
- schema_name, schema
292
- ):
363
+ if not NameConverter._is_schema_an_m4_header_parameter(schema_name, schema):
293
364
  # only escaping name if it's not a content_type header parameter
294
365
  schema_python_name = NameConverter._to_valid_python_name(
295
366
  name=schema_name, pad_string=pad_string, convert_name=convert_name
@@ -297,12 +368,16 @@ class NameConverter:
297
368
  # need to add the lower in case certain words, like LRO, are overriden to
298
369
  # always return LRO. Without .lower(), for example, begin_lro would be
299
370
  # begin_LRO
300
- schema['language']['python']['name'] = (
371
+ schema["language"]["python"]["name"] = (
301
372
  schema_python_name.upper() if all_upper else schema_python_name.lower()
302
373
  )
303
374
 
304
375
  schema_description = schema["language"]["default"]["description"].strip()
305
- if pad_string == PadType.Method and not schema_description and not schema["language"]["default"].get("summary"):
376
+ if (
377
+ pad_string == PadType.Method
378
+ and not schema_description
379
+ and not schema["language"]["default"].get("summary")
380
+ ):
306
381
  schema_description = schema["language"]["python"]["name"]
307
382
  if schema_description and schema_description[-1] != ".":
308
383
  schema_description += "."
@@ -319,7 +394,7 @@ class NameConverter:
319
394
  def _convert_language_default_pascal_case(schema: Dict[str, Any]) -> None:
320
395
  if schema["language"].get("python"):
321
396
  return
322
- schema['language']['python'] = dict(schema['language']['default'])
397
+ schema["language"]["python"] = dict(schema["language"]["default"])
323
398
 
324
399
  schema_description = schema["language"]["default"]["description"].strip()
325
400
 
@@ -328,11 +403,15 @@ class NameConverter:
328
403
  @staticmethod
329
404
  def _to_pascal_case(name: str) -> str:
330
405
  name_list = re.split("[^a-zA-Z\\d]", name)
331
- name_list = [s[0].upper() + s[1:] if len(s) > 1 else s.upper() for s in name_list]
406
+ name_list = [
407
+ s[0].upper() + s[1:] if len(s) > 1 else s.upper() for s in name_list
408
+ ]
332
409
  return "".join(name_list)
333
410
 
334
411
  @staticmethod
335
- def _to_valid_python_name(name: str, *, pad_string: Optional[PadType] = None, convert_name: bool = False) -> str:
412
+ def _to_valid_python_name(
413
+ name: str, *, pad_string: Optional[PadType] = None, convert_name: bool = False
414
+ ) -> str:
336
415
  if not name:
337
416
  return NameConverter._to_python_case(pad_string.value if pad_string else "")
338
417
  escaped_name = NameConverter._get_escaped_reserved_name(
@@ -360,13 +439,21 @@ class NameConverter:
360
439
  and name[next_non_upper_case_char_location].isalpha()
361
440
  ):
362
441
 
363
- return prefix + match_str[: len(match_str) - 1] + "_" + match_str[len(match_str) - 1]
442
+ return (
443
+ prefix
444
+ + match_str[: len(match_str) - 1]
445
+ + "_"
446
+ + match_str[len(match_str) - 1]
447
+ )
364
448
 
365
449
  return prefix + match_str
450
+
366
451
  return re.sub("[A-Z]+", replace_upper_characters, name)
367
452
 
368
453
  @staticmethod
369
- def _get_escaped_reserved_name(name: str, pad_string: Optional[PadType] = None) -> str:
454
+ def _get_escaped_reserved_name(
455
+ name: str, pad_string: Optional[PadType] = None
456
+ ) -> str:
370
457
  if name is None:
371
458
  raise ValueError("The value for name can not be None")
372
459
  try:
@@ -383,17 +470,23 @@ class NameConverter:
383
470
  name += pad_string.value
384
471
  return name_prefix + name
385
472
  except AttributeError:
386
- raise ValueError(f"The name {name} is a reserved word and you have not specified a pad string for it.")
473
+ raise ValueError(
474
+ f"The name {name} is a reserved word and you have not specified a pad string for it."
475
+ )
387
476
 
388
477
  @staticmethod
389
478
  def _remove_invalid_characters(name: str, allowed_characters: List[str]) -> str:
390
479
  name = name.replace("[]", "Sequence")
391
- valid_string = "".join([n for n in name if n.isalpha() or n.isdigit() or n in allowed_characters])
480
+ valid_string = "".join(
481
+ [n for n in name if n.isalpha() or n.isdigit() or n in allowed_characters]
482
+ )
392
483
  return valid_string
393
484
 
394
485
  @staticmethod
395
486
  def _to_valid_name(name: str, allowed_characters: List[str]) -> str:
396
- correct_name = NameConverter._remove_invalid_characters(name, allowed_characters)
487
+ correct_name = NameConverter._remove_invalid_characters(
488
+ name, allowed_characters
489
+ )
397
490
 
398
491
  # here we have an empty string or a string that consists only of invalid characters
399
492
  if not correct_name or correct_name[0] in basic_latin_chars.keys():
@@ -403,10 +496,14 @@ class NameConverter:
403
496
  ret_name += basic_latin_chars[c]
404
497
  else:
405
498
  ret_name += c
406
- correct_name = NameConverter._remove_invalid_characters(ret_name, allowed_characters)
499
+ correct_name = NameConverter._remove_invalid_characters(
500
+ ret_name, allowed_characters
501
+ )
407
502
 
408
503
  if not correct_name:
409
504
  raise ValueError(
410
- "Property name {} cannot be used as an identifier, as it contains only invalid characters.".format(name)
505
+ "Property name {} cannot be used as an identifier, as it contains only invalid characters.".format(
506
+ name
507
+ )
411
508
  )
412
509
  return correct_name
@@ -50,6 +50,7 @@ basic_latin_chars = {
50
50
  "~": "Tilde",
51
51
  }
52
52
 
53
+
53
54
  class PadType(Enum):
54
55
  Model = "Model"
55
56
  Method = "Method"
@@ -59,6 +60,7 @@ class PadType(Enum):
59
60
  OperationGroup = "Operations"
60
61
  BuilderGroup = "Builders"
61
62
 
63
+
62
64
  _always_reserved = [
63
65
  "and",
64
66
  "as",
@@ -91,13 +93,11 @@ _always_reserved = [
91
93
  "with",
92
94
  "yield",
93
95
  "async",
94
- "await"
96
+ "await",
95
97
  ]
96
98
 
97
99
  reserved_words = {
98
- PadType.Method: [
99
- *_always_reserved
100
- ],
100
+ PadType.Method: [*_always_reserved],
101
101
  PadType.Parameter: [
102
102
  "self",
103
103
  # these are kwargs we've reserved for our autorest generated operations
@@ -161,23 +161,11 @@ reserved_words = {
161
161
  "retry_backoff_max",
162
162
  "retry_mode",
163
163
  "retry_on_status_codes",
164
- *_always_reserved
165
- ],
166
- PadType.Model: [
167
- *_always_reserved
168
- ],
169
- PadType.Property: [
170
- "self",
171
- *_always_reserved
172
- ],
173
- PadType.Enum: [
174
- "mro",
175
- *_always_reserved
176
- ],
177
- PadType.OperationGroup: [
178
- *_always_reserved
164
+ *_always_reserved,
179
165
  ],
180
- PadType.BuilderGroup: [
181
- *_always_reserved
182
- ]
166
+ PadType.Model: [*_always_reserved],
167
+ PadType.Property: ["self", *_always_reserved],
168
+ PadType.Enum: ["mro", *_always_reserved],
169
+ PadType.OperationGroup: [*_always_reserved],
170
+ PadType.BuilderGroup: [*_always_reserved],
183
171
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "5.15.0",
3
+ "version": "5.16.0",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "scripts": {
6
6
  "prepare": "node run-python3.js prepare.py",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "homepage": "https://github.com/Azure/autorest.python/blob/autorestv3/README.md",
26
26
  "dependencies": {
27
- "@azure-tools/extension": "~3.2.1"
27
+ "@autorest/system-requirements": "~1.0.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@microsoft.azure/autorest.testserver": "3.3.23"
package/run-python3.js CHANGED
@@ -7,11 +7,10 @@
7
7
  // Invoke it like so: "node run-python3.js script.py"
8
8
 
9
9
  const cp = require("child_process");
10
- const extension = require("@azure-tools/extension");
10
+ const extension = require("@autorest/system-requirements");
11
11
 
12
12
  async function runPython3(scriptName, debug = "") {
13
- const command = ["python", scriptName, debug];
14
- await extension.updatePythonPath(command);
13
+ const command = await extension.patchPythonPath(["python", scriptName, debug], { version: ">=3.6", environmentVariable: "AUTOREST_PYTHON_EXE" });
15
14
  cp.execSync(command.join(" "), {
16
15
  stdio: [0, 1, 2]
17
16
  });
package/venvtools.py CHANGED
@@ -21,7 +21,7 @@ class ExtendedEnvBuilder(venv.EnvBuilder):
21
21
 
22
22
  def __init__(self, *args, **kwargs):
23
23
  self.context = None
24
- super(ExtendedEnvBuilder, self).__init__(*args, **kwargs)
24
+ super().__init__(*args, **kwargs)
25
25
 
26
26
  def ensure_directories(self, env_dir):
27
27
  self.context = super(ExtendedEnvBuilder, self).ensure_directories(env_dir)