@autorest/python 5.15.0 → 5.16.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 +20 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +145 -73
- package/autorest/codegen/models/__init__.py +29 -18
- package/autorest/codegen/models/base_builder.py +48 -11
- package/autorest/codegen/models/base_model.py +6 -4
- package/autorest/codegen/models/base_schema.py +19 -18
- package/autorest/codegen/models/client.py +65 -21
- package/autorest/codegen/models/code_model.py +107 -61
- package/autorest/codegen/models/constant_schema.py +25 -13
- package/autorest/codegen/models/credential_model.py +23 -15
- package/autorest/codegen/models/credential_schema.py +18 -14
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +20 -17
- package/autorest/codegen/models/enum_schema.py +35 -25
- package/autorest/codegen/models/imports.py +70 -41
- package/autorest/codegen/models/list_schema.py +25 -13
- package/autorest/codegen/models/lro_operation.py +58 -22
- package/autorest/codegen/models/lro_paging_operation.py +2 -3
- package/autorest/codegen/models/object_schema.py +99 -49
- package/autorest/codegen/models/operation.py +236 -117
- package/autorest/codegen/models/operation_group.py +64 -34
- package/autorest/codegen/models/paging_operation.py +45 -18
- package/autorest/codegen/models/parameter.py +151 -83
- package/autorest/codegen/models/parameter_list.py +183 -162
- package/autorest/codegen/models/primitive_schemas.py +84 -55
- package/autorest/codegen/models/property.py +44 -26
- package/autorest/codegen/models/request_builder.py +65 -30
- package/autorest/codegen/models/request_builder_parameter.py +47 -23
- package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
- package/autorest/codegen/models/schema_request.py +16 -6
- package/autorest/codegen/models/schema_response.py +18 -13
- package/autorest/codegen/models/utils.py +5 -2
- package/autorest/codegen/serializers/__init__.py +182 -91
- package/autorest/codegen/serializers/builder_serializer.py +667 -331
- package/autorest/codegen/serializers/client_serializer.py +98 -37
- package/autorest/codegen/serializers/general_serializer.py +61 -26
- package/autorest/codegen/serializers/import_serializer.py +93 -31
- package/autorest/codegen/serializers/metadata_serializer.py +73 -24
- package/autorest/codegen/serializers/model_base_serializer.py +35 -15
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
- package/autorest/codegen/serializers/model_init_serializer.py +5 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +4 -1
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +35 -21
- package/autorest/codegen/templates/init.py.jinja2 +2 -2
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
- package/autorest/codegen/templates/operation.py.jinja2 +7 -9
- package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +13 -6
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +24 -17
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +18 -23
- package/autorest/multiapi/serializers/import_serializer.py +47 -17
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/namer/__init__.py +2 -4
- package/autorest/namer/name_converter.py +200 -103
- package/autorest/namer/python_mappings.py +10 -22
- package/package.json +2 -2
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/rest.py +0 -42
|
@@ -6,21 +6,24 @@
|
|
|
6
6
|
import logging
|
|
7
7
|
import datetime
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import cast, Any, Dict, List, Optional, Union
|
|
9
|
+
from typing import cast, Any, Dict, List, Optional, Union, TYPE_CHECKING
|
|
10
10
|
|
|
11
11
|
from .base_schema import BaseSchema
|
|
12
12
|
from .imports import FileImport, ImportType, TypingSection
|
|
13
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from .code_model import CodeModel
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
_LOGGER = logging.getLogger(__name__)
|
|
16
19
|
|
|
20
|
+
|
|
17
21
|
class RawString(object):
|
|
18
22
|
def __init__(self, string: str) -> None:
|
|
19
23
|
self.string = string
|
|
20
24
|
|
|
21
25
|
def __repr__(self) -> str:
|
|
22
|
-
return "r'{}'".format(self.string.replace('
|
|
23
|
-
|
|
26
|
+
return "r'{}'".format(self.string.replace("'", "\\'"))
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
class PrimitiveSchema(BaseSchema):
|
|
@@ -39,7 +42,9 @@ class PrimitiveSchema(BaseSchema):
|
|
|
39
42
|
def docstring_type(self) -> str:
|
|
40
43
|
return self._to_python_type()
|
|
41
44
|
|
|
42
|
-
def type_annotation(
|
|
45
|
+
def type_annotation(
|
|
46
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
47
|
+
) -> str:
|
|
43
48
|
return self.docstring_type
|
|
44
49
|
|
|
45
50
|
@property
|
|
@@ -69,28 +74,18 @@ class PrimitiveSchema(BaseSchema):
|
|
|
69
74
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
70
75
|
if self.default_value:
|
|
71
76
|
kwargs["default_value_declaration"] = kwargs.get(
|
|
72
|
-
"default_value_declaration",
|
|
73
|
-
self.get_declaration(self.default_value)
|
|
77
|
+
"default_value_declaration", self.get_declaration(self.default_value)
|
|
74
78
|
)
|
|
75
|
-
return self._add_optional_and_default_value_template_representation(
|
|
76
|
-
**kwargs
|
|
77
|
-
)
|
|
79
|
+
return self._add_optional_and_default_value_template_representation(**kwargs)
|
|
78
80
|
|
|
79
81
|
@property
|
|
80
82
|
def default_template_representation_declaration(self) -> str:
|
|
81
83
|
return self.get_declaration(self.docstring_type)
|
|
82
84
|
|
|
83
|
-
def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
|
|
84
|
-
"""Template of what the files input should look like
|
|
85
|
-
"""
|
|
86
|
-
return self._add_optional_and_default_value_template_representation(
|
|
87
|
-
**kwargs
|
|
88
|
-
)
|
|
89
85
|
|
|
90
86
|
class IOSchema(PrimitiveSchema):
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
super(IOSchema, self).__init__(namespace=namespace, yaml_data=yaml_data)
|
|
87
|
+
def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
|
|
88
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
94
89
|
self.type = "IO"
|
|
95
90
|
|
|
96
91
|
@property
|
|
@@ -101,7 +96,9 @@ class IOSchema(PrimitiveSchema):
|
|
|
101
96
|
def docstring_type(self) -> str:
|
|
102
97
|
return self.type
|
|
103
98
|
|
|
104
|
-
def type_annotation(
|
|
99
|
+
def type_annotation(
|
|
100
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
101
|
+
) -> str:
|
|
105
102
|
return self.docstring_type
|
|
106
103
|
|
|
107
104
|
@property
|
|
@@ -114,9 +111,12 @@ class IOSchema(PrimitiveSchema):
|
|
|
114
111
|
|
|
115
112
|
def imports(self) -> FileImport:
|
|
116
113
|
file_import = FileImport()
|
|
117
|
-
file_import.add_submodule_import(
|
|
114
|
+
file_import.add_submodule_import(
|
|
115
|
+
"typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
116
|
+
)
|
|
118
117
|
return file_import
|
|
119
118
|
|
|
119
|
+
|
|
120
120
|
class AnySchema(PrimitiveSchema):
|
|
121
121
|
@property
|
|
122
122
|
def serialization_type(self) -> str:
|
|
@@ -126,7 +126,9 @@ class AnySchema(PrimitiveSchema):
|
|
|
126
126
|
def docstring_type(self) -> str:
|
|
127
127
|
return "any"
|
|
128
128
|
|
|
129
|
-
def type_annotation(
|
|
129
|
+
def type_annotation(
|
|
130
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
131
|
+
) -> str:
|
|
130
132
|
return "Any"
|
|
131
133
|
|
|
132
134
|
@property
|
|
@@ -135,22 +137,15 @@ class AnySchema(PrimitiveSchema):
|
|
|
135
137
|
|
|
136
138
|
def imports(self) -> FileImport:
|
|
137
139
|
file_import = FileImport()
|
|
138
|
-
file_import.add_submodule_import(
|
|
140
|
+
file_import.add_submodule_import(
|
|
141
|
+
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
142
|
+
)
|
|
139
143
|
return file_import
|
|
140
144
|
|
|
141
|
-
class JSONSchema(AnySchema):
|
|
142
|
-
|
|
143
|
-
@property
|
|
144
|
-
def docstring_type(self) -> str:
|
|
145
|
-
return "JSONType"
|
|
146
|
-
|
|
147
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
|
|
148
|
-
return "JSONType"
|
|
149
|
-
|
|
150
145
|
|
|
151
146
|
class NumberSchema(PrimitiveSchema):
|
|
152
|
-
def __init__(self,
|
|
153
|
-
super(
|
|
147
|
+
def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
|
|
148
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
154
149
|
self.precision = cast(int, yaml_data["precision"])
|
|
155
150
|
self.multiple = cast(int, yaml_data.get("multipleOf"))
|
|
156
151
|
self.maximum = cast(int, yaml_data.get("maximum"))
|
|
@@ -161,10 +156,18 @@ class NumberSchema(PrimitiveSchema):
|
|
|
161
156
|
@property
|
|
162
157
|
def serialization_constraints(self) -> List[str]:
|
|
163
158
|
validation_constraints = [
|
|
164
|
-
f"maximum_ex={self.maximum}"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
f"
|
|
159
|
+
f"maximum_ex={self.maximum}"
|
|
160
|
+
if self.maximum is not None and self.exclusive_maximum
|
|
161
|
+
else None,
|
|
162
|
+
f"maximum={self.maximum}"
|
|
163
|
+
if self.maximum is not None and not self.exclusive_maximum
|
|
164
|
+
else None,
|
|
165
|
+
f"minimum_ex={self.minimum}"
|
|
166
|
+
if self.minimum is not None and self.exclusive_minimum
|
|
167
|
+
else None,
|
|
168
|
+
f"minimum={self.minimum}"
|
|
169
|
+
if self.minimum is not None and not self.exclusive_minimum
|
|
170
|
+
else None,
|
|
168
171
|
f"multiple={self.multiple}" if self.multiple else None,
|
|
169
172
|
]
|
|
170
173
|
return [x for x in validation_constraints if x is not None]
|
|
@@ -202,7 +205,9 @@ class NumberSchema(PrimitiveSchema):
|
|
|
202
205
|
return "int"
|
|
203
206
|
return "float"
|
|
204
207
|
|
|
205
|
-
def type_annotation(
|
|
208
|
+
def type_annotation(
|
|
209
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
210
|
+
) -> str:
|
|
206
211
|
python_type = self.docstring_type
|
|
207
212
|
if python_type == "long":
|
|
208
213
|
return "int"
|
|
@@ -213,13 +218,18 @@ class NumberSchema(PrimitiveSchema):
|
|
|
213
218
|
default_value = 0 if self.docstring_type == "int" else 0.0
|
|
214
219
|
return self.get_declaration(default_value)
|
|
215
220
|
|
|
216
|
-
class StringSchema(PrimitiveSchema):
|
|
217
221
|
|
|
218
|
-
|
|
219
|
-
|
|
222
|
+
class StringSchema(PrimitiveSchema):
|
|
223
|
+
def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
|
|
224
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
220
225
|
self.max_length = cast(int, yaml_data.get("maxLength"))
|
|
221
226
|
self.min_length = cast(
|
|
222
|
-
int,
|
|
227
|
+
int,
|
|
228
|
+
(
|
|
229
|
+
yaml_data.get("minLength", 0)
|
|
230
|
+
if yaml_data.get("maxLength")
|
|
231
|
+
else yaml_data.get("minLength")
|
|
232
|
+
),
|
|
223
233
|
)
|
|
224
234
|
self.pattern = cast(str, yaml_data.get("pattern"))
|
|
225
235
|
|
|
@@ -249,8 +259,8 @@ class StringSchema(PrimitiveSchema):
|
|
|
249
259
|
|
|
250
260
|
|
|
251
261
|
class DatetimeSchema(PrimitiveSchema):
|
|
252
|
-
def __init__(self,
|
|
253
|
-
super(
|
|
262
|
+
def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
|
|
263
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
254
264
|
self.format = self.Formats(yaml_data["format"])
|
|
255
265
|
|
|
256
266
|
class Formats(str, Enum):
|
|
@@ -259,14 +269,19 @@ class DatetimeSchema(PrimitiveSchema):
|
|
|
259
269
|
|
|
260
270
|
@property
|
|
261
271
|
def serialization_type(self) -> str:
|
|
262
|
-
formats_to_attribute_type = {
|
|
272
|
+
formats_to_attribute_type = {
|
|
273
|
+
self.Formats.datetime: "iso-8601",
|
|
274
|
+
self.Formats.rfc1123: "rfc-1123",
|
|
275
|
+
}
|
|
263
276
|
return formats_to_attribute_type[self.format]
|
|
264
277
|
|
|
265
278
|
@property
|
|
266
279
|
def docstring_type(self) -> str:
|
|
267
280
|
return "~" + self.type_annotation()
|
|
268
281
|
|
|
269
|
-
def type_annotation(
|
|
282
|
+
def type_annotation(
|
|
283
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
284
|
+
) -> str:
|
|
270
285
|
return "datetime.datetime"
|
|
271
286
|
|
|
272
287
|
@property
|
|
@@ -288,6 +303,7 @@ class DatetimeSchema(PrimitiveSchema):
|
|
|
288
303
|
def default_template_representation_declaration(self):
|
|
289
304
|
return self.get_declaration(datetime.datetime(2020, 2, 20))
|
|
290
305
|
|
|
306
|
+
|
|
291
307
|
class TimeSchema(PrimitiveSchema):
|
|
292
308
|
@property
|
|
293
309
|
def serialization_type(self) -> str:
|
|
@@ -297,7 +313,9 @@ class TimeSchema(PrimitiveSchema):
|
|
|
297
313
|
def docstring_type(self) -> str:
|
|
298
314
|
return "~" + self.type_annotation()
|
|
299
315
|
|
|
300
|
-
def type_annotation(
|
|
316
|
+
def type_annotation(
|
|
317
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
318
|
+
) -> str:
|
|
301
319
|
return "datetime.time"
|
|
302
320
|
|
|
303
321
|
@property
|
|
@@ -329,7 +347,9 @@ class UnixTimeSchema(PrimitiveSchema):
|
|
|
329
347
|
def docstring_type(self) -> str:
|
|
330
348
|
return "~" + self.type_annotation()
|
|
331
349
|
|
|
332
|
-
def type_annotation(
|
|
350
|
+
def type_annotation(
|
|
351
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
352
|
+
) -> str:
|
|
333
353
|
return "datetime.datetime"
|
|
334
354
|
|
|
335
355
|
@property
|
|
@@ -361,7 +381,9 @@ class DateSchema(PrimitiveSchema):
|
|
|
361
381
|
def docstring_type(self) -> str:
|
|
362
382
|
return "~" + self.type_annotation()
|
|
363
383
|
|
|
364
|
-
def type_annotation(
|
|
384
|
+
def type_annotation(
|
|
385
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
386
|
+
) -> str:
|
|
365
387
|
return "datetime.date"
|
|
366
388
|
|
|
367
389
|
@property
|
|
@@ -393,7 +415,9 @@ class DurationSchema(PrimitiveSchema):
|
|
|
393
415
|
def docstring_type(self) -> str:
|
|
394
416
|
return "~" + self.type_annotation()
|
|
395
417
|
|
|
396
|
-
def type_annotation(
|
|
418
|
+
def type_annotation(
|
|
419
|
+
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
420
|
+
) -> str:
|
|
397
421
|
return "datetime.timedelta"
|
|
398
422
|
|
|
399
423
|
@property
|
|
@@ -417,8 +441,8 @@ class DurationSchema(PrimitiveSchema):
|
|
|
417
441
|
|
|
418
442
|
|
|
419
443
|
class ByteArraySchema(PrimitiveSchema):
|
|
420
|
-
def __init__(self,
|
|
421
|
-
super(
|
|
444
|
+
def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
|
|
445
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
422
446
|
self.format = self.Formats(yaml_data["format"])
|
|
423
447
|
|
|
424
448
|
class Formats(str, Enum):
|
|
@@ -443,7 +467,9 @@ class ByteArraySchema(PrimitiveSchema):
|
|
|
443
467
|
return f'bytearray("{value}", encoding="utf-8")'
|
|
444
468
|
|
|
445
469
|
|
|
446
|
-
def get_primitive_schema(
|
|
470
|
+
def get_primitive_schema(
|
|
471
|
+
yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
472
|
+
) -> "PrimitiveSchema":
|
|
447
473
|
mapping = {
|
|
448
474
|
"integer": NumberSchema,
|
|
449
475
|
"number": NumberSchema,
|
|
@@ -457,10 +483,13 @@ def get_primitive_schema(namespace: str, yaml_data: Dict[str, Any]) -> "Primitiv
|
|
|
457
483
|
"byte-array": ByteArraySchema,
|
|
458
484
|
"any": AnySchema,
|
|
459
485
|
"any-object": AnySchema,
|
|
460
|
-
"binary": IOSchema
|
|
486
|
+
"binary": IOSchema,
|
|
461
487
|
}
|
|
462
488
|
schema_type = yaml_data["type"]
|
|
463
489
|
primitive_schema = cast(
|
|
464
|
-
PrimitiveSchema,
|
|
490
|
+
PrimitiveSchema,
|
|
491
|
+
mapping.get(schema_type, PrimitiveSchema).from_yaml(
|
|
492
|
+
yaml_data=yaml_data, code_model=code_model
|
|
493
|
+
),
|
|
465
494
|
)
|
|
466
495
|
return primitive_schema
|
|
@@ -3,7 +3,7 @@
|
|
|
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 cast, Any, Dict, Union, List, Optional
|
|
6
|
+
from typing import cast, Any, Dict, Union, List, Optional, TYPE_CHECKING
|
|
7
7
|
|
|
8
8
|
from .base_model import BaseModel
|
|
9
9
|
from .constant_schema import ConstantSchema
|
|
@@ -11,19 +11,24 @@ from .imports import FileImport, ImportType, TypingSection
|
|
|
11
11
|
from .base_schema import BaseSchema
|
|
12
12
|
from .enum_schema import EnumSchema
|
|
13
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from .code_model import CodeModel
|
|
16
|
+
|
|
17
|
+
|
|
14
18
|
class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
15
19
|
def __init__(
|
|
16
20
|
self,
|
|
17
21
|
yaml_data: Dict[str, Any],
|
|
22
|
+
code_model: "CodeModel",
|
|
18
23
|
name: str,
|
|
19
24
|
schema: BaseSchema,
|
|
20
25
|
original_swagger_name: str,
|
|
21
26
|
*,
|
|
22
27
|
flattened_names: Optional[List[str]] = None,
|
|
23
28
|
description: Optional[str] = None,
|
|
24
|
-
client_default_value: Optional[Any] = None
|
|
29
|
+
client_default_value: Optional[Any] = None,
|
|
25
30
|
) -> None:
|
|
26
|
-
super().__init__(yaml_data)
|
|
31
|
+
super().__init__(yaml_data, code_model)
|
|
27
32
|
self.name = name
|
|
28
33
|
self.schema = schema
|
|
29
34
|
self.original_swagger_name = original_swagger_name
|
|
@@ -35,15 +40,18 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
35
40
|
self.client_default_value = client_default_value
|
|
36
41
|
self.description = self._create_description(description, yaml_data)
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
def _create_description(
|
|
44
|
+
self, description_input: Optional[str], yaml_data: Dict[str, Any]
|
|
45
|
+
) -> str:
|
|
46
|
+
description: str = (
|
|
47
|
+
description_input or yaml_data["language"]["python"]["description"]
|
|
48
|
+
)
|
|
41
49
|
if description and description[-1] != ".":
|
|
42
50
|
description += "."
|
|
43
51
|
if self.name == "tags":
|
|
44
52
|
description = "A set of tags. " + description
|
|
45
53
|
if self.constant:
|
|
46
|
-
description += f
|
|
54
|
+
description += f" Has constant value: {self.constant_declaration}."
|
|
47
55
|
elif self.required:
|
|
48
56
|
if description:
|
|
49
57
|
description = "Required. " + description
|
|
@@ -51,13 +59,16 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
51
59
|
description = "Required. "
|
|
52
60
|
elif isinstance(self.schema, ConstantSchema):
|
|
53
61
|
description += (
|
|
54
|
-
f" The only acceptable values to pass in are None and {self.constant_declaration}. "
|
|
55
|
-
f"The default value is {self.default_value_declaration}."
|
|
62
|
+
f" The only acceptable values to pass in are None and {self.constant_declaration}. "
|
|
63
|
+
+ f"The default value is {self.default_value_declaration}."
|
|
56
64
|
)
|
|
57
65
|
if self.is_discriminator:
|
|
58
66
|
description += "Constant filled by server. "
|
|
59
67
|
if isinstance(self.schema, EnumSchema):
|
|
60
|
-
values = [
|
|
68
|
+
values = [
|
|
69
|
+
self.schema.enum_type.get_declaration(v.value)
|
|
70
|
+
for v in self.schema.values
|
|
71
|
+
]
|
|
61
72
|
if description and description[-1] != " ":
|
|
62
73
|
description += " "
|
|
63
74
|
description += "Known values are: {}.".format(", ".join(values))
|
|
@@ -70,9 +81,9 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
70
81
|
# this bool doesn't consider you to be constant if you are a discriminator
|
|
71
82
|
# you also have to be required to be considered a constant
|
|
72
83
|
return (
|
|
73
|
-
isinstance(self.schema, ConstantSchema)
|
|
74
|
-
self.required
|
|
75
|
-
not self.is_discriminator
|
|
84
|
+
isinstance(self.schema, ConstantSchema)
|
|
85
|
+
and self.required
|
|
86
|
+
and not self.is_discriminator
|
|
76
87
|
)
|
|
77
88
|
|
|
78
89
|
@property
|
|
@@ -85,29 +96,36 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
85
96
|
if self.constant:
|
|
86
97
|
retval["constant"] = True
|
|
87
98
|
if self.schema.validation_map:
|
|
88
|
-
validation_map_from_schema = cast(
|
|
99
|
+
validation_map_from_schema = cast(
|
|
100
|
+
Dict[str, Union[bool, int, str]], self.schema.validation_map
|
|
101
|
+
)
|
|
89
102
|
retval.update(validation_map_from_schema)
|
|
90
103
|
return retval or None
|
|
91
104
|
|
|
92
105
|
@property
|
|
93
106
|
def escaped_swagger_name(self) -> str:
|
|
94
|
-
"""Return the RestAPI name correctly escaped for serialization.
|
|
95
|
-
"""
|
|
107
|
+
"""Return the RestAPI name correctly escaped for serialization."""
|
|
96
108
|
if self.flattened_names:
|
|
97
109
|
return ".".join(n.replace(".", "\\\\.") for n in self.flattened_names)
|
|
98
110
|
return self.original_swagger_name.replace(".", "\\\\.")
|
|
99
111
|
|
|
100
112
|
@classmethod
|
|
101
|
-
def from_yaml(
|
|
113
|
+
def from_yaml(
|
|
114
|
+
cls,
|
|
115
|
+
yaml_data: Dict[str, Any],
|
|
116
|
+
code_model: "CodeModel",
|
|
117
|
+
*,
|
|
118
|
+
has_additional_properties: Optional[bool] = None,
|
|
119
|
+
) -> "Property":
|
|
102
120
|
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
103
121
|
|
|
104
122
|
name = yaml_data["language"]["python"]["name"]
|
|
105
|
-
has_additional_properties = kwargs.pop("has_additional_properties", None)
|
|
106
123
|
if name == "additional_properties" and has_additional_properties:
|
|
107
124
|
name = "additional_properties1"
|
|
108
|
-
schema = build_schema(yaml_data=yaml_data["schema"],
|
|
125
|
+
schema = build_schema(yaml_data=yaml_data["schema"], code_model=code_model)
|
|
109
126
|
return cls(
|
|
110
127
|
yaml_data=yaml_data,
|
|
128
|
+
code_model=code_model,
|
|
111
129
|
name=name,
|
|
112
130
|
schema=schema,
|
|
113
131
|
original_swagger_name=yaml_data["serializedName"],
|
|
@@ -126,7 +144,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
126
144
|
return self.schema.get_declaration(self.schema.value)
|
|
127
145
|
raise ValueError(
|
|
128
146
|
"Trying to get constant declaration for a schema that is not ConstantSchema"
|
|
129
|
-
|
|
147
|
+
)
|
|
130
148
|
raise ValueError("Trying to get a declaration for a schema that doesn't exist")
|
|
131
149
|
|
|
132
150
|
@property
|
|
@@ -157,18 +175,18 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
157
175
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
158
176
|
kwargs["optional"] = not self.required
|
|
159
177
|
if self.default_value:
|
|
160
|
-
kwargs["default_value_declaration"] = self.schema.get_declaration(
|
|
178
|
+
kwargs["default_value_declaration"] = self.schema.get_declaration(
|
|
179
|
+
self.default_value
|
|
180
|
+
)
|
|
161
181
|
if self.description:
|
|
162
182
|
kwargs["description"] = self.description
|
|
163
183
|
return self.schema.get_json_template_representation(**kwargs)
|
|
164
184
|
|
|
165
|
-
def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
|
|
166
|
-
kwargs["optional"] = not self.required
|
|
167
|
-
return self.schema.get_files_and_data_template_representation(**kwargs)
|
|
168
|
-
|
|
169
185
|
def model_file_imports(self) -> FileImport:
|
|
170
186
|
file_import = self.schema.model_file_imports()
|
|
171
187
|
if not self.required:
|
|
172
|
-
file_import.add_submodule_import(
|
|
188
|
+
file_import.add_submodule_import(
|
|
189
|
+
"typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
190
|
+
)
|
|
173
191
|
file_import.merge(self.schema.model_file_imports())
|
|
174
192
|
return file_import
|
|
@@ -3,7 +3,8 @@
|
|
|
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 Any, Dict, List, TypeVar, Optional
|
|
6
|
+
from typing import Any, Dict, List, TypeVar, Optional, TYPE_CHECKING
|
|
7
|
+
import logging
|
|
7
8
|
|
|
8
9
|
from .base_builder import BaseBuilder, create_parameters
|
|
9
10
|
from .request_builder_parameter import RequestBuilderParameter
|
|
@@ -13,15 +14,20 @@ from .schema_response import SchemaResponse
|
|
|
13
14
|
from .imports import FileImport, ImportType, TypingSection
|
|
14
15
|
from .parameter import Parameter
|
|
15
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .code_model import CodeModel
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
_LOGGER = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
T = TypeVar("T")
|
|
18
23
|
OrderedSet = Dict[T, None]
|
|
19
24
|
|
|
25
|
+
|
|
20
26
|
class RequestBuilder(BaseBuilder):
|
|
21
27
|
def __init__(
|
|
22
28
|
self,
|
|
23
|
-
code_model,
|
|
24
29
|
yaml_data: Dict[str, Any],
|
|
30
|
+
code_model: "CodeModel",
|
|
25
31
|
name: str,
|
|
26
32
|
url: str,
|
|
27
33
|
method: str,
|
|
@@ -31,16 +37,20 @@ class RequestBuilder(BaseBuilder):
|
|
|
31
37
|
description: str,
|
|
32
38
|
summary: str,
|
|
33
39
|
responses: Optional[List[SchemaResponse]] = None,
|
|
40
|
+
*,
|
|
41
|
+
abstract: bool = False,
|
|
34
42
|
):
|
|
35
43
|
super().__init__(
|
|
36
|
-
code_model=code_model,
|
|
37
44
|
yaml_data=yaml_data,
|
|
45
|
+
code_model=code_model,
|
|
38
46
|
name=name,
|
|
39
47
|
description=description,
|
|
40
48
|
parameters=parameters,
|
|
41
49
|
responses=responses,
|
|
42
50
|
schema_requests=schema_requests,
|
|
43
51
|
summary=summary,
|
|
52
|
+
abstract=abstract,
|
|
53
|
+
want_tracing=False,
|
|
44
54
|
)
|
|
45
55
|
self.url = url
|
|
46
56
|
self.method = method
|
|
@@ -65,62 +75,86 @@ class RequestBuilder(BaseBuilder):
|
|
|
65
75
|
|
|
66
76
|
def imports(self) -> FileImport:
|
|
67
77
|
file_import = FileImport()
|
|
68
|
-
for parameter in self.parameters:
|
|
69
|
-
if parameter.
|
|
70
|
-
|
|
78
|
+
for parameter in self.parameters.method:
|
|
79
|
+
if self.abstract and (parameter.is_multipart or parameter.is_data_input):
|
|
80
|
+
continue
|
|
81
|
+
file_import.merge(parameter.imports())
|
|
71
82
|
|
|
72
83
|
file_import.add_submodule_import(
|
|
73
84
|
"azure.core.rest",
|
|
74
85
|
"HttpRequest",
|
|
75
86
|
ImportType.AZURECORE,
|
|
76
87
|
)
|
|
77
|
-
if self.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
if not self.abstract:
|
|
89
|
+
if self.parameters.path:
|
|
90
|
+
relative_path = ".."
|
|
91
|
+
if (
|
|
92
|
+
not self.code_model.options["builders_visibility"] == "embedded"
|
|
93
|
+
and self.operation_group_name
|
|
94
|
+
):
|
|
95
|
+
relative_path = "..." if self.operation_group_name else ".."
|
|
96
|
+
file_import.add_submodule_import(
|
|
97
|
+
f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
|
|
98
|
+
)
|
|
99
|
+
if self.parameters.headers or self.parameters.query:
|
|
100
|
+
file_import.add_submodule_import(
|
|
101
|
+
"azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
|
|
102
|
+
)
|
|
86
103
|
file_import.add_submodule_import(
|
|
87
104
|
"typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
|
|
88
105
|
)
|
|
89
106
|
file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
|
|
90
|
-
if self.parameters.has_body and (
|
|
91
|
-
self.code_model.options["builders_visibility"] != "embedded" or
|
|
92
|
-
self.code_model.options["add_python3_operation_files"]
|
|
93
|
-
):
|
|
94
|
-
file_import.define_mypy_type("JSONType", "Any")
|
|
95
107
|
return file_import
|
|
96
108
|
|
|
97
109
|
@classmethod
|
|
98
|
-
def from_yaml(
|
|
110
|
+
def from_yaml(
|
|
111
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
112
|
+
) -> "RequestBuilder":
|
|
99
113
|
|
|
100
114
|
# when combine embeded builders into one operation file, we need to avoid duplicated build function name.
|
|
101
115
|
# So add operation group name is effective method
|
|
102
116
|
additional_mark = ""
|
|
103
|
-
if
|
|
117
|
+
if (
|
|
118
|
+
code_model.options["combine_operation_files"]
|
|
119
|
+
and code_model.options["builders_visibility"] == "embedded"
|
|
120
|
+
):
|
|
104
121
|
additional_mark = yaml_data["language"]["python"]["builderGroupName"]
|
|
105
122
|
names = [
|
|
106
123
|
"build",
|
|
107
124
|
additional_mark,
|
|
108
125
|
yaml_data["language"]["python"]["name"],
|
|
109
|
-
"request"
|
|
126
|
+
"request",
|
|
110
127
|
]
|
|
111
128
|
name = "_".join([n for n in names if n])
|
|
112
129
|
|
|
113
130
|
first_request = yaml_data["requests"][0]
|
|
114
|
-
schema_requests = [
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
schema_requests = [
|
|
132
|
+
SchemaRequest.from_yaml(yaml, code_model=code_model)
|
|
133
|
+
for yaml in yaml_data["requests"]
|
|
134
|
+
]
|
|
135
|
+
parameters, multiple_content_type_parameters = create_parameters(
|
|
136
|
+
yaml_data, code_model, RequestBuilderParameter.from_yaml
|
|
117
137
|
)
|
|
118
138
|
parameter_list = RequestBuilderParameterList(
|
|
119
139
|
code_model, parameters + multiple_content_type_parameters, schema_requests
|
|
120
140
|
)
|
|
141
|
+
abstract = False
|
|
142
|
+
if (
|
|
143
|
+
code_model.options["version_tolerant"]
|
|
144
|
+
or code_model.options["low_level_client"]
|
|
145
|
+
) and any(p for p in parameter_list if p.is_multipart or p.is_data_input):
|
|
146
|
+
_LOGGER.warning(
|
|
147
|
+
'Not going to generate request_builder "%s" because it has multipart / urlencoded '
|
|
148
|
+
"body parameters. Multipart / urlencoded body parameters are not supported for version "
|
|
149
|
+
"tolerant and low level generations right now. Please write your own custom operation "
|
|
150
|
+
"in the _patch.py file following https://aka.ms/azsdk/python/dpcodegen/python/customize.",
|
|
151
|
+
name,
|
|
152
|
+
)
|
|
153
|
+
abstract = True
|
|
154
|
+
|
|
121
155
|
request_builder_class = cls(
|
|
122
|
-
code_model=code_model,
|
|
123
156
|
yaml_data=yaml_data,
|
|
157
|
+
code_model=code_model,
|
|
124
158
|
name=name,
|
|
125
159
|
url=first_request["protocol"]["http"]["path"],
|
|
126
160
|
method=first_request["protocol"]["http"]["method"].upper(),
|
|
@@ -129,10 +163,11 @@ class RequestBuilder(BaseBuilder):
|
|
|
129
163
|
parameters=parameter_list,
|
|
130
164
|
description=yaml_data["language"]["python"]["description"],
|
|
131
165
|
responses=[
|
|
132
|
-
SchemaResponse.from_yaml(yaml, code_model=code_model)
|
|
166
|
+
SchemaResponse.from_yaml(yaml, code_model=code_model)
|
|
167
|
+
for yaml in yaml_data.get("responses", [])
|
|
133
168
|
],
|
|
134
169
|
summary=yaml_data["language"]["python"].get("summary"),
|
|
170
|
+
abstract=abstract,
|
|
135
171
|
)
|
|
136
|
-
code_model.request_builder_ids[id(yaml_data)] = request_builder_class
|
|
137
172
|
parameter_list.add_body_kwargs()
|
|
138
173
|
return request_builder_class
|