@autorest/python 5.16.0 → 5.19.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 +79 -4
- package/README.md +30 -4
- package/autorest/__init__.py +1 -1
- package/autorest/codegen/__init__.py +55 -211
- package/autorest/codegen/models/__init__.py +116 -83
- package/autorest/codegen/models/base_builder.py +49 -88
- package/autorest/codegen/models/base_model.py +1 -1
- package/autorest/codegen/models/{base_schema.py → base_type.py} +61 -39
- package/autorest/codegen/models/client.py +165 -53
- package/autorest/codegen/models/code_model.py +122 -257
- package/autorest/codegen/models/combined_type.py +107 -0
- package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
- package/autorest/codegen/models/credential_types.py +224 -0
- package/autorest/codegen/models/dictionary_type.py +131 -0
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +80 -2
- package/autorest/codegen/models/list_type.py +149 -0
- package/autorest/codegen/models/lro_operation.py +79 -156
- package/autorest/codegen/models/lro_paging_operation.py +28 -11
- package/autorest/codegen/models/model_type.py +262 -0
- package/autorest/codegen/models/operation.py +331 -298
- package/autorest/codegen/models/operation_group.py +54 -91
- package/autorest/codegen/models/paging_operation.py +82 -123
- package/autorest/codegen/models/parameter.py +289 -396
- package/autorest/codegen/models/parameter_list.py +355 -360
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +123 -139
- package/autorest/codegen/models/request_builder.py +130 -102
- package/autorest/codegen/models/request_builder_parameter.py +112 -100
- package/autorest/codegen/models/response.py +325 -0
- package/autorest/codegen/models/utils.py +12 -19
- package/autorest/codegen/serializers/__init__.py +55 -37
- package/autorest/codegen/serializers/builder_serializer.py +695 -1144
- package/autorest/codegen/serializers/client_serializer.py +92 -89
- package/autorest/codegen/serializers/general_serializer.py +15 -69
- package/autorest/codegen/serializers/import_serializer.py +7 -4
- package/autorest/codegen/serializers/metadata_serializer.py +15 -104
- package/autorest/codegen/serializers/model_base_serializer.py +49 -36
- package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
- package/autorest/codegen/serializers/model_init_serializer.py +2 -4
- package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
- package/autorest/codegen/serializers/operation_groups_serializer.py +7 -13
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/request_builders_serializer.py +13 -30
- package/autorest/codegen/serializers/utils.py +0 -140
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +10 -7
- package/autorest/codegen/templates/config.py.jinja2 +13 -13
- package/autorest/codegen/templates/enum.py.jinja2 +4 -4
- package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/init.py.jinja2 +2 -2
- package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
- package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
- package/autorest/codegen/templates/model.py.jinja2 +23 -24
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
- package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
- package/autorest/codegen/templates/operation.py.jinja2 +6 -8
- package/autorest/codegen/templates/operation_group.py.jinja2 +21 -8
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -2
- package/autorest/codegen/templates/operation_tools.jinja2 +11 -3
- package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
- package/autorest/codegen/templates/request_builder.py.jinja2 +10 -15
- package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
- package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
- package/autorest/codegen/templates/setup.py.jinja2 +13 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +11 -1
- package/autorest/jsonrpc/server.py +15 -3
- package/autorest/m4reformatter/__init__.py +1126 -0
- package/autorest/multiapi/models/client.py +12 -2
- package/autorest/multiapi/models/code_model.py +1 -1
- package/autorest/multiapi/serializers/__init__.py +18 -4
- package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
- package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
- package/autorest/postprocess/__init__.py +202 -0
- package/autorest/postprocess/get_all.py +19 -0
- package/autorest/postprocess/venvtools.py +73 -0
- package/autorest/preprocess/__init__.py +210 -0
- package/autorest/preprocess/helpers.py +54 -0
- package/autorest/{namer → preprocess}/python_mappings.py +21 -16
- package/package.json +2 -2
- package/autorest/codegen/models/credential_model.py +0 -55
- package/autorest/codegen/models/credential_schema.py +0 -95
- package/autorest/codegen/models/credential_schema_policy.py +0 -73
- package/autorest/codegen/models/dictionary_schema.py +0 -106
- package/autorest/codegen/models/enum_schema.py +0 -225
- package/autorest/codegen/models/list_schema.py +0 -135
- package/autorest/codegen/models/object_schema.py +0 -303
- package/autorest/codegen/models/primitive_schemas.py +0 -495
- package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
- package/autorest/codegen/models/schema_request.py +0 -55
- package/autorest/codegen/models/schema_response.py +0 -141
- package/autorest/namer/__init__.py +0 -23
- package/autorest/namer/name_converter.py +0 -509
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
"""The preprocessing autorest plugin.
|
|
7
|
+
"""
|
|
8
|
+
from typing import Callable, Dict, Any, List, Optional
|
|
9
|
+
from .helpers import to_snake_case, pad_reserved_words, add_redefined_builtin_info
|
|
10
|
+
from .python_mappings import PadType
|
|
11
|
+
|
|
12
|
+
from .. import YamlUpdatePlugin
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def update_description(
|
|
16
|
+
description: Optional[str], default_description: str = ""
|
|
17
|
+
) -> str:
|
|
18
|
+
if not description:
|
|
19
|
+
description = default_description
|
|
20
|
+
description.rstrip(" ")
|
|
21
|
+
if description and description[-1] != ".":
|
|
22
|
+
description += "."
|
|
23
|
+
return description
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def update_operation_group_class_name(
|
|
27
|
+
yaml_data: Dict[str, Any], class_name: str
|
|
28
|
+
) -> str:
|
|
29
|
+
if class_name == "":
|
|
30
|
+
return yaml_data["client"]["name"] + "OperationsMixin"
|
|
31
|
+
if class_name == "Operations":
|
|
32
|
+
return "Operations"
|
|
33
|
+
return class_name + "Operations"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def update_parameter(yaml_data: Dict[str, Any]) -> None:
|
|
37
|
+
yaml_data["description"] = update_description(yaml_data["description"])
|
|
38
|
+
if not (
|
|
39
|
+
yaml_data["location"] == "header"
|
|
40
|
+
and yaml_data["clientName"] in ("content_type", "accept")
|
|
41
|
+
):
|
|
42
|
+
yaml_data["clientName"] = pad_reserved_words(
|
|
43
|
+
yaml_data["clientName"].lower(), PadType.PARAMETER
|
|
44
|
+
)
|
|
45
|
+
if yaml_data.get("propertyToParameterName"):
|
|
46
|
+
# need to create a new one with padded keys and values
|
|
47
|
+
yaml_data["propertyToParameterName"] = {
|
|
48
|
+
pad_reserved_words(prop, PadType.PROPERTY)
|
|
49
|
+
.lower(): pad_reserved_words(param_name, PadType.PARAMETER)
|
|
50
|
+
.lower()
|
|
51
|
+
for prop, param_name in yaml_data["propertyToParameterName"].items()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def update_types(yaml_data: List[Dict[str, Any]]) -> None:
|
|
56
|
+
for type in yaml_data:
|
|
57
|
+
for property in type.get("properties", []):
|
|
58
|
+
property["description"] = update_description(property["description"])
|
|
59
|
+
property["clientName"] = pad_reserved_words(
|
|
60
|
+
property["clientName"].lower(), PadType.PROPERTY
|
|
61
|
+
)
|
|
62
|
+
add_redefined_builtin_info(property["clientName"], property)
|
|
63
|
+
if type.get("name"):
|
|
64
|
+
type["description"] = update_description(type["description"], type["name"])
|
|
65
|
+
type["snakeCaseName"] = to_snake_case(type["name"])
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def update_client(yaml_data: Dict[str, Any]) -> None:
|
|
69
|
+
yaml_data["description"] = update_description(
|
|
70
|
+
yaml_data["description"], default_description=yaml_data["name"]
|
|
71
|
+
)
|
|
72
|
+
yaml_data["moduleName"] = to_snake_case(yaml_data["name"].replace(" ", "_"))
|
|
73
|
+
for parameter in yaml_data["parameters"]:
|
|
74
|
+
update_parameter(parameter)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def update_paging_response(yaml_data: Dict[str, Any]) -> None:
|
|
78
|
+
yaml_data["discriminator"] = "paging"
|
|
79
|
+
yaml_data["pagerSync"] = yaml_data.get("pagerSync") or "azure.core.paging.ItemPaged"
|
|
80
|
+
yaml_data["pagerAsync"] = (
|
|
81
|
+
yaml_data.get("pagerAsync") or "azure.core.async_paging.AsyncItemPaged"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class PreProcessPlugin(YamlUpdatePlugin):
|
|
86
|
+
"""Add Python naming information."""
|
|
87
|
+
|
|
88
|
+
def get_operation_updater(
|
|
89
|
+
self, yaml_data: Dict[str, Any]
|
|
90
|
+
) -> Callable[[Dict[str, Any]], None]:
|
|
91
|
+
if yaml_data["discriminator"] == "lropaging":
|
|
92
|
+
return self.update_lro_paging_operation
|
|
93
|
+
if yaml_data["discriminator"] == "lro":
|
|
94
|
+
return self.update_lro_operation
|
|
95
|
+
if yaml_data["discriminator"] == "paging":
|
|
96
|
+
return self.update_paging_operation
|
|
97
|
+
return self.update_operation
|
|
98
|
+
|
|
99
|
+
def update_operation(self, yaml_data: Dict[str, Any]) -> None:
|
|
100
|
+
yaml_data["groupName"] = pad_reserved_words(
|
|
101
|
+
yaml_data["groupName"], PadType.OPERATION_GROUP
|
|
102
|
+
)
|
|
103
|
+
yaml_data["groupName"] = to_snake_case(yaml_data["groupName"])
|
|
104
|
+
yaml_data["name"] = yaml_data["name"].lower()
|
|
105
|
+
yaml_data["name"] = pad_reserved_words(yaml_data["name"], PadType.METHOD)
|
|
106
|
+
yaml_data["description"] = update_description(
|
|
107
|
+
yaml_data["description"], yaml_data["name"]
|
|
108
|
+
)
|
|
109
|
+
yaml_data["summary"] = update_description(yaml_data.get("summary", ""))
|
|
110
|
+
for parameter in yaml_data["parameters"]:
|
|
111
|
+
update_parameter(parameter)
|
|
112
|
+
if yaml_data.get("bodyParameter"):
|
|
113
|
+
update_parameter(yaml_data["bodyParameter"])
|
|
114
|
+
for entry in yaml_data["bodyParameter"].get("entries", []):
|
|
115
|
+
update_parameter(entry)
|
|
116
|
+
for overload in yaml_data.get("overloads", []):
|
|
117
|
+
self.update_operation(overload)
|
|
118
|
+
for response in yaml_data.get("responses", []):
|
|
119
|
+
response["discriminator"] = "operation"
|
|
120
|
+
|
|
121
|
+
def _update_lro_operation_helper(self, yaml_data: Dict[str, Any]) -> None:
|
|
122
|
+
azure_arm = self._autorestapi.get_boolean_value("azure-arm", False)
|
|
123
|
+
for response in yaml_data.get("responses", []):
|
|
124
|
+
response["discriminator"] = "lro"
|
|
125
|
+
response["pollerSync"] = (
|
|
126
|
+
response.get("pollerSync") or "azure.core.polling.LROPoller"
|
|
127
|
+
)
|
|
128
|
+
response["pollerAsync"] = (
|
|
129
|
+
response.get("pollerAsync") or "azure.core.polling.AsyncLROPoller"
|
|
130
|
+
)
|
|
131
|
+
if not response.get("pollingMethodSync"):
|
|
132
|
+
response["pollingMethodSync"] = (
|
|
133
|
+
"azure.mgmt.core.polling.arm_polling.ARMPolling"
|
|
134
|
+
if azure_arm
|
|
135
|
+
else "azure.core.polling.base_polling.LROBasePolling"
|
|
136
|
+
)
|
|
137
|
+
if not response.get("pollingMethodAsync"):
|
|
138
|
+
response["pollingMethodAsync"] = (
|
|
139
|
+
"azure.mgmt.core.polling.async_arm_polling.AsyncARMPolling"
|
|
140
|
+
if azure_arm
|
|
141
|
+
else "azure.core.polling.async_base_polling.AsyncLROBasePolling"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def update_lro_paging_operation(self, yaml_data: Dict[str, Any]) -> None:
|
|
145
|
+
self.update_lro_operation(yaml_data)
|
|
146
|
+
self.update_paging_operation(yaml_data)
|
|
147
|
+
for response in yaml_data.get("responses", []):
|
|
148
|
+
response["discriminator"] = "lropaging"
|
|
149
|
+
|
|
150
|
+
def update_lro_operation(self, yaml_data: Dict[str, Any]) -> None:
|
|
151
|
+
self.update_operation(yaml_data)
|
|
152
|
+
self._update_lro_operation_helper(yaml_data)
|
|
153
|
+
for overload in yaml_data["overloads"]:
|
|
154
|
+
self._update_lro_operation_helper(overload)
|
|
155
|
+
|
|
156
|
+
def update_paging_operation(self, yaml_data: Dict[str, Any]) -> None:
|
|
157
|
+
self.update_operation(yaml_data)
|
|
158
|
+
if not yaml_data.get("pagerSync"):
|
|
159
|
+
yaml_data["pagerSync"] = "azure.core.paging.ItemPaged"
|
|
160
|
+
if not yaml_data.get("pagerAsync"):
|
|
161
|
+
yaml_data["pagerAsync"] = "azure.core.async_paging.AsyncItemPaged"
|
|
162
|
+
returned_response_object = (
|
|
163
|
+
yaml_data["nextOperation"]["responses"][0]
|
|
164
|
+
if yaml_data.get("nextOperation")
|
|
165
|
+
else yaml_data["responses"][0]
|
|
166
|
+
)
|
|
167
|
+
# if we're in version tolerant, hide the paging model
|
|
168
|
+
if self._autorestapi.get_boolean_value("version-tolerant"):
|
|
169
|
+
returned_response_object["type"]["isPublic"] = False
|
|
170
|
+
item_type = next(
|
|
171
|
+
p["type"]["elementType"]
|
|
172
|
+
for p in returned_response_object["type"]["properties"]
|
|
173
|
+
if p["restApiName"] == yaml_data["itemName"]
|
|
174
|
+
)
|
|
175
|
+
if yaml_data.get("nextOperation"):
|
|
176
|
+
yaml_data["nextOperation"]["groupName"] = pad_reserved_words(
|
|
177
|
+
yaml_data["nextOperation"]["groupName"], PadType.OPERATION_GROUP
|
|
178
|
+
)
|
|
179
|
+
yaml_data["nextOperation"]["groupName"] = to_snake_case(
|
|
180
|
+
yaml_data["nextOperation"]["groupName"]
|
|
181
|
+
)
|
|
182
|
+
for response in yaml_data["nextOperation"].get("responses", []):
|
|
183
|
+
update_paging_response(response)
|
|
184
|
+
response["itemType"] = item_type
|
|
185
|
+
for response in yaml_data.get("responses", []):
|
|
186
|
+
update_paging_response(response)
|
|
187
|
+
response["itemType"] = item_type
|
|
188
|
+
for overload in yaml_data.get("overloads", []):
|
|
189
|
+
self.update_paging_operation(overload)
|
|
190
|
+
|
|
191
|
+
def update_operation_groups(self, yaml_data: Dict[str, Any]) -> None:
|
|
192
|
+
operation_groups_yaml_data = yaml_data["operationGroups"]
|
|
193
|
+
for operation_group in operation_groups_yaml_data:
|
|
194
|
+
operation_group["propertyName"] = pad_reserved_words(
|
|
195
|
+
operation_group["propertyName"], PadType.OPERATION_GROUP
|
|
196
|
+
)
|
|
197
|
+
operation_group["propertyName"] = to_snake_case(
|
|
198
|
+
operation_group["propertyName"]
|
|
199
|
+
)
|
|
200
|
+
operation_group["className"] = update_operation_group_class_name(
|
|
201
|
+
yaml_data, operation_group["className"]
|
|
202
|
+
)
|
|
203
|
+
for operation in operation_group["operations"]:
|
|
204
|
+
self.get_operation_updater(operation)(operation)
|
|
205
|
+
|
|
206
|
+
def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
|
|
207
|
+
"""Convert in place the YAML str."""
|
|
208
|
+
update_client(yaml_data["client"])
|
|
209
|
+
update_types(yaml_data["types"])
|
|
210
|
+
self.update_operation_groups(yaml_data)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import Any, Dict
|
|
7
|
+
import re
|
|
8
|
+
from .python_mappings import PadType, RESERVED_WORDS, REDEFINED_BUILTINS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def to_snake_case(name: str) -> str:
|
|
12
|
+
def replace_upper_characters(m) -> str:
|
|
13
|
+
match_str = m.group().lower()
|
|
14
|
+
if m.start() > 0 and name[m.start() - 1] == "_":
|
|
15
|
+
# we are good if a '_' already exists
|
|
16
|
+
return match_str
|
|
17
|
+
# the first letter should not have _
|
|
18
|
+
prefix = "_" if m.start() > 0 else ""
|
|
19
|
+
|
|
20
|
+
# we will add an extra _ if there are multiple upper case chars together
|
|
21
|
+
next_non_upper_case_char_location = m.start() + len(match_str)
|
|
22
|
+
if (
|
|
23
|
+
len(match_str) > 2
|
|
24
|
+
and len(name) - next_non_upper_case_char_location > 1
|
|
25
|
+
and name[next_non_upper_case_char_location].isalpha()
|
|
26
|
+
):
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
prefix
|
|
30
|
+
+ match_str[: len(match_str) - 1]
|
|
31
|
+
+ "_"
|
|
32
|
+
+ match_str[len(match_str) - 1]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return prefix + match_str
|
|
36
|
+
|
|
37
|
+
return re.sub("[A-Z]+", replace_upper_characters, name)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def pad_reserved_words(name: str, pad_type: PadType):
|
|
41
|
+
# we want to pad hidden variables as well
|
|
42
|
+
if not name:
|
|
43
|
+
# we'll pass in empty operation groups sometime etc.
|
|
44
|
+
return name
|
|
45
|
+
name_prefix = "_" if name[0] == "_" else ""
|
|
46
|
+
name = name[1:] if name[0] == "_" else name
|
|
47
|
+
if name.lower() in RESERVED_WORDS[pad_type]:
|
|
48
|
+
return name_prefix + name + pad_type
|
|
49
|
+
return name_prefix + name
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def add_redefined_builtin_info(name: str, yaml_data: Dict[str, Any]) -> None:
|
|
53
|
+
if name in REDEFINED_BUILTINS:
|
|
54
|
+
yaml_data["pylintDisable"] = "redefined-builtin"
|
|
@@ -51,14 +51,13 @@ basic_latin_chars = {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
class PadType(Enum):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
BuilderGroup = "Builders"
|
|
54
|
+
class PadType(str, Enum):
|
|
55
|
+
MODEL = "Model"
|
|
56
|
+
METHOD = "_method"
|
|
57
|
+
PARAMETER = "_parameter"
|
|
58
|
+
ENUM = "_enum"
|
|
59
|
+
PROPERTY = "_property"
|
|
60
|
+
OPERATION_GROUP = "Operations"
|
|
62
61
|
|
|
63
62
|
|
|
64
63
|
_always_reserved = [
|
|
@@ -96,9 +95,9 @@ _always_reserved = [
|
|
|
96
95
|
"await",
|
|
97
96
|
]
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
PadType.
|
|
101
|
-
PadType.
|
|
98
|
+
RESERVED_WORDS = {
|
|
99
|
+
PadType.METHOD: [*_always_reserved],
|
|
100
|
+
PadType.PARAMETER: [
|
|
102
101
|
"self",
|
|
103
102
|
# these are kwargs we've reserved for our autorest generated operations
|
|
104
103
|
"content_type",
|
|
@@ -163,9 +162,15 @@ reserved_words = {
|
|
|
163
162
|
"retry_on_status_codes",
|
|
164
163
|
*_always_reserved,
|
|
165
164
|
],
|
|
166
|
-
PadType.
|
|
167
|
-
PadType.
|
|
168
|
-
PadType.
|
|
169
|
-
PadType.
|
|
170
|
-
PadType.BuilderGroup: [*_always_reserved],
|
|
165
|
+
PadType.MODEL: [*_always_reserved],
|
|
166
|
+
PadType.PROPERTY: ["self", *_always_reserved],
|
|
167
|
+
PadType.ENUM: ["mro", *_always_reserved],
|
|
168
|
+
PadType.OPERATION_GROUP: [*_always_reserved],
|
|
171
169
|
}
|
|
170
|
+
|
|
171
|
+
REDEFINED_BUILTINS = [ # we don't pad, but we need to do lint ignores
|
|
172
|
+
"id",
|
|
173
|
+
"min",
|
|
174
|
+
"max",
|
|
175
|
+
"filter",
|
|
176
|
+
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autorest/python",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.19.0",
|
|
4
4
|
"description": "The Python extension for generators in AutoRest.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepare": "node run-python3.js prepare.py",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@autorest/system-requirements": "~1.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@microsoft.azure/autorest.testserver": "3.3.
|
|
30
|
+
"@microsoft.azure/autorest.testserver": "^3.3.28"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"autorest/**/*.py",
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Set, Optional, Type
|
|
7
|
-
from .credential_schema_policy import (
|
|
8
|
-
CredentialSchemaPolicy,
|
|
9
|
-
BearerTokenCredentialPolicy,
|
|
10
|
-
)
|
|
11
|
-
from .credential_schema_policy import ARMChallengeAuthenticationPolicy
|
|
12
|
-
from .credential_schema import TokenCredentialSchema, AzureKeyCredentialSchema
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class CredentialModel:
|
|
16
|
-
"""Store info about credential."""
|
|
17
|
-
|
|
18
|
-
def __init__(self, azure_arm: bool) -> None:
|
|
19
|
-
self.azure_arm: bool = azure_arm
|
|
20
|
-
self.credential_scopes: Set[str] = set()
|
|
21
|
-
self.key_header_name: str = ""
|
|
22
|
-
self.policy_type: Optional[Type[CredentialSchemaPolicy]] = None
|
|
23
|
-
self._credential_schema_policy: Optional[CredentialSchemaPolicy] = None
|
|
24
|
-
|
|
25
|
-
@property
|
|
26
|
-
def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
|
|
27
|
-
return (
|
|
28
|
-
ARMChallengeAuthenticationPolicy
|
|
29
|
-
if self.azure_arm
|
|
30
|
-
else BearerTokenCredentialPolicy
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def credential_schema_policy(self) -> CredentialSchemaPolicy:
|
|
35
|
-
if not self._credential_schema_policy:
|
|
36
|
-
raise ValueError(
|
|
37
|
-
"You want to find the Credential Schema Policy, but have not given a value"
|
|
38
|
-
)
|
|
39
|
-
return self._credential_schema_policy
|
|
40
|
-
|
|
41
|
-
def build_authentication_policy(self):
|
|
42
|
-
if hasattr(self.policy_type, "credential_scopes"):
|
|
43
|
-
self._credential_schema_policy = (
|
|
44
|
-
self.policy_type( # pylint: disable=not-callable
|
|
45
|
-
credential=TokenCredentialSchema(async_mode=False),
|
|
46
|
-
credential_scopes=list(self.credential_scopes),
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
elif hasattr(self.policy_type, "credential_key_header_name"):
|
|
50
|
-
self._credential_schema_policy = (
|
|
51
|
-
self.policy_type( # pylint: disable=not-callable
|
|
52
|
-
credential=AzureKeyCredentialSchema(),
|
|
53
|
-
credential_key_header_name=self.key_header_name,
|
|
54
|
-
)
|
|
55
|
-
)
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any
|
|
7
|
-
from .base_schema import BaseSchema
|
|
8
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class CredentialSchema(BaseSchema):
|
|
12
|
-
def __init__(self) -> None: # pylint: disable=super-init-not-called
|
|
13
|
-
self.default_value = None
|
|
14
|
-
|
|
15
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
16
|
-
raise ValueError("Children classes should set their own type annotation")
|
|
17
|
-
|
|
18
|
-
@property
|
|
19
|
-
def docstring_type(self) -> str:
|
|
20
|
-
return self.serialization_type
|
|
21
|
-
|
|
22
|
-
@property
|
|
23
|
-
def docstring_text(self) -> str:
|
|
24
|
-
return "credential"
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def serialization_type(self) -> str:
|
|
28
|
-
# this property is added, because otherwise pylint says that
|
|
29
|
-
# abstract serialization_type in BaseSchema is not overridden
|
|
30
|
-
pass
|
|
31
|
-
|
|
32
|
-
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
33
|
-
raise TypeError(
|
|
34
|
-
"You should not try to get a JSON template representation of a CredentialSchema"
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class AzureKeyCredentialSchema(CredentialSchema):
|
|
39
|
-
@property
|
|
40
|
-
def serialization_type(self) -> str:
|
|
41
|
-
return "~azure.core.credentials.AzureKeyCredential"
|
|
42
|
-
|
|
43
|
-
def type_annotation(
|
|
44
|
-
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
45
|
-
) -> str:
|
|
46
|
-
return "AzureKeyCredential"
|
|
47
|
-
|
|
48
|
-
def imports(self) -> FileImport:
|
|
49
|
-
file_import = FileImport()
|
|
50
|
-
file_import.add_submodule_import(
|
|
51
|
-
"azure.core.credentials",
|
|
52
|
-
"AzureKeyCredential",
|
|
53
|
-
ImportType.AZURECORE,
|
|
54
|
-
typing_section=TypingSection.CONDITIONAL,
|
|
55
|
-
)
|
|
56
|
-
return file_import
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class TokenCredentialSchema(CredentialSchema):
|
|
60
|
-
def __init__(self, async_mode) -> None:
|
|
61
|
-
super().__init__()
|
|
62
|
-
self.async_mode = async_mode
|
|
63
|
-
self.async_type = "~azure.core.credentials_async.AsyncTokenCredential"
|
|
64
|
-
self.sync_type = "~azure.core.credentials.TokenCredential"
|
|
65
|
-
|
|
66
|
-
@property
|
|
67
|
-
def serialization_type(self) -> str:
|
|
68
|
-
if self.async_mode:
|
|
69
|
-
return self.async_type
|
|
70
|
-
return self.sync_type
|
|
71
|
-
|
|
72
|
-
def type_annotation(
|
|
73
|
-
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
74
|
-
) -> str:
|
|
75
|
-
if self.async_mode:
|
|
76
|
-
return '"AsyncTokenCredential"'
|
|
77
|
-
return '"TokenCredential"'
|
|
78
|
-
|
|
79
|
-
def imports(self) -> FileImport:
|
|
80
|
-
file_import = FileImport()
|
|
81
|
-
if self.async_mode:
|
|
82
|
-
file_import.add_submodule_import(
|
|
83
|
-
"azure.core.credentials_async",
|
|
84
|
-
"AsyncTokenCredential",
|
|
85
|
-
ImportType.AZURECORE,
|
|
86
|
-
typing_section=TypingSection.TYPING,
|
|
87
|
-
)
|
|
88
|
-
else:
|
|
89
|
-
file_import.add_submodule_import(
|
|
90
|
-
"azure.core.credentials",
|
|
91
|
-
"TokenCredential",
|
|
92
|
-
ImportType.AZURECORE,
|
|
93
|
-
typing_section=TypingSection.TYPING,
|
|
94
|
-
)
|
|
95
|
-
return file_import
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from abc import abstractmethod
|
|
7
|
-
from typing import List
|
|
8
|
-
from .credential_schema import CredentialSchema
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class CredentialSchemaPolicy:
|
|
12
|
-
def __init__(self, credential: CredentialSchema) -> None:
|
|
13
|
-
self.credential = credential
|
|
14
|
-
|
|
15
|
-
@abstractmethod
|
|
16
|
-
def call(self, async_mode: bool) -> str:
|
|
17
|
-
...
|
|
18
|
-
|
|
19
|
-
@classmethod
|
|
20
|
-
def name(cls):
|
|
21
|
-
return cls.__name__
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class BearerTokenCredentialPolicy(CredentialSchemaPolicy):
|
|
25
|
-
def __init__(
|
|
26
|
-
self, credential: CredentialSchema, credential_scopes: List[str]
|
|
27
|
-
) -> None:
|
|
28
|
-
super().__init__(credential)
|
|
29
|
-
self._credential_scopes = credential_scopes
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def credential_scopes(self):
|
|
33
|
-
return self._credential_scopes
|
|
34
|
-
|
|
35
|
-
def call(self, async_mode: bool) -> str:
|
|
36
|
-
policy_name = f"Async{self.name()}" if async_mode else self.name()
|
|
37
|
-
return f"policies.{policy_name}(self.credential, *self.credential_scopes, **kwargs)"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class ARMChallengeAuthenticationPolicy(BearerTokenCredentialPolicy):
|
|
41
|
-
def call(self, async_mode: bool) -> str:
|
|
42
|
-
policy_name = f"Async{self.name()}" if async_mode else self.name()
|
|
43
|
-
return f"{policy_name}(self.credential, *self.credential_scopes, **kwargs)"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class AzureKeyCredentialPolicy(CredentialSchemaPolicy):
|
|
47
|
-
def __init__(
|
|
48
|
-
self, credential: CredentialSchema, credential_key_header_name: str
|
|
49
|
-
) -> None:
|
|
50
|
-
super().__init__(credential)
|
|
51
|
-
self._credential_key_header_name = credential_key_header_name
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def credential_key_header_name(self):
|
|
55
|
-
return self._credential_key_header_name
|
|
56
|
-
|
|
57
|
-
def call(self, async_mode: bool) -> str:
|
|
58
|
-
return f'policies.AzureKeyCredentialPolicy(self.credential, "{self.credential_key_header_name}", **kwargs)'
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def get_credential_schema_policy_type(name):
|
|
62
|
-
policies = [
|
|
63
|
-
ARMChallengeAuthenticationPolicy,
|
|
64
|
-
BearerTokenCredentialPolicy,
|
|
65
|
-
AzureKeyCredentialPolicy,
|
|
66
|
-
]
|
|
67
|
-
try:
|
|
68
|
-
return next(p for p in policies if p.name().lower() == name.lower())
|
|
69
|
-
except StopIteration:
|
|
70
|
-
raise ValueError(
|
|
71
|
-
"The credential policy you pass in with --credential-default-policy-type must be either "
|
|
72
|
-
"{}".format(" or ".join([p.name() for p in policies]))
|
|
73
|
-
)
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
7
|
-
from .base_schema import BaseSchema
|
|
8
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from .code_model import CodeModel
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class DictionarySchema(BaseSchema):
|
|
15
|
-
"""Schema for dictionaries that will be serialized.
|
|
16
|
-
|
|
17
|
-
:param yaml_data: the yaml data for this schema
|
|
18
|
-
:type yaml_data: dict[str, Any]
|
|
19
|
-
:param element_type: The type of the value for the dictionary
|
|
20
|
-
:type element_type: ~autorest.models.BaseSchema
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
yaml_data: Dict[str, Any],
|
|
26
|
-
code_model: "CodeModel",
|
|
27
|
-
element_type: "BaseSchema",
|
|
28
|
-
) -> None:
|
|
29
|
-
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
30
|
-
self.element_type = element_type
|
|
31
|
-
|
|
32
|
-
@property
|
|
33
|
-
def serialization_type(self) -> str:
|
|
34
|
-
"""Returns the serialization value for msrest.
|
|
35
|
-
|
|
36
|
-
:return: The serialization value for msrest
|
|
37
|
-
:rtype: str
|
|
38
|
-
"""
|
|
39
|
-
return f"{{{self.element_type.serialization_type}}}"
|
|
40
|
-
|
|
41
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
42
|
-
"""The python type used for type annotation
|
|
43
|
-
|
|
44
|
-
:return: The type annotation for this schema
|
|
45
|
-
:rtype: str
|
|
46
|
-
"""
|
|
47
|
-
return f"Dict[str, {self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
|
|
48
|
-
|
|
49
|
-
@property
|
|
50
|
-
def docstring_text(self) -> str:
|
|
51
|
-
return f"dict mapping str to {self.element_type.docstring_text}"
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def docstring_type(self) -> str:
|
|
55
|
-
"""The python type used for RST syntax input and type annotation.
|
|
56
|
-
|
|
57
|
-
:param str namespace: Optional. The namespace for the models.
|
|
58
|
-
"""
|
|
59
|
-
return f"dict[str, {self.element_type.docstring_type}]"
|
|
60
|
-
|
|
61
|
-
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
62
|
-
raise NotImplementedError(
|
|
63
|
-
"Dictionary schema does not support XML serialization."
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
67
|
-
return {
|
|
68
|
-
f'"{"str"}"': self.element_type.get_json_template_representation(**kwargs)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
@classmethod
|
|
72
|
-
def from_yaml(
|
|
73
|
-
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
74
|
-
) -> "DictionarySchema":
|
|
75
|
-
"""Constructs a DictionarySchema from yaml data.
|
|
76
|
-
|
|
77
|
-
:param yaml_data: the yaml data from which we will construct this schema
|
|
78
|
-
:type yaml_data: dict[str, Any]
|
|
79
|
-
|
|
80
|
-
:return: A created DictionarySchema
|
|
81
|
-
:rtype: ~autorest.models.DictionarySchema
|
|
82
|
-
"""
|
|
83
|
-
element_schema = yaml_data["elementType"]
|
|
84
|
-
|
|
85
|
-
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
86
|
-
|
|
87
|
-
element_type = build_schema(yaml_data=element_schema, code_model=code_model)
|
|
88
|
-
|
|
89
|
-
return cls(
|
|
90
|
-
yaml_data=yaml_data,
|
|
91
|
-
code_model=code_model,
|
|
92
|
-
element_type=element_type,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
def imports(self) -> FileImport:
|
|
96
|
-
file_import = FileImport()
|
|
97
|
-
file_import.add_submodule_import(
|
|
98
|
-
"typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
99
|
-
)
|
|
100
|
-
file_import.merge(self.element_type.imports())
|
|
101
|
-
return file_import
|
|
102
|
-
|
|
103
|
-
def model_file_imports(self) -> FileImport:
|
|
104
|
-
file_import = self.imports()
|
|
105
|
-
file_import.merge(self.element_type.model_file_imports())
|
|
106
|
-
return file_import
|