@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
|
@@ -3,10 +3,14 @@
|
|
|
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
|
|
6
|
+
from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
7
7
|
from .base_schema import BaseSchema
|
|
8
8
|
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .code_model import CodeModel
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
class DictionarySchema(BaseSchema):
|
|
11
15
|
"""Schema for dictionaries that will be serialized.
|
|
12
16
|
|
|
@@ -18,11 +22,11 @@ class DictionarySchema(BaseSchema):
|
|
|
18
22
|
|
|
19
23
|
def __init__(
|
|
20
24
|
self,
|
|
21
|
-
namespace: str,
|
|
22
25
|
yaml_data: Dict[str, Any],
|
|
23
|
-
|
|
26
|
+
code_model: "CodeModel",
|
|
27
|
+
element_type: "BaseSchema",
|
|
24
28
|
) -> None:
|
|
25
|
-
super(
|
|
29
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
26
30
|
self.element_type = element_type
|
|
27
31
|
|
|
28
32
|
@property
|
|
@@ -55,20 +59,19 @@ class DictionarySchema(BaseSchema):
|
|
|
55
59
|
return f"dict[str, {self.element_type.docstring_type}]"
|
|
56
60
|
|
|
57
61
|
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
58
|
-
raise NotImplementedError(
|
|
62
|
+
raise NotImplementedError(
|
|
63
|
+
"Dictionary schema does not support XML serialization."
|
|
64
|
+
)
|
|
59
65
|
|
|
60
66
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
61
67
|
return {
|
|
62
|
-
f'"{"str"}"'
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
|
|
66
|
-
return {
|
|
67
|
-
f'"{"str"}"' : self.element_type.get_files_and_data_template_representation(**kwargs)
|
|
68
|
+
f'"{"str"}"': self.element_type.get_json_template_representation(**kwargs)
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
@classmethod
|
|
71
|
-
def from_yaml(
|
|
72
|
+
def from_yaml(
|
|
73
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
74
|
+
) -> "DictionarySchema":
|
|
72
75
|
"""Constructs a DictionarySchema from yaml data.
|
|
73
76
|
|
|
74
77
|
:param yaml_data: the yaml data from which we will construct this schema
|
|
@@ -81,19 +84,19 @@ class DictionarySchema(BaseSchema):
|
|
|
81
84
|
|
|
82
85
|
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
83
86
|
|
|
84
|
-
element_type = build_schema(
|
|
85
|
-
yaml_data=element_schema, **kwargs
|
|
86
|
-
)
|
|
87
|
+
element_type = build_schema(yaml_data=element_schema, code_model=code_model)
|
|
87
88
|
|
|
88
89
|
return cls(
|
|
89
|
-
namespace=namespace,
|
|
90
90
|
yaml_data=yaml_data,
|
|
91
|
+
code_model=code_model,
|
|
91
92
|
element_type=element_type,
|
|
92
93
|
)
|
|
93
94
|
|
|
94
95
|
def imports(self) -> FileImport:
|
|
95
96
|
file_import = FileImport()
|
|
96
|
-
file_import.add_submodule_import(
|
|
97
|
+
file_import.add_submodule_import(
|
|
98
|
+
"typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
99
|
+
)
|
|
97
100
|
file_import.merge(self.element_type.imports())
|
|
98
101
|
return file_import
|
|
99
102
|
|
|
@@ -3,11 +3,14 @@
|
|
|
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, Optional, Set, Type
|
|
6
|
+
from typing import Any, Dict, List, Optional, Set, Type, TYPE_CHECKING
|
|
7
7
|
from .base_schema import BaseSchema
|
|
8
8
|
from .primitive_schemas import PrimitiveSchema, get_primitive_schema, StringSchema
|
|
9
9
|
from .imports import FileImport, ImportType, TypingSection
|
|
10
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .code_model import CodeModel
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
class EnumValue:
|
|
13
16
|
"""Model containing necessary information for a single value of an enum.
|
|
@@ -17,7 +20,9 @@ class EnumValue:
|
|
|
17
20
|
:param str description: Optional. The description for this enum value
|
|
18
21
|
"""
|
|
19
22
|
|
|
20
|
-
def __init__(
|
|
23
|
+
def __init__(
|
|
24
|
+
self, name: str, value: str, description: Optional[str] = None
|
|
25
|
+
) -> None:
|
|
21
26
|
self.name = name
|
|
22
27
|
self.value = value
|
|
23
28
|
self.description = description
|
|
@@ -53,14 +58,14 @@ class EnumSchema(BaseSchema):
|
|
|
53
58
|
|
|
54
59
|
def __init__(
|
|
55
60
|
self,
|
|
56
|
-
namespace: str,
|
|
57
61
|
yaml_data: Dict[str, Any],
|
|
62
|
+
code_model: "CodeModel",
|
|
58
63
|
description: str,
|
|
59
64
|
name: str,
|
|
60
65
|
values: List["EnumValue"],
|
|
61
66
|
enum_type: PrimitiveSchema,
|
|
62
67
|
) -> None:
|
|
63
|
-
super(
|
|
68
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
64
69
|
self.description = description
|
|
65
70
|
self.name = name
|
|
66
71
|
self.values = values
|
|
@@ -95,9 +100,8 @@ class EnumSchema(BaseSchema):
|
|
|
95
100
|
|
|
96
101
|
@property
|
|
97
102
|
def docstring_type(self) -> str:
|
|
98
|
-
"""The python type used for RST syntax input and type annotation.
|
|
99
|
-
""
|
|
100
|
-
return f"{self.enum_type.type_annotation()} or ~{self.namespace}.models.{self.name}"
|
|
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}"
|
|
101
105
|
|
|
102
106
|
@staticmethod
|
|
103
107
|
def _get_enum_values(yaml_data: List[Dict[str, Any]]) -> List["EnumValue"]:
|
|
@@ -121,21 +125,23 @@ class EnumSchema(BaseSchema):
|
|
|
121
125
|
|
|
122
126
|
def _template_kwargs(self, **kwargs: Any) -> Any:
|
|
123
127
|
if len(self.values) == 1 and not kwargs.get("default_value_declaration"):
|
|
124
|
-
kwargs[
|
|
128
|
+
kwargs["default_value_declaration"] = self.enum_type.get_declaration(
|
|
129
|
+
self.values[0].value
|
|
130
|
+
)
|
|
125
131
|
description = kwargs.pop("description", "")
|
|
126
132
|
kwargs["description"] = description
|
|
127
133
|
return kwargs
|
|
128
134
|
|
|
129
|
-
|
|
130
135
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
131
136
|
# for better display effect, use the only value instead of var type
|
|
132
|
-
return self.enum_type.get_json_template_representation(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return self.enum_type.get_files_and_data_template_representation(**self._template_kwargs(**kwargs))
|
|
137
|
+
return self.enum_type.get_json_template_representation(
|
|
138
|
+
**self._template_kwargs(**kwargs)
|
|
139
|
+
)
|
|
136
140
|
|
|
137
141
|
@classmethod
|
|
138
|
-
def from_yaml(
|
|
142
|
+
def from_yaml(
|
|
143
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
144
|
+
) -> "EnumSchema":
|
|
139
145
|
"""Constructs an EnumSchema from yaml data.
|
|
140
146
|
|
|
141
147
|
:param yaml_data: the yaml data from which we will construct this schema
|
|
@@ -148,13 +154,13 @@ class EnumSchema(BaseSchema):
|
|
|
148
154
|
|
|
149
155
|
# choice type doesn't always exist. if there is no choiceType, we default to string
|
|
150
156
|
if yaml_data.get("choiceType"):
|
|
151
|
-
enum_type = get_primitive_schema(
|
|
157
|
+
enum_type = get_primitive_schema(yaml_data["choiceType"], code_model)
|
|
152
158
|
else:
|
|
153
|
-
enum_type = StringSchema(
|
|
159
|
+
enum_type = StringSchema({"type": "str"}, code_model)
|
|
154
160
|
values = EnumSchema._get_enum_values(yaml_data["choices"])
|
|
155
161
|
return cls(
|
|
156
|
-
namespace=namespace,
|
|
157
162
|
yaml_data=yaml_data,
|
|
163
|
+
code_model=code_model,
|
|
158
164
|
description=yaml_data["language"]["python"]["description"],
|
|
159
165
|
name=name,
|
|
160
166
|
values=values,
|
|
@@ -163,13 +169,14 @@ class EnumSchema(BaseSchema):
|
|
|
163
169
|
|
|
164
170
|
def imports(self) -> FileImport:
|
|
165
171
|
file_import = FileImport()
|
|
166
|
-
file_import.add_submodule_import(
|
|
172
|
+
file_import.add_submodule_import(
|
|
173
|
+
"typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
174
|
+
)
|
|
167
175
|
file_import.merge(self.enum_type.imports())
|
|
168
176
|
return file_import
|
|
169
177
|
|
|
170
178
|
|
|
171
179
|
class HiddenModelEnumSchema(EnumSchema):
|
|
172
|
-
|
|
173
180
|
def imports(self) -> FileImport:
|
|
174
181
|
file_import = FileImport()
|
|
175
182
|
file_import.merge(self.enum_type.imports())
|
|
@@ -185,7 +192,9 @@ class HiddenModelEnumSchema(EnumSchema):
|
|
|
185
192
|
|
|
186
193
|
@property
|
|
187
194
|
def docstring_text(self) -> str:
|
|
188
|
-
return
|
|
195
|
+
return (
|
|
196
|
+
f"{self.enum_type.type_annotation()}. {self.extra_description_information}"
|
|
197
|
+
)
|
|
189
198
|
|
|
190
199
|
@property
|
|
191
200
|
def extra_description_information(self):
|
|
@@ -197,18 +206,19 @@ class HiddenModelEnumSchema(EnumSchema):
|
|
|
197
206
|
if len(possible_values) == 2:
|
|
198
207
|
possible_values_str = " or ".join(possible_values)
|
|
199
208
|
else:
|
|
200
|
-
possible_values_str =
|
|
201
|
-
possible_values[: len(possible_values) - 1]
|
|
202
|
-
|
|
209
|
+
possible_values_str = (
|
|
210
|
+
", ".join(possible_values[: len(possible_values) - 1])
|
|
211
|
+
+ f", and {possible_values[-1]}"
|
|
212
|
+
)
|
|
203
213
|
|
|
204
214
|
return "Known values are: {}.".format(possible_values_str)
|
|
205
215
|
|
|
206
216
|
@property
|
|
207
217
|
def docstring_type(self) -> str:
|
|
208
|
-
"""The python type used for RST syntax input and type annotation.
|
|
209
|
-
"""
|
|
218
|
+
"""The python type used for RST syntax input and type annotation."""
|
|
210
219
|
return self.enum_type.type_annotation()
|
|
211
220
|
|
|
221
|
+
|
|
212
222
|
def get_enum_schema(code_model) -> Type[EnumSchema]:
|
|
213
223
|
if code_model.options["models_mode"]:
|
|
214
224
|
return EnumSchema
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from enum import Enum
|
|
7
|
-
from typing import Dict, List, Optional, Tuple, Union, Set
|
|
7
|
+
from typing import Dict, List, Optional, Tuple, Union, Set, Mapping
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
class ImportType(str, Enum):
|
|
10
11
|
STDLIB = "stdlib"
|
|
@@ -12,11 +13,13 @@ class ImportType(str, Enum):
|
|
|
12
13
|
AZURECORE = "azurecore"
|
|
13
14
|
LOCAL = "local"
|
|
14
15
|
|
|
16
|
+
|
|
15
17
|
class TypingSection(str, Enum):
|
|
16
18
|
REGULAR = "regular" # this import is always a typing import
|
|
17
19
|
CONDITIONAL = "conditional" # is a typing import when we're dealing with files that py2 will use, else regular
|
|
18
20
|
TYPING = "typing" # never a typing import
|
|
19
21
|
|
|
22
|
+
|
|
20
23
|
class ImportModel:
|
|
21
24
|
def __init__(
|
|
22
25
|
self,
|
|
@@ -36,11 +39,11 @@ class ImportModel:
|
|
|
36
39
|
def __eq__(self, other):
|
|
37
40
|
try:
|
|
38
41
|
return (
|
|
39
|
-
self.typing_section == other.typing_section
|
|
40
|
-
self.import_type == other.import_type
|
|
41
|
-
self.module_name == other.module_name
|
|
42
|
-
self.submodule_name == other.submodule_name
|
|
43
|
-
self.alias == other.alias
|
|
42
|
+
self.typing_section == other.typing_section
|
|
43
|
+
and self.import_type == other.import_type
|
|
44
|
+
and self.module_name == other.module_name
|
|
45
|
+
and self.submodule_name == other.submodule_name
|
|
46
|
+
and self.alias == other.alias
|
|
44
47
|
)
|
|
45
48
|
except AttributeError:
|
|
46
49
|
return False
|
|
@@ -52,18 +55,32 @@ class ImportModel:
|
|
|
52
55
|
retval += hash(getattr(self, attr))
|
|
53
56
|
return retval
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
|
|
59
|
+
class TypeDefinition:
|
|
56
60
|
def __init__(
|
|
57
61
|
self,
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
sync_definition: str,
|
|
63
|
+
async_definition: str,
|
|
64
|
+
version_imports: Mapping[Optional[Tuple[int, int]], ImportModel] = None,
|
|
65
|
+
):
|
|
66
|
+
# version_imports: a map of "python version -> ImportModel".
|
|
67
|
+
# The python version is in form of (major, minor), for instance (3, 9) stands for py3.9.
|
|
68
|
+
# If the python version is None, it's a default ImportModel.
|
|
69
|
+
self.sync_definition = sync_definition
|
|
70
|
+
self.async_definition = async_definition
|
|
71
|
+
self.version_imports = version_imports
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class FileImport:
|
|
75
|
+
def __init__(self, imports: List[ImportModel] = None) -> None:
|
|
60
76
|
self.imports = imports or []
|
|
61
77
|
# has sync and async type definitions
|
|
62
|
-
self.type_definitions: Dict[str,
|
|
78
|
+
self.type_definitions: Dict[str, TypeDefinition] = {}
|
|
63
79
|
|
|
64
80
|
def _append_import(self, import_model: ImportModel) -> None:
|
|
65
81
|
if not any(
|
|
66
|
-
i
|
|
82
|
+
i
|
|
83
|
+
for i in self.imports
|
|
67
84
|
if all(
|
|
68
85
|
getattr(i, attr) == getattr(import_model, attr)
|
|
69
86
|
for attr in dir(i)
|
|
@@ -72,7 +89,9 @@ class FileImport:
|
|
|
72
89
|
):
|
|
73
90
|
self.imports.append(import_model)
|
|
74
91
|
|
|
75
|
-
def get_imports_from_section(
|
|
92
|
+
def get_imports_from_section(
|
|
93
|
+
self, typing_section: TypingSection
|
|
94
|
+
) -> List[ImportModel]:
|
|
76
95
|
return [i for i in self.imports if i.typing_section == typing_section]
|
|
77
96
|
|
|
78
97
|
def add_submodule_import(
|
|
@@ -83,15 +102,16 @@ class FileImport:
|
|
|
83
102
|
typing_section: TypingSection = TypingSection.REGULAR,
|
|
84
103
|
alias: Optional[str] = None,
|
|
85
104
|
) -> None:
|
|
86
|
-
"""Add an import to this import block.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
"""Add an import to this import block."""
|
|
106
|
+
self._append_import(
|
|
107
|
+
ImportModel(
|
|
108
|
+
typing_section=typing_section,
|
|
109
|
+
import_type=import_type,
|
|
110
|
+
module_name=module_name,
|
|
111
|
+
submodule_name=submodule_name,
|
|
112
|
+
alias=alias,
|
|
113
|
+
)
|
|
114
|
+
)
|
|
95
115
|
|
|
96
116
|
def add_import(
|
|
97
117
|
self,
|
|
@@ -101,16 +121,25 @@ class FileImport:
|
|
|
101
121
|
alias: Optional[str] = None,
|
|
102
122
|
) -> None:
|
|
103
123
|
# Implementation detail: a regular import is just a "from" with no from
|
|
104
|
-
self._append_import(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
self._append_import(
|
|
125
|
+
ImportModel(
|
|
126
|
+
typing_section=typing_section,
|
|
127
|
+
import_type=import_type,
|
|
128
|
+
module_name=module_name,
|
|
129
|
+
alias=alias,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
110
132
|
|
|
111
|
-
def define_mypy_type(
|
|
112
|
-
self
|
|
113
|
-
|
|
133
|
+
def define_mypy_type(
|
|
134
|
+
self,
|
|
135
|
+
type_name: str,
|
|
136
|
+
type_value: str,
|
|
137
|
+
async_type_value: Optional[str] = None,
|
|
138
|
+
version_imports: Mapping[Optional[Tuple[int, int]], ImportModel] = None,
|
|
139
|
+
):
|
|
140
|
+
self.type_definitions[type_name] = TypeDefinition(
|
|
141
|
+
type_value, async_type_value or type_value, version_imports
|
|
142
|
+
)
|
|
114
143
|
|
|
115
144
|
def merge(self, file_import: "FileImport") -> None:
|
|
116
145
|
"""Merge the given file import format."""
|
|
@@ -118,23 +147,23 @@ class FileImport:
|
|
|
118
147
|
self._append_import(i)
|
|
119
148
|
self.type_definitions.update(file_import.type_definitions)
|
|
120
149
|
|
|
121
|
-
def to_dict(
|
|
150
|
+
def to_dict(
|
|
151
|
+
self,
|
|
152
|
+
) -> Dict[
|
|
122
153
|
TypingSection,
|
|
123
|
-
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]
|
|
154
|
+
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
|
|
124
155
|
]:
|
|
125
156
|
retval: Dict[
|
|
126
157
|
TypingSection,
|
|
127
|
-
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]]
|
|
158
|
+
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
|
|
128
159
|
] = dict()
|
|
129
160
|
for i in self.imports:
|
|
130
161
|
name_import: Optional[Union[str, Tuple[str, str]]] = None
|
|
131
162
|
if i.submodule_name:
|
|
132
|
-
name_import = (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
i.module_name, set()
|
|
139
|
-
).add(name_import)
|
|
163
|
+
name_import = (
|
|
164
|
+
(i.submodule_name, i.alias) if i.alias else i.submodule_name
|
|
165
|
+
)
|
|
166
|
+
retval.setdefault(i.typing_section, dict()).setdefault(
|
|
167
|
+
i.import_type, dict()
|
|
168
|
+
).setdefault(i.module_name, set()).add(name_import)
|
|
140
169
|
return retval
|
|
@@ -3,23 +3,26 @@
|
|
|
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
|
|
6
|
+
from typing import Any, Dict, Optional, Union, TYPE_CHECKING
|
|
7
7
|
from .base_schema import BaseSchema
|
|
8
8
|
from .imports import FileImport, ImportType, TypingSection
|
|
9
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .code_model import CodeModel
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
class ListSchema(BaseSchema):
|
|
12
15
|
def __init__(
|
|
13
16
|
self,
|
|
14
|
-
namespace: str,
|
|
15
17
|
yaml_data: Dict[str, Any],
|
|
18
|
+
code_model: "CodeModel",
|
|
16
19
|
element_type: BaseSchema,
|
|
17
20
|
*,
|
|
18
21
|
max_items: Optional[int] = None,
|
|
19
22
|
min_items: Optional[int] = None,
|
|
20
23
|
unique_items: Optional[int] = None,
|
|
21
24
|
) -> None:
|
|
22
|
-
super(
|
|
25
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
23
26
|
self.element_type = element_type
|
|
24
27
|
self.max_items = max_items
|
|
25
28
|
self.min_items = min_items
|
|
@@ -32,7 +35,9 @@ class ListSchema(BaseSchema):
|
|
|
32
35
|
def type_annotation(self, *, is_operation_file: bool = False) -> str:
|
|
33
36
|
if self.element_type.type_annotation() == "ET.Element":
|
|
34
37
|
# this means we're version tolerant XML, we just return the XML element
|
|
35
|
-
return self.element_type.type_annotation(
|
|
38
|
+
return self.element_type.type_annotation(
|
|
39
|
+
is_operation_file=is_operation_file
|
|
40
|
+
)
|
|
36
41
|
return f"List[{self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
|
|
37
42
|
|
|
38
43
|
@property
|
|
@@ -63,14 +68,14 @@ class ListSchema(BaseSchema):
|
|
|
63
68
|
|
|
64
69
|
@property
|
|
65
70
|
def has_xml_serialization_ctxt(self) -> bool:
|
|
66
|
-
return
|
|
71
|
+
return (
|
|
72
|
+
super().has_xml_serialization_ctxt
|
|
73
|
+
or self.element_type.has_xml_serialization_ctxt
|
|
74
|
+
)
|
|
67
75
|
|
|
68
76
|
def get_json_template_representation(self, **kwargs: Any) -> Any:
|
|
69
77
|
return [self.element_type.get_json_template_representation(**kwargs)]
|
|
70
78
|
|
|
71
|
-
def get_files_and_data_template_representation(self, **kwargs: Any) -> Any:
|
|
72
|
-
return [self.element_type.get_files_and_data_template_representation(**kwargs)]
|
|
73
|
-
|
|
74
79
|
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
75
80
|
attrs_list = []
|
|
76
81
|
base_xml_map = super().xml_serialization_ctxt()
|
|
@@ -93,17 +98,19 @@ class ListSchema(BaseSchema):
|
|
|
93
98
|
return ", ".join(attrs_list)
|
|
94
99
|
|
|
95
100
|
@classmethod
|
|
96
|
-
def from_yaml(
|
|
101
|
+
def from_yaml(
|
|
102
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
103
|
+
) -> "ListSchema":
|
|
97
104
|
# TODO: for items, if the type is a primitive is it listed in type instead of $ref?
|
|
98
105
|
element_schema = yaml_data["elementType"]
|
|
99
106
|
|
|
100
107
|
from . import build_schema # pylint: disable=import-outside-toplevel
|
|
101
108
|
|
|
102
|
-
element_type = build_schema(yaml_data=element_schema,
|
|
109
|
+
element_type = build_schema(yaml_data=element_schema, code_model=code_model)
|
|
103
110
|
|
|
104
111
|
return cls(
|
|
105
|
-
namespace=namespace,
|
|
106
112
|
yaml_data=yaml_data,
|
|
113
|
+
code_model=code_model,
|
|
107
114
|
element_type=element_type,
|
|
108
115
|
max_items=yaml_data.get("maxItems"),
|
|
109
116
|
min_items=yaml_data.get("minItems"),
|
|
@@ -112,8 +119,13 @@ class ListSchema(BaseSchema):
|
|
|
112
119
|
|
|
113
120
|
def imports(self) -> FileImport:
|
|
114
121
|
file_import = FileImport()
|
|
115
|
-
if
|
|
116
|
-
|
|
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
|
+
)
|
|
117
129
|
file_import.merge(self.element_type.imports())
|
|
118
130
|
return file_import
|
|
119
131
|
|