@autorest/python 5.17.0 → 5.18.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 +35 -1
- package/autorest/codegen/models/base_type.py +6 -0
- package/autorest/codegen/models/dictionary_type.py +16 -1
- package/autorest/codegen/models/list_type.py +16 -1
- package/autorest/codegen/models/model_type.py +33 -10
- package/autorest/codegen/models/parameter_list.py +11 -4
- package/autorest/codegen/models/property.py +14 -0
- package/autorest/codegen/models/request_builder.py +1 -1
- package/autorest/codegen/serializers/builder_serializer.py +106 -9
- package/autorest/codegen/serializers/client_serializer.py +1 -1
- package/autorest/codegen/serializers/model_base_serializer.py +1 -1
- package/autorest/codegen/serializers/utils.py +2 -0
- package/autorest/codegen/templates/model.py.jinja2 +1 -1
- package/autorest/m4reformatter/__init__.py +73 -55
- package/autorest/preprocess/__init__.py +1 -0
- package/package.json +2 -2
package/ChangeLog.md
CHANGED
|
@@ -1,4 +1,38 @@
|
|
|
1
|
-
# Change
|
|
1
|
+
# Change
|
|
2
|
+
|
|
3
|
+
### 2022-07-09 - 5.18.0
|
|
4
|
+
|
|
5
|
+
| Library | Min Version |
|
|
6
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
7
|
+
| `@autorest/core` | `3.8.1` |
|
|
8
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
9
|
+
| `azure-core` dep of generated code | `1.23.0` |
|
|
10
|
+
| `msrest` dep of generated code | `0.6.21` |
|
|
11
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
12
|
+
|
|
13
|
+
**Breaking Changes in Version Tolerant**
|
|
14
|
+
|
|
15
|
+
- No longer allow users to specify `api_version` on the method level #1281
|
|
16
|
+
- Make `content_type` param required with no default if streaming with no `application/octet-stream` #1288
|
|
17
|
+
|
|
18
|
+
**Bug Fixes**
|
|
19
|
+
|
|
20
|
+
- Fix duplicate params in signature with `--payload-flattening-threshold` #1289
|
|
21
|
+
- Fix overloaded request builder signatures #1289
|
|
22
|
+
|
|
23
|
+
### 2022-xx-xx - 5.17.1
|
|
24
|
+
|
|
25
|
+
| Library | Min Version |
|
|
26
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
27
|
+
| `@autorest/core` | `3.8.1` |
|
|
28
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
29
|
+
| `azure-core` dep of generated code | `1.23.0` |
|
|
30
|
+
| `msrest` dep of generated code | `0.6.21` |
|
|
31
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
32
|
+
|
|
33
|
+
**Bug Fixes**
|
|
34
|
+
|
|
35
|
+
- Improve docstring templates, specifically for polymorphic bodies #1279
|
|
2
36
|
|
|
3
37
|
### 2022-06-02 - 5.17.0
|
|
4
38
|
|
|
@@ -11,6 +11,7 @@ from .imports import FileImport
|
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from .code_model import CodeModel
|
|
14
|
+
from .model_type import ModelType
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class BaseType(BaseModel, ABC):
|
|
@@ -143,6 +144,11 @@ class BaseType(BaseModel, ABC):
|
|
|
143
144
|
"""Template of what this schema would look like as JSON input"""
|
|
144
145
|
...
|
|
145
146
|
|
|
147
|
+
def get_polymorphic_subtypes( # pylint: disable=no-self-use
|
|
148
|
+
self, polymorphic_subtypes: List["ModelType"] # pylint: disable=unused-argument
|
|
149
|
+
) -> None:
|
|
150
|
+
return None
|
|
151
|
+
|
|
146
152
|
@property
|
|
147
153
|
@abstractmethod
|
|
148
154
|
def instance_check_template(self) -> str:
|
|
@@ -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
|
-
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
6
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING, List
|
|
7
7
|
from .base_type import BaseType
|
|
8
8
|
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from .code_model import CodeModel
|
|
12
|
+
from .model_type import ModelType
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class DictionaryType(BaseType):
|
|
@@ -79,6 +80,20 @@ class DictionaryType(BaseType):
|
|
|
79
80
|
)
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
84
|
+
from .model_type import ModelType
|
|
85
|
+
|
|
86
|
+
if isinstance(self.element_type, ModelType):
|
|
87
|
+
is_polymorphic_subtype = (
|
|
88
|
+
self.element_type.discriminator_value
|
|
89
|
+
and not self.element_type.discriminated_subtypes
|
|
90
|
+
)
|
|
91
|
+
if (
|
|
92
|
+
self.element_type.name not in (m.name for m in polymorphic_subtypes)
|
|
93
|
+
and is_polymorphic_subtype
|
|
94
|
+
):
|
|
95
|
+
polymorphic_subtypes.append(self.element_type)
|
|
96
|
+
|
|
82
97
|
@classmethod
|
|
83
98
|
def from_yaml(
|
|
84
99
|
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
@@ -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
|
-
from typing import Any, Dict, Optional, Union, TYPE_CHECKING
|
|
6
|
+
from typing import Any, Dict, Optional, Union, TYPE_CHECKING, List
|
|
7
7
|
from .base_type import BaseType
|
|
8
8
|
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from .code_model import CodeModel
|
|
12
|
+
from .model_type import ModelType
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class ListType(BaseType):
|
|
@@ -104,6 +105,20 @@ class ListType(BaseType):
|
|
|
104
105
|
)
|
|
105
106
|
]
|
|
106
107
|
|
|
108
|
+
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
109
|
+
from .model_type import ModelType
|
|
110
|
+
|
|
111
|
+
if isinstance(self.element_type, ModelType):
|
|
112
|
+
is_polymorphic_subtype = (
|
|
113
|
+
self.element_type.discriminator_value
|
|
114
|
+
and not self.element_type.discriminated_subtypes
|
|
115
|
+
)
|
|
116
|
+
if (
|
|
117
|
+
self.element_type.name not in (m.name for m in polymorphic_subtypes)
|
|
118
|
+
and is_polymorphic_subtype
|
|
119
|
+
):
|
|
120
|
+
polymorphic_subtypes.append(self.element_type)
|
|
121
|
+
|
|
107
122
|
@property
|
|
108
123
|
def instance_check_template(self) -> str:
|
|
109
124
|
return "isinstance({}, list)"
|
|
@@ -47,7 +47,7 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
47
47
|
*,
|
|
48
48
|
properties: Optional[List[Property]] = None,
|
|
49
49
|
parents: Optional[List["ModelType"]] = None,
|
|
50
|
-
discriminated_subtypes: Optional[Dict[str,
|
|
50
|
+
discriminated_subtypes: Optional[Dict[str, "ModelType"]] = None,
|
|
51
51
|
) -> None:
|
|
52
52
|
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
53
53
|
self.name: str = self.yaml_data["name"]
|
|
@@ -61,6 +61,7 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
61
61
|
)
|
|
62
62
|
self._created_json_template_representation = False
|
|
63
63
|
self.is_public: bool = self.yaml_data.get("isPublic", True)
|
|
64
|
+
self.snake_case_name: str = self.yaml_data["snakeCaseName"]
|
|
64
65
|
|
|
65
66
|
@property
|
|
66
67
|
def is_xml(self) -> bool:
|
|
@@ -111,6 +112,10 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
111
112
|
# but we don't want to write a serialization context for an object.
|
|
112
113
|
return super().xml_serialization_ctxt
|
|
113
114
|
|
|
115
|
+
@property
|
|
116
|
+
def discriminated_subtypes_name_mapping(self) -> Dict[str, str]:
|
|
117
|
+
return {k: v.name for k, v in self.discriminated_subtypes.items()}
|
|
118
|
+
|
|
114
119
|
def get_json_template_representation(
|
|
115
120
|
self,
|
|
116
121
|
*,
|
|
@@ -121,6 +126,11 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
121
126
|
if self._created_json_template_representation:
|
|
122
127
|
return "..." # do this to avoid loop
|
|
123
128
|
self._created_json_template_representation = True
|
|
129
|
+
if self.discriminated_subtypes:
|
|
130
|
+
# we will instead print the discriminated subtypes
|
|
131
|
+
self._created_json_template_representation = False
|
|
132
|
+
return self.snake_case_name
|
|
133
|
+
|
|
124
134
|
# don't add additional properties, because there's not really a concept of
|
|
125
135
|
# additional properties in the template
|
|
126
136
|
representation = {
|
|
@@ -135,20 +145,30 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
135
145
|
if not (p.is_discriminator or p.client_name == "additional_properties")
|
|
136
146
|
]
|
|
137
147
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.discriminator_value or discriminator.rest_api_name
|
|
143
|
-
)
|
|
144
|
-
except StopIteration:
|
|
145
|
-
pass
|
|
148
|
+
if self.discriminator and self.discriminator_value:
|
|
149
|
+
representation[
|
|
150
|
+
f'"{self.discriminator.rest_api_name}"'
|
|
151
|
+
] = f'"{self.discriminator_value}"'
|
|
146
152
|
|
|
147
153
|
# once we've finished, we want to reset created_json_template_representation to false
|
|
148
154
|
# so we can call it again
|
|
149
155
|
self._created_json_template_representation = False
|
|
150
156
|
return representation
|
|
151
157
|
|
|
158
|
+
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
159
|
+
is_polymorphic_subtype = (
|
|
160
|
+
self.discriminator_value and not self.discriminated_subtypes
|
|
161
|
+
)
|
|
162
|
+
if (
|
|
163
|
+
self.name not in (m.name for m in polymorphic_subtypes)
|
|
164
|
+
and is_polymorphic_subtype
|
|
165
|
+
):
|
|
166
|
+
polymorphic_subtypes.append(self)
|
|
167
|
+
for discriminated_subtype in self.discriminated_subtypes.values():
|
|
168
|
+
discriminated_subtype.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
169
|
+
for property in self.properties:
|
|
170
|
+
property.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
171
|
+
|
|
152
172
|
@classmethod
|
|
153
173
|
def from_yaml(
|
|
154
174
|
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
@@ -172,7 +192,10 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
|
172
192
|
]
|
|
173
193
|
self.properties = _get_properties(self, properties)
|
|
174
194
|
# checking to see if this is a polymorphic class
|
|
175
|
-
self.discriminated_subtypes =
|
|
195
|
+
self.discriminated_subtypes = {
|
|
196
|
+
k: cast(ModelType, build_type(v, code_model))
|
|
197
|
+
for k, v in self.yaml_data.get("discriminatedSubtypes", {}).items()
|
|
198
|
+
}
|
|
176
199
|
|
|
177
200
|
@property
|
|
178
201
|
def has_readonly_or_constant_property(self) -> bool:
|
|
@@ -416,10 +416,17 @@ class RequestBuilderParameterList(_RequestBuilderParameterList):
|
|
|
416
416
|
class OverloadedRequestBuilderParameterList(_RequestBuilderParameterList):
|
|
417
417
|
"""Parameter list for OverloadedRequestBuilder"""
|
|
418
418
|
|
|
419
|
-
def
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
419
|
+
def method_signature_keyword_only(
|
|
420
|
+
self, is_python3_file: bool, async_mode: bool
|
|
421
|
+
) -> List[str]:
|
|
422
|
+
"""Signature for keyword only parameters"""
|
|
423
|
+
if not (self.keyword_only and is_python3_file):
|
|
424
|
+
return []
|
|
425
|
+
return ["*,"] + [
|
|
426
|
+
parameter.method_signature(is_python3_file, async_mode)
|
|
427
|
+
for parameter in self.keyword_only
|
|
428
|
+
if parameter.location != ParameterLocation.BODY
|
|
429
|
+
]
|
|
423
430
|
|
|
424
431
|
|
|
425
432
|
class _ClientGlobalParameterList(
|
|
@@ -13,6 +13,7 @@ from .utils import add_to_description, add_to_pylint_disable
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from .code_model import CodeModel
|
|
16
|
+
from .model_type import ModelType
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
@@ -105,6 +106,19 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
105
106
|
description=description,
|
|
106
107
|
)
|
|
107
108
|
|
|
109
|
+
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
110
|
+
from .model_type import ModelType
|
|
111
|
+
|
|
112
|
+
if isinstance(self.type, ModelType):
|
|
113
|
+
is_polymorphic_subtype = (
|
|
114
|
+
self.type.discriminator_value and not self.type.discriminated_subtypes
|
|
115
|
+
)
|
|
116
|
+
if (
|
|
117
|
+
self.type.name not in (m.name for m in polymorphic_subtypes)
|
|
118
|
+
and is_polymorphic_subtype
|
|
119
|
+
):
|
|
120
|
+
polymorphic_subtypes.append(self.type)
|
|
121
|
+
|
|
108
122
|
@property
|
|
109
123
|
def validation(self) -> Optional[Dict[str, Any]]:
|
|
110
124
|
retval: Dict[str, Any] = {}
|
|
@@ -64,7 +64,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
|
|
|
64
64
|
def response_docstring_text(self, **kwargs) -> str:
|
|
65
65
|
return (
|
|
66
66
|
"Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
|
|
67
|
-
+ "`send_request` method. See https://aka.ms/azsdk/python/
|
|
67
|
+
+ "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
|
|
68
68
|
+ "incorporate this response into your code flow."
|
|
69
69
|
)
|
|
70
70
|
|
|
@@ -30,6 +30,7 @@ from ..models import (
|
|
|
30
30
|
OverloadedRequestBuilder,
|
|
31
31
|
ConstantType,
|
|
32
32
|
MultipartBodyParameter,
|
|
33
|
+
Property,
|
|
33
34
|
RequestBuilderType,
|
|
34
35
|
)
|
|
35
36
|
from .parameter_serializer import ParameterSerializer, PopKwargType
|
|
@@ -83,6 +84,37 @@ def _json_dumps_template(template_representation: Any) -> Any:
|
|
|
83
84
|
)
|
|
84
85
|
|
|
85
86
|
|
|
87
|
+
def _get_polymorphic_subtype_template(polymorphic_subtype: ModelType) -> List[str]:
|
|
88
|
+
retval: List[str] = []
|
|
89
|
+
retval.append("")
|
|
90
|
+
retval.append(
|
|
91
|
+
f'# JSON input template for discriminator value "{polymorphic_subtype.discriminator_value}":'
|
|
92
|
+
)
|
|
93
|
+
subtype_template = _json_dumps_template(
|
|
94
|
+
polymorphic_subtype.get_json_template_representation(),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def _get_polymorphic_parent(
|
|
98
|
+
polymorphic_subtype: Optional[ModelType],
|
|
99
|
+
) -> Optional[ModelType]:
|
|
100
|
+
if not polymorphic_subtype:
|
|
101
|
+
return None
|
|
102
|
+
try:
|
|
103
|
+
return next(
|
|
104
|
+
p for p in polymorphic_subtype.parents if p.discriminated_subtypes
|
|
105
|
+
)
|
|
106
|
+
except StopIteration:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
polymorphic_parent = _get_polymorphic_parent(polymorphic_subtype)
|
|
110
|
+
while _get_polymorphic_parent(polymorphic_parent):
|
|
111
|
+
polymorphic_parent = _get_polymorphic_parent(polymorphic_parent)
|
|
112
|
+
retval.extend(
|
|
113
|
+
f"{cast(ModelType, polymorphic_parent).snake_case_name} = {subtype_template}".splitlines()
|
|
114
|
+
)
|
|
115
|
+
return retval
|
|
116
|
+
|
|
117
|
+
|
|
86
118
|
def _serialize_grouped_body(builder: BuilderType) -> List[str]:
|
|
87
119
|
retval: List[str] = []
|
|
88
120
|
for grouped_parameter in builder.parameters.grouped:
|
|
@@ -268,6 +300,11 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
|
|
|
268
300
|
return []
|
|
269
301
|
return self.param_description(builder) + self.response_docstring(builder)
|
|
270
302
|
|
|
303
|
+
@property
|
|
304
|
+
@abstractmethod
|
|
305
|
+
def _json_response_template_name(self) -> str:
|
|
306
|
+
...
|
|
307
|
+
|
|
271
308
|
def _json_input_example_template(self, builder: BuilderType) -> List[str]:
|
|
272
309
|
template: List[str] = []
|
|
273
310
|
if self.code_model.options["models_mode"]:
|
|
@@ -287,14 +324,26 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
|
|
|
287
324
|
if not isinstance(body_param.type, (ListType, DictionaryType, ModelType)):
|
|
288
325
|
return template
|
|
289
326
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
327
|
+
polymorphic_subtypes: List[ModelType] = []
|
|
328
|
+
body_param.type.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
329
|
+
if polymorphic_subtypes:
|
|
330
|
+
# we just assume one kind of polymorphic body for input
|
|
331
|
+
discriminator_name = cast(
|
|
332
|
+
Property, polymorphic_subtypes[0].discriminator
|
|
333
|
+
).rest_api_name
|
|
293
334
|
template.append(
|
|
294
|
-
"
|
|
295
|
-
|
|
296
|
-
)
|
|
335
|
+
"# The input is polymorphic. The following are possible polymorphic "
|
|
336
|
+
f'inputs based off discriminator "{discriminator_name}":'
|
|
297
337
|
)
|
|
338
|
+
for idx in range(
|
|
339
|
+
min(
|
|
340
|
+
self.code_model.options["polymorphic_examples"],
|
|
341
|
+
len(polymorphic_subtypes),
|
|
342
|
+
)
|
|
343
|
+
):
|
|
344
|
+
template.extend(
|
|
345
|
+
_get_polymorphic_subtype_template(polymorphic_subtypes[idx])
|
|
346
|
+
)
|
|
298
347
|
template.append("")
|
|
299
348
|
template.append(
|
|
300
349
|
"# JSON input template you can fill out and use as your body input."
|
|
@@ -337,7 +386,7 @@ class RequestBuilderSerializer(
|
|
|
337
386
|
def description_and_summary(self, builder: RequestBuilderType) -> List[str]:
|
|
338
387
|
retval = super().description_and_summary(builder)
|
|
339
388
|
retval += [
|
|
340
|
-
"See https://aka.ms/azsdk/python/
|
|
389
|
+
"See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this "
|
|
341
390
|
"request builder into your code flow.",
|
|
342
391
|
"",
|
|
343
392
|
]
|
|
@@ -351,6 +400,10 @@ class RequestBuilderSerializer(
|
|
|
351
400
|
def serializer_name(self) -> str:
|
|
352
401
|
return "_SERIALIZER"
|
|
353
402
|
|
|
403
|
+
@property
|
|
404
|
+
def _json_response_template_name(self) -> str:
|
|
405
|
+
return "response.json()"
|
|
406
|
+
|
|
354
407
|
@staticmethod
|
|
355
408
|
def declare_non_inputtable_constants(builder: RequestBuilderType) -> List[str]:
|
|
356
409
|
def _get_value(param):
|
|
@@ -381,7 +434,7 @@ class RequestBuilderSerializer(
|
|
|
381
434
|
def response_docstring(self, builder: RequestBuilderType) -> List[str]:
|
|
382
435
|
response_str = (
|
|
383
436
|
f":return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
|
|
384
|
-
+ "`send_request` method. See https://aka.ms/azsdk/python/
|
|
437
|
+
+ "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
|
|
385
438
|
+ "incorporate this response into your code flow."
|
|
386
439
|
)
|
|
387
440
|
rtype_str = f":rtype: ~azure.core.rest.HttpRequest"
|
|
@@ -473,10 +526,38 @@ class _OperationSerializer(
|
|
|
473
526
|
retval.append("")
|
|
474
527
|
return retval
|
|
475
528
|
|
|
529
|
+
@property
|
|
530
|
+
def _json_response_template_name(self) -> str:
|
|
531
|
+
return "response"
|
|
532
|
+
|
|
476
533
|
def example_template(self, builder: OperationType) -> List[str]:
|
|
477
534
|
retval = super().example_template(builder)
|
|
478
535
|
if self.code_model.options["models_mode"]:
|
|
479
536
|
return retval
|
|
537
|
+
for response in builder.responses:
|
|
538
|
+
polymorphic_subtypes: List[ModelType] = []
|
|
539
|
+
if not response.type:
|
|
540
|
+
continue
|
|
541
|
+
response.type.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
542
|
+
if polymorphic_subtypes:
|
|
543
|
+
# we just assume one kind of polymorphic body for input
|
|
544
|
+
discriminator_name = cast(
|
|
545
|
+
Property, polymorphic_subtypes[0].discriminator
|
|
546
|
+
).rest_api_name
|
|
547
|
+
retval.append(
|
|
548
|
+
"# The response is polymorphic. The following are possible polymorphic "
|
|
549
|
+
f'responses based off discriminator "{discriminator_name}":'
|
|
550
|
+
)
|
|
551
|
+
for idx in range(
|
|
552
|
+
min(
|
|
553
|
+
self.code_model.options["polymorphic_examples"],
|
|
554
|
+
len(polymorphic_subtypes),
|
|
555
|
+
)
|
|
556
|
+
):
|
|
557
|
+
retval.extend(
|
|
558
|
+
_get_polymorphic_subtype_template(polymorphic_subtypes[idx])
|
|
559
|
+
)
|
|
560
|
+
|
|
480
561
|
if _get_json_response_template_to_status_codes(builder):
|
|
481
562
|
retval.append("")
|
|
482
563
|
for (
|
|
@@ -488,7 +569,9 @@ class _OperationSerializer(
|
|
|
488
569
|
", ".join(status_codes)
|
|
489
570
|
)
|
|
490
571
|
)
|
|
491
|
-
retval.extend(
|
|
572
|
+
retval.extend(
|
|
573
|
+
f"{self._json_response_template_name} == {response_body}".splitlines()
|
|
574
|
+
)
|
|
492
575
|
return retval
|
|
493
576
|
|
|
494
577
|
def make_pipeline_call(self, builder: OperationType) -> List[str]:
|
|
@@ -616,6 +699,20 @@ class _OperationSerializer(
|
|
|
616
699
|
body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
|
|
617
700
|
if isinstance(body_param.type, BinaryType):
|
|
618
701
|
retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
|
|
702
|
+
if (
|
|
703
|
+
not body_param.default_content_type
|
|
704
|
+
and not next(
|
|
705
|
+
p for p in builder.parameters if p.rest_api_name == "Content-Type"
|
|
706
|
+
).optional
|
|
707
|
+
):
|
|
708
|
+
content_types = "'" + "', '".join(body_param.content_types) + "'"
|
|
709
|
+
retval.extend(
|
|
710
|
+
[
|
|
711
|
+
"if not content_type:",
|
|
712
|
+
f' raise TypeError("Missing required keyword-only argument: content_type. '
|
|
713
|
+
f'Known values are:" + "{content_types}")',
|
|
714
|
+
]
|
|
715
|
+
)
|
|
619
716
|
else:
|
|
620
717
|
retval.extend(self._serialize_body_parameter(builder))
|
|
621
718
|
return retval
|
|
@@ -224,7 +224,7 @@ class ClientSerializer:
|
|
|
224
224
|
retval.extend(self._rest_request_example(async_mode))
|
|
225
225
|
retval.append("")
|
|
226
226
|
retval.append(
|
|
227
|
-
"For more information on this code flow, see https://aka.ms/azsdk/python/
|
|
227
|
+
"For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request"
|
|
228
228
|
)
|
|
229
229
|
retval.append(f"")
|
|
230
230
|
retval.append(":param request: The network request you want to make. Required.")
|
|
@@ -127,7 +127,7 @@ class ModelBaseSerializer:
|
|
|
127
127
|
def discriminator_docstring(model: ModelType) -> str:
|
|
128
128
|
return (
|
|
129
129
|
"You probably want to use the sub-classes and not this class directly. "
|
|
130
|
-
f"Known sub-classes are: {', '.join(model.discriminated_subtypes.values())}"
|
|
130
|
+
f"Known sub-classes are: {', '.join(v.name for v in model.discriminated_subtypes.values())}"
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
@abstractmethod
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
|
|
6
8
|
def method_signature_and_response_type_annotation_template(
|
|
7
9
|
*,
|
|
8
10
|
is_python3_file: bool,
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
{% if model.discriminated_subtypes %}
|
|
46
46
|
|
|
47
47
|
_subtype_map = {
|
|
48
|
-
'{{ model.discriminator.client_name }}': {{ str(model.
|
|
48
|
+
'{{ model.discriminator.client_name }}': {{ str(model.discriminated_subtypes_name_mapping) }}
|
|
49
49
|
}
|
|
50
50
|
{% endif %}
|
|
51
51
|
{% if model.xml_map_content %}
|
|
@@ -134,7 +134,7 @@ def update_property(
|
|
|
134
134
|
|
|
135
135
|
def update_discriminated_subtypes(yaml_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
136
136
|
return {
|
|
137
|
-
obj["discriminatorValue"]: obj
|
|
137
|
+
obj["discriminatorValue"]: update_type(obj)
|
|
138
138
|
for obj in yaml_data.get("discriminator", {}).get("immediate", {}).values()
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -431,39 +431,6 @@ def update_client_url(yaml_data: Dict[str, Any]) -> str:
|
|
|
431
431
|
]["uri"]
|
|
432
432
|
|
|
433
433
|
|
|
434
|
-
def update_content_type_parameter(
|
|
435
|
-
yaml_data: Dict[str, Any],
|
|
436
|
-
body_parameter: Optional[Dict[str, Any]],
|
|
437
|
-
request_media_types: List[str],
|
|
438
|
-
*,
|
|
439
|
-
in_overload: bool = False,
|
|
440
|
-
in_overriden: bool = False,
|
|
441
|
-
) -> Dict[str, Any]:
|
|
442
|
-
# override content type type to string
|
|
443
|
-
if not body_parameter:
|
|
444
|
-
return yaml_data
|
|
445
|
-
param = copy.deepcopy(yaml_data)
|
|
446
|
-
param["schema"] = KNOWN_TYPES["string"] # override to string type
|
|
447
|
-
param["required"] = False
|
|
448
|
-
description = param["language"]["default"]["description"]
|
|
449
|
-
if description and description[-1] != ".":
|
|
450
|
-
description += "."
|
|
451
|
-
if not (in_overriden or in_overload):
|
|
452
|
-
param["inDocstring"] = False
|
|
453
|
-
elif in_overload:
|
|
454
|
-
description += (
|
|
455
|
-
" Content type parameter for "
|
|
456
|
-
f"{get_body_type_for_description(body_parameter)} body."
|
|
457
|
-
)
|
|
458
|
-
elif not in_overload:
|
|
459
|
-
content_types = "'" + "', '".join(request_media_types) + "'"
|
|
460
|
-
description += f" Known values are: {content_types}."
|
|
461
|
-
if not in_overload and not in_overriden:
|
|
462
|
-
param["clientDefaultValue"] = body_parameter["defaultContentType"]
|
|
463
|
-
param["language"]["default"]["description"] = description
|
|
464
|
-
return param
|
|
465
|
-
|
|
466
|
-
|
|
467
434
|
class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-methods
|
|
468
435
|
"""Add Python naming information."""
|
|
469
436
|
|
|
@@ -471,11 +438,23 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
471
438
|
def azure_arm(self) -> bool:
|
|
472
439
|
return bool(self._autorestapi.get_boolean_value("azure-arm"))
|
|
473
440
|
|
|
441
|
+
@property
|
|
442
|
+
def version_tolerant(self) -> bool:
|
|
443
|
+
return bool(self._autorestapi.get_boolean_value("version-tolerant"))
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def low_level_client(self) -> bool:
|
|
447
|
+
return bool(self._autorestapi.get_boolean_value("low-level-client"))
|
|
448
|
+
|
|
449
|
+
@property
|
|
450
|
+
def legacy(self) -> bool:
|
|
451
|
+
return not (self.version_tolerant or self.low_level_client)
|
|
452
|
+
|
|
474
453
|
@property
|
|
475
454
|
def default_optional_constants_to_none(self) -> bool:
|
|
476
455
|
return bool(
|
|
477
456
|
self._autorestapi.get_boolean_value("default-optional-constants-to-none")
|
|
478
|
-
or self.
|
|
457
|
+
or self.version_tolerant
|
|
479
458
|
)
|
|
480
459
|
|
|
481
460
|
def update_overloads(
|
|
@@ -689,6 +668,9 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
689
668
|
body_param["defaultContentType"] = _get_default_content_type(
|
|
690
669
|
body_param["contentTypes"]
|
|
691
670
|
)
|
|
671
|
+
# python supports IO input with all kinds of content_types
|
|
672
|
+
if body_type["type"] == "binary":
|
|
673
|
+
body_param["contentTypes"] = content_types or list(yaml_data.keys())
|
|
692
674
|
if body_param["type"]["type"] == "constant":
|
|
693
675
|
if not body_param["optional"] or (
|
|
694
676
|
body_param["optional"] and not self.default_optional_constants_to_none
|
|
@@ -771,11 +753,53 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
771
753
|
param["inFlattenedBody"] = True
|
|
772
754
|
return param
|
|
773
755
|
|
|
756
|
+
def _update_content_type_parameter(
|
|
757
|
+
self,
|
|
758
|
+
yaml_data: Dict[str, Any],
|
|
759
|
+
body_parameter: Optional[Dict[str, Any]],
|
|
760
|
+
request_media_types: List[str],
|
|
761
|
+
*,
|
|
762
|
+
in_overload: bool = False,
|
|
763
|
+
in_overriden: bool = False,
|
|
764
|
+
) -> Dict[str, Any]:
|
|
765
|
+
# override content type type to string
|
|
766
|
+
if not body_parameter:
|
|
767
|
+
return yaml_data
|
|
768
|
+
param = copy.deepcopy(yaml_data)
|
|
769
|
+
param["schema"] = KNOWN_TYPES["string"] # override to string type
|
|
770
|
+
if (
|
|
771
|
+
body_parameter["type"]["type"] == "binary"
|
|
772
|
+
and not body_parameter["defaultContentType"]
|
|
773
|
+
and not self.legacy
|
|
774
|
+
):
|
|
775
|
+
param["required"] = True
|
|
776
|
+
else:
|
|
777
|
+
param["required"] = False
|
|
778
|
+
description = param["language"]["default"]["description"]
|
|
779
|
+
if description and description[-1] != ".":
|
|
780
|
+
description += "."
|
|
781
|
+
if not (in_overriden or in_overload):
|
|
782
|
+
param["inDocstring"] = False
|
|
783
|
+
elif in_overload:
|
|
784
|
+
description += (
|
|
785
|
+
" Content type parameter for "
|
|
786
|
+
f"{get_body_type_for_description(body_parameter)} body."
|
|
787
|
+
)
|
|
788
|
+
if not in_overload or (
|
|
789
|
+
body_parameter["type"]["type"] == "binary" and len(request_media_types) > 1
|
|
790
|
+
):
|
|
791
|
+
content_types = "'" + "', '".join(request_media_types) + "'"
|
|
792
|
+
description += f" Known values are: {content_types}."
|
|
793
|
+
if not in_overload and not in_overriden:
|
|
794
|
+
param["clientDefaultValue"] = body_parameter["defaultContentType"]
|
|
795
|
+
param["language"]["default"]["description"] = description
|
|
796
|
+
return param
|
|
797
|
+
|
|
774
798
|
def _update_parameters_helper(
|
|
775
799
|
self,
|
|
776
800
|
parameters: List[Dict[str, Any]],
|
|
777
801
|
body_parameter: Optional[Dict[str, Any]],
|
|
778
|
-
|
|
802
|
+
seen_client_names: Set[str],
|
|
779
803
|
groupers: Dict[str, Dict[str, Any]],
|
|
780
804
|
request_media_types: List[str],
|
|
781
805
|
*,
|
|
@@ -785,15 +809,17 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
785
809
|
retval: List[Dict[str, Any]] = []
|
|
786
810
|
has_flattened_body = body_parameter and body_parameter.get("flattened")
|
|
787
811
|
for param in parameters:
|
|
788
|
-
|
|
812
|
+
client_name = param["language"]["default"]["name"]
|
|
789
813
|
if param["language"]["default"]["name"] == "$host" or (
|
|
790
|
-
|
|
814
|
+
client_name in seen_client_names
|
|
791
815
|
):
|
|
792
816
|
continue
|
|
817
|
+
seen_client_names.add(client_name)
|
|
793
818
|
if param.get("origin") == "modelerfour:synthesized/api-version":
|
|
794
819
|
param["inDocstring"] = False
|
|
795
|
-
|
|
796
|
-
|
|
820
|
+
if self.legacy:
|
|
821
|
+
param["implementation"] = "Method"
|
|
822
|
+
param["checkClientInput"] = True
|
|
797
823
|
if has_flattened_body and param.get("targetProperty"):
|
|
798
824
|
retval.append(self.update_flattened_parameter(param, body_parameter))
|
|
799
825
|
continue
|
|
@@ -806,8 +832,8 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
806
832
|
continue
|
|
807
833
|
if is_body(param):
|
|
808
834
|
continue
|
|
809
|
-
if
|
|
810
|
-
param =
|
|
835
|
+
if param["language"]["default"].get("serializedName") == "Content-Type":
|
|
836
|
+
param = self._update_content_type_parameter(
|
|
811
837
|
param,
|
|
812
838
|
body_parameter,
|
|
813
839
|
request_media_types,
|
|
@@ -818,7 +844,6 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
818
844
|
param, in_overload=in_overload, in_overriden=in_overriden
|
|
819
845
|
)
|
|
820
846
|
retval.append(updated_param)
|
|
821
|
-
seen_rest_api_names.add(updated_param["restApiName"])
|
|
822
847
|
return retval
|
|
823
848
|
|
|
824
849
|
def update_parameters(
|
|
@@ -830,7 +855,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
830
855
|
in_overriden: bool = False,
|
|
831
856
|
) -> List[Dict[str, Any]]:
|
|
832
857
|
retval: List[Dict[str, Any]] = []
|
|
833
|
-
|
|
858
|
+
seen_client_names: Set[str] = set()
|
|
834
859
|
groupers: Dict[str, Dict[str, Any]] = {}
|
|
835
860
|
# first update top level parameters
|
|
836
861
|
request_media_types = yaml_data.get("requestMediaTypes", [])
|
|
@@ -838,7 +863,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
838
863
|
self._update_parameters_helper(
|
|
839
864
|
yaml_data["parameters"],
|
|
840
865
|
body_parameter,
|
|
841
|
-
|
|
866
|
+
seen_client_names,
|
|
842
867
|
groupers,
|
|
843
868
|
request_media_types,
|
|
844
869
|
in_overload=in_overload,
|
|
@@ -857,7 +882,7 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
857
882
|
self._update_parameters_helper(
|
|
858
883
|
request.get("parameters", []),
|
|
859
884
|
body_parameter,
|
|
860
|
-
|
|
885
|
+
seen_client_names,
|
|
861
886
|
groupers,
|
|
862
887
|
request_media_types,
|
|
863
888
|
in_overload=in_overload,
|
|
@@ -921,15 +946,8 @@ class M4Reformatter(YamlUpdatePlugin): # pylint: disable=too-many-public-method
|
|
|
921
946
|
name = global_parameter["language"]["default"]["name"]
|
|
922
947
|
if name == "$host":
|
|
923
948
|
# I am the non-parameterized endpoint. Modify name based off of flag
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
)
|
|
927
|
-
low_level_client = self._autorestapi.get_boolean_value(
|
|
928
|
-
"low-level-client", False
|
|
929
|
-
)
|
|
930
|
-
client_name = (
|
|
931
|
-
"endpoint" if (version_tolerant or low_level_client) else "base_url"
|
|
932
|
-
)
|
|
949
|
+
|
|
950
|
+
client_name = "base_url" if self.legacy else "endpoint"
|
|
933
951
|
global_parameter["language"]["default"]["description"] = "Service URL."
|
|
934
952
|
global_params.append(
|
|
935
953
|
self.update_parameter(
|
|
@@ -62,6 +62,7 @@ def update_types(yaml_data: List[Dict[str, Any]]) -> None:
|
|
|
62
62
|
add_redefined_builtin_info(property["clientName"], property)
|
|
63
63
|
if type.get("name"):
|
|
64
64
|
type["description"] = update_description(type["description"], type["name"])
|
|
65
|
+
type["snakeCaseName"] = to_snake_case(type["name"])
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
def update_client(yaml_data: Dict[str, Any]) -> None:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autorest/python",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.18.0",
|
|
4
4
|
"description": "The Python extension for generators in AutoRest.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepare": "node run-python3.js prepare.py",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@autorest/system-requirements": "~1.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@microsoft.azure/autorest.testserver": "^3.3.
|
|
30
|
+
"@microsoft.azure/autorest.testserver": "^3.3.28"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"autorest/**/*.py",
|