@autorest/python 5.13.0 → 5.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +67 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +239 -105
- package/autorest/codegen/models/__init__.py +29 -18
- package/autorest/codegen/models/base_builder.py +48 -11
- package/autorest/codegen/models/base_model.py +6 -4
- package/autorest/codegen/models/base_schema.py +21 -24
- package/autorest/codegen/models/client.py +70 -20
- package/autorest/codegen/models/code_model.py +144 -129
- package/autorest/codegen/models/constant_schema.py +32 -16
- package/autorest/codegen/models/credential_model.py +55 -0
- package/autorest/codegen/models/credential_schema.py +21 -16
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +27 -24
- package/autorest/codegen/models/enum_schema.py +41 -62
- package/autorest/codegen/models/imports.py +72 -41
- package/autorest/codegen/models/list_schema.py +40 -18
- package/autorest/codegen/models/lro_operation.py +61 -25
- package/autorest/codegen/models/lro_paging_operation.py +5 -6
- package/autorest/codegen/models/object_schema.py +113 -59
- package/autorest/codegen/models/operation.py +251 -111
- package/autorest/codegen/models/operation_group.py +67 -32
- package/autorest/codegen/models/paging_operation.py +48 -21
- package/autorest/codegen/models/parameter.py +182 -90
- package/autorest/codegen/models/parameter_list.py +184 -163
- package/autorest/codegen/models/primitive_schemas.py +89 -70
- package/autorest/codegen/models/property.py +49 -31
- package/autorest/codegen/models/request_builder.py +67 -32
- package/autorest/codegen/models/request_builder_parameter.py +54 -23
- package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
- package/autorest/codegen/models/schema_request.py +16 -6
- package/autorest/codegen/models/schema_response.py +35 -17
- package/autorest/codegen/models/utils.py +24 -1
- package/autorest/codegen/serializers/__init__.py +273 -89
- package/autorest/codegen/serializers/builder_serializer.py +711 -333
- package/autorest/codegen/serializers/client_serializer.py +114 -43
- package/autorest/codegen/serializers/general_serializer.py +84 -25
- package/autorest/codegen/serializers/import_serializer.py +93 -31
- package/autorest/codegen/serializers/metadata_serializer.py +73 -24
- package/autorest/codegen/serializers/model_base_serializer.py +42 -14
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
- package/autorest/codegen/serializers/model_init_serializer.py +5 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +9 -8
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +60 -21
- package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
- package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
- package/autorest/codegen/templates/README.md.jinja2 +105 -0
- package/autorest/codegen/templates/config.py.jinja2 +4 -4
- package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
- package/autorest/codegen/templates/enum.py.jinja2 +1 -1
- package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
- package/autorest/codegen/templates/model.py.jinja2 +1 -6
- package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
- package/autorest/codegen/templates/operation.py.jinja2 +8 -11
- package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
- package/autorest/codegen/templates/setup.py.jinja2 +79 -20
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +13 -6
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +35 -18
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +18 -23
- package/autorest/multiapi/serializers/import_serializer.py +47 -15
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/namer/__init__.py +2 -4
- package/autorest/namer/name_converter.py +200 -103
- package/autorest/namer/python_mappings.py +10 -22
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- 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[
|
|
16
|
-
content_types.append(h[
|
|
16
|
+
if h["schema"]["type"] == "constant":
|
|
17
|
+
content_types.append(h["schema"]["value"]["value"])
|
|
17
18
|
elif any(
|
|
18
|
-
choice_type
|
|
19
|
-
|
|
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[
|
|
50
|
-
|
|
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"] =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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(
|
|
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[
|
|
83
|
+
operation_group_name = operation_group["language"]["default"]["name"]
|
|
73
84
|
if not operation_group_name:
|
|
74
|
-
operation_group[
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
operation_group[
|
|
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[
|
|
80
|
-
|
|
81
|
-
|
|
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[
|
|
84
|
-
|
|
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,
|
|
88
|
-
|
|
89
|
-
|
|
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[
|
|
94
|
-
operation[
|
|
95
|
-
for exception in operation.get(
|
|
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(
|
|
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(
|
|
105
|
-
|
|
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(
|
|
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
|
-
|
|
119
|
-
|
|
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
|
|
125
|
-
|
|
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[
|
|
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(
|
|
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
|
|
145
|
-
|
|
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[
|
|
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[
|
|
192
|
+
constant_schema = param_with_constant_schema["schema"]
|
|
154
193
|
constant_choice = {
|
|
155
194
|
"language": {
|
|
156
195
|
"default": {
|
|
157
|
-
"description": constant_schema[
|
|
158
|
-
|
|
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[
|
|
162
|
-
|
|
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[
|
|
210
|
+
"value": constant_schema["value"]["value"],
|
|
166
211
|
}
|
|
167
|
-
param_with_enum_schema[
|
|
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(
|
|
216
|
+
if not request.get("parameters"):
|
|
172
217
|
continue
|
|
173
|
-
request[
|
|
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[
|
|
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(
|
|
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 =
|
|
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,
|
|
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,
|
|
262
|
+
sync_polling_method_directive,
|
|
263
|
+
"azure.core.polling.base_polling.LROBasePolling",
|
|
213
264
|
),
|
|
214
265
|
}
|
|
215
|
-
async_polling_method_directive =
|
|
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,
|
|
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,
|
|
275
|
+
async_polling_method_directive,
|
|
276
|
+
"azure.core.polling.async_base_polling.AsyncLROBasePolling",
|
|
222
277
|
),
|
|
223
278
|
}
|
|
224
279
|
|
|
225
|
-
operation["extensions"][
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
operation["extensions"][
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
273
|
-
schema.get(
|
|
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[
|
|
287
|
-
schema_name = schema[
|
|
288
|
-
schema_python_name = schema[
|
|
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[
|
|
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
|
|
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[
|
|
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 = [
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
181
|
-
|
|
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.
|
|
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,10 +24,10 @@
|
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://github.com/Azure/autorest.python/blob/autorestv3/README.md",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@
|
|
27
|
+
"@autorest/system-requirements": "~1.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@microsoft.azure/autorest.testserver": "
|
|
30
|
+
"@microsoft.azure/autorest.testserver": "3.3.23"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"autorest/**/*.py",
|
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("@
|
|
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(
|
|
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)
|