@autorest/python 5.16.0 → 5.17.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 +43 -3
- package/README.md +30 -4
- package/autorest/__init__.py +1 -1
- package/autorest/codegen/__init__.py +48 -209
- 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} +56 -40
- package/autorest/codegen/models/client.py +157 -48
- package/autorest/codegen/models/code_model.py +108 -254
- 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_schema.py → dictionary_type.py} +41 -31
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +23 -0
- package/autorest/codegen/models/list_type.py +134 -0
- package/autorest/codegen/models/lro_operation.py +77 -156
- package/autorest/codegen/models/lro_paging_operation.py +28 -11
- package/autorest/codegen/models/model_type.py +239 -0
- package/autorest/codegen/models/operation.py +303 -269
- package/autorest/codegen/models/operation_group.py +48 -89
- package/autorest/codegen/models/paging_operation.py +80 -123
- package/autorest/codegen/models/parameter.py +289 -396
- package/autorest/codegen/models/parameter_list.py +348 -360
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +109 -139
- package/autorest/codegen/models/request_builder.py +105 -88
- 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 +46 -37
- package/autorest/codegen/serializers/builder_serializer.py +604 -1146
- package/autorest/codegen/serializers/client_serializer.py +83 -88
- package/autorest/codegen/serializers/general_serializer.py +5 -64
- 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 +40 -32
- 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 +4 -13
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/request_builders_serializer.py +12 -29
- package/autorest/codegen/serializers/utils.py +0 -142
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -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 +7 -7
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
- package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
- package/autorest/codegen/templates/request_builder.py.jinja2 +13 -11
- package/autorest/codegen/templates/setup.py.jinja2 +9 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
- package/autorest/jsonrpc/server.py +15 -3
- package/autorest/m4reformatter/__init__.py +1108 -0
- package/autorest/multiapi/models/code_model.py +1 -1
- package/autorest/multiapi/serializers/__init__.py +4 -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 +3 -3
- 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 +209 -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/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
|
@@ -3,24 +3,15 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
import
|
|
7
|
-
from typing import cast, List, Dict, Optional, Any, Set
|
|
6
|
+
from typing import List, Dict, Optional, Any, Set, Union
|
|
8
7
|
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
8
|
+
from .base_type import BaseType
|
|
9
|
+
from .enum_type import EnumType
|
|
10
|
+
from .model_type import ModelType
|
|
12
11
|
from .operation_group import OperationGroup
|
|
13
|
-
from .
|
|
14
|
-
from .
|
|
15
|
-
from .paging_operation import PagingOperation
|
|
12
|
+
from .client import Client, Config
|
|
13
|
+
from .request_builder import OverloadedRequestBuilder, RequestBuilder
|
|
16
14
|
from .parameter import Parameter
|
|
17
|
-
from .client import Client
|
|
18
|
-
from .parameter_list import GlobalParameterList
|
|
19
|
-
from .property import Property
|
|
20
|
-
from .request_builder import RequestBuilder
|
|
21
|
-
from .credential_model import CredentialModel
|
|
22
|
-
|
|
23
|
-
_LOGGER = logging.getLogger(__name__)
|
|
24
15
|
|
|
25
16
|
|
|
26
17
|
class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
|
|
@@ -34,21 +25,19 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
34
25
|
:param str description: The description of the client
|
|
35
26
|
:param str namespace: The namespace of our module
|
|
36
27
|
:param schemas: The list of schemas we are going to serialize in the models files. Maps their yaml
|
|
37
|
-
id to our created
|
|
38
|
-
:type schemas: dict[int, ~autorest.models.
|
|
28
|
+
id to our created ModelType.
|
|
29
|
+
:type schemas: dict[int, ~autorest.models.ModelType]
|
|
39
30
|
:param sorted_schemas: Our schemas in order by inheritance and alphabet
|
|
40
|
-
:type sorted_schemas: list[~autorest.models.
|
|
41
|
-
:param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created
|
|
42
|
-
:type enums: Dict[int, ~autorest.models.
|
|
31
|
+
:type sorted_schemas: list[~autorest.models.ModelType]
|
|
32
|
+
:param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumType.
|
|
33
|
+
:type enums: Dict[int, ~autorest.models.EnumType]
|
|
43
34
|
:param primitives: List of schemas we've created that are not EnumSchemas or ObjectSchemas. Maps their
|
|
44
35
|
yaml id to our created schemas.
|
|
45
|
-
:type primitives: Dict[int, ~autorest.models.
|
|
36
|
+
:type primitives: Dict[int, ~autorest.models.BaseType]
|
|
46
37
|
:param operation_groups: The operation groups we are going to serialize
|
|
47
38
|
:type operation_groups: list[~autorest.models.OperationGroup]
|
|
48
39
|
:param package_dependency: All the dependencies needed in setup.py
|
|
49
40
|
:type package_dependency: Dict[str, str]
|
|
50
|
-
:param credential_model: The class contains all the credential info
|
|
51
|
-
:type credential_model: CredentialMode
|
|
52
41
|
"""
|
|
53
42
|
|
|
54
43
|
def __init__(
|
|
@@ -57,53 +46,60 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
57
46
|
options: Dict[str, Any],
|
|
58
47
|
) -> None:
|
|
59
48
|
self.yaml_data = yaml_data
|
|
60
|
-
self.send_request_name = (
|
|
61
|
-
"send_request" if options["show_send_request"] else "_send_request"
|
|
62
|
-
)
|
|
63
|
-
self.rest_layer_name = (
|
|
64
|
-
"rest" if options["builders_visibility"] == "public" else "_rest"
|
|
65
|
-
)
|
|
66
49
|
self.options = options
|
|
67
|
-
self.
|
|
68
|
-
self.class_name: str = ""
|
|
69
|
-
self.description: str = ""
|
|
70
|
-
self.namespace: str = ""
|
|
71
|
-
self.namespace_path: str = ""
|
|
72
|
-
self.schemas: Dict[int, ObjectSchema] = {}
|
|
73
|
-
self.sorted_schemas: List[ObjectSchema] = []
|
|
74
|
-
self.enums: Dict[int, EnumSchema] = {}
|
|
75
|
-
self.primitives: Dict[int, BaseSchema] = {}
|
|
50
|
+
self.types_map: Dict[int, BaseType] = {} # map yaml id to schema
|
|
76
51
|
self.operation_groups: List[OperationGroup] = []
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
self.
|
|
80
|
-
self.request_builders: List[
|
|
52
|
+
self._model_types: List[ModelType] = []
|
|
53
|
+
self._client: Optional[Client] = None
|
|
54
|
+
self._config: Optional[Config] = None
|
|
55
|
+
self.request_builders: List[
|
|
56
|
+
Union[RequestBuilder, OverloadedRequestBuilder]
|
|
57
|
+
] = []
|
|
81
58
|
self.package_dependency: Dict[str, str] = {}
|
|
82
|
-
self.
|
|
83
|
-
|
|
84
|
-
@property
|
|
85
|
-
def global_parameters(self) -> GlobalParameterList:
|
|
86
|
-
return self.service_client.parameters
|
|
59
|
+
self.namespace: str = yaml_data["client"]["namespace"].lower()
|
|
60
|
+
self.module_name: str = self.yaml_data["client"]["moduleName"]
|
|
87
61
|
|
|
88
|
-
|
|
89
|
-
def global_parameters(self, val: GlobalParameterList) -> None:
|
|
90
|
-
self.service_client.parameters = val
|
|
91
|
-
|
|
92
|
-
def lookup_schema(self, schema_id: int) -> BaseSchema:
|
|
62
|
+
def lookup_type(self, schema_id: int) -> BaseType:
|
|
93
63
|
"""Looks to see if the schema has already been created.
|
|
94
64
|
|
|
95
65
|
:param int schema_id: The yaml id of the schema
|
|
96
66
|
:return: If created, we return the created schema, otherwise, we throw.
|
|
97
|
-
:rtype: ~autorest.models.
|
|
67
|
+
:rtype: ~autorest.models.BaseType
|
|
98
68
|
:raises: KeyError if schema is not found
|
|
99
69
|
"""
|
|
100
|
-
|
|
101
|
-
for
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
70
|
+
try:
|
|
71
|
+
return next(type for id, type in self.types_map.items() if id == schema_id)
|
|
72
|
+
except StopIteration:
|
|
73
|
+
raise KeyError(f"Couldn't find schema with id {schema_id}")
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def credential(self) -> Optional[Parameter]:
|
|
77
|
+
"""The credential param, if one exists"""
|
|
78
|
+
return self.client.parameters.credential
|
|
105
79
|
|
|
106
|
-
|
|
80
|
+
@property
|
|
81
|
+
def client(self) -> Client:
|
|
82
|
+
if not self._client:
|
|
83
|
+
raise ValueError("You haven't linked the client yet")
|
|
84
|
+
return self._client
|
|
85
|
+
|
|
86
|
+
@client.setter
|
|
87
|
+
def client(self, val: Client) -> None:
|
|
88
|
+
self._client = val
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def config(self) -> Config:
|
|
92
|
+
if not self._config:
|
|
93
|
+
raise ValueError("You haven't linked the config yet")
|
|
94
|
+
return self._config
|
|
95
|
+
|
|
96
|
+
@config.setter
|
|
97
|
+
def config(self, val: Config) -> None:
|
|
98
|
+
self._config = val
|
|
99
|
+
|
|
100
|
+
def lookup_request_builder(
|
|
101
|
+
self, request_builder_id: int
|
|
102
|
+
) -> Union[RequestBuilder, OverloadedRequestBuilder]:
|
|
107
103
|
"""Find the request builder based off of id"""
|
|
108
104
|
try:
|
|
109
105
|
return next(
|
|
@@ -115,20 +111,31 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
115
111
|
raise KeyError(f"No request builder with id {request_builder_id} found.")
|
|
116
112
|
|
|
117
113
|
@property
|
|
118
|
-
def
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
def model_types(self) -> List[ModelType]:
|
|
115
|
+
"""All of the model types in this class"""
|
|
116
|
+
if not self._model_types:
|
|
117
|
+
self._model_types = [
|
|
118
|
+
t for t in self.types_map.values() if isinstance(t, ModelType)
|
|
119
|
+
]
|
|
120
|
+
return self._model_types
|
|
121
|
+
|
|
122
|
+
@model_types.setter
|
|
123
|
+
def model_types(self, val: List[ModelType]) -> None:
|
|
124
|
+
self._model_types = val
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def public_model_types(self) -> List[ModelType]:
|
|
128
|
+
return [m for m in self.model_types if m.is_public]
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def enums(self) -> List[EnumType]:
|
|
132
|
+
"""All of the enums"""
|
|
133
|
+
return [t for t in self.types_map.values() if isinstance(t, EnumType)]
|
|
129
134
|
|
|
130
135
|
@staticmethod
|
|
131
|
-
def
|
|
136
|
+
def _sort_model_types_helper(
|
|
137
|
+
current: ModelType, seen_schema_names: Set[str], seen_schema_yaml_ids: Set[int]
|
|
138
|
+
):
|
|
132
139
|
if current.id in seen_schema_yaml_ids:
|
|
133
140
|
return []
|
|
134
141
|
if current.name in seen_schema_names:
|
|
@@ -136,15 +143,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
136
143
|
f"We have already generated a schema with name {current.name}"
|
|
137
144
|
)
|
|
138
145
|
ancestors = [current]
|
|
139
|
-
if current.
|
|
140
|
-
for
|
|
141
|
-
parent = cast(ObjectSchema, base_model)
|
|
146
|
+
if current.parents:
|
|
147
|
+
for parent in current.parents:
|
|
142
148
|
if parent.id in seen_schema_yaml_ids:
|
|
143
149
|
continue
|
|
144
150
|
seen_schema_names.add(current.name)
|
|
145
151
|
seen_schema_yaml_ids.add(current.id)
|
|
146
152
|
ancestors = (
|
|
147
|
-
CodeModel.
|
|
153
|
+
CodeModel._sort_model_types_helper(
|
|
148
154
|
parent, seen_schema_names, seen_schema_yaml_ids
|
|
149
155
|
)
|
|
150
156
|
+ ancestors
|
|
@@ -153,7 +159,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
153
159
|
seen_schema_yaml_ids.add(current.id)
|
|
154
160
|
return ancestors
|
|
155
161
|
|
|
156
|
-
def
|
|
162
|
+
def sort_model_types(self) -> None:
|
|
157
163
|
"""Sorts the final object schemas by inheritance and by alphabetical order.
|
|
158
164
|
|
|
159
165
|
:return: None
|
|
@@ -161,38 +167,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
161
167
|
"""
|
|
162
168
|
seen_schema_names: Set[str] = set()
|
|
163
169
|
seen_schema_yaml_ids: Set[int] = set()
|
|
164
|
-
|
|
165
|
-
for schema in sorted(self.
|
|
166
|
-
|
|
167
|
-
CodeModel.
|
|
170
|
+
sorted_object_schemas: List[ModelType] = []
|
|
171
|
+
for schema in sorted(self.model_types, key=lambda x: x.name.lower()):
|
|
172
|
+
sorted_object_schemas.extend(
|
|
173
|
+
CodeModel._sort_model_types_helper(
|
|
168
174
|
schema, seen_schema_names, seen_schema_yaml_ids
|
|
169
175
|
)
|
|
170
176
|
)
|
|
171
|
-
self.
|
|
172
|
-
|
|
173
|
-
def setup_client_input_parameters(self, yaml_data: Dict[str, Any]):
|
|
174
|
-
dollar_host = [
|
|
175
|
-
parameter
|
|
176
|
-
for parameter in self.global_parameters
|
|
177
|
-
if parameter.rest_api_name == "$host"
|
|
178
|
-
]
|
|
179
|
-
if not dollar_host:
|
|
180
|
-
# We don't want to support multi-api customurl YET (will see if that goes well....)
|
|
181
|
-
# So far now, let's get the first one in the first operation
|
|
182
|
-
# UGLY as hell.....
|
|
183
|
-
if yaml_data.get("operationGroups"):
|
|
184
|
-
first_req_of_first_op_of_first_grp = yaml_data["operationGroups"][0][
|
|
185
|
-
"operations"
|
|
186
|
-
][0]["requests"][0]
|
|
187
|
-
self.service_client.parameterized_host_template = (
|
|
188
|
-
first_req_of_first_op_of_first_grp["protocol"]["http"]["uri"]
|
|
189
|
-
)
|
|
190
|
-
else:
|
|
191
|
-
for host in dollar_host:
|
|
192
|
-
self.global_parameters.remove(host)
|
|
193
|
-
self.service_client.parameters.add_host(
|
|
194
|
-
dollar_host[0].yaml_data["clientDefaultValue"]
|
|
195
|
-
)
|
|
177
|
+
self.model_types = sorted_object_schemas
|
|
196
178
|
|
|
197
179
|
def format_lro_operations(self) -> None:
|
|
198
180
|
"""Adds operations and attributes needed for LROs.
|
|
@@ -203,156 +185,23 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
203
185
|
i = 0
|
|
204
186
|
while i < len(operation_group.operations):
|
|
205
187
|
operation = operation_group.operations[i]
|
|
206
|
-
if
|
|
207
|
-
operation_group.operations.insert(i, operation.initial_operation)
|
|
188
|
+
if operation.operation_type in ("lro", "lropaging"):
|
|
189
|
+
operation_group.operations.insert(i, operation.initial_operation) # type: ignore
|
|
208
190
|
i += 1
|
|
209
191
|
i += 1
|
|
210
192
|
|
|
211
|
-
def remove_next_operation(self) -> None:
|
|
212
|
-
"""Linking paging operations together."""
|
|
213
|
-
|
|
214
|
-
def _lookup_operation(yaml_id: int) -> Operation:
|
|
215
|
-
for operation_group in self.operation_groups:
|
|
216
|
-
for operation in operation_group.operations:
|
|
217
|
-
if operation.id == yaml_id:
|
|
218
|
-
return operation
|
|
219
|
-
raise KeyError("Didn't find it!!!!!")
|
|
220
|
-
|
|
221
|
-
for operation_group in self.operation_groups:
|
|
222
|
-
next_operations = []
|
|
223
|
-
for operation in operation_group.operations:
|
|
224
|
-
# when we add in "LRO" functions we don't include yaml_data, so yaml_data can be empty in these cases
|
|
225
|
-
next_link_yaml = None
|
|
226
|
-
if operation.yaml_data and operation.yaml_data["language"][
|
|
227
|
-
"python"
|
|
228
|
-
].get("paging"):
|
|
229
|
-
next_link_yaml = operation.yaml_data["language"]["python"][
|
|
230
|
-
"paging"
|
|
231
|
-
].get("nextLinkOperation")
|
|
232
|
-
if isinstance(operation, PagingOperation) and next_link_yaml:
|
|
233
|
-
next_operation = _lookup_operation(id(next_link_yaml))
|
|
234
|
-
operation.next_operation = next_operation
|
|
235
|
-
next_operations.append(next_operation)
|
|
236
|
-
|
|
237
|
-
operation_group.operations = [
|
|
238
|
-
operation
|
|
239
|
-
for operation in operation_group.operations
|
|
240
|
-
if operation not in next_operations
|
|
241
|
-
]
|
|
242
|
-
|
|
243
|
-
@property
|
|
244
|
-
def has_schemas(self):
|
|
245
|
-
return self.schemas or self.enums
|
|
246
|
-
|
|
247
|
-
@property
|
|
248
|
-
def credential_model(self) -> CredentialModel:
|
|
249
|
-
if not self._credential_model:
|
|
250
|
-
raise ValueError(
|
|
251
|
-
"You want to find the Credential Model, but have not given a value"
|
|
252
|
-
)
|
|
253
|
-
return self._credential_model
|
|
254
|
-
|
|
255
|
-
@credential_model.setter
|
|
256
|
-
def credential_model(self, val: CredentialModel) -> None:
|
|
257
|
-
self._credential_model = val
|
|
258
|
-
|
|
259
|
-
@staticmethod
|
|
260
|
-
def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
|
|
261
|
-
if not schema.base_models:
|
|
262
|
-
return properties
|
|
263
|
-
if schema.base_models:
|
|
264
|
-
for base_model in schema.base_models:
|
|
265
|
-
parent = cast(ObjectSchema, base_model)
|
|
266
|
-
# need to make sure that the properties we choose from our parent also don't contain
|
|
267
|
-
# any of our own properties
|
|
268
|
-
schema_property_names = set(
|
|
269
|
-
[p.name for p in properties] + [p.name for p in schema.properties]
|
|
270
|
-
)
|
|
271
|
-
chosen_parent_properties = [
|
|
272
|
-
p for p in parent.properties if p.name not in schema_property_names
|
|
273
|
-
]
|
|
274
|
-
properties = (
|
|
275
|
-
CodeModel._add_properties_from_inheritance_helper(
|
|
276
|
-
parent, chosen_parent_properties
|
|
277
|
-
)
|
|
278
|
-
+ properties
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
return properties
|
|
282
|
-
|
|
283
193
|
@property
|
|
284
194
|
def operations_folder_name(self) -> str:
|
|
195
|
+
"""Get the name of the operations folder that holds operations."""
|
|
285
196
|
name = "operations"
|
|
286
197
|
if self.options["version_tolerant"] and not any(
|
|
287
|
-
og for og in self.operation_groups if not og.
|
|
198
|
+
og for og in self.operation_groups if not og.is_mixin
|
|
288
199
|
):
|
|
289
200
|
name = f"_{name}"
|
|
290
201
|
return name
|
|
291
202
|
|
|
292
|
-
def _add_properties_from_inheritance(self) -> None:
|
|
293
|
-
"""Adds properties from base classes to schemas with parents.
|
|
294
|
-
|
|
295
|
-
:return: None
|
|
296
|
-
:rtype: None
|
|
297
|
-
"""
|
|
298
|
-
for schema in self.schemas.values():
|
|
299
|
-
schema.properties = CodeModel._add_properties_from_inheritance_helper(
|
|
300
|
-
schema, schema.properties
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
@staticmethod
|
|
304
|
-
def _add_exceptions_from_inheritance_helper(schema) -> bool:
|
|
305
|
-
if schema.is_exception:
|
|
306
|
-
return True
|
|
307
|
-
parent_is_exception: List[bool] = []
|
|
308
|
-
for base_model in schema.base_models:
|
|
309
|
-
parent = cast(ObjectSchema, base_model)
|
|
310
|
-
parent_is_exception.append(
|
|
311
|
-
CodeModel._add_exceptions_from_inheritance_helper(parent)
|
|
312
|
-
)
|
|
313
|
-
return any(parent_is_exception)
|
|
314
|
-
|
|
315
|
-
def _add_exceptions_from_inheritance(self) -> None:
|
|
316
|
-
"""Sets a class as an exception if it's parent is an exception.
|
|
317
|
-
|
|
318
|
-
:return: None
|
|
319
|
-
:rtype: None
|
|
320
|
-
"""
|
|
321
|
-
for schema in self.schemas.values():
|
|
322
|
-
schema.is_exception = CodeModel._add_exceptions_from_inheritance_helper(
|
|
323
|
-
schema
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
def add_inheritance_to_models(self) -> None:
|
|
327
|
-
"""Adds base classes and properties from base classes to schemas with parents.
|
|
328
|
-
|
|
329
|
-
:return: None
|
|
330
|
-
:rtype: None
|
|
331
|
-
"""
|
|
332
|
-
for schema in self.schemas.values():
|
|
333
|
-
if schema.base_models:
|
|
334
|
-
# right now, the base model property just holds the name of the parent class
|
|
335
|
-
schema.base_models = [
|
|
336
|
-
b for b in self.schemas.values() if b.id in schema.base_models
|
|
337
|
-
]
|
|
338
|
-
self._add_properties_from_inheritance()
|
|
339
|
-
self._add_exceptions_from_inheritance()
|
|
340
|
-
|
|
341
|
-
def _populate_target_property(self, parameter: Parameter) -> None:
|
|
342
|
-
for obj in self.schemas.values():
|
|
343
|
-
for prop in obj.properties:
|
|
344
|
-
if prop.id == parameter.target_property_name:
|
|
345
|
-
parameter.target_property_name = prop.name
|
|
346
|
-
return
|
|
347
|
-
raise KeyError("Didn't find the target property")
|
|
348
|
-
|
|
349
|
-
def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
|
|
350
|
-
for operation_group in self.operation_groups:
|
|
351
|
-
for operation in operation_group.operations:
|
|
352
|
-
if operation.multiple_content_type_parameters:
|
|
353
|
-
operation.convert_multiple_content_type_parameters()
|
|
354
|
-
|
|
355
203
|
def need_vendored_code(self, async_mode: bool) -> bool:
|
|
204
|
+
"""Whether we need to vendor code in the _vendor.py file for this SDK"""
|
|
356
205
|
if async_mode:
|
|
357
206
|
return self.need_mixin_abc
|
|
358
207
|
return (
|
|
@@ -361,6 +210,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
361
210
|
|
|
362
211
|
@property
|
|
363
212
|
def need_request_converter(self) -> bool:
|
|
213
|
+
"""
|
|
214
|
+
Whether we need to convert our created azure.core.rest.HttpRequests to
|
|
215
|
+
azure.core.pipeline.transport.HttpRequests
|
|
216
|
+
"""
|
|
364
217
|
return (
|
|
365
218
|
self.options["show_operations"]
|
|
366
219
|
and bool(self.request_builders)
|
|
@@ -369,36 +222,31 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
369
222
|
|
|
370
223
|
@property
|
|
371
224
|
def need_format_url(self) -> bool:
|
|
225
|
+
"""Whether we need to format urls. If so, we need to vendor core."""
|
|
372
226
|
return any(rq for rq in self.request_builders if rq.parameters.path)
|
|
373
227
|
|
|
374
228
|
@property
|
|
375
229
|
def need_mixin_abc(self) -> bool:
|
|
230
|
+
"""Do we want a mixin ABC class for typing purposes?"""
|
|
376
231
|
return any(
|
|
377
232
|
o
|
|
378
233
|
for o in self.operation_groups
|
|
379
|
-
if o.
|
|
234
|
+
if o.is_mixin and self.options["python3_only"]
|
|
380
235
|
)
|
|
381
236
|
|
|
382
237
|
@property
|
|
383
238
|
def has_lro_operations(self) -> bool:
|
|
239
|
+
"""Are there any LRO operations in this SDK?"""
|
|
384
240
|
return any(
|
|
385
241
|
[
|
|
386
|
-
|
|
242
|
+
operation.operation_type in ("lro", "lropaging")
|
|
387
243
|
for operation_group in self.operation_groups
|
|
388
244
|
for operation in operation_group.operations
|
|
389
245
|
]
|
|
390
246
|
)
|
|
391
247
|
|
|
392
|
-
def link_operation_to_request_builder(self) -> None:
|
|
393
|
-
for operation_group in self.operation_groups:
|
|
394
|
-
for operation in operation_group.operations:
|
|
395
|
-
request_builder = operation.request_builder
|
|
396
|
-
if isinstance(operation, LROOperation):
|
|
397
|
-
request_builder.name = request_builder.name + "_initial"
|
|
398
|
-
operation.request_builder = request_builder
|
|
399
|
-
operation.link_body_kwargs_to_body_params()
|
|
400
|
-
|
|
401
248
|
def get_models_filename(self, is_python3_file: bool) -> str:
|
|
249
|
+
"""Get the names of the model file(s)"""
|
|
402
250
|
if (
|
|
403
251
|
self.options["version_tolerant"] or self.options["low_level_client"]
|
|
404
252
|
) and self.options["python3_only"]:
|
|
@@ -409,6 +257,12 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
409
257
|
|
|
410
258
|
@property
|
|
411
259
|
def enums_filename(self) -> str:
|
|
260
|
+
"""The name of the enums file"""
|
|
412
261
|
if self.options["version_tolerant"] or self.options["low_level_client"]:
|
|
413
262
|
return "_enums"
|
|
414
263
|
return f"_{self.module_name}_enums"
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def rest_layer_name(self) -> str:
|
|
267
|
+
"""If we have a separate rest layer, what is its name?"""
|
|
268
|
+
return "rest" if self.options["builders_visibility"] == "public" else "_rest"
|
|
@@ -0,0 +1,107 @@
|
|
|
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, List, Optional, TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from autorest.codegen.models.imports import FileImport, ImportType
|
|
9
|
+
from .base_type import BaseType
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .code_model import CodeModel
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CombinedType(BaseType):
|
|
16
|
+
"""A type that consists of multiple different types.
|
|
17
|
+
|
|
18
|
+
Used by body parameters that have multiple types, i.e. one that can be
|
|
19
|
+
a stream body or a JSON body.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self, yaml_data: Dict[str, Any], code_model: "CodeModel", types: List[BaseType]
|
|
24
|
+
) -> None:
|
|
25
|
+
super().__init__(yaml_data, code_model)
|
|
26
|
+
self.types = types # the types that this type is combining
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def serialization_type(self) -> str:
|
|
30
|
+
"""The tag recognized by 'msrest' as a serialization/deserialization.
|
|
31
|
+
|
|
32
|
+
'str', 'int', 'float', 'bool' or
|
|
33
|
+
https://github.com/Azure/msrest-for-python/blob/b505e3627b547bd8fdc38327e86c70bdb16df061/msrest/serialization.py#L407-L416
|
|
34
|
+
|
|
35
|
+
or the object schema name (e.g. DotSalmon).
|
|
36
|
+
|
|
37
|
+
If list: '[str]'
|
|
38
|
+
If dict: '{str}'
|
|
39
|
+
"""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def client_default_value(self) -> Any:
|
|
44
|
+
return self.yaml_data.get("clientDefaultValue")
|
|
45
|
+
|
|
46
|
+
def description(
|
|
47
|
+
self, *, is_operation_file: bool # pylint: disable=unused-argument
|
|
48
|
+
) -> str:
|
|
49
|
+
if len(self.types) == 2:
|
|
50
|
+
return (
|
|
51
|
+
f"Is either a {self.types[0].type} type or a {self.types[1].type} type."
|
|
52
|
+
)
|
|
53
|
+
return (
|
|
54
|
+
f"Is one of the following types: {', '.join([t.type for t in self.types])}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def docstring_text(self, **kwargs: Any) -> str:
|
|
58
|
+
return " or ".join(t.docstring_text(**kwargs) for t in self.types)
|
|
59
|
+
|
|
60
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
61
|
+
return " or ".join(t.docstring_type(**kwargs) for t in self.types)
|
|
62
|
+
|
|
63
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
64
|
+
"""The python type used for type annotation
|
|
65
|
+
|
|
66
|
+
Special case for enum, for instance: Union[str, "EnumName"]
|
|
67
|
+
"""
|
|
68
|
+
kwargs["is_operation_file"] = True
|
|
69
|
+
return (
|
|
70
|
+
f'Union[{", ".join(type.type_annotation(**kwargs) for type in self.types)}]'
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def get_json_template_representation(
|
|
74
|
+
self,
|
|
75
|
+
*,
|
|
76
|
+
optional: bool = True,
|
|
77
|
+
client_default_value_declaration: Optional[str] = None,
|
|
78
|
+
description: Optional[str] = None,
|
|
79
|
+
) -> Any:
|
|
80
|
+
"""Template of what this schema would look like as JSON input"""
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"You shouldn't get a JSON template representation of multiple types"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def instance_check_template(self) -> str:
|
|
87
|
+
"""Template of what an instance check of a variable for this type would look like"""
|
|
88
|
+
raise ValueError("You shouldn't do instance checks on a multiple type")
|
|
89
|
+
|
|
90
|
+
def imports(self, **kwargs: Any) -> FileImport:
|
|
91
|
+
file_import = FileImport()
|
|
92
|
+
for type in self.types:
|
|
93
|
+
file_import.merge(type.imports(**kwargs))
|
|
94
|
+
file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
|
|
95
|
+
return file_import
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def from_yaml(
|
|
99
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
100
|
+
) -> "BaseType":
|
|
101
|
+
from . import build_type
|
|
102
|
+
|
|
103
|
+
return cls(
|
|
104
|
+
yaml_data,
|
|
105
|
+
code_model,
|
|
106
|
+
[build_type(t, code_model) for t in yaml_data["types"]],
|
|
107
|
+
)
|