@autorest/python 5.10.0 → 5.12.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 +74 -0
- package/autorest/codegen/__init__.py +7 -7
- package/autorest/codegen/models/__init__.py +2 -1
- package/autorest/codegen/models/base_builder.py +16 -8
- package/autorest/codegen/models/client.py +5 -3
- package/autorest/codegen/models/code_model.py +19 -5
- package/autorest/codegen/models/imports.py +7 -0
- package/autorest/codegen/models/lro_operation.py +7 -3
- package/autorest/codegen/models/object_schema.py +3 -3
- package/autorest/codegen/models/operation.py +69 -38
- package/autorest/codegen/models/operation_group.py +13 -8
- package/autorest/codegen/models/paging_operation.py +5 -2
- package/autorest/codegen/models/parameter.py +46 -13
- package/autorest/codegen/models/parameter_list.py +62 -70
- package/autorest/codegen/models/primitive_schemas.py +11 -0
- package/autorest/codegen/models/request_builder.py +21 -8
- package/autorest/codegen/models/request_builder_parameter.py +9 -5
- package/autorest/codegen/models/request_builder_parameter_list.py +179 -77
- package/autorest/codegen/models/rest.py +3 -2
- package/autorest/codegen/models/schema_request.py +4 -17
- package/autorest/codegen/models/schema_response.py +4 -4
- package/autorest/codegen/serializers/__init__.py +57 -53
- package/autorest/codegen/serializers/builder_serializer.py +76 -46
- package/autorest/codegen/serializers/client_serializer.py +37 -9
- package/autorest/codegen/serializers/general_serializer.py +7 -5
- package/autorest/codegen/serializers/import_serializer.py +22 -7
- package/autorest/codegen/serializers/metadata_serializer.py +2 -2
- package/autorest/codegen/serializers/model_base_serializer.py +3 -3
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +1 -1
- package/autorest/codegen/serializers/operation_groups_serializer.py +70 -0
- package/autorest/codegen/serializers/operations_init_serializer.py +34 -2
- package/autorest/codegen/serializers/patch_serializer.py +15 -0
- package/autorest/codegen/serializers/rest_serializer.py +9 -4
- package/autorest/codegen/serializers/utils.py +2 -2
- package/autorest/codegen/templates/config.py.jinja2 +1 -11
- package/autorest/codegen/templates/init.py.jinja2 +4 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +2 -2
- package/autorest/codegen/templates/model_init.py.jinja2 +1 -1
- package/autorest/codegen/templates/{operations_class.py.jinja2 → operation_group.py.jinja2} +2 -0
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +26 -0
- package/autorest/codegen/templates/operation_tools.jinja2 +7 -0
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +13 -0
- package/autorest/codegen/templates/patch.py.jinja2 +31 -0
- package/autorest/codegen/templates/request_builder.py.jinja2 +7 -2
- package/autorest/codegen/templates/request_builders.py.jinja2 +3 -3
- package/autorest/codegen/templates/setup.py.jinja2 +1 -1
- package/autorest/multiapi/serializers/__init__.py +3 -3
- package/autorest/multiapi/serializers/import_serializer.py +5 -5
- package/autorest/namer/name_converter.py +48 -3
- package/package.json +2 -2
- package/setup.py +1 -0
- package/autorest/codegen/serializers/operation_group_serializer.py +0 -71
- package/autorest/codegen/templates/operations_class_mixin.py.jinja2 +0 -16
- package/autorest/codegen/templates/operations_container.py.jinja2 +0 -42
- package/autorest/codegen/templates/operations_container_init.py.jinja2 +0 -24
- package/autorest/codegen/templates/operations_container_mixin.py.jinja2 +0 -23
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
import re
|
|
6
7
|
from copy import copy
|
|
7
|
-
from typing import List, Optional, TypeVar, Dict
|
|
8
|
+
from typing import List, Optional, Tuple, TypeVar, Dict
|
|
8
9
|
from .request_builder_parameter import RequestBuilderParameter
|
|
9
10
|
from .parameter_list import ParameterList
|
|
10
|
-
from .parameter import ParameterLocation, Parameter
|
|
11
|
-
from .primitive_schemas import AnySchema
|
|
11
|
+
from .parameter import ParameterLocation, Parameter, ParameterStyle
|
|
12
|
+
from .primitive_schemas import AnySchema, JSONSchema
|
|
12
13
|
from .dictionary_schema import DictionarySchema
|
|
13
14
|
from .base_schema import BaseSchema
|
|
14
15
|
from .schema_request import SchemaRequest
|
|
@@ -17,14 +18,25 @@ T = TypeVar('T')
|
|
|
17
18
|
OrderedSet = Dict[T, None]
|
|
18
19
|
|
|
19
20
|
_REQUEST_BUILDER_BODY_NAMES = ["files", "json", "content", "data"]
|
|
21
|
+
_JSON_REGEXP = re.compile(r'^(application|text)/([0-9a-z+.]+\+)?json$')
|
|
20
22
|
|
|
23
|
+
def _update_content_types(content_types_to_assign: List[str], param: Parameter):
|
|
24
|
+
return [
|
|
25
|
+
c for c in content_types_to_assign if c not in param.content_types
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
def _kwarg_not_added(body_method_params, serialized_name: str) -> bool:
|
|
29
|
+
return not any(b for b in body_method_params if b.serialized_name == serialized_name)
|
|
21
30
|
|
|
22
31
|
class RequestBuilderParameterList(ParameterList):
|
|
23
32
|
def __init__(
|
|
24
|
-
self,
|
|
33
|
+
self,
|
|
34
|
+
code_model,
|
|
35
|
+
parameters: Optional[List[RequestBuilderParameter]] = None,
|
|
36
|
+
schema_requests: Optional[List[SchemaRequest]] = None,
|
|
25
37
|
) -> None:
|
|
26
38
|
super(RequestBuilderParameterList, self).__init__(
|
|
27
|
-
code_model, parameters # type: ignore
|
|
39
|
+
code_model, parameters, schema_requests # type: ignore
|
|
28
40
|
)
|
|
29
41
|
self.body_kwarg_names: OrderedSet[str] = {}
|
|
30
42
|
self.parameters: List[RequestBuilderParameter] = parameters or [] # type: ignore
|
|
@@ -32,90 +44,170 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
32
44
|
def _change_body_param_name(self, parameter: Parameter, name: str) -> None:
|
|
33
45
|
self.body_kwarg_names[name] = None
|
|
34
46
|
parameter.serialized_name = name
|
|
47
|
+
parameter.is_body_kwarg = True
|
|
35
48
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
def _is_json(self, body_method_param: Parameter) -> bool:
|
|
50
|
+
if 'json' in body_method_param.serialization_formats:
|
|
51
|
+
return True
|
|
52
|
+
if not any(
|
|
53
|
+
flag for flag in ["version_tolerant", "low_level_client"]
|
|
54
|
+
if self.code_model.options.get(flag)
|
|
55
|
+
):
|
|
56
|
+
if body_method_param.style == ParameterStyle.binary:
|
|
57
|
+
return False
|
|
58
|
+
if any(
|
|
59
|
+
sr for sr in self.schema_requests
|
|
60
|
+
if sr.yaml_data.get("protocol", {}).get('http', {}).get('knownMediaType') == "json"
|
|
61
|
+
):
|
|
62
|
+
return True
|
|
63
|
+
return any(c for c in self.content_types if _JSON_REGEXP.match(c))
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def body_kwargs_to_get(self) -> List[Parameter]:
|
|
67
|
+
if not self.body_kwarg_names:
|
|
68
|
+
return []
|
|
69
|
+
return [b for b in self.body if b.content_types]
|
|
70
|
+
|
|
71
|
+
def _update_constant_params(self):
|
|
72
|
+
# we don't currently have a fully constant data or files input
|
|
73
|
+
# so we don't need to modify the body kwarg
|
|
74
|
+
constant_bodies = [
|
|
75
|
+
p for p in self.parameters
|
|
76
|
+
if p.location == ParameterLocation.Body
|
|
77
|
+
and p.constant
|
|
78
|
+
and not p.is_data_input
|
|
79
|
+
and not p.is_multipart
|
|
80
|
+
]
|
|
81
|
+
for constant_body in constant_bodies:
|
|
82
|
+
if self._is_json(constant_body):
|
|
83
|
+
constant_body.serialized_name = "json"
|
|
84
|
+
else:
|
|
85
|
+
constant_body.serialized_name = "content"
|
|
86
|
+
|
|
87
|
+
def _add_files_kwarg(
|
|
88
|
+
self, content_types_to_assign, body_method_param
|
|
89
|
+
) -> Tuple[List[str], RequestBuilderParameter]:
|
|
90
|
+
file_kwarg = copy(body_method_param)
|
|
91
|
+
self._change_body_param_name(file_kwarg, "files")
|
|
92
|
+
file_kwarg.schema = DictionarySchema(
|
|
93
|
+
namespace="",
|
|
94
|
+
yaml_data={},
|
|
95
|
+
element_type=AnySchema(namespace="", yaml_data={}),
|
|
96
|
+
)
|
|
97
|
+
file_kwarg.description = (
|
|
98
|
+
"Multipart input for files. See the template in our example to find the input shape. " +
|
|
99
|
+
file_kwarg.description
|
|
100
|
+
)
|
|
101
|
+
file_kwarg.content_types = [
|
|
102
|
+
c for c in content_types_to_assign
|
|
103
|
+
if c == "multipart/form-data"
|
|
104
|
+
]
|
|
105
|
+
content_types_to_assign = _update_content_types(content_types_to_assign, file_kwarg)
|
|
106
|
+
return content_types_to_assign, file_kwarg
|
|
107
|
+
|
|
108
|
+
def _add_data_kwarg(
|
|
109
|
+
self, content_types_to_assign, body_method_param
|
|
110
|
+
) -> Tuple[List[str], RequestBuilderParameter]:
|
|
111
|
+
data_kwarg = copy(body_method_param)
|
|
112
|
+
self._change_body_param_name(data_kwarg, "data")
|
|
113
|
+
data_kwarg.schema = DictionarySchema(
|
|
114
|
+
namespace="",
|
|
115
|
+
yaml_data={},
|
|
116
|
+
element_type=AnySchema(namespace="", yaml_data={}),
|
|
117
|
+
)
|
|
118
|
+
data_kwarg.description = (
|
|
119
|
+
"Pass in dictionary that contains form data to include in the body of the request. " +
|
|
120
|
+
data_kwarg.description
|
|
121
|
+
)
|
|
122
|
+
data_kwarg.content_types = [
|
|
123
|
+
c for c in content_types_to_assign
|
|
124
|
+
if c == "application/x-www-form-urlencoded"
|
|
125
|
+
]
|
|
126
|
+
content_types_to_assign = _update_content_types(content_types_to_assign, data_kwarg)
|
|
127
|
+
return content_types_to_assign, data_kwarg
|
|
128
|
+
|
|
129
|
+
def _add_json_kwarg(
|
|
130
|
+
self, content_types_to_assign, body_method_param
|
|
131
|
+
) -> Tuple[List[str], RequestBuilderParameter]:
|
|
132
|
+
json_kwarg = copy(body_method_param)
|
|
133
|
+
self._change_body_param_name(json_kwarg, "json")
|
|
134
|
+
json_kwarg.description = (
|
|
135
|
+
"Pass in a JSON-serializable object (usually a dictionary). "
|
|
136
|
+
"See the template in our example to find the input shape. " +
|
|
137
|
+
json_kwarg.description
|
|
138
|
+
)
|
|
139
|
+
json_kwarg.schema = JSONSchema(namespace="", yaml_data={})
|
|
140
|
+
json_kwarg.content_types = [
|
|
141
|
+
c for c in content_types_to_assign
|
|
142
|
+
if _JSON_REGEXP.match(c)
|
|
143
|
+
]
|
|
144
|
+
content_types_to_assign = _update_content_types(content_types_to_assign, json_kwarg)
|
|
145
|
+
return content_types_to_assign, json_kwarg
|
|
146
|
+
|
|
147
|
+
def _add_content_kwarg(
|
|
148
|
+
self, content_types_to_assign, body_method_param
|
|
149
|
+
) -> RequestBuilderParameter:
|
|
150
|
+
content_kwarg = copy(body_method_param)
|
|
151
|
+
self._change_body_param_name(content_kwarg, "content")
|
|
152
|
+
content_kwarg.schema = AnySchema(namespace="", yaml_data={})
|
|
153
|
+
content_kwarg.description = (
|
|
154
|
+
"Pass in binary content you want in the body of the request (typically bytes, "
|
|
155
|
+
"a byte iterator, or stream input). " +
|
|
156
|
+
content_kwarg.description
|
|
157
|
+
)
|
|
158
|
+
content_kwarg.is_data_input = False
|
|
159
|
+
content_kwarg.is_multipart = False
|
|
160
|
+
content_kwarg.content_types = content_types_to_assign
|
|
161
|
+
return content_kwarg
|
|
162
|
+
|
|
163
|
+
def add_body_kwargs(self) -> None:
|
|
164
|
+
self._update_constant_params()
|
|
165
|
+
body_kwargs_added: List[RequestBuilderParameter] = []
|
|
166
|
+
body_method_params = [
|
|
167
|
+
p for p in self.parameters
|
|
168
|
+
if p.location == ParameterLocation.Body and not p.constant
|
|
169
|
+
]
|
|
170
|
+
if not body_method_params:
|
|
171
|
+
return
|
|
172
|
+
content_types_to_assign = copy(self.content_types)
|
|
173
|
+
for body_method_param in body_method_params:
|
|
174
|
+
if body_method_param.is_multipart and _kwarg_not_added(body_kwargs_added, "files"):
|
|
175
|
+
content_types_to_assign, file_kwarg = self._add_files_kwarg(
|
|
176
|
+
content_types_to_assign, body_method_param
|
|
58
177
|
)
|
|
59
|
-
file_kwarg.is_multipart = False
|
|
60
178
|
body_kwargs_added.append(file_kwarg)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
data_kwarg =
|
|
64
|
-
|
|
65
|
-
data_kwarg.schema = DictionarySchema(
|
|
66
|
-
namespace="",
|
|
67
|
-
yaml_data={},
|
|
68
|
-
element_type=AnySchema(namespace="", yaml_data={}),
|
|
69
|
-
)
|
|
70
|
-
data_kwarg.description = (
|
|
71
|
-
"Pass in dictionary that contains form data to include in the body of the request. " +
|
|
72
|
-
data_kwarg.description
|
|
179
|
+
|
|
180
|
+
elif body_method_param.is_data_input and _kwarg_not_added(body_kwargs_added, "data"):
|
|
181
|
+
content_types_to_assign, data_kwarg = self._add_data_kwarg(
|
|
182
|
+
content_types_to_assign, body_method_param
|
|
73
183
|
)
|
|
74
|
-
data_kwarg.is_data_input = False
|
|
75
184
|
body_kwargs_added.append(data_kwarg)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
serialized_name = "json" if body_method_param.is_json_parameter else "content"
|
|
80
|
-
body_method_param.serialized_name = serialized_name
|
|
81
|
-
return
|
|
82
|
-
if (
|
|
83
|
-
any(sr for sr in schema_requests if not sr.is_stream_request) and
|
|
84
|
-
any([ct for ct in self.content_types if "json" in ct])
|
|
85
|
-
):
|
|
86
|
-
json_kwarg = copy(body_method_param)
|
|
87
|
-
self._change_body_param_name(json_kwarg, "json")
|
|
88
|
-
json_kwarg.description = (
|
|
89
|
-
"Pass in a JSON-serializable object (usually a dictionary). "
|
|
90
|
-
"See the template in our example to find the input shape. " +
|
|
91
|
-
json_kwarg.description
|
|
185
|
+
elif self._is_json(body_method_param) and _kwarg_not_added(body_kwargs_added, "json"):
|
|
186
|
+
content_types_to_assign, json_kwarg = self._add_json_kwarg(
|
|
187
|
+
content_types_to_assign, body_method_param
|
|
92
188
|
)
|
|
93
|
-
json_kwarg.schema = AnySchema(namespace="", yaml_data={})
|
|
94
189
|
body_kwargs_added.append(json_kwarg)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
content_kwarg.description
|
|
190
|
+
|
|
191
|
+
first_body_param = body_method_params[0]
|
|
192
|
+
if _kwarg_not_added(body_kwargs_added, "content"):
|
|
193
|
+
# we always add a content kwarg so users can pass in input by stream
|
|
194
|
+
content_kwarg = self._add_content_kwarg(
|
|
195
|
+
content_types_to_assign, first_body_param
|
|
102
196
|
)
|
|
103
|
-
content_kwarg.is_data_input = False
|
|
104
|
-
content_kwarg.is_multipart = False
|
|
105
197
|
body_kwargs_added.append(content_kwarg)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
198
|
+
if len(body_kwargs_added) == 1:
|
|
199
|
+
body_kwargs_added[0].required = first_body_param.required
|
|
200
|
+
else:
|
|
201
|
+
for kwarg in body_kwargs_added:
|
|
202
|
+
kwarg.required = False
|
|
203
|
+
self.parameters = body_kwargs_added + self.parameters
|
|
112
204
|
|
|
113
205
|
@property
|
|
114
206
|
def json_body(self) -> BaseSchema:
|
|
115
207
|
if not self._json_body:
|
|
116
208
|
try:
|
|
117
209
|
json_param = next(
|
|
118
|
-
b for b in self.body if b.
|
|
210
|
+
b for b in self.body if not b.is_body_kwarg and
|
|
119
211
|
b.is_json_parameter
|
|
120
212
|
)
|
|
121
213
|
self._json_body = json_param.schema
|
|
@@ -124,10 +216,10 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
124
216
|
raise ValueError("There is no JSON body in these parameters")
|
|
125
217
|
return self._json_body
|
|
126
218
|
|
|
127
|
-
def kwargs_to_pop(self,
|
|
219
|
+
def kwargs_to_pop(self, is_python3_file: bool) -> List[Parameter]:
|
|
128
220
|
# we don't want to pop the body kwargs in py2.7. We send them straight to HttpRequest
|
|
129
221
|
kwargs_to_pop = self.kwargs
|
|
130
|
-
if not
|
|
222
|
+
if not is_python3_file:
|
|
131
223
|
kwargs_to_pop += [k for k in self.keyword_only if not (k.is_body and not k.constant)]
|
|
132
224
|
return kwargs_to_pop
|
|
133
225
|
|
|
@@ -147,9 +239,19 @@ class RequestBuilderParameterList(ParameterList):
|
|
|
147
239
|
seen_content_type = False
|
|
148
240
|
|
|
149
241
|
for parameter in parameters:
|
|
242
|
+
|
|
243
|
+
if (
|
|
244
|
+
parameter.location == ParameterLocation.Body and
|
|
245
|
+
(parameter.is_data_input or parameter.is_multipart) and
|
|
246
|
+
not parameter.is_body_kwarg
|
|
247
|
+
):
|
|
248
|
+
# if i am a part of files or data, and i'm not the files or
|
|
249
|
+
# data kwarg, ignore me
|
|
250
|
+
continue
|
|
150
251
|
if (
|
|
151
252
|
parameter.location == ParameterLocation.Body and
|
|
152
|
-
parameter.
|
|
253
|
+
not parameter.is_body_kwarg and
|
|
254
|
+
not parameter.constant
|
|
153
255
|
):
|
|
154
256
|
# we keep the original body param from the swagger for documentation purposes
|
|
155
257
|
# we don't want it in the method signature
|
|
@@ -19,10 +19,11 @@ class Rest(BaseModel):
|
|
|
19
19
|
super(Rest, self). __init__(yaml_data=yaml_data)
|
|
20
20
|
self.request_builders = request_builders
|
|
21
21
|
|
|
22
|
-
def imports(self) -> FileImport:
|
|
22
|
+
def imports(self, builder_group_name: str) -> FileImport:
|
|
23
23
|
file_import = FileImport()
|
|
24
24
|
for request_builder in self.request_builders:
|
|
25
|
-
|
|
25
|
+
if request_builder.builder_group_name == builder_group_name:
|
|
26
|
+
file_import.merge(request_builder.imports())
|
|
26
27
|
return file_import
|
|
27
28
|
|
|
28
29
|
@classmethod
|
|
@@ -13,26 +13,13 @@ class SchemaRequest(BaseModel):
|
|
|
13
13
|
def __init__(
|
|
14
14
|
self,
|
|
15
15
|
yaml_data: Dict[str, Any],
|
|
16
|
-
|
|
16
|
+
content_types: List[str],
|
|
17
17
|
parameters: ParameterList,
|
|
18
18
|
) -> None:
|
|
19
19
|
super().__init__(yaml_data)
|
|
20
|
-
self.
|
|
20
|
+
self.content_types = content_types
|
|
21
21
|
self.parameters = parameters
|
|
22
22
|
|
|
23
|
-
@property
|
|
24
|
-
def pre_semicolon_media_types(self) -> List[str]:
|
|
25
|
-
"""Splits on semicolon of media types and returns the first half.
|
|
26
|
-
I.e. ["text/plain; encoding=UTF-8"] -> ["text/plain"]
|
|
27
|
-
"""
|
|
28
|
-
return [media_type.split(";")[0] for media_type in self.media_types]
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def body_parameter_has_schema(self) -> bool:
|
|
32
|
-
"""Tell if that request has a parameter that defines a body.
|
|
33
|
-
"""
|
|
34
|
-
return any([p for p in self.parameters if hasattr(p, 'schema') and p.schema])
|
|
35
|
-
|
|
36
23
|
@property
|
|
37
24
|
def is_stream_request(self) -> bool:
|
|
38
25
|
"""Is the request expected to be streamable, like a download."""
|
|
@@ -50,9 +37,9 @@ class SchemaRequest(BaseModel):
|
|
|
50
37
|
|
|
51
38
|
return cls(
|
|
52
39
|
yaml_data=yaml_data,
|
|
53
|
-
|
|
40
|
+
content_types=yaml_data["protocol"]["http"].get("mediaTypes", []),
|
|
54
41
|
parameters=ParameterList(code_model, parameters)
|
|
55
42
|
)
|
|
56
43
|
|
|
57
44
|
def __repr__(self) -> str:
|
|
58
|
-
return f"<{self.__class__.__name__} {self.
|
|
45
|
+
return f"<{self.__class__.__name__} {self.content_types}>"
|
|
@@ -26,14 +26,14 @@ class SchemaResponse(BaseModel):
|
|
|
26
26
|
self,
|
|
27
27
|
yaml_data: Dict[str, Any],
|
|
28
28
|
schema: Optional[BaseSchema],
|
|
29
|
-
|
|
29
|
+
content_types: List[str],
|
|
30
30
|
status_codes: List[Union[str, int]],
|
|
31
31
|
headers: List[HeaderResponse],
|
|
32
32
|
binary: bool,
|
|
33
33
|
) -> None:
|
|
34
34
|
super().__init__(yaml_data)
|
|
35
35
|
self.schema = schema
|
|
36
|
-
self.
|
|
36
|
+
self.content_types = content_types
|
|
37
37
|
self.status_codes = status_codes
|
|
38
38
|
self.headers = headers
|
|
39
39
|
self.binary = binary
|
|
@@ -94,7 +94,7 @@ class SchemaResponse(BaseModel):
|
|
|
94
94
|
|
|
95
95
|
@property
|
|
96
96
|
def is_xml(self) -> bool:
|
|
97
|
-
return any(["xml" in ct for ct in self.
|
|
97
|
+
return any(["xml" in ct for ct in self.content_types])
|
|
98
98
|
|
|
99
99
|
def imports(self, code_model) -> FileImport:
|
|
100
100
|
file_import = FileImport()
|
|
@@ -108,7 +108,7 @@ class SchemaResponse(BaseModel):
|
|
|
108
108
|
return cls(
|
|
109
109
|
yaml_data=yaml_data,
|
|
110
110
|
schema=yaml_data.get("schema", None), # FIXME replace by operation model
|
|
111
|
-
|
|
111
|
+
content_types=yaml_data["protocol"]["http"].get("mediaTypes", []),
|
|
112
112
|
status_codes=[
|
|
113
113
|
int(code) if code != "default" else "default" for code in yaml_data["protocol"]["http"]["statusCodes"]
|
|
114
114
|
],
|
|
@@ -3,29 +3,32 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import List, Optional
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from jinja2 import PackageLoader, Environment
|
|
9
9
|
from autorest.codegen.models.operation_group import OperationGroup
|
|
10
10
|
|
|
11
11
|
from ...jsonrpc import AutorestAPI
|
|
12
|
-
from ..models import
|
|
13
|
-
|
|
12
|
+
from ..models import (
|
|
13
|
+
CodeModel,
|
|
14
|
+
OperationGroup,
|
|
15
|
+
RequestBuilder,
|
|
16
|
+
)
|
|
14
17
|
from .enum_serializer import EnumSerializer
|
|
15
18
|
from .general_serializer import GeneralSerializer
|
|
16
19
|
from .model_generic_serializer import ModelGenericSerializer
|
|
17
20
|
from .model_init_serializer import ModelInitSerializer
|
|
18
21
|
from .model_python3_serializer import ModelPython3Serializer
|
|
19
22
|
from .operations_init_serializer import OperationsInitSerializer
|
|
20
|
-
from .
|
|
23
|
+
from .operation_groups_serializer import OperationGroupsSerializer
|
|
21
24
|
from .metadata_serializer import MetadataSerializer
|
|
22
25
|
from .rest_serializer import RestPython3Serializer, RestGenericSerializer, RestSerializer
|
|
26
|
+
from .patch_serializer import PatchSerializer
|
|
23
27
|
|
|
24
28
|
__all__ = [
|
|
25
29
|
"JinjaSerializer",
|
|
26
30
|
]
|
|
27
31
|
|
|
28
|
-
|
|
29
32
|
class JinjaSerializer:
|
|
30
33
|
def __init__(self, autorestapi: AutorestAPI) -> None:
|
|
31
34
|
self._autorestapi = autorestapi
|
|
@@ -45,11 +48,8 @@ class JinjaSerializer:
|
|
|
45
48
|
)
|
|
46
49
|
|
|
47
50
|
# if there was a patch file before, we keep it
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
namespace_path / Path("_patch.py"),
|
|
51
|
-
self._autorestapi.read_file(namespace_path / "_patch.py")
|
|
52
|
-
)
|
|
51
|
+
self._keep_patch_file(namespace_path / Path("_patch.py"), env)
|
|
52
|
+
self._keep_patch_file(namespace_path / Path("aio") / Path("_patch.py"), env)
|
|
53
53
|
|
|
54
54
|
self._serialize_and_write_top_level_folder(code_model=code_model, env=env, namespace_path=namespace_path)
|
|
55
55
|
|
|
@@ -72,11 +72,19 @@ class JinjaSerializer:
|
|
|
72
72
|
self._serialize_and_write_models_folder(code_model=code_model, env=env, namespace_path=namespace_path)
|
|
73
73
|
|
|
74
74
|
|
|
75
|
+
|
|
76
|
+
def _keep_patch_file(self, path_file: Path, env: Environment):
|
|
77
|
+
if self._autorestapi.read_file(path_file):
|
|
78
|
+
self._autorestapi.write_file(path_file, self._autorestapi.read_file(path_file))
|
|
79
|
+
else:
|
|
80
|
+
self._autorestapi.write_file(path_file, PatchSerializer(env=env).serialize())
|
|
81
|
+
|
|
82
|
+
|
|
75
83
|
def _serialize_and_write_models_folder(self, code_model: CodeModel, env: Environment, namespace_path: Path) -> None:
|
|
76
84
|
# Write the models folder
|
|
77
85
|
models_path = namespace_path / Path("models")
|
|
78
86
|
if code_model.schemas:
|
|
79
|
-
if not code_model.options['
|
|
87
|
+
if not code_model.options['python3_only']:
|
|
80
88
|
self._autorestapi.write_file(
|
|
81
89
|
models_path / Path("_models.py"), ModelGenericSerializer(code_model=code_model, env=env).serialize()
|
|
82
90
|
)
|
|
@@ -141,96 +149,92 @@ class JinjaSerializer:
|
|
|
141
149
|
).serialize_init()
|
|
142
150
|
)
|
|
143
151
|
|
|
144
|
-
def
|
|
152
|
+
def _serialize_and_write_operations_file(
|
|
145
153
|
self,
|
|
146
154
|
code_model: CodeModel,
|
|
147
155
|
env: Environment,
|
|
148
156
|
namespace_path: Path,
|
|
149
|
-
|
|
150
|
-
filename: str
|
|
157
|
+
operation_group: Optional[OperationGroup] = None
|
|
151
158
|
) -> None:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
filename = operation_group.filename if operation_group else "_operations"
|
|
160
|
+
# write first sync file
|
|
161
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
162
|
+
code_model=code_model,
|
|
163
|
+
env=env,
|
|
164
|
+
async_mode=False,
|
|
165
|
+
is_python3_file=code_model.options['python3_only'],
|
|
166
|
+
operation_group=operation_group
|
|
167
|
+
)
|
|
168
|
+
self._autorestapi.write_file(
|
|
169
|
+
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}.py"),
|
|
170
|
+
operation_group_serializer.serialize(),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if not code_model.options['python3_only'] and code_model.options["add_python3_operation_files"]:
|
|
174
|
+
# write typed second file if not python 3 only
|
|
175
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
155
176
|
code_model=code_model,
|
|
156
177
|
env=env,
|
|
157
|
-
operation_groups=operation_groups,
|
|
158
178
|
async_mode=False,
|
|
159
|
-
|
|
179
|
+
is_python3_file=True,
|
|
180
|
+
|
|
160
181
|
)
|
|
161
182
|
self._autorestapi.write_file(
|
|
162
|
-
namespace_path / Path(
|
|
183
|
+
namespace_path / Path(code_model.operations_folder_name) / Path(f"{filename}_py3.py"),
|
|
163
184
|
operation_group_serializer.serialize(),
|
|
164
185
|
)
|
|
165
186
|
|
|
166
187
|
if not code_model.options["no_async"]:
|
|
167
188
|
# write async operation group and operation files
|
|
168
|
-
operation_group_async_serializer =
|
|
189
|
+
operation_group_async_serializer = OperationGroupsSerializer(
|
|
169
190
|
code_model=code_model,
|
|
170
191
|
env=env,
|
|
171
|
-
operation_groups=operation_groups,
|
|
172
192
|
async_mode=True,
|
|
173
|
-
|
|
193
|
+
is_python3_file=True,
|
|
194
|
+
operation_group=operation_group
|
|
174
195
|
)
|
|
175
196
|
self._autorestapi.write_file(
|
|
176
197
|
(
|
|
177
198
|
namespace_path
|
|
178
199
|
/ Path("aio")
|
|
179
|
-
/ Path(
|
|
200
|
+
/ Path(code_model.operations_folder_name)
|
|
180
201
|
/ Path(f"{filename}.py")
|
|
181
202
|
),
|
|
182
203
|
operation_group_async_serializer.serialize(),
|
|
183
204
|
)
|
|
184
205
|
|
|
185
|
-
if code_model.options["add_python_3_operation_files"]:
|
|
186
|
-
# write typed sync operation files
|
|
187
|
-
operation_group_serializer = OperationGroupSerializer(
|
|
188
|
-
code_model=code_model,
|
|
189
|
-
env=env,
|
|
190
|
-
operation_groups=operation_groups,
|
|
191
|
-
async_mode=False,
|
|
192
|
-
is_python_3_file=True,
|
|
193
|
-
)
|
|
194
|
-
self._autorestapi.write_file(
|
|
195
|
-
namespace_path / Path(f"operations") / Path(f"{filename}_py3.py"),
|
|
196
|
-
operation_group_serializer.serialize(),
|
|
197
|
-
)
|
|
198
|
-
|
|
199
206
|
def _serialize_and_write_operations_folder(
|
|
200
207
|
self, code_model: CodeModel, env: Environment, namespace_path: Path
|
|
201
208
|
) -> None:
|
|
202
209
|
# write sync operations init file
|
|
203
210
|
operations_init_serializer = OperationsInitSerializer(code_model=code_model, env=env, async_mode=False)
|
|
204
211
|
self._autorestapi.write_file(
|
|
205
|
-
namespace_path / Path(
|
|
212
|
+
namespace_path / Path(code_model.operations_folder_name) / Path("__init__.py"),
|
|
213
|
+
operations_init_serializer.serialize(),
|
|
206
214
|
)
|
|
207
215
|
|
|
208
216
|
# write async operations init file
|
|
209
217
|
if not code_model.options["no_async"]:
|
|
210
218
|
operations_async_init_serializer = OperationsInitSerializer(code_model=code_model, env=env, async_mode=True)
|
|
211
219
|
self._autorestapi.write_file(
|
|
212
|
-
namespace_path / Path("aio") / Path(
|
|
220
|
+
namespace_path / Path("aio") / Path(code_model.operations_folder_name) / Path("__init__.py"),
|
|
213
221
|
operations_async_init_serializer.serialize(),
|
|
214
222
|
)
|
|
215
223
|
|
|
216
|
-
if
|
|
224
|
+
if code_model.options["combine_operation_files"]:
|
|
225
|
+
self._serialize_and_write_operations_file(
|
|
226
|
+
code_model=code_model,
|
|
227
|
+
env=env,
|
|
228
|
+
namespace_path=namespace_path,
|
|
229
|
+
)
|
|
230
|
+
else:
|
|
217
231
|
for operation_group in code_model.operation_groups:
|
|
218
|
-
self.
|
|
232
|
+
self._serialize_and_write_operations_file(
|
|
219
233
|
code_model=code_model,
|
|
220
234
|
env=env,
|
|
221
235
|
namespace_path=namespace_path,
|
|
222
|
-
|
|
223
|
-
filename=operation_group.filename
|
|
236
|
+
operation_group=operation_group,
|
|
224
237
|
)
|
|
225
|
-
else:
|
|
226
|
-
self._serialize_and_write_operations_folder_process(
|
|
227
|
-
code_model=code_model,
|
|
228
|
-
env=env,
|
|
229
|
-
namespace_path=namespace_path,
|
|
230
|
-
operation_groups=code_model.operation_groups,
|
|
231
|
-
filename="_operations"
|
|
232
|
-
)
|
|
233
|
-
|
|
234
238
|
|
|
235
239
|
def _serialize_and_write_version_file(
|
|
236
240
|
self, code_model: CodeModel, namespace_path: Path, general_serializer: GeneralSerializer
|