@autorest/python 6.2.16 → 6.3.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/autorest/codegen/models/__init__.py +2 -1
- package/autorest/codegen/models/base.py +1 -1
- package/autorest/codegen/models/base_builder.py +1 -0
- package/autorest/codegen/models/combined_type.py +18 -0
- package/autorest/codegen/models/credential_types.py +4 -0
- package/autorest/codegen/models/dictionary_type.py +4 -0
- package/autorest/codegen/models/list_type.py +4 -0
- package/autorest/codegen/models/model_type.py +4 -0
- package/autorest/codegen/models/parameter.py +18 -19
- package/autorest/codegen/serializers/builder_serializer.py +52 -17
- package/autorest/codegen/serializers/operation_groups_serializer.py +4 -1
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/autorest/m4reformatter/__init__.py +1 -0
- package/autorest/preprocess/__init__.py +5 -1
- package/package.json +1 -1
- package/requirements.txt +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import logging
|
|
7
7
|
from typing import Any, Dict, Union
|
|
8
8
|
from .base import BaseModel
|
|
9
|
-
from .base_builder import BaseBuilder
|
|
9
|
+
from .base_builder import BaseBuilder, ParameterListType
|
|
10
10
|
from .code_model import CodeModel
|
|
11
11
|
from .client import Client
|
|
12
12
|
from .model_type import ModelType, JSONModelType, DPGModelType, MsrestModelType
|
|
@@ -116,6 +116,7 @@ __all__ = [
|
|
|
116
116
|
"CredentialType",
|
|
117
117
|
"ClientParameter",
|
|
118
118
|
"ConfigParameter",
|
|
119
|
+
"ParameterListType",
|
|
119
120
|
]
|
|
120
121
|
|
|
121
122
|
TYPE_TO_OBJECT = {
|
|
@@ -63,6 +63,7 @@ class BaseBuilder(
|
|
|
63
63
|
self.is_overload: bool = yaml_data["isOverload"]
|
|
64
64
|
self.api_versions: List[str] = yaml_data["apiVersions"]
|
|
65
65
|
self.added_on: Optional[str] = yaml_data.get("addedOn")
|
|
66
|
+
self.external_docs: Optional[Dict[str, Any]] = yaml_data.get("externalDocs")
|
|
66
67
|
|
|
67
68
|
if code_model.options["version_tolerant"] and yaml_data.get("abstract"):
|
|
68
69
|
_LOGGER.warning(
|
|
@@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional, TYPE_CHECKING
|
|
|
7
7
|
import re
|
|
8
8
|
from autorest.codegen.models.imports import FileImport, ImportType
|
|
9
9
|
from .base import BaseType
|
|
10
|
+
from .model_type import JSONModelType
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
12
13
|
from .code_model import CodeModel
|
|
@@ -111,3 +112,20 @@ class CombinedType(BaseType):
|
|
|
111
112
|
code_model,
|
|
112
113
|
[build_type(t, code_model) for t in yaml_data["types"]],
|
|
113
114
|
)
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _get_json_model_type(t: BaseType) -> Optional[JSONModelType]:
|
|
118
|
+
if isinstance(t, JSONModelType):
|
|
119
|
+
return t
|
|
120
|
+
if isinstance(t, CombinedType):
|
|
121
|
+
try:
|
|
122
|
+
return next(
|
|
123
|
+
CombinedType._get_json_model_type(sub_t) for sub_t in t.types
|
|
124
|
+
)
|
|
125
|
+
except StopIteration:
|
|
126
|
+
pass
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def json_subtype(self) -> Optional[JSONModelType]:
|
|
131
|
+
return CombinedType._get_json_model_type(self)
|
|
@@ -162,6 +162,10 @@ class TokenCredentialType(
|
|
|
162
162
|
return '"AsyncTokenCredential"'
|
|
163
163
|
return '"TokenCredential"'
|
|
164
164
|
|
|
165
|
+
@property
|
|
166
|
+
def type_description(self) -> str:
|
|
167
|
+
return "TokenCredential"
|
|
168
|
+
|
|
165
169
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
166
170
|
if kwargs.get("async_mode"):
|
|
167
171
|
return "~azure.core.credentials_async.AsyncTokenCredential"
|
|
@@ -295,6 +295,10 @@ class GeneratedModelType(ModelType): # pylint: disable=abstract-method
|
|
|
295
295
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
296
296
|
return self.name
|
|
297
297
|
|
|
298
|
+
@property
|
|
299
|
+
def type_description(self) -> str:
|
|
300
|
+
return self.name
|
|
301
|
+
|
|
298
302
|
def imports(self, **kwargs: Any) -> FileImport:
|
|
299
303
|
file_import = super().imports(**kwargs)
|
|
300
304
|
relative_path = kwargs.pop("relative_path", None)
|
|
@@ -86,6 +86,10 @@ class _ParameterBase(
|
|
|
86
86
|
self.check_client_input: bool = self.yaml_data.get("checkClientInput", False)
|
|
87
87
|
self.added_on: Optional[str] = self.yaml_data.get("addedOn")
|
|
88
88
|
self.is_api_version: bool = self.yaml_data.get("isApiVersion", False)
|
|
89
|
+
self.in_overload: bool = self.yaml_data.get("inOverload", False)
|
|
90
|
+
self.default_to_unset_sentinel: bool = self.yaml_data.get(
|
|
91
|
+
"defaultToUnsetSentinel", False
|
|
92
|
+
)
|
|
89
93
|
|
|
90
94
|
@property
|
|
91
95
|
def constant(self) -> bool:
|
|
@@ -168,6 +172,12 @@ class _ParameterBase(
|
|
|
168
172
|
file_import.merge(
|
|
169
173
|
self.type.imports(is_operation_file=True, async_mode=async_mode, **kwargs)
|
|
170
174
|
)
|
|
175
|
+
if self.default_to_unset_sentinel:
|
|
176
|
+
file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
|
|
177
|
+
file_import.define_mypy_type(
|
|
178
|
+
"_Unset: Any",
|
|
179
|
+
"object()",
|
|
180
|
+
)
|
|
171
181
|
return file_import
|
|
172
182
|
|
|
173
183
|
def imports_for_multiapi(self, async_mode: bool, **kwargs: Any) -> FileImport:
|
|
@@ -208,11 +218,13 @@ class _ParameterBase(
|
|
|
208
218
|
type_annot = self.type_annotation(async_mode=async_mode)
|
|
209
219
|
if self.client_default_value is not None or self.optional:
|
|
210
220
|
return f"{self.client_name}: {type_annot} = {self.client_default_value_declaration},"
|
|
221
|
+
if self.default_to_unset_sentinel:
|
|
222
|
+
return f"{self.client_name}: {type_annot} = _Unset,"
|
|
211
223
|
return f"{self.client_name}: {type_annot},"
|
|
212
224
|
|
|
213
225
|
|
|
214
|
-
class
|
|
215
|
-
"""
|
|
226
|
+
class BodyParameter(_ParameterBase):
|
|
227
|
+
"""Body parameter."""
|
|
216
228
|
|
|
217
229
|
@property
|
|
218
230
|
def is_partial_body(self) -> bool:
|
|
@@ -231,10 +243,6 @@ class _BodyParameterBase(_ParameterBase):
|
|
|
231
243
|
def in_method_signature(self) -> bool:
|
|
232
244
|
return not (self.flattened or self.grouped_by)
|
|
233
245
|
|
|
234
|
-
|
|
235
|
-
class BodyParameter(_BodyParameterBase):
|
|
236
|
-
"""Body parameter."""
|
|
237
|
-
|
|
238
246
|
@property
|
|
239
247
|
def content_types(self) -> List[str]:
|
|
240
248
|
return self.yaml_data["contentTypes"]
|
|
@@ -243,19 +251,11 @@ class BodyParameter(_BodyParameterBase):
|
|
|
243
251
|
def default_content_type(self) -> str:
|
|
244
252
|
return self.yaml_data["defaultContentType"]
|
|
245
253
|
|
|
246
|
-
@staticmethod
|
|
247
|
-
def _has_json_model_type(t: BaseType) -> bool:
|
|
248
|
-
if isinstance(t, JSONModelType):
|
|
249
|
-
return True
|
|
250
|
-
if isinstance(t, CombinedType):
|
|
251
|
-
for sub_t in t.types:
|
|
252
|
-
if BodyParameter._has_json_model_type(sub_t):
|
|
253
|
-
return True
|
|
254
|
-
return False
|
|
255
|
-
|
|
256
254
|
@property
|
|
257
255
|
def has_json_model_type(self) -> bool:
|
|
258
|
-
|
|
256
|
+
if isinstance(self.type, CombinedType):
|
|
257
|
+
return self.type.json_subtype is not None
|
|
258
|
+
return isinstance(self.type, JSONModelType)
|
|
259
259
|
|
|
260
260
|
@classmethod
|
|
261
261
|
def from_yaml(
|
|
@@ -327,10 +327,9 @@ class Parameter(_ParameterBase):
|
|
|
327
327
|
self.implementation: str = yaml_data["implementation"]
|
|
328
328
|
self.skip_url_encoding: bool = self.yaml_data.get("skipUrlEncoding", False)
|
|
329
329
|
self.explode: bool = self.yaml_data.get("explode", False)
|
|
330
|
-
self.in_overload: bool = self.yaml_data["inOverload"]
|
|
331
330
|
self.in_overriden: bool = self.yaml_data.get("inOverriden", False)
|
|
332
331
|
self.delimiter: Optional[ParameterDelimeter] = self.yaml_data.get("delimiter")
|
|
333
|
-
self.
|
|
332
|
+
self._default_to_unset_sentinel: bool = False
|
|
334
333
|
|
|
335
334
|
@property
|
|
336
335
|
def in_method_signature(self) -> bool:
|
|
@@ -31,10 +31,11 @@ from ..models import (
|
|
|
31
31
|
MultipartBodyParameter,
|
|
32
32
|
Property,
|
|
33
33
|
RequestBuilderType,
|
|
34
|
-
JSONModelType,
|
|
35
34
|
CombinedType,
|
|
35
|
+
ParameterListType,
|
|
36
36
|
)
|
|
37
37
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
38
|
+
from ..models.parameter_list import ParameterType
|
|
38
39
|
from . import utils
|
|
39
40
|
|
|
40
41
|
T = TypeVar("T")
|
|
@@ -148,22 +149,39 @@ def _serialize_flattened_body(body_parameter: BodyParameter) -> List[str]:
|
|
|
148
149
|
return retval
|
|
149
150
|
|
|
150
151
|
|
|
151
|
-
def _serialize_json_model_body(
|
|
152
|
+
def _serialize_json_model_body(
|
|
153
|
+
body_parameter: BodyParameter, parameters: List[ParameterType]
|
|
154
|
+
) -> List[str]:
|
|
152
155
|
retval: List[str] = []
|
|
153
156
|
if not body_parameter.property_to_parameter_name:
|
|
154
157
|
raise ValueError(
|
|
155
158
|
"This method can't be called if the operation doesn't need parameter flattening"
|
|
156
159
|
)
|
|
157
160
|
|
|
158
|
-
retval.append(f"if {body_parameter.client_name} is
|
|
161
|
+
retval.append(f"if {body_parameter.client_name} is _Unset:")
|
|
162
|
+
for p in parameters:
|
|
163
|
+
if (
|
|
164
|
+
p.client_default_value is None
|
|
165
|
+
and not p.optional
|
|
166
|
+
and p.default_to_unset_sentinel
|
|
167
|
+
):
|
|
168
|
+
retval.append(f" if {p.client_name} is _Unset:")
|
|
169
|
+
retval.append(
|
|
170
|
+
f" raise TypeError('missing required argument: {p.client_name}')"
|
|
171
|
+
)
|
|
159
172
|
parameter_string = ", \n".join(
|
|
160
173
|
f'"{property_name}": {parameter_name}'
|
|
161
174
|
for property_name, parameter_name in body_parameter.property_to_parameter_name.items()
|
|
162
175
|
)
|
|
163
176
|
model_type = cast(ModelType, body_parameter.type)
|
|
164
|
-
if isinstance(model_type, CombinedType):
|
|
165
|
-
model_type =
|
|
177
|
+
if isinstance(model_type, CombinedType) and model_type.json_subtype:
|
|
178
|
+
model_type = model_type.json_subtype
|
|
166
179
|
retval.append(f" {body_parameter.client_name} = {{{parameter_string}}}")
|
|
180
|
+
retval.append(f" {body_parameter.client_name} = {{")
|
|
181
|
+
retval.append(
|
|
182
|
+
f" k: v for k, v in {body_parameter.client_name}.items() if v is not None"
|
|
183
|
+
)
|
|
184
|
+
retval.append(" }")
|
|
167
185
|
return retval
|
|
168
186
|
|
|
169
187
|
|
|
@@ -209,6 +227,14 @@ def _api_version_validation(builder: OperationType) -> str:
|
|
|
209
227
|
return ""
|
|
210
228
|
|
|
211
229
|
|
|
230
|
+
def is_json_model_type(parameters: ParameterListType) -> bool:
|
|
231
|
+
return (
|
|
232
|
+
parameters.has_body
|
|
233
|
+
and parameters.body_parameter.has_json_model_type
|
|
234
|
+
and any(p.in_flattened_body for p in parameters.parameters)
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
|
|
212
238
|
class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-method
|
|
213
239
|
def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
|
|
214
240
|
self.code_model = code_model
|
|
@@ -334,12 +360,11 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
|
|
|
334
360
|
):
|
|
335
361
|
# No input template if now body parameter
|
|
336
362
|
return template
|
|
337
|
-
if builder.overloads:
|
|
338
|
-
# if there's overloads, we do the json input example template on the overload
|
|
339
|
-
return template
|
|
340
363
|
|
|
341
364
|
body_param = builder.parameters.body_parameter
|
|
342
|
-
if not isinstance(
|
|
365
|
+
if not isinstance(
|
|
366
|
+
body_param.type, (ListType, DictionaryType, ModelType, CombinedType)
|
|
367
|
+
):
|
|
343
368
|
return template
|
|
344
369
|
|
|
345
370
|
if (
|
|
@@ -351,8 +376,14 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
|
|
|
351
376
|
if isinstance(body_param.type, ModelType) and body_param.type.base != "json":
|
|
352
377
|
return template
|
|
353
378
|
|
|
379
|
+
json_type = body_param.type
|
|
380
|
+
if isinstance(body_param.type, CombinedType):
|
|
381
|
+
if body_param.type.json_subtype is None:
|
|
382
|
+
return template
|
|
383
|
+
json_type = body_param.type.json_subtype
|
|
384
|
+
|
|
354
385
|
polymorphic_subtypes: List[ModelType] = []
|
|
355
|
-
|
|
386
|
+
json_type.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
356
387
|
if polymorphic_subtypes:
|
|
357
388
|
# we just assume one kind of polymorphic body for input
|
|
358
389
|
discriminator_name = cast(
|
|
@@ -376,7 +407,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
|
|
|
376
407
|
"# JSON input template you can fill out and use as your body input."
|
|
377
408
|
)
|
|
378
409
|
json_template = _json_dumps_template(
|
|
379
|
-
|
|
410
|
+
json_type.get_json_template_representation(),
|
|
380
411
|
)
|
|
381
412
|
template.extend(
|
|
382
413
|
f"{builder.parameters.body_parameter.client_name} = {json_template}".splitlines()
|
|
@@ -552,6 +583,10 @@ class _OperationSerializer(
|
|
|
552
583
|
retval.append(".. warning::")
|
|
553
584
|
retval.append(" This method is deprecated")
|
|
554
585
|
retval.append("")
|
|
586
|
+
if builder.external_docs and builder.external_docs.get("url"):
|
|
587
|
+
retval.append(".. seealso::")
|
|
588
|
+
retval.append(f" - {builder.external_docs['url']}")
|
|
589
|
+
retval.append("")
|
|
555
590
|
return retval
|
|
556
591
|
|
|
557
592
|
@property
|
|
@@ -949,12 +984,12 @@ class _OperationSerializer(
|
|
|
949
984
|
if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
|
|
950
985
|
# unflatten before passing to request builder as well
|
|
951
986
|
retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
|
|
952
|
-
if (
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
987
|
+
if is_json_model_type(builder.parameters):
|
|
988
|
+
retval.extend(
|
|
989
|
+
_serialize_json_model_body(
|
|
990
|
+
builder.parameters.body_parameter, builder.parameters.parameters
|
|
991
|
+
)
|
|
992
|
+
)
|
|
958
993
|
if builder.overloads:
|
|
959
994
|
# we are only dealing with two overloads. If there are three, we generate an abstract operation
|
|
960
995
|
retval.extend(self._initialize_overloads(builder, is_paging=is_paging))
|
|
@@ -16,7 +16,10 @@ from ..models import (
|
|
|
16
16
|
Client,
|
|
17
17
|
)
|
|
18
18
|
from .import_serializer import FileImportSerializer
|
|
19
|
-
from .builder_serializer import
|
|
19
|
+
from .builder_serializer import (
|
|
20
|
+
get_operation_serializer,
|
|
21
|
+
RequestBuilderSerializer,
|
|
22
|
+
)
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
class OperationGroupsSerializer:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# coding=utf-8
|
|
6
6
|
{{ code_model.options['license_header'] }}
|
|
7
7
|
{{ imports }}
|
|
8
|
-
|
|
8
|
+
{{ unset }}
|
|
9
9
|
{% if code_model.options["builders_visibility"] == "embedded" and not async_mode %}
|
|
10
10
|
{{ op_tools.declare_serializer(code_model) }}
|
|
11
11
|
{% for operation_group in operation_groups %}
|
|
@@ -66,7 +66,7 @@ def add_overload(
|
|
|
66
66
|
overload = copy.deepcopy(yaml_data)
|
|
67
67
|
overload["isOverload"] = True
|
|
68
68
|
overload["bodyParameter"]["type"] = body_type
|
|
69
|
-
|
|
69
|
+
overload["bodyParameter"]["defaultToUnsetSentinel"] = False
|
|
70
70
|
overload["overloads"] = []
|
|
71
71
|
|
|
72
72
|
if for_flatten_params:
|
|
@@ -95,6 +95,10 @@ def add_overload(
|
|
|
95
95
|
if body_type["type"] == "binary" and len(content_types) > 1:
|
|
96
96
|
content_types = "'" + "', '".join(content_types) + "'"
|
|
97
97
|
content_type_param["description"] += f" Known values are: {content_types}."
|
|
98
|
+
overload["bodyParameter"]["inOverload"] = True
|
|
99
|
+
for parameter in overload["parameters"]:
|
|
100
|
+
parameter["inOverload"] = True
|
|
101
|
+
parameter["defaultToUnsetSentinel"] = False
|
|
98
102
|
return overload
|
|
99
103
|
|
|
100
104
|
|
package/package.json
CHANGED