@autorest/python 5.16.0 → 5.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +79 -4
- package/README.md +30 -4
- package/autorest/__init__.py +1 -1
- package/autorest/codegen/__init__.py +55 -211
- package/autorest/codegen/models/__init__.py +116 -83
- package/autorest/codegen/models/base_builder.py +49 -88
- package/autorest/codegen/models/base_model.py +1 -1
- package/autorest/codegen/models/{base_schema.py → base_type.py} +61 -39
- package/autorest/codegen/models/client.py +165 -53
- package/autorest/codegen/models/code_model.py +122 -257
- package/autorest/codegen/models/combined_type.py +107 -0
- package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
- package/autorest/codegen/models/credential_types.py +224 -0
- package/autorest/codegen/models/dictionary_type.py +131 -0
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +80 -2
- package/autorest/codegen/models/list_type.py +149 -0
- package/autorest/codegen/models/lro_operation.py +79 -156
- package/autorest/codegen/models/lro_paging_operation.py +28 -11
- package/autorest/codegen/models/model_type.py +262 -0
- package/autorest/codegen/models/operation.py +331 -298
- package/autorest/codegen/models/operation_group.py +54 -91
- package/autorest/codegen/models/paging_operation.py +82 -123
- package/autorest/codegen/models/parameter.py +289 -396
- package/autorest/codegen/models/parameter_list.py +355 -360
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +123 -139
- package/autorest/codegen/models/request_builder.py +130 -102
- package/autorest/codegen/models/request_builder_parameter.py +112 -100
- package/autorest/codegen/models/response.py +325 -0
- package/autorest/codegen/models/utils.py +12 -19
- package/autorest/codegen/serializers/__init__.py +55 -37
- package/autorest/codegen/serializers/builder_serializer.py +695 -1144
- package/autorest/codegen/serializers/client_serializer.py +92 -89
- package/autorest/codegen/serializers/general_serializer.py +15 -69
- package/autorest/codegen/serializers/import_serializer.py +7 -4
- package/autorest/codegen/serializers/metadata_serializer.py +15 -104
- package/autorest/codegen/serializers/model_base_serializer.py +49 -36
- package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
- package/autorest/codegen/serializers/model_init_serializer.py +2 -4
- package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
- package/autorest/codegen/serializers/operation_groups_serializer.py +7 -13
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/request_builders_serializer.py +13 -30
- package/autorest/codegen/serializers/utils.py +0 -140
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +10 -7
- package/autorest/codegen/templates/config.py.jinja2 +13 -13
- package/autorest/codegen/templates/enum.py.jinja2 +4 -4
- package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/init.py.jinja2 +2 -2
- package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
- package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
- package/autorest/codegen/templates/model.py.jinja2 +23 -24
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
- package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
- package/autorest/codegen/templates/operation.py.jinja2 +6 -8
- package/autorest/codegen/templates/operation_group.py.jinja2 +21 -8
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -2
- package/autorest/codegen/templates/operation_tools.jinja2 +11 -3
- package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
- package/autorest/codegen/templates/request_builder.py.jinja2 +10 -15
- package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
- package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
- package/autorest/codegen/templates/setup.py.jinja2 +13 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +11 -1
- package/autorest/jsonrpc/server.py +15 -3
- package/autorest/m4reformatter/__init__.py +1126 -0
- package/autorest/multiapi/models/client.py +12 -2
- package/autorest/multiapi/models/code_model.py +1 -1
- package/autorest/multiapi/serializers/__init__.py +18 -4
- package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
- package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
- package/autorest/postprocess/__init__.py +202 -0
- package/autorest/postprocess/get_all.py +19 -0
- package/autorest/postprocess/venvtools.py +73 -0
- package/autorest/preprocess/__init__.py +210 -0
- package/autorest/preprocess/helpers.py +54 -0
- package/autorest/{namer → preprocess}/python_mappings.py +21 -16
- package/package.json +2 -2
- package/autorest/codegen/models/credential_model.py +0 -55
- package/autorest/codegen/models/credential_schema.py +0 -95
- package/autorest/codegen/models/credential_schema_policy.py +0 -73
- package/autorest/codegen/models/dictionary_schema.py +0 -106
- package/autorest/codegen/models/enum_schema.py +0 -225
- package/autorest/codegen/models/list_schema.py +0 -135
- package/autorest/codegen/models/object_schema.py +0 -303
- package/autorest/codegen/models/primitive_schemas.py +0 -495
- package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
- package/autorest/codegen/models/schema_request.py +0 -55
- package/autorest/codegen/models/schema_response.py +0 -141
- package/autorest/namer/__init__.py +0 -23
- package/autorest/namer/name_converter.py +0 -509
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any, Dict, List, Optional, Set, Type, TYPE_CHECKING
|
|
7
|
-
from .base_schema import BaseSchema
|
|
8
|
-
from .primitive_schemas import PrimitiveSchema, get_primitive_schema, StringSchema
|
|
9
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from .code_model import CodeModel
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class EnumValue:
|
|
16
|
-
"""Model containing necessary information for a single value of an enum.
|
|
17
|
-
|
|
18
|
-
:param str name: The name of this enum value
|
|
19
|
-
:param str value: The value of this enum value
|
|
20
|
-
:param str description: Optional. The description for this enum value
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(
|
|
24
|
-
self, name: str, value: str, description: Optional[str] = None
|
|
25
|
-
) -> None:
|
|
26
|
-
self.name = name
|
|
27
|
-
self.value = value
|
|
28
|
-
self.description = description
|
|
29
|
-
|
|
30
|
-
@classmethod
|
|
31
|
-
def from_yaml(cls, yaml_data: Dict[str, Any]) -> "EnumValue":
|
|
32
|
-
"""Constructs an EnumValue from yaml data.
|
|
33
|
-
|
|
34
|
-
:param yaml_data: the yaml data from which we will construct this object
|
|
35
|
-
:type yaml_data: dict[str, Any]
|
|
36
|
-
|
|
37
|
-
:return: A created EnumValue
|
|
38
|
-
:rtype: ~autorest.models.EnumValue
|
|
39
|
-
"""
|
|
40
|
-
return cls(
|
|
41
|
-
name=yaml_data["language"]["python"]["name"],
|
|
42
|
-
value=yaml_data["value"],
|
|
43
|
-
description=yaml_data["language"]["python"].get("description"),
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class EnumSchema(BaseSchema):
|
|
48
|
-
"""Schema for enums that will be serialized.
|
|
49
|
-
|
|
50
|
-
:param yaml_data: the yaml data for this schema
|
|
51
|
-
:type yaml_data: dict[str, Any]
|
|
52
|
-
:param str description: The description of this enum
|
|
53
|
-
:param str name: The name of the enum.
|
|
54
|
-
:type element_type: ~autorest.models.PrimitiveSchema
|
|
55
|
-
:param values: List of the values for this enum
|
|
56
|
-
:type values: list[~autorest.models.EnumValue]
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
def __init__(
|
|
60
|
-
self,
|
|
61
|
-
yaml_data: Dict[str, Any],
|
|
62
|
-
code_model: "CodeModel",
|
|
63
|
-
description: str,
|
|
64
|
-
name: str,
|
|
65
|
-
values: List["EnumValue"],
|
|
66
|
-
enum_type: PrimitiveSchema,
|
|
67
|
-
) -> None:
|
|
68
|
-
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
69
|
-
self.description = description
|
|
70
|
-
self.name = name
|
|
71
|
-
self.values = values
|
|
72
|
-
self.enum_type = enum_type
|
|
73
|
-
|
|
74
|
-
def __lt__(self, other):
|
|
75
|
-
return self.name.lower() < other.name.lower()
|
|
76
|
-
|
|
77
|
-
@property
|
|
78
|
-
def serialization_type(self) -> str:
|
|
79
|
-
"""Returns the serialization value for msrest.
|
|
80
|
-
|
|
81
|
-
:return: The serialization value for msrest
|
|
82
|
-
:rtype: str
|
|
83
|
-
"""
|
|
84
|
-
return self.enum_type.serialization_type
|
|
85
|
-
|
|
86
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
87
|
-
"""The python type used for type annotation
|
|
88
|
-
|
|
89
|
-
:return: The type annotation for this schema
|
|
90
|
-
:rtype: str
|
|
91
|
-
"""
|
|
92
|
-
return f'Union[{self.enum_type.type_annotation(is_operation_file=is_operation_file)}, "_models.{self.name}"]'
|
|
93
|
-
|
|
94
|
-
def get_declaration(self, value: Any) -> str:
|
|
95
|
-
return self.enum_type.get_declaration(value)
|
|
96
|
-
|
|
97
|
-
@property
|
|
98
|
-
def docstring_text(self) -> str:
|
|
99
|
-
return self.name
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def docstring_type(self) -> str:
|
|
103
|
-
"""The python type used for RST syntax input and type annotation."""
|
|
104
|
-
return f"{self.enum_type.type_annotation()} or ~{self.code_model.namespace}.models.{self.name}"
|
|
105
|
-
|
|
106
|
-
@staticmethod
|
|
107
|
-
def _get_enum_values(yaml_data: List[Dict[str, Any]]) -> List["EnumValue"]:
|
|
108
|
-
"""Creates the list of values for this enum.
|
|
109
|
-
|
|
110
|
-
:param yaml_data: yaml data about the enum's values
|
|
111
|
-
:type yaml_data: dict[str, Any]
|
|
112
|
-
:return: The list of values for this enum
|
|
113
|
-
:rtype: list[~autorest.models.EnumValue]
|
|
114
|
-
"""
|
|
115
|
-
values = []
|
|
116
|
-
seen_enums: Set[str] = set()
|
|
117
|
-
|
|
118
|
-
for enum in yaml_data:
|
|
119
|
-
enum_name = enum["language"]["python"]["name"]
|
|
120
|
-
if enum_name in seen_enums:
|
|
121
|
-
continue
|
|
122
|
-
values.append(EnumValue.from_yaml(enum))
|
|
123
|
-
seen_enums.add(enum_name)
|
|
124
|
-
return values
|
|
125
|
-
|
|
126
|
-
def _template_kwargs(self, **kwargs: Any) -> Any:
|
|
127
|
-
if len(self.values) == 1 and not kwargs.get("default_value_declaration"):
|
|
128
|
-
kwargs["default_value_declaration"] = self.enum_type.get_declaration(
|
|
129
|
-
self.values[0].value
|
|
130
|
-
)
|
|
131
|
-
description = kwargs.pop("description", "")
|
|
132
|
-
kwargs["description"] = description
|
|
133
|
-
return kwargs
|
|
134
|
-
|
|
135
|
-
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
136
|
-
# for better display effect, use the only value instead of var type
|
|
137
|
-
return self.enum_type.get_json_template_representation(
|
|
138
|
-
**self._template_kwargs(**kwargs)
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
@classmethod
|
|
142
|
-
def from_yaml(
|
|
143
|
-
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
144
|
-
) -> "EnumSchema":
|
|
145
|
-
"""Constructs an EnumSchema from yaml data.
|
|
146
|
-
|
|
147
|
-
:param yaml_data: the yaml data from which we will construct this schema
|
|
148
|
-
:type yaml_data: dict[str, Any]
|
|
149
|
-
|
|
150
|
-
:return: A created EnumSchema
|
|
151
|
-
:rtype: ~autorest.models.EnumSchema
|
|
152
|
-
"""
|
|
153
|
-
name = yaml_data["language"]["python"]["name"]
|
|
154
|
-
|
|
155
|
-
# choice type doesn't always exist. if there is no choiceType, we default to string
|
|
156
|
-
if yaml_data.get("choiceType"):
|
|
157
|
-
enum_type = get_primitive_schema(yaml_data["choiceType"], code_model)
|
|
158
|
-
else:
|
|
159
|
-
enum_type = StringSchema({"type": "str"}, code_model)
|
|
160
|
-
values = EnumSchema._get_enum_values(yaml_data["choices"])
|
|
161
|
-
return cls(
|
|
162
|
-
yaml_data=yaml_data,
|
|
163
|
-
code_model=code_model,
|
|
164
|
-
description=yaml_data["language"]["python"]["description"],
|
|
165
|
-
name=name,
|
|
166
|
-
values=values,
|
|
167
|
-
enum_type=enum_type,
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
def imports(self) -> FileImport:
|
|
171
|
-
file_import = FileImport()
|
|
172
|
-
file_import.add_submodule_import(
|
|
173
|
-
"typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
174
|
-
)
|
|
175
|
-
file_import.merge(self.enum_type.imports())
|
|
176
|
-
return file_import
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
class HiddenModelEnumSchema(EnumSchema):
|
|
180
|
-
def imports(self) -> FileImport:
|
|
181
|
-
file_import = FileImport()
|
|
182
|
-
file_import.merge(self.enum_type.imports())
|
|
183
|
-
return file_import
|
|
184
|
-
|
|
185
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
186
|
-
"""The python type used for type annotation
|
|
187
|
-
|
|
188
|
-
:return: The type annotation for this schema
|
|
189
|
-
:rtype: str
|
|
190
|
-
"""
|
|
191
|
-
return self.enum_type.type_annotation(is_operation_file=is_operation_file)
|
|
192
|
-
|
|
193
|
-
@property
|
|
194
|
-
def docstring_text(self) -> str:
|
|
195
|
-
return (
|
|
196
|
-
f"{self.enum_type.type_annotation()}. {self.extra_description_information}"
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
@property
|
|
200
|
-
def extra_description_information(self):
|
|
201
|
-
possible_values = [self.get_declaration(v.value) for v in self.values]
|
|
202
|
-
if not possible_values:
|
|
203
|
-
return ""
|
|
204
|
-
if len(possible_values) == 1:
|
|
205
|
-
return possible_values[0]
|
|
206
|
-
if len(possible_values) == 2:
|
|
207
|
-
possible_values_str = " or ".join(possible_values)
|
|
208
|
-
else:
|
|
209
|
-
possible_values_str = (
|
|
210
|
-
", ".join(possible_values[: len(possible_values) - 1])
|
|
211
|
-
+ f", and {possible_values[-1]}"
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
return "Known values are: {}.".format(possible_values_str)
|
|
215
|
-
|
|
216
|
-
@property
|
|
217
|
-
def docstring_type(self) -> str:
|
|
218
|
-
"""The python type used for RST syntax input and type annotation."""
|
|
219
|
-
return self.enum_type.type_annotation()
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
def get_enum_schema(code_model) -> Type[EnumSchema]:
|
|
223
|
-
if code_model.options["models_mode"]:
|
|
224
|
-
return EnumSchema
|
|
225
|
-
return HiddenModelEnumSchema
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any, Dict, Optional, Union, TYPE_CHECKING
|
|
7
|
-
from .base_schema import BaseSchema
|
|
8
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from .code_model import CodeModel
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ListSchema(BaseSchema):
|
|
15
|
-
def __init__(
|
|
16
|
-
self,
|
|
17
|
-
yaml_data: Dict[str, Any],
|
|
18
|
-
code_model: "CodeModel",
|
|
19
|
-
element_type: BaseSchema,
|
|
20
|
-
*,
|
|
21
|
-
max_items: Optional[int] = None,
|
|
22
|
-
min_items: Optional[int] = None,
|
|
23
|
-
unique_items: Optional[int] = None,
|
|
24
|
-
) -> None:
|
|
25
|
-
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
26
|
-
self.element_type = element_type
|
|
27
|
-
self.max_items = max_items
|
|
28
|
-
self.min_items = min_items
|
|
29
|
-
self.unique_items = unique_items
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def serialization_type(self) -> str:
|
|
33
|
-
return f"[{self.element_type.serialization_type}]"
|
|
34
|
-
|
|
35
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
36
|
-
if self.element_type.type_annotation() == "ET.Element":
|
|
37
|
-
# this means we're version tolerant XML, we just return the XML element
|
|
38
|
-
return self.element_type.type_annotation(
|
|
39
|
-
is_operation_file=is_operation_file
|
|
40
|
-
)
|
|
41
|
-
return f"List[{self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def docstring_type(self) -> str:
|
|
45
|
-
if self.element_type.docstring_type == "ET.Element":
|
|
46
|
-
# this means we're version tolerant XML, we just return the XML element
|
|
47
|
-
return self.element_type.docstring_type
|
|
48
|
-
return f"list[{self.element_type.docstring_type}]"
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def docstring_text(self) -> str:
|
|
52
|
-
if self.element_type.docstring_text == "XML Element":
|
|
53
|
-
# this means we're version tolerant XML, we just return the XML element
|
|
54
|
-
return self.element_type.docstring_text
|
|
55
|
-
return f"list of {self.element_type.docstring_text}"
|
|
56
|
-
|
|
57
|
-
@property
|
|
58
|
-
def validation_map(self) -> Optional[Dict[str, Union[bool, int, str]]]:
|
|
59
|
-
validation_map: Dict[str, Union[bool, int, str]] = {}
|
|
60
|
-
if self.max_items:
|
|
61
|
-
validation_map["max_items"] = self.max_items
|
|
62
|
-
validation_map["min_items"] = self.min_items or 0
|
|
63
|
-
if self.min_items:
|
|
64
|
-
validation_map["min_items"] = self.min_items
|
|
65
|
-
if self.unique_items:
|
|
66
|
-
validation_map["unique"] = True
|
|
67
|
-
return validation_map or None
|
|
68
|
-
|
|
69
|
-
@property
|
|
70
|
-
def has_xml_serialization_ctxt(self) -> bool:
|
|
71
|
-
return (
|
|
72
|
-
super().has_xml_serialization_ctxt
|
|
73
|
-
or self.element_type.has_xml_serialization_ctxt
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
77
|
-
return [self.element_type.get_json_template_representation(**kwargs)]
|
|
78
|
-
|
|
79
|
-
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
80
|
-
attrs_list = []
|
|
81
|
-
base_xml_map = super().xml_serialization_ctxt()
|
|
82
|
-
if base_xml_map:
|
|
83
|
-
attrs_list.append(base_xml_map)
|
|
84
|
-
|
|
85
|
-
# Attribute at the list level
|
|
86
|
-
if self.xml_metadata.get("wrapped", False):
|
|
87
|
-
attrs_list.append("'wrapped': True")
|
|
88
|
-
|
|
89
|
-
# Attributes of the items
|
|
90
|
-
item_xml_metadata = self.element_type.xml_metadata
|
|
91
|
-
if item_xml_metadata.get("name"):
|
|
92
|
-
attrs_list.append(f"'itemsName': '{item_xml_metadata['name']}'")
|
|
93
|
-
if item_xml_metadata.get("prefix", False):
|
|
94
|
-
attrs_list.append(f"'itemsPrefix': '{item_xml_metadata['prefix']}'")
|
|
95
|
-
if item_xml_metadata.get("namespace", False):
|
|
96
|
-
attrs_list.append(f"'itemsNs': '{item_xml_metadata['namespace']}'")
|
|
97
|
-
|
|
98
|
-
return ", ".join(attrs_list)
|
|
99
|
-
|
|
100
|
-
@classmethod
|
|
101
|
-
def from_yaml(
|
|
102
|
-
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
103
|
-
) -> "ListSchema":
|
|
104
|
-
# TODO: for items, if the type is a primitive is it listed in type instead of $ref?
|
|
105
|
-
element_schema = yaml_data["elementType"]
|
|
106
|
-
|
|
107
|
-
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
108
|
-
|
|
109
|
-
element_type = build_schema(yaml_data=element_schema, code_model=code_model)
|
|
110
|
-
|
|
111
|
-
return cls(
|
|
112
|
-
yaml_data=yaml_data,
|
|
113
|
-
code_model=code_model,
|
|
114
|
-
element_type=element_type,
|
|
115
|
-
max_items=yaml_data.get("maxItems"),
|
|
116
|
-
min_items=yaml_data.get("minItems"),
|
|
117
|
-
unique_items=yaml_data.get("uniqueItems"),
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
def imports(self) -> FileImport:
|
|
121
|
-
file_import = FileImport()
|
|
122
|
-
if (
|
|
123
|
-
not self.element_type.type_annotation(is_operation_file=True)
|
|
124
|
-
== "ET.Element"
|
|
125
|
-
):
|
|
126
|
-
file_import.add_submodule_import(
|
|
127
|
-
"typing", "List", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
128
|
-
)
|
|
129
|
-
file_import.merge(self.element_type.imports())
|
|
130
|
-
return file_import
|
|
131
|
-
|
|
132
|
-
def model_file_imports(self) -> FileImport:
|
|
133
|
-
file_import = self.imports()
|
|
134
|
-
file_import.merge(self.element_type.model_file_imports())
|
|
135
|
-
return file_import
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
# -------------------------------------------------------------------------
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
-
# license information.
|
|
5
|
-
# --------------------------------------------------------------------------
|
|
6
|
-
from typing import Any, Dict, List, Optional, Union, Type, TYPE_CHECKING
|
|
7
|
-
from .base_schema import BaseSchema
|
|
8
|
-
from .dictionary_schema import DictionarySchema
|
|
9
|
-
from .property import Property
|
|
10
|
-
from .imports import FileImport, ImportModel, ImportType, TypingSection
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from .code_model import CodeModel
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class ObjectSchema(BaseSchema): # pylint: disable=too-many-instance-attributes
|
|
17
|
-
"""Represents a class ready to be serialized in Python.
|
|
18
|
-
|
|
19
|
-
:param str name: The name of the class.
|
|
20
|
-
:param str description: The description of the class.
|
|
21
|
-
:param properties: the optional properties of the class.
|
|
22
|
-
:type properties: dict(str, str)
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
yaml_data: Dict[str, Any],
|
|
28
|
-
code_model: "CodeModel",
|
|
29
|
-
name: str,
|
|
30
|
-
description: str = "",
|
|
31
|
-
**kwargs,
|
|
32
|
-
) -> None:
|
|
33
|
-
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
34
|
-
self.name = name
|
|
35
|
-
self.description = description
|
|
36
|
-
self.max_properties: Optional[int] = kwargs.pop("max_properties", None)
|
|
37
|
-
self.min_properties: Optional[int] = kwargs.pop("min_properties", None)
|
|
38
|
-
self.properties: List[Property] = kwargs.pop("properties", [])
|
|
39
|
-
self.is_exception: bool = kwargs.pop("is_exception", False)
|
|
40
|
-
self.base_models: Union[List[int], List["ObjectSchema"]] = kwargs.pop(
|
|
41
|
-
"base_models", []
|
|
42
|
-
)
|
|
43
|
-
self.subtype_map: Optional[Dict[str, str]] = kwargs.pop("subtype_map", None)
|
|
44
|
-
self.discriminator_name: Optional[str] = kwargs.pop("discriminator_name", None)
|
|
45
|
-
self.discriminator_value: Optional[str] = kwargs.pop(
|
|
46
|
-
"discriminator_value", None
|
|
47
|
-
)
|
|
48
|
-
self._created_json_template_representation = False
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def serialization_type(self) -> str:
|
|
52
|
-
return self.name
|
|
53
|
-
|
|
54
|
-
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
55
|
-
retval = f"_models.{self.name}"
|
|
56
|
-
return retval if is_operation_file else f'"{retval}"'
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def docstring_type(self) -> str:
|
|
60
|
-
return f"~{self.code_model.namespace}.models.{self.name}"
|
|
61
|
-
|
|
62
|
-
@property
|
|
63
|
-
def docstring_text(self) -> str:
|
|
64
|
-
return self.name
|
|
65
|
-
|
|
66
|
-
def get_declaration(self, value: Any) -> str:
|
|
67
|
-
return f"{self.name}()"
|
|
68
|
-
|
|
69
|
-
def __repr__(self) -> str:
|
|
70
|
-
return f"<{self.__class__.__name__} {self.name}>"
|
|
71
|
-
|
|
72
|
-
@property
|
|
73
|
-
def has_xml_serialization_ctxt(self) -> bool:
|
|
74
|
-
return False
|
|
75
|
-
|
|
76
|
-
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
77
|
-
# object schema contains _xml_map, they don't need serialization context
|
|
78
|
-
return ""
|
|
79
|
-
|
|
80
|
-
def xml_map_content(self) -> Optional[str]:
|
|
81
|
-
if not self.xml_metadata:
|
|
82
|
-
raise ValueError("This object does not contain XML metadata")
|
|
83
|
-
# This is NOT an error on the super call, we use the serialization context for "xml_map",
|
|
84
|
-
# but we don't want to write a serialization context for an object.
|
|
85
|
-
return super().xml_serialization_ctxt()
|
|
86
|
-
|
|
87
|
-
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
88
|
-
if self._created_json_template_representation:
|
|
89
|
-
return "..." # do this to avoid loop
|
|
90
|
-
self._created_json_template_representation = True
|
|
91
|
-
# don't add additional properties, because there's not really a concept of
|
|
92
|
-
# additional properties in the template
|
|
93
|
-
representation = {
|
|
94
|
-
f'"{prop.original_swagger_name}"': prop.get_json_template_representation(
|
|
95
|
-
**kwargs
|
|
96
|
-
)
|
|
97
|
-
for prop in [
|
|
98
|
-
p
|
|
99
|
-
for p in self.properties
|
|
100
|
-
if not (p.is_discriminator or p.name == "additional_properties")
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
try:
|
|
104
|
-
# add discriminator prop if there is one
|
|
105
|
-
discriminator = next(p for p in self.properties if p.is_discriminator)
|
|
106
|
-
representation[discriminator.original_swagger_name] = (
|
|
107
|
-
self.discriminator_value or discriminator.original_swagger_name
|
|
108
|
-
)
|
|
109
|
-
except StopIteration:
|
|
110
|
-
pass
|
|
111
|
-
|
|
112
|
-
# once we've finished, we want to reset created_json_template_representation to false
|
|
113
|
-
# so we can call it again
|
|
114
|
-
self._created_json_template_representation = False
|
|
115
|
-
return representation
|
|
116
|
-
|
|
117
|
-
@classmethod
|
|
118
|
-
def from_yaml(
|
|
119
|
-
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
120
|
-
) -> "ObjectSchema":
|
|
121
|
-
"""Returns a ClassType from the dict object constructed from a yaml file.
|
|
122
|
-
|
|
123
|
-
WARNING: This guy might create an infinite loop.
|
|
124
|
-
|
|
125
|
-
:param str name: The name of the class type.
|
|
126
|
-
:param yaml_data: A representation of the schema of a class type from a yaml file.
|
|
127
|
-
:type yaml_data: dict(str, str)
|
|
128
|
-
:returns: A ClassType.
|
|
129
|
-
:rtype: ~autorest.models.schema.ClassType
|
|
130
|
-
"""
|
|
131
|
-
obj = cls(yaml_data, code_model, "", description="")
|
|
132
|
-
obj.fill_instance_from_yaml(yaml_data, code_model)
|
|
133
|
-
return obj
|
|
134
|
-
|
|
135
|
-
def fill_instance_from_yaml(
|
|
136
|
-
self, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
137
|
-
) -> None:
|
|
138
|
-
properties = []
|
|
139
|
-
base_models = []
|
|
140
|
-
|
|
141
|
-
name = yaml_data["language"]["python"]["name"]
|
|
142
|
-
|
|
143
|
-
# checking to see if there is a parent class and / or additional properties
|
|
144
|
-
if yaml_data.get("parents"):
|
|
145
|
-
immediate_parents = yaml_data["parents"]["immediate"]
|
|
146
|
-
# checking if object has a parent
|
|
147
|
-
if immediate_parents:
|
|
148
|
-
for immediate_parent in immediate_parents:
|
|
149
|
-
if immediate_parent["type"] == "dictionary":
|
|
150
|
-
additional_properties_schema = DictionarySchema.from_yaml(
|
|
151
|
-
yaml_data=immediate_parent, code_model=code_model
|
|
152
|
-
)
|
|
153
|
-
properties.append(
|
|
154
|
-
Property(
|
|
155
|
-
yaml_data={},
|
|
156
|
-
code_model=code_model,
|
|
157
|
-
name="additional_properties",
|
|
158
|
-
schema=additional_properties_schema,
|
|
159
|
-
original_swagger_name="",
|
|
160
|
-
description=(
|
|
161
|
-
"Unmatched properties from the message are "
|
|
162
|
-
"deserialized to this collection."
|
|
163
|
-
),
|
|
164
|
-
)
|
|
165
|
-
)
|
|
166
|
-
elif (
|
|
167
|
-
immediate_parent["language"]["default"]["name"] != name
|
|
168
|
-
and immediate_parent["type"] == "object"
|
|
169
|
-
):
|
|
170
|
-
base_models.append(id(immediate_parent))
|
|
171
|
-
|
|
172
|
-
# checking to see if this is a polymorphic class
|
|
173
|
-
subtype_map = None
|
|
174
|
-
if yaml_data.get("discriminator"):
|
|
175
|
-
subtype_map = {}
|
|
176
|
-
# map of discriminator value to child's name
|
|
177
|
-
for children_yaml in yaml_data["discriminator"]["immediate"].values():
|
|
178
|
-
subtype_map[children_yaml["discriminatorValue"]] = children_yaml[
|
|
179
|
-
"language"
|
|
180
|
-
]["python"]["name"]
|
|
181
|
-
if yaml_data.get("properties"):
|
|
182
|
-
properties += [
|
|
183
|
-
Property.from_yaml(
|
|
184
|
-
p, code_model, has_additional_properties=len(properties) > 0
|
|
185
|
-
)
|
|
186
|
-
for p in yaml_data["properties"]
|
|
187
|
-
]
|
|
188
|
-
# this is to ensure that the attribute map type and property type are generated correctly
|
|
189
|
-
|
|
190
|
-
description = yaml_data["language"]["python"]["description"]
|
|
191
|
-
is_exception = False
|
|
192
|
-
if code_model.exception_ids:
|
|
193
|
-
if id(yaml_data) in code_model.exception_ids:
|
|
194
|
-
is_exception = True
|
|
195
|
-
|
|
196
|
-
self.yaml_data = yaml_data
|
|
197
|
-
self.name = name
|
|
198
|
-
self.description = description
|
|
199
|
-
self.properties = properties
|
|
200
|
-
self.base_models = base_models
|
|
201
|
-
self.is_exception = is_exception
|
|
202
|
-
self.subtype_map = subtype_map
|
|
203
|
-
self.discriminator_name = (
|
|
204
|
-
yaml_data["discriminator"]["property"]["language"]["python"]["name"]
|
|
205
|
-
if yaml_data.get("discriminator")
|
|
206
|
-
else None
|
|
207
|
-
)
|
|
208
|
-
self.discriminator_value = yaml_data.get("discriminatorValue", None)
|
|
209
|
-
|
|
210
|
-
@property
|
|
211
|
-
def has_readonly_or_constant_property(self) -> bool:
|
|
212
|
-
return any(x.readonly or x.constant for x in self.properties)
|
|
213
|
-
|
|
214
|
-
@property
|
|
215
|
-
def property_with_discriminator(self) -> Any:
|
|
216
|
-
try:
|
|
217
|
-
return next(
|
|
218
|
-
p
|
|
219
|
-
for p in self.properties
|
|
220
|
-
if getattr(p.schema, "discriminator_name", None)
|
|
221
|
-
)
|
|
222
|
-
except StopIteration:
|
|
223
|
-
return None
|
|
224
|
-
|
|
225
|
-
def imports(self) -> FileImport:
|
|
226
|
-
file_import = FileImport()
|
|
227
|
-
if self.is_exception:
|
|
228
|
-
file_import.add_submodule_import(
|
|
229
|
-
"azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE
|
|
230
|
-
)
|
|
231
|
-
return file_import
|
|
232
|
-
|
|
233
|
-
def model_file_imports(self) -> FileImport:
|
|
234
|
-
file_import = self.imports()
|
|
235
|
-
file_import.add_import(
|
|
236
|
-
"__init__",
|
|
237
|
-
ImportType.LOCAL,
|
|
238
|
-
typing_section=TypingSection.TYPING,
|
|
239
|
-
alias="_models",
|
|
240
|
-
)
|
|
241
|
-
return file_import
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
class HiddenModelObjectSchema(ObjectSchema):
|
|
245
|
-
@property
|
|
246
|
-
def serialization_type(self) -> str:
|
|
247
|
-
return "object"
|
|
248
|
-
|
|
249
|
-
def type_annotation(
|
|
250
|
-
self, *, is_operation_file: bool = False # pylint: disable=unused-argument
|
|
251
|
-
) -> str:
|
|
252
|
-
if self.xml_metadata:
|
|
253
|
-
return "ET.Element"
|
|
254
|
-
return "JSON"
|
|
255
|
-
|
|
256
|
-
@property
|
|
257
|
-
def docstring_type(self) -> str:
|
|
258
|
-
if self.xml_metadata:
|
|
259
|
-
return "ET.Element"
|
|
260
|
-
return "JSON"
|
|
261
|
-
|
|
262
|
-
@property
|
|
263
|
-
def docstring_text(self) -> str:
|
|
264
|
-
if self.xml_metadata:
|
|
265
|
-
return "XML Element"
|
|
266
|
-
return "JSON object"
|
|
267
|
-
|
|
268
|
-
def imports(self) -> FileImport:
|
|
269
|
-
file_import = FileImport()
|
|
270
|
-
file_import.add_submodule_import(
|
|
271
|
-
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
272
|
-
)
|
|
273
|
-
if self.xml_metadata:
|
|
274
|
-
file_import.add_submodule_import(
|
|
275
|
-
"xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
|
|
276
|
-
)
|
|
277
|
-
file_import.add_import("sys", ImportType.STDLIB)
|
|
278
|
-
file_import.define_mypy_type(
|
|
279
|
-
"JSON",
|
|
280
|
-
"MutableMapping[str, Any] # pylint: disable=unsubscriptable-object",
|
|
281
|
-
None,
|
|
282
|
-
{
|
|
283
|
-
(3, 9): ImportModel(
|
|
284
|
-
TypingSection.CONDITIONAL,
|
|
285
|
-
ImportType.STDLIB,
|
|
286
|
-
"collections.abc",
|
|
287
|
-
submodule_name="MutableMapping",
|
|
288
|
-
),
|
|
289
|
-
None: ImportModel(
|
|
290
|
-
TypingSection.CONDITIONAL,
|
|
291
|
-
ImportType.STDLIB,
|
|
292
|
-
"typing",
|
|
293
|
-
submodule_name="MutableMapping",
|
|
294
|
-
),
|
|
295
|
-
},
|
|
296
|
-
)
|
|
297
|
-
return file_import
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
def get_object_schema(code_model) -> Type[ObjectSchema]:
|
|
301
|
-
if code_model.options["models_mode"]:
|
|
302
|
-
return ObjectSchema
|
|
303
|
-
return HiddenModelObjectSchema
|