@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
|
@@ -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,30 @@ 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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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()
|
|
203
|
+
@property
|
|
204
|
+
def has_abstract_operations(self) -> bool:
|
|
205
|
+
"""Whether there is abstract operation in any operation group."""
|
|
206
|
+
return any(og.has_abstract_operations for og in self.operation_groups)
|
|
354
207
|
|
|
355
208
|
def need_vendored_code(self, async_mode: bool) -> bool:
|
|
209
|
+
"""Whether we need to vendor code in the _vendor.py file for this SDK"""
|
|
210
|
+
if self.has_abstract_operations:
|
|
211
|
+
return True
|
|
356
212
|
if async_mode:
|
|
357
213
|
return self.need_mixin_abc
|
|
358
214
|
return (
|
|
@@ -361,6 +217,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
361
217
|
|
|
362
218
|
@property
|
|
363
219
|
def need_request_converter(self) -> bool:
|
|
220
|
+
"""
|
|
221
|
+
Whether we need to convert our created azure.core.rest.HttpRequests to
|
|
222
|
+
azure.core.pipeline.transport.HttpRequests
|
|
223
|
+
"""
|
|
364
224
|
return (
|
|
365
225
|
self.options["show_operations"]
|
|
366
226
|
and bool(self.request_builders)
|
|
@@ -369,39 +229,32 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
369
229
|
|
|
370
230
|
@property
|
|
371
231
|
def need_format_url(self) -> bool:
|
|
232
|
+
"""Whether we need to format urls. If so, we need to vendor core."""
|
|
372
233
|
return any(rq for rq in self.request_builders if rq.parameters.path)
|
|
373
234
|
|
|
374
235
|
@property
|
|
375
236
|
def need_mixin_abc(self) -> bool:
|
|
237
|
+
"""Do we want a mixin ABC class for typing purposes?"""
|
|
376
238
|
return any(
|
|
377
239
|
o
|
|
378
240
|
for o in self.operation_groups
|
|
379
|
-
if o.
|
|
241
|
+
if o.is_mixin and self.options["python3_only"]
|
|
380
242
|
)
|
|
381
243
|
|
|
382
244
|
@property
|
|
383
245
|
def has_lro_operations(self) -> bool:
|
|
246
|
+
"""Are there any LRO operations in this SDK?"""
|
|
384
247
|
return any(
|
|
385
248
|
[
|
|
386
|
-
|
|
249
|
+
operation.operation_type in ("lro", "lropaging")
|
|
387
250
|
for operation_group in self.operation_groups
|
|
388
251
|
for operation in operation_group.operations
|
|
389
252
|
]
|
|
390
253
|
)
|
|
391
254
|
|
|
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
255
|
def get_models_filename(self, is_python3_file: bool) -> str:
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
) and self.options["python3_only"]:
|
|
256
|
+
"""Get the names of the model file(s)"""
|
|
257
|
+
if not self.is_legacy and self.options["python3_only"]:
|
|
405
258
|
return "_models"
|
|
406
259
|
if is_python3_file:
|
|
407
260
|
return "_models_py3"
|
|
@@ -409,6 +262,18 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
409
262
|
|
|
410
263
|
@property
|
|
411
264
|
def enums_filename(self) -> str:
|
|
412
|
-
|
|
265
|
+
"""The name of the enums file"""
|
|
266
|
+
if not self.is_legacy:
|
|
413
267
|
return "_enums"
|
|
414
268
|
return f"_{self.module_name}_enums"
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def is_legacy(self) -> bool:
|
|
272
|
+
return not (
|
|
273
|
+
self.options["version_tolerant"] or self.options["low_level_client"]
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def rest_layer_name(self) -> str:
|
|
278
|
+
"""If we have a separate rest layer, what is its name?"""
|
|
279
|
+
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
|
+
)
|