@autorest/python 6.2.11 → 6.2.15
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/autorest/__init__.py +7 -5
- package/autorest/_utils.py +7 -1
- package/autorest/black/__init__.py +6 -1
- package/autorest/codegen/__init__.py +1 -1
- package/autorest/codegen/models/__init__.py +8 -2
- package/autorest/codegen/models/base.py +4 -13
- package/autorest/codegen/models/client.py +9 -11
- package/autorest/codegen/models/code_model.py +3 -3
- package/autorest/codegen/models/combined_type.py +4 -3
- package/autorest/codegen/models/credential_types.py +7 -14
- package/autorest/codegen/models/dictionary_type.py +1 -1
- package/autorest/codegen/models/imports.py +3 -3
- package/autorest/codegen/models/lro_operation.py +5 -5
- package/autorest/codegen/models/model_type.py +89 -47
- package/autorest/codegen/models/operation.py +8 -8
- package/autorest/codegen/models/operation_group.py +3 -1
- package/autorest/codegen/models/paging_operation.py +2 -2
- package/autorest/codegen/models/parameter.py +27 -6
- package/autorest/codegen/models/parameter_list.py +1 -9
- package/autorest/codegen/models/primitive_types.py +1 -1
- package/autorest/codegen/models/property.py +15 -3
- package/autorest/codegen/models/response.py +2 -2
- package/autorest/codegen/serializers/__init__.py +2 -2
- package/autorest/codegen/serializers/builder_serializer.py +64 -28
- package/autorest/codegen/serializers/client_serializer.py +6 -4
- package/autorest/codegen/serializers/general_serializer.py +7 -2
- package/autorest/codegen/serializers/model_serializer.py +14 -4
- package/autorest/codegen/serializers/sample_serializer.py +2 -6
- package/autorest/codegen/templates/config.py.jinja2 +25 -6
- package/autorest/codegen/templates/enum.py.jinja2 +2 -2
- package/autorest/codegen/templates/metadata.json.jinja2 +18 -9
- package/autorest/codegen/templates/model_base.py.jinja2 +74 -63
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -2
- package/autorest/codegen/templates/model_dpg.py.jinja2 +6 -4
- package/autorest/codegen/templates/model_msrest.py.jinja2 +2 -2
- package/autorest/codegen/templates/serialization.py.jinja2 +57 -29
- package/autorest/codegen/templates/vendor.py.jinja2 +3 -2
- package/autorest/jsonrpc/localapi.py +3 -3
- package/autorest/jsonrpc/server.py +3 -3
- package/autorest/m2r/__init__.py +1 -1
- package/autorest/m4reformatter/__init__.py +13 -2
- package/autorest/multiapi/models/__init__.py +2 -0
- package/autorest/multiapi/models/code_model.py +13 -0
- package/autorest/multiapi/models/global_parameter.py +1 -0
- package/autorest/multiapi/models/imports.py +3 -3
- package/autorest/multiapi/serializers/__init__.py +30 -3
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +8 -12
- package/autorest/postprocess/get_all.py +3 -1
- package/autorest/postprocess/venvtools.py +5 -4
- package/autorest/preprocess/__init__.py +19 -7
- package/autorest/preprocess/python_mappings.py +1 -0
- package/index.js +0 -0
- package/package.json +2 -1
- package/requirements.txt +6 -6
- package/setup.py +0 -1
- package/venvtools.py +2 -3
package/autorest/__init__.py
CHANGED
|
@@ -25,7 +25,9 @@ class ReaderAndWriter:
|
|
|
25
25
|
self._list_file: List[str] = []
|
|
26
26
|
try:
|
|
27
27
|
with open(
|
|
28
|
-
Path(self.output_folder) / Path("..") / Path("python.json"),
|
|
28
|
+
Path(self.output_folder) / Path("..") / Path("python.json"),
|
|
29
|
+
"r",
|
|
30
|
+
encoding="utf-8-sig",
|
|
29
31
|
) as fd:
|
|
30
32
|
python_json = json.load(fd)
|
|
31
33
|
except Exception: # pylint: disable=broad-except
|
|
@@ -41,7 +43,7 @@ class ReaderAndWriter:
|
|
|
41
43
|
"""Directly reading from disk"""
|
|
42
44
|
# make path relative to output folder
|
|
43
45
|
try:
|
|
44
|
-
with open(self.output_folder / Path(path), "r") as fd:
|
|
46
|
+
with open(self.output_folder / Path(path), "r", encoding="utf-8-sig") as fd:
|
|
45
47
|
return fd.read()
|
|
46
48
|
except FileNotFoundError:
|
|
47
49
|
return ""
|
|
@@ -51,7 +53,7 @@ class ReaderAndWriter:
|
|
|
51
53
|
file_folder = Path(filename).parent
|
|
52
54
|
if not Path.is_dir(self.output_folder / file_folder):
|
|
53
55
|
Path.mkdir(self.output_folder / file_folder, parents=True)
|
|
54
|
-
with open(self.output_folder / Path(filename), "w") as fd:
|
|
56
|
+
with open(self.output_folder / Path(filename), "w", encoding="utf-8") as fd:
|
|
55
57
|
fd.write(file_content)
|
|
56
58
|
|
|
57
59
|
def list_file(self) -> List[str]:
|
|
@@ -111,11 +113,11 @@ class YamlUpdatePlugin(Plugin):
|
|
|
111
113
|
|
|
112
114
|
def get_yaml(self) -> Dict[str, Any]:
|
|
113
115
|
# cadl file doesn't have to be relative to output folder
|
|
114
|
-
with open(self.options["cadl_file"], "r") as fd:
|
|
116
|
+
with open(self.options["cadl_file"], "r", encoding="utf-8-sig") as fd:
|
|
115
117
|
return yaml.safe_load(fd.read())
|
|
116
118
|
|
|
117
119
|
def write_yaml(self, yaml_string: str) -> None:
|
|
118
|
-
with open(self.options["cadl_file"], "w") as fd:
|
|
120
|
+
with open(self.options["cadl_file"], "w", encoding="utf-8-sig") as fd:
|
|
119
121
|
fd.write(yaml_string)
|
|
120
122
|
|
|
121
123
|
def process(self) -> bool:
|
package/autorest/_utils.py
CHANGED
|
@@ -77,7 +77,13 @@ def parse_args(
|
|
|
77
77
|
return value
|
|
78
78
|
|
|
79
79
|
unknown_args_ret = {
|
|
80
|
-
ua.strip("--").split("=")[
|
|
80
|
+
ua.strip("--").split("=", maxsplit=1)[ # pylint: disable=bad-str-strip-call
|
|
81
|
+
0
|
|
82
|
+
]: _get_value(
|
|
83
|
+
ua.strip("--").split("=", maxsplit=1)[ # pylint: disable=bad-str-strip-call
|
|
84
|
+
1
|
|
85
|
+
]
|
|
86
|
+
)
|
|
81
87
|
for ua in unknown_args
|
|
82
88
|
}
|
|
83
89
|
return args, unknown_args_ret
|
|
@@ -31,7 +31,12 @@ class BlackScriptPlugin(Plugin): # pylint: disable=abstract-method
|
|
|
31
31
|
|
|
32
32
|
def process(self) -> bool:
|
|
33
33
|
# apply format_file on every file in the output folder
|
|
34
|
-
list(
|
|
34
|
+
list(
|
|
35
|
+
map(
|
|
36
|
+
self.format_file,
|
|
37
|
+
[Path(f) for f in self.list_file() if "__pycache__" not in f],
|
|
38
|
+
)
|
|
39
|
+
)
|
|
35
40
|
return True
|
|
36
41
|
|
|
37
42
|
def format_file(self, file: Path) -> None:
|
|
@@ -186,7 +186,7 @@ class CodeGenerator(Plugin):
|
|
|
186
186
|
|
|
187
187
|
def get_yaml(self) -> Dict[str, Any]:
|
|
188
188
|
# cadl file doesn't have to be relative to output folder
|
|
189
|
-
with open(self.options["cadl_file"], "r") as fd:
|
|
189
|
+
with open(self.options["cadl_file"], "r", encoding="utf-8-sig") as fd:
|
|
190
190
|
return yaml.safe_load(fd.read())
|
|
191
191
|
|
|
192
192
|
def get_serializer(self, code_model: CodeModel):
|
|
@@ -9,7 +9,7 @@ from .base import BaseModel
|
|
|
9
9
|
from .base_builder import BaseBuilder
|
|
10
10
|
from .code_model import CodeModel
|
|
11
11
|
from .client import Client
|
|
12
|
-
from .model_type import ModelType
|
|
12
|
+
from .model_type import ModelType, JSONModelType, DPGModelType, MsrestModelType
|
|
13
13
|
from .dictionary_type import DictionaryType
|
|
14
14
|
from .list_type import ListType
|
|
15
15
|
from .combined_type import CombinedType
|
|
@@ -156,7 +156,13 @@ def build_type(yaml_data: Dict[str, Any], code_model: CodeModel) -> BaseType:
|
|
|
156
156
|
pass
|
|
157
157
|
if yaml_data["type"] == "model":
|
|
158
158
|
# need to special case model to avoid recursion
|
|
159
|
-
|
|
159
|
+
if yaml_data["base"] == "json" or not code_model.options["models_mode"]:
|
|
160
|
+
model_type = JSONModelType
|
|
161
|
+
elif yaml_data["base"] == "dpg":
|
|
162
|
+
model_type = DPGModelType # type: ignore
|
|
163
|
+
else:
|
|
164
|
+
model_type = MsrestModelType # type: ignore
|
|
165
|
+
response = model_type(yaml_data, code_model)
|
|
160
166
|
code_model.types_map[yaml_id] = response
|
|
161
167
|
response.fill_instance_from_yaml(yaml_data, code_model)
|
|
162
168
|
else:
|
|
@@ -52,9 +52,7 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
52
52
|
) -> "BaseType":
|
|
53
53
|
return cls(yaml_data=yaml_data, code_model=code_model)
|
|
54
54
|
|
|
55
|
-
def imports( # pylint: disable=
|
|
56
|
-
self, **kwargs # pylint: disable=unused-argument
|
|
57
|
-
) -> FileImport:
|
|
55
|
+
def imports(self, **kwargs) -> FileImport: # pylint: disable=unused-argument
|
|
58
56
|
return FileImport()
|
|
59
57
|
|
|
60
58
|
def imports_for_multiapi(self, **kwargs: Any) -> FileImport:
|
|
@@ -91,7 +89,7 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
91
89
|
if self.xml_metadata.get("namespace", False):
|
|
92
90
|
attrs_list.append(f"'ns': '{self.xml_metadata['namespace']}'")
|
|
93
91
|
if self.xml_metadata.get("text"):
|
|
94
|
-
attrs_list.append(
|
|
92
|
+
attrs_list.append("'text': True")
|
|
95
93
|
return ", ".join(attrs_list)
|
|
96
94
|
|
|
97
95
|
@property
|
|
@@ -106,7 +104,6 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
106
104
|
If list: '[str]'
|
|
107
105
|
If dict: '{str}'
|
|
108
106
|
"""
|
|
109
|
-
...
|
|
110
107
|
raise NotImplementedError()
|
|
111
108
|
|
|
112
109
|
@property
|
|
@@ -121,12 +118,10 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
121
118
|
@abstractmethod
|
|
122
119
|
def description(self, *, is_operation_file: bool) -> str:
|
|
123
120
|
"""The description"""
|
|
124
|
-
...
|
|
125
121
|
|
|
126
122
|
@abstractmethod
|
|
127
123
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
128
124
|
"""The names used in rtype documentation"""
|
|
129
|
-
...
|
|
130
125
|
|
|
131
126
|
@abstractmethod
|
|
132
127
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
@@ -134,7 +129,6 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
134
129
|
|
|
135
130
|
Special case for enum, for instance: 'str or ~namespace.EnumName'
|
|
136
131
|
"""
|
|
137
|
-
...
|
|
138
132
|
|
|
139
133
|
@abstractmethod
|
|
140
134
|
def type_annotation(self, **kwargs: Any) -> str:
|
|
@@ -142,7 +136,6 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
142
136
|
|
|
143
137
|
Special case for enum, for instance: Union[str, "EnumName"]
|
|
144
138
|
"""
|
|
145
|
-
...
|
|
146
139
|
|
|
147
140
|
@property
|
|
148
141
|
def validation(self) -> Optional[Dict[str, Any]]:
|
|
@@ -153,7 +146,7 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
153
146
|
"""
|
|
154
147
|
return None
|
|
155
148
|
|
|
156
|
-
def get_declaration(self, value: Any) -> str:
|
|
149
|
+
def get_declaration(self, value: Any) -> str:
|
|
157
150
|
"""Return the current value from YAML as a Python string that represents the constant.
|
|
158
151
|
|
|
159
152
|
Example, if schema is "bytearray" and value is "foo",
|
|
@@ -175,9 +168,8 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
175
168
|
description: Optional[str] = None,
|
|
176
169
|
) -> Any:
|
|
177
170
|
"""Template of what this schema would look like as JSON input"""
|
|
178
|
-
...
|
|
179
171
|
|
|
180
|
-
def get_polymorphic_subtypes(
|
|
172
|
+
def get_polymorphic_subtypes(
|
|
181
173
|
self, polymorphic_subtypes: List["ModelType"] # pylint: disable=unused-argument
|
|
182
174
|
) -> None:
|
|
183
175
|
return None
|
|
@@ -186,7 +178,6 @@ class BaseType(BaseModel, ABC): # pylint: disable=too-many-public-methods
|
|
|
186
178
|
@abstractmethod
|
|
187
179
|
def instance_check_template(self) -> str:
|
|
188
180
|
"""Template of what an instance check of a variable for this type would look like"""
|
|
189
|
-
...
|
|
190
181
|
|
|
191
182
|
@property
|
|
192
183
|
def serialization_constraints(self) -> List[str]:
|
|
@@ -155,8 +155,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
155
155
|
for rb in self.request_builders
|
|
156
156
|
if id(rb.yaml_data) == request_builder_id
|
|
157
157
|
)
|
|
158
|
-
except StopIteration:
|
|
159
|
-
raise KeyError(
|
|
158
|
+
except StopIteration as exc:
|
|
159
|
+
raise KeyError(
|
|
160
|
+
f"No request builder with id {request_builder_id} found."
|
|
161
|
+
) from exc
|
|
160
162
|
|
|
161
163
|
def _imports_shared(self, async_mode: bool) -> FileImport:
|
|
162
164
|
file_import = FileImport()
|
|
@@ -207,20 +209,16 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
207
209
|
def has_lro_operations(self) -> bool:
|
|
208
210
|
"""Are there any LRO operations in this SDK?"""
|
|
209
211
|
return any(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
for operation in operation_group.operations
|
|
214
|
-
]
|
|
212
|
+
operation.operation_type in ("lro", "lropaging")
|
|
213
|
+
for operation_group in self.operation_groups
|
|
214
|
+
for operation in operation_group.operations
|
|
215
215
|
)
|
|
216
216
|
|
|
217
217
|
@property
|
|
218
218
|
def has_operations(self) -> bool:
|
|
219
219
|
return any(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
for operation_group in self.operation_groups
|
|
223
|
-
]
|
|
220
|
+
bool(operation_group.operations)
|
|
221
|
+
for operation_group in self.operation_groups
|
|
224
222
|
)
|
|
225
223
|
|
|
226
224
|
def format_lro_operations(self) -> None:
|
|
@@ -172,8 +172,8 @@ class CodeModel: # pylint: disable=too-many-public-methods
|
|
|
172
172
|
"""
|
|
173
173
|
try:
|
|
174
174
|
return next(type for id, type in self.types_map.items() if id == schema_id)
|
|
175
|
-
except StopIteration:
|
|
176
|
-
raise KeyError(f"Couldn't find schema with id {schema_id}")
|
|
175
|
+
except StopIteration as exc:
|
|
176
|
+
raise KeyError(f"Couldn't find schema with id {schema_id}") from exc
|
|
177
177
|
|
|
178
178
|
@property
|
|
179
179
|
def model_types(self) -> List[ModelType]:
|
|
@@ -190,7 +190,7 @@ class CodeModel: # pylint: disable=too-many-public-methods
|
|
|
190
190
|
|
|
191
191
|
@property
|
|
192
192
|
def public_model_types(self) -> List[ModelType]:
|
|
193
|
-
return [m for m in self.model_types if m.is_public]
|
|
193
|
+
return [m for m in self.model_types if m.is_public and not m.base == "json"]
|
|
194
194
|
|
|
195
195
|
@property
|
|
196
196
|
def enums(self) -> List[EnumType]:
|
|
@@ -79,9 +79,10 @@ class CombinedType(BaseType):
|
|
|
79
79
|
client_default_value_declaration: Optional[str] = None,
|
|
80
80
|
description: Optional[str] = None,
|
|
81
81
|
) -> Any:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
return self.types[0].get_json_template_representation(
|
|
83
|
+
optional=optional,
|
|
84
|
+
client_default_value_declaration=client_default_value_declaration,
|
|
85
|
+
description=description,
|
|
85
86
|
)
|
|
86
87
|
|
|
87
88
|
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
@@ -38,7 +38,6 @@ class _CredentialPolicyBaseType:
|
|
|
38
38
|
"""
|
|
39
39
|
How to call this credential policy. Used to initialize the credential policy in the config file.
|
|
40
40
|
"""
|
|
41
|
-
...
|
|
42
41
|
|
|
43
42
|
|
|
44
43
|
class BearerTokenCredentialPolicyType(_CredentialPolicyBaseType):
|
|
@@ -158,17 +157,17 @@ class TokenCredentialType(
|
|
|
158
157
|
):
|
|
159
158
|
"""Type of a token credential. Used by BearerAuth and ARMChallenge policies"""
|
|
160
159
|
|
|
161
|
-
def type_annotation(self, **kwargs: Any) -> str:
|
|
160
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
162
161
|
if kwargs.get("async_mode"):
|
|
163
162
|
return '"AsyncTokenCredential"'
|
|
164
163
|
return '"TokenCredential"'
|
|
165
164
|
|
|
166
|
-
def docstring_type(self, **kwargs: Any) -> str:
|
|
165
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
167
166
|
if kwargs.get("async_mode"):
|
|
168
167
|
return "~azure.core.credentials_async.AsyncTokenCredential"
|
|
169
168
|
return "~azure.core.credentials.TokenCredential"
|
|
170
169
|
|
|
171
|
-
def imports(self, **kwargs: Any) -> FileImport:
|
|
170
|
+
def imports(self, **kwargs: Any) -> FileImport:
|
|
172
171
|
file_import = FileImport()
|
|
173
172
|
if kwargs.get("async_mode"):
|
|
174
173
|
file_import.add_submodule_import(
|
|
@@ -188,7 +187,7 @@ class TokenCredentialType(
|
|
|
188
187
|
|
|
189
188
|
@property
|
|
190
189
|
def instance_check_template(self) -> str:
|
|
191
|
-
return "hasattr({}, get_token)"
|
|
190
|
+
return "hasattr({}, 'get_token')"
|
|
192
191
|
|
|
193
192
|
|
|
194
193
|
class AzureKeyCredentialType(
|
|
@@ -197,23 +196,17 @@ class AzureKeyCredentialType(
|
|
|
197
196
|
):
|
|
198
197
|
"""Type for an AzureKeyCredential"""
|
|
199
198
|
|
|
200
|
-
def docstring_type( # pylint: disable=
|
|
201
|
-
self, **kwargs: Any # pylint: disable=unused-argument
|
|
202
|
-
) -> str:
|
|
199
|
+
def docstring_type(self, **kwargs: Any) -> str: # pylint: disable=unused-argument
|
|
203
200
|
return "~azure.core.credentials.AzureKeyCredential"
|
|
204
201
|
|
|
205
|
-
def type_annotation( # pylint: disable=
|
|
206
|
-
self, **kwargs: Any # pylint: disable=unused-argument
|
|
207
|
-
) -> str:
|
|
202
|
+
def type_annotation(self, **kwargs: Any) -> str: # pylint: disable=unused-argument
|
|
208
203
|
return "AzureKeyCredential"
|
|
209
204
|
|
|
210
205
|
@property
|
|
211
206
|
def instance_check_template(self) -> str:
|
|
212
207
|
return "isinstance({}, AzureKeyCredential)"
|
|
213
208
|
|
|
214
|
-
def imports( # pylint: disable=
|
|
215
|
-
self, **kwargs: Any # pylint: disable=unused-argument
|
|
216
|
-
) -> FileImport:
|
|
209
|
+
def imports(self, **kwargs: Any) -> FileImport: # pylint: disable=unused-argument
|
|
217
210
|
file_import = FileImport()
|
|
218
211
|
file_import.add_submodule_import(
|
|
219
212
|
"azure.core.credentials",
|
|
@@ -73,7 +73,7 @@ class DictionaryType(BaseType):
|
|
|
73
73
|
description: Optional[str] = None,
|
|
74
74
|
) -> Any:
|
|
75
75
|
return {
|
|
76
|
-
|
|
76
|
+
'"str"': self.element_type.get_json_template_representation(
|
|
77
77
|
optional=optional,
|
|
78
78
|
client_default_value_declaration=client_default_value_declaration,
|
|
79
79
|
description=description,
|
|
@@ -228,7 +228,7 @@ class FileImport:
|
|
|
228
228
|
],
|
|
229
229
|
],
|
|
230
230
|
],
|
|
231
|
-
] =
|
|
231
|
+
] = {}
|
|
232
232
|
for i in self.imports:
|
|
233
233
|
name_import: Optional[
|
|
234
234
|
Union[
|
|
@@ -248,8 +248,8 @@ class FileImport:
|
|
|
248
248
|
name_import = (i.submodule_name, i.alias)
|
|
249
249
|
else:
|
|
250
250
|
name_import = i.submodule_name
|
|
251
|
-
retval.setdefault(i.typing_section,
|
|
252
|
-
i.import_type,
|
|
251
|
+
retval.setdefault(i.typing_section, {}).setdefault(
|
|
252
|
+
i.import_type, {}
|
|
253
253
|
).setdefault(i.module_name, set()).add(name_import)
|
|
254
254
|
return retval
|
|
255
255
|
|
|
@@ -73,11 +73,11 @@ class LROOperationBase(OperationBase[LROResponseType]):
|
|
|
73
73
|
response = next(
|
|
74
74
|
r for r in responses_with_bodies if 200 in r.status_codes
|
|
75
75
|
)
|
|
76
|
-
except StopIteration:
|
|
76
|
+
except StopIteration as exc:
|
|
77
77
|
raise ValueError(
|
|
78
|
-
|
|
78
|
+
"Your swagger is invalid because you have multiple response schemas for LRO"
|
|
79
79
|
+ f" method {self.name} and none of them have a 200 status code."
|
|
80
|
-
)
|
|
80
|
+
) from exc
|
|
81
81
|
|
|
82
82
|
elif num_response_schemas:
|
|
83
83
|
response = responses_with_bodies[0]
|
|
@@ -134,8 +134,8 @@ class LROOperationBase(OperationBase[LROResponseType]):
|
|
|
134
134
|
return file_import
|
|
135
135
|
if async_mode:
|
|
136
136
|
file_import.add_submodule_import(
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
"azure.core.tracing.decorator_async",
|
|
138
|
+
"distributed_trace_async",
|
|
139
139
|
ImportType.AZURECORE,
|
|
140
140
|
)
|
|
141
141
|
file_import.add_submodule_import(
|
|
@@ -5,13 +5,20 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from collections import OrderedDict
|
|
7
7
|
from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
|
|
8
|
-
|
|
8
|
+
import sys
|
|
9
9
|
from autorest.codegen.models.utils import add_to_pylint_disable
|
|
10
10
|
from .base import BaseType
|
|
11
11
|
from .constant_type import ConstantType
|
|
12
12
|
from .property import Property
|
|
13
13
|
from .imports import FileImport, ImportType, TypingSection
|
|
14
14
|
|
|
15
|
+
|
|
16
|
+
if sys.version_info >= (3, 8):
|
|
17
|
+
from typing import Literal # pylint: disable=no-name-in-module, ungrouped-imports
|
|
18
|
+
else:
|
|
19
|
+
from typing_extensions import Literal # type: ignore # pylint: disable=ungrouped-imports
|
|
20
|
+
|
|
21
|
+
|
|
15
22
|
if TYPE_CHECKING:
|
|
16
23
|
from .code_model import CodeModel
|
|
17
24
|
|
|
@@ -33,7 +40,7 @@ def _get_properties(type: "ModelType", properties: List[Property]) -> List[Prope
|
|
|
33
40
|
return properties
|
|
34
41
|
|
|
35
42
|
|
|
36
|
-
class ModelType(
|
|
43
|
+
class ModelType( # pylint: disable=abstract-method
|
|
37
44
|
BaseType
|
|
38
45
|
): # pylint: disable=too-many-instance-attributes, too-many-public-methods
|
|
39
46
|
"""Represents a class ready to be serialized in Python.
|
|
@@ -44,6 +51,8 @@ class ModelType(
|
|
|
44
51
|
:type properties: dict(str, str)
|
|
45
52
|
"""
|
|
46
53
|
|
|
54
|
+
base: Literal["msrest", "dpg", "json"]
|
|
55
|
+
|
|
47
56
|
def __init__(
|
|
48
57
|
self,
|
|
49
58
|
yaml_data: Dict[str, Any],
|
|
@@ -72,15 +81,6 @@ class ModelType(
|
|
|
72
81
|
def is_xml(self) -> bool:
|
|
73
82
|
return self.yaml_data.get("isXml", False)
|
|
74
83
|
|
|
75
|
-
@property
|
|
76
|
-
def serialization_type(self) -> str:
|
|
77
|
-
if self.code_model.options["models_mode"] == "msrest":
|
|
78
|
-
private_model_path = f"_models.{self.code_model.models_filename}."
|
|
79
|
-
return f"{'' if self.is_public else private_model_path}{self.name}"
|
|
80
|
-
if self.code_model.options["models_mode"] == "dpg":
|
|
81
|
-
return f"{'' if self.is_public else '_models.'}_models.{self.name}"
|
|
82
|
-
return "object"
|
|
83
|
-
|
|
84
84
|
@property
|
|
85
85
|
def msrest_deserialization_key(self) -> str:
|
|
86
86
|
return self.name
|
|
@@ -89,28 +89,9 @@ class ModelType(
|
|
|
89
89
|
def is_polymorphic(self) -> bool:
|
|
90
90
|
return any(p.is_polymorphic for p in self.properties)
|
|
91
91
|
|
|
92
|
-
def type_annotation(self, **kwargs: Any) -> str:
|
|
93
|
-
if self.code_model.options["models_mode"]:
|
|
94
|
-
is_operation_file = kwargs.pop("is_operation_file", False)
|
|
95
|
-
retval = f"_models.{self.name}"
|
|
96
|
-
if not self.is_public:
|
|
97
|
-
retval = f"{self.code_model.models_filename}.{retval}"
|
|
98
|
-
return retval if is_operation_file else f'"{retval}"'
|
|
99
|
-
return "ET.Element" if self.is_xml else "JSON"
|
|
100
|
-
|
|
101
|
-
def docstring_type(self, **kwargs: Any) -> str:
|
|
102
|
-
if self.code_model.options["models_mode"]:
|
|
103
|
-
return f"~{self.code_model.namespace}.models.{self.name}"
|
|
104
|
-
return "ET.Element" if self.is_xml else "JSON"
|
|
105
|
-
|
|
106
92
|
def description(self, *, is_operation_file: bool = False) -> str:
|
|
107
93
|
return "" if is_operation_file else self.yaml_data.get("description", self.name)
|
|
108
94
|
|
|
109
|
-
def docstring_text(self, **kwargs: Any) -> str:
|
|
110
|
-
if self.code_model.options["models_mode"]:
|
|
111
|
-
return self.name
|
|
112
|
-
return "XML Element" if self.is_xml else "JSON object"
|
|
113
|
-
|
|
114
95
|
def get_declaration(self, value: Any) -> str:
|
|
115
96
|
return f"{self.name}()"
|
|
116
97
|
|
|
@@ -252,15 +233,6 @@ class ModelType(
|
|
|
252
233
|
except StopIteration:
|
|
253
234
|
return None
|
|
254
235
|
|
|
255
|
-
@property
|
|
256
|
-
def instance_check_template(self) -> str:
|
|
257
|
-
models_mode = self.code_model.options["models_mode"]
|
|
258
|
-
if models_mode == "msrest":
|
|
259
|
-
return "isinstance({}, msrest.Model)"
|
|
260
|
-
if models_mode == "dpg":
|
|
261
|
-
return "isinstance({}, _model_base.Model)"
|
|
262
|
-
return "isinstance({}, MutableMapping)"
|
|
263
|
-
|
|
264
236
|
@property
|
|
265
237
|
def pylint_disable(self) -> str:
|
|
266
238
|
retval: str = ""
|
|
@@ -275,16 +247,29 @@ class ModelType(
|
|
|
275
247
|
retval = add_to_pylint_disable(retval, "too-many-locals")
|
|
276
248
|
return retval
|
|
277
249
|
|
|
250
|
+
|
|
251
|
+
class JSONModelType(ModelType):
|
|
252
|
+
base = "json"
|
|
253
|
+
|
|
254
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
255
|
+
return "ET.Element" if self.is_xml else "JSON"
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def serialization_type(self) -> str:
|
|
259
|
+
return "object"
|
|
260
|
+
|
|
261
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
262
|
+
return "ET.Element" if self.is_xml else "JSON"
|
|
263
|
+
|
|
264
|
+
def docstring_text(self, **kwargs: Any) -> str:
|
|
265
|
+
return "XML Element" if self.is_xml else "JSON object"
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def instance_check_template(self) -> str:
|
|
269
|
+
return "isinstance({}, MutableMapping)"
|
|
270
|
+
|
|
278
271
|
def imports(self, **kwargs: Any) -> FileImport:
|
|
279
272
|
file_import = FileImport()
|
|
280
|
-
relative_path = kwargs.pop("relative_path", None)
|
|
281
|
-
if self.code_model.options["models_mode"] and relative_path:
|
|
282
|
-
# add import for models in operations file
|
|
283
|
-
file_import.add_submodule_import(
|
|
284
|
-
relative_path, "models", ImportType.LOCAL, alias="_models"
|
|
285
|
-
)
|
|
286
|
-
if self.code_model.options["models_mode"] == "msrest":
|
|
287
|
-
return file_import
|
|
288
273
|
file_import.add_submodule_import(
|
|
289
274
|
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
290
275
|
)
|
|
@@ -294,3 +279,60 @@ class ModelType(
|
|
|
294
279
|
"xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
|
|
295
280
|
)
|
|
296
281
|
return file_import
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class GeneratedModelType(ModelType): # pylint: disable=abstract-method
|
|
285
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
286
|
+
is_operation_file = kwargs.pop("is_operation_file", False)
|
|
287
|
+
retval = f"_models.{self.name}"
|
|
288
|
+
if not self.is_public:
|
|
289
|
+
retval = f"{self.code_model.models_filename}.{retval}"
|
|
290
|
+
return retval if is_operation_file else f'"{retval}"'
|
|
291
|
+
|
|
292
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
293
|
+
return f"~{self.code_model.namespace}.models.{self.name}"
|
|
294
|
+
|
|
295
|
+
def docstring_text(self, **kwargs: Any) -> str:
|
|
296
|
+
return self.name
|
|
297
|
+
|
|
298
|
+
def imports(self, **kwargs: Any) -> FileImport:
|
|
299
|
+
file_import = super().imports(**kwargs)
|
|
300
|
+
relative_path = kwargs.pop("relative_path", None)
|
|
301
|
+
if relative_path:
|
|
302
|
+
# add import for models in operations file
|
|
303
|
+
file_import.add_submodule_import(
|
|
304
|
+
relative_path, "models", ImportType.LOCAL, alias="_models"
|
|
305
|
+
)
|
|
306
|
+
return file_import
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class MsrestModelType(GeneratedModelType):
|
|
310
|
+
base = "msrest"
|
|
311
|
+
|
|
312
|
+
@property
|
|
313
|
+
def serialization_type(self) -> str:
|
|
314
|
+
private_model_path = f"_models.{self.code_model.models_filename}."
|
|
315
|
+
return f"{'' if self.is_public else private_model_path}{self.name}"
|
|
316
|
+
|
|
317
|
+
@property
|
|
318
|
+
def instance_check_template(self) -> str:
|
|
319
|
+
return "isinstance({}, msrest.Model)"
|
|
320
|
+
|
|
321
|
+
def imports(self, **kwargs: Any) -> FileImport:
|
|
322
|
+
file_import = super().imports(**kwargs)
|
|
323
|
+
file_import.add_submodule_import(
|
|
324
|
+
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
325
|
+
)
|
|
326
|
+
return file_import
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
class DPGModelType(GeneratedModelType):
|
|
330
|
+
base = "dpg"
|
|
331
|
+
|
|
332
|
+
@property
|
|
333
|
+
def serialization_type(self) -> str:
|
|
334
|
+
return f"{'' if self.is_public else '_models.'}_models.{self.name}"
|
|
335
|
+
|
|
336
|
+
@property
|
|
337
|
+
def instance_check_template(self) -> str:
|
|
338
|
+
return "isinstance({}, _model_base.Model)"
|
|
@@ -394,8 +394,8 @@ class OperationBase( # pylint: disable=too-many-public-methods
|
|
|
394
394
|
)
|
|
395
395
|
if self.code_model.options["tracing"] and self.want_tracing and not async_mode:
|
|
396
396
|
file_import.add_submodule_import(
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
"azure.core.tracing.decorator",
|
|
398
|
+
"distributed_trace",
|
|
399
399
|
ImportType.AZURECORE,
|
|
400
400
|
)
|
|
401
401
|
file_import.merge(
|
|
@@ -410,10 +410,10 @@ class OperationBase( # pylint: disable=too-many-public-methods
|
|
|
410
410
|
) -> ResponseType:
|
|
411
411
|
try:
|
|
412
412
|
return next(r for r in self.responses if status_code in r.status_codes)
|
|
413
|
-
except StopIteration:
|
|
413
|
+
except StopIteration as exc:
|
|
414
414
|
raise ValueError(
|
|
415
415
|
f"Incorrect status code {status_code}, operation {self.name}"
|
|
416
|
-
)
|
|
416
|
+
) from exc
|
|
417
417
|
|
|
418
418
|
@property
|
|
419
419
|
def success_status_codes(self) -> List[Union[str, int]]:
|
|
@@ -431,7 +431,7 @@ class OperationBase( # pylint: disable=too-many-public-methods
|
|
|
431
431
|
basename == "operations"
|
|
432
432
|
or self.code_model.options["combine_operation_files"]
|
|
433
433
|
):
|
|
434
|
-
return
|
|
434
|
+
return "_operations"
|
|
435
435
|
return f"_{basename}_operations"
|
|
436
436
|
|
|
437
437
|
@property
|
|
@@ -481,8 +481,8 @@ class Operation(OperationBase[Response]):
|
|
|
481
481
|
return file_import
|
|
482
482
|
if async_mode:
|
|
483
483
|
file_import.add_submodule_import(
|
|
484
|
-
|
|
485
|
-
|
|
484
|
+
"azure.core.tracing.decorator_async",
|
|
485
|
+
"distributed_trace_async",
|
|
486
486
|
ImportType.AZURECORE,
|
|
487
487
|
)
|
|
488
488
|
if (
|
|
@@ -499,7 +499,7 @@ class Operation(OperationBase[Response]):
|
|
|
499
499
|
)
|
|
500
500
|
file_import.add_import("json", ImportType.STDLIB)
|
|
501
501
|
if self.default_error_deserialization or any(
|
|
502
|
-
|
|
502
|
+
r.type for r in self.responses
|
|
503
503
|
):
|
|
504
504
|
file_import.add_submodule_import(
|
|
505
505
|
f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL
|
|
@@ -76,7 +76,9 @@ class OperationGroup(BaseModel):
|
|
|
76
76
|
def imports(self, async_mode: bool) -> FileImport:
|
|
77
77
|
file_import = FileImport()
|
|
78
78
|
|
|
79
|
-
relative_path = "..." if async_mode else ".."
|
|
79
|
+
relative_path = ("..." if async_mode else "..") + (
|
|
80
|
+
"." if self.client.is_subclient else ""
|
|
81
|
+
)
|
|
80
82
|
for operation in self.operations:
|
|
81
83
|
file_import.merge(
|
|
82
84
|
operation.imports(async_mode, relative_path=relative_path)
|
|
@@ -74,10 +74,10 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
74
74
|
for p in cast(ModelType, response.type).properties
|
|
75
75
|
if p.rest_api_name == rest_api_name
|
|
76
76
|
)
|
|
77
|
-
except StopIteration:
|
|
77
|
+
except StopIteration as exc:
|
|
78
78
|
raise ValueError(
|
|
79
79
|
f"Can't find a matching property in response for {rest_api_name}"
|
|
80
|
-
)
|
|
80
|
+
) from exc
|
|
81
81
|
|
|
82
82
|
def get_pager(self, async_mode: bool) -> str:
|
|
83
83
|
return self.responses[0].get_pager(async_mode)
|