@autorest/python 5.14.0 → 5.17.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 +91 -2
- package/README.md +30 -4
- package/autorest/__init__.py +2 -3
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +130 -179
- package/autorest/codegen/models/__init__.py +122 -78
- package/autorest/codegen/models/base_builder.py +70 -72
- package/autorest/codegen/models/base_model.py +7 -5
- package/autorest/codegen/models/{base_schema.py → base_type.py} +62 -49
- package/autorest/codegen/models/client.py +195 -36
- package/autorest/codegen/models/code_model.py +165 -299
- package/autorest/codegen/models/combined_type.py +107 -0
- package/autorest/codegen/models/constant_type.py +122 -0
- package/autorest/codegen/models/credential_types.py +224 -0
- package/autorest/codegen/models/dictionary_type.py +116 -0
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +95 -41
- package/autorest/codegen/models/list_type.py +134 -0
- package/autorest/codegen/models/lro_operation.py +90 -133
- package/autorest/codegen/models/lro_paging_operation.py +28 -12
- package/autorest/codegen/models/model_type.py +239 -0
- package/autorest/codegen/models/operation.py +415 -241
- package/autorest/codegen/models/operation_group.py +82 -88
- package/autorest/codegen/models/paging_operation.py +101 -117
- package/autorest/codegen/models/parameter.py +307 -322
- package/autorest/codegen/models/parameter_list.py +366 -357
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +122 -134
- package/autorest/codegen/models/request_builder.py +138 -86
- package/autorest/codegen/models/request_builder_parameter.py +122 -79
- package/autorest/codegen/models/response.py +325 -0
- package/autorest/codegen/models/utils.py +17 -1
- package/autorest/codegen/serializers/__init__.py +242 -118
- package/autorest/codegen/serializers/builder_serializer.py +863 -1027
- package/autorest/codegen/serializers/client_serializer.py +148 -82
- package/autorest/codegen/serializers/general_serializer.py +44 -47
- package/autorest/codegen/serializers/import_serializer.py +96 -31
- package/autorest/codegen/serializers/metadata_serializer.py +39 -79
- package/autorest/codegen/serializers/model_base_serializer.py +65 -29
- package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
- package/autorest/codegen/serializers/model_init_serializer.py +4 -2
- package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
- package/autorest/codegen/serializers/operation_groups_serializer.py +21 -18
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
- package/autorest/codegen/serializers/utils.py +0 -103
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -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 -2
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
- package/autorest/codegen/templates/model.py.jinja2 +23 -29
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
- package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
- package/autorest/codegen/templates/operation.py.jinja2 +10 -15
- package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
- package/autorest/codegen/templates/setup.py.jinja2 +9 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +28 -9
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/m4reformatter/__init__.py +1108 -0
- 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 +35 -18
- 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 +20 -25
- package/autorest/multiapi/serializers/import_serializer.py +47 -15
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- 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/multiapi/utils.py +3 -3
- 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 +209 -0
- package/autorest/preprocess/helpers.py +54 -0
- package/autorest/{namer → preprocess}/python_mappings.py +25 -32
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/constant_schema.py +0 -97
- package/autorest/codegen/models/credential_schema.py +0 -90
- package/autorest/codegen/models/credential_schema_policy.py +0 -77
- package/autorest/codegen/models/dictionary_schema.py +0 -103
- package/autorest/codegen/models/enum_schema.py +0 -246
- package/autorest/codegen/models/list_schema.py +0 -113
- package/autorest/codegen/models/object_schema.py +0 -249
- package/autorest/codegen/models/primitive_schemas.py +0 -476
- package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
- package/autorest/codegen/models/rest.py +0 -42
- package/autorest/codegen/models/schema_request.py +0 -45
- package/autorest/codegen/models/schema_response.py +0 -123
- package/autorest/codegen/serializers/rest_serializer.py +0 -57
- package/autorest/namer/__init__.py +0 -25
- package/autorest/namer/name_converter.py +0 -412
|
@@ -5,49 +5,69 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from copy import deepcopy
|
|
7
7
|
from typing import List
|
|
8
|
-
from ..models.imports import
|
|
8
|
+
from ..models.imports import (
|
|
9
|
+
ImportType,
|
|
10
|
+
FileImport,
|
|
11
|
+
ImportModel,
|
|
12
|
+
TypingSection,
|
|
13
|
+
TypeDefinition,
|
|
14
|
+
)
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
) -> str:
|
|
16
|
+
|
|
17
|
+
def _serialize_package(imports: List[ImportModel], delimiter: str) -> str:
|
|
13
18
|
buffer = []
|
|
14
19
|
if any(i for i in imports if i.submodule_name is None):
|
|
15
|
-
buffer.append(
|
|
20
|
+
buffer.append(
|
|
21
|
+
f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}"
|
|
22
|
+
)
|
|
16
23
|
else:
|
|
17
|
-
import_str = ", ".join(
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
import_str = ", ".join(
|
|
25
|
+
sorted(
|
|
26
|
+
set(
|
|
27
|
+
f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name # type: ignore
|
|
28
|
+
for i in imports
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
)
|
|
20
32
|
buffer.append(f"from {imports[0].module_name} import {import_str}")
|
|
21
33
|
return delimiter.join(buffer)
|
|
22
34
|
|
|
35
|
+
|
|
23
36
|
def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
|
|
24
37
|
"""Serialize a given import type."""
|
|
25
38
|
import_list = []
|
|
26
39
|
for module_name in sorted(set(i.module_name for i in imports)):
|
|
27
40
|
|
|
28
|
-
import_list.append(
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
import_list.append(
|
|
42
|
+
_serialize_package(
|
|
43
|
+
[i for i in imports if i.module_name == module_name], delimiter
|
|
44
|
+
)
|
|
45
|
+
)
|
|
31
46
|
return delimiter.join(import_list)
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
) -> List[str]:
|
|
48
|
+
|
|
49
|
+
def _get_import_clauses(imports: List[ImportModel], delimiter: str) -> List[str]:
|
|
36
50
|
import_clause = []
|
|
37
51
|
for import_type in ImportType:
|
|
38
52
|
imports_with_import_type = [i for i in imports if i.import_type == import_type]
|
|
39
53
|
if imports_with_import_type:
|
|
40
|
-
import_clause.append(
|
|
54
|
+
import_clause.append(
|
|
55
|
+
_serialize_import_type(imports_with_import_type, delimiter)
|
|
56
|
+
)
|
|
41
57
|
return import_clause
|
|
42
58
|
|
|
43
59
|
|
|
44
60
|
class FileImportSerializer:
|
|
45
|
-
def __init__(
|
|
61
|
+
def __init__(
|
|
62
|
+
self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False
|
|
63
|
+
) -> None:
|
|
46
64
|
self.file_import = file_import
|
|
47
65
|
self.is_python3_file = is_python3_file
|
|
48
66
|
self.async_mode = async_mode
|
|
49
67
|
|
|
50
|
-
def _get_imports_list(
|
|
68
|
+
def _get_imports_list(
|
|
69
|
+
self, baseline_typing_section: TypingSection, add_conditional_typing: bool
|
|
70
|
+
):
|
|
51
71
|
# If this is a python 3 file, our regular imports include the CONDITIONAL category
|
|
52
72
|
# If this is not a python 3 file, our typing imports include the CONDITIONAL category
|
|
53
73
|
file_import_copy = deepcopy(self.file_import)
|
|
@@ -62,33 +82,75 @@ class FileImportSerializer:
|
|
|
62
82
|
return file_import_copy.get_imports_from_section(baseline_typing_section)
|
|
63
83
|
|
|
64
84
|
def _add_type_checking_import(self):
|
|
65
|
-
any_typing = any(
|
|
85
|
+
any_typing = any(
|
|
86
|
+
self.file_import.get_imports_from_section(TypingSection.TYPING)
|
|
87
|
+
)
|
|
66
88
|
conditional_and_not_py3 = not self.is_python3_file and any(
|
|
67
89
|
self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
|
|
68
90
|
)
|
|
69
91
|
if any_typing or conditional_and_not_py3:
|
|
70
|
-
self.file_import.add_submodule_import(
|
|
92
|
+
self.file_import.add_submodule_import(
|
|
93
|
+
"typing", "TYPE_CHECKING", ImportType.STDLIB
|
|
94
|
+
)
|
|
71
95
|
|
|
72
96
|
def _get_typing_definitions(self) -> str:
|
|
97
|
+
def declare_defintion(
|
|
98
|
+
spacing: str, type_name: str, type_definition: TypeDefinition
|
|
99
|
+
) -> List[str]:
|
|
100
|
+
ret: List[str] = []
|
|
101
|
+
definition_value = (
|
|
102
|
+
type_definition.async_definition
|
|
103
|
+
if self.async_mode
|
|
104
|
+
else type_definition.sync_definition
|
|
105
|
+
)
|
|
106
|
+
if type_definition.version_imports is not None:
|
|
107
|
+
versions = type_definition.version_imports.keys()
|
|
108
|
+
for i, version in enumerate(
|
|
109
|
+
sorted(
|
|
110
|
+
versions, key=lambda x: x if x is not None else (), reverse=True
|
|
111
|
+
)
|
|
112
|
+
):
|
|
113
|
+
if version is not None:
|
|
114
|
+
ret.append(
|
|
115
|
+
"{}{} sys.version_info >= {}:".format(
|
|
116
|
+
spacing, "if" if i == 0 else "elif", version
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
elif i > 0:
|
|
120
|
+
ret.append("{}else:".format(spacing))
|
|
121
|
+
for import_clause in _get_import_clauses(
|
|
122
|
+
[type_definition.version_imports[version]], "\n"
|
|
123
|
+
):
|
|
124
|
+
ret.append(
|
|
125
|
+
"{}{}{}".format(
|
|
126
|
+
" "
|
|
127
|
+
if len(versions) > 1 or version is not None
|
|
128
|
+
else "",
|
|
129
|
+
spacing,
|
|
130
|
+
import_clause,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if i > 0:
|
|
134
|
+
ret[
|
|
135
|
+
-1
|
|
136
|
+
] += " # type: ignore # pylint: disable=ungrouped-imports"
|
|
137
|
+
ret.append("{}{} = {}".format(spacing, type_name, definition_value))
|
|
138
|
+
return ret
|
|
139
|
+
|
|
73
140
|
if not self.file_import.type_definitions:
|
|
74
141
|
return ""
|
|
75
142
|
spacing = "" if self.is_python3_file else " "
|
|
76
|
-
declarations: List[str] = [
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
spacing,
|
|
80
|
-
type_name,
|
|
81
|
-
values[1] if self.async_mode else values[0]
|
|
82
|
-
)
|
|
83
|
-
for type_name, values in self.file_import.type_definitions.items()
|
|
84
|
-
])
|
|
143
|
+
declarations: List[str] = [""]
|
|
144
|
+
for type_name, value in self.file_import.type_definitions.items():
|
|
145
|
+
declarations.extend(declare_defintion(spacing, type_name, value))
|
|
85
146
|
return "\n".join(declarations)
|
|
86
147
|
|
|
87
148
|
def __str__(self) -> str:
|
|
88
149
|
self._add_type_checking_import()
|
|
89
150
|
regular_imports = ""
|
|
90
151
|
regular_imports_list = self._get_imports_list(
|
|
91
|
-
baseline_typing_section=TypingSection.REGULAR,
|
|
152
|
+
baseline_typing_section=TypingSection.REGULAR,
|
|
153
|
+
add_conditional_typing=self.is_python3_file,
|
|
92
154
|
)
|
|
93
155
|
|
|
94
156
|
if regular_imports_list:
|
|
@@ -98,9 +160,12 @@ class FileImportSerializer:
|
|
|
98
160
|
|
|
99
161
|
typing_imports = ""
|
|
100
162
|
typing_imports_list = self._get_imports_list(
|
|
101
|
-
baseline_typing_section=TypingSection.TYPING,
|
|
163
|
+
baseline_typing_section=TypingSection.TYPING,
|
|
164
|
+
add_conditional_typing=not self.is_python3_file,
|
|
102
165
|
)
|
|
103
166
|
if typing_imports_list:
|
|
104
167
|
typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
|
|
105
|
-
typing_imports += "\n\n ".join(
|
|
168
|
+
typing_imports += "\n\n ".join(
|
|
169
|
+
_get_import_clauses(typing_imports_list, "\n ")
|
|
170
|
+
)
|
|
106
171
|
return regular_imports + typing_imports + self._get_typing_definitions()
|
|
@@ -4,36 +4,28 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import functools
|
|
7
|
-
import copy
|
|
8
7
|
import json
|
|
9
8
|
from typing import List, Optional, Set, Tuple, Dict, Union
|
|
10
9
|
from jinja2 import Environment
|
|
11
|
-
from .general_serializer import config_imports
|
|
12
10
|
from ..models import (
|
|
13
11
|
CodeModel,
|
|
14
|
-
FileImport,
|
|
15
12
|
OperationGroup,
|
|
16
13
|
LROOperation,
|
|
17
14
|
PagingOperation,
|
|
18
|
-
TokenCredentialSchema,
|
|
19
|
-
ParameterList,
|
|
20
15
|
TypingSection,
|
|
21
16
|
ImportType,
|
|
22
|
-
GlobalParameterList,
|
|
23
17
|
)
|
|
24
18
|
from .builder_serializer import get_operation_serializer
|
|
25
19
|
|
|
26
20
|
|
|
27
|
-
def _correct_credential_parameter(global_parameters: ParameterList, async_mode: bool) -> None:
|
|
28
|
-
credential_param = [gp for gp in global_parameters.parameters if isinstance(gp.schema, TokenCredentialSchema)][0]
|
|
29
|
-
credential_param.schema = TokenCredentialSchema(async_mode=async_mode)
|
|
30
|
-
|
|
31
|
-
|
|
32
21
|
def _json_serialize_imports(
|
|
33
|
-
imports: Dict[
|
|
34
|
-
|
|
22
|
+
imports: Dict[
|
|
23
|
+
TypingSection,
|
|
24
|
+
Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]],
|
|
25
|
+
]
|
|
26
|
+
) -> str:
|
|
35
27
|
if not imports:
|
|
36
|
-
return
|
|
28
|
+
return ""
|
|
37
29
|
|
|
38
30
|
json_serialize_imports = {}
|
|
39
31
|
# need to make name_import set -> list to make the dictionary json serializable
|
|
@@ -55,14 +47,18 @@ def _json_serialize_imports(
|
|
|
55
47
|
return json.dumps(json_serialize_imports)
|
|
56
48
|
|
|
57
49
|
|
|
58
|
-
def _mixin_imports(
|
|
50
|
+
def _mixin_imports(
|
|
51
|
+
mixin_operation_group: Optional[OperationGroup],
|
|
52
|
+
) -> Tuple[Optional[str], Optional[str]]:
|
|
59
53
|
if not mixin_operation_group:
|
|
60
54
|
return None, None
|
|
61
55
|
|
|
62
56
|
sync_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=False)
|
|
63
57
|
async_mixin_imports = mixin_operation_group.imports_for_multiapi(async_mode=True)
|
|
64
58
|
|
|
65
|
-
return _json_serialize_imports(
|
|
59
|
+
return _json_serialize_imports(
|
|
60
|
+
sync_mixin_imports.to_dict()
|
|
61
|
+
), _json_serialize_imports(async_mixin_imports.to_dict())
|
|
66
62
|
|
|
67
63
|
|
|
68
64
|
class MetadataSerializer:
|
|
@@ -80,7 +76,9 @@ class MetadataSerializer:
|
|
|
80
76
|
total_api_version_list.sort()
|
|
81
77
|
|
|
82
78
|
# switching ' to " so json can decode the dict we end up writing to file
|
|
83
|
-
total_api_version_list = [
|
|
79
|
+
total_api_version_list = [
|
|
80
|
+
str(api_version).replace("'", '"') for api_version in total_api_version_list
|
|
81
|
+
]
|
|
84
82
|
if len(total_api_version_list) == 1:
|
|
85
83
|
chosen_version = total_api_version_list[0]
|
|
86
84
|
elif len(total_api_version_list) > 1:
|
|
@@ -91,34 +89,6 @@ class MetadataSerializer:
|
|
|
91
89
|
|
|
92
90
|
return chosen_version, total_api_version_list
|
|
93
91
|
|
|
94
|
-
def _make_async_copy_of_global_parameters(self) -> GlobalParameterList:
|
|
95
|
-
global_parameters = copy.deepcopy(self.code_model.global_parameters)
|
|
96
|
-
_correct_credential_parameter(global_parameters, True)
|
|
97
|
-
return global_parameters
|
|
98
|
-
|
|
99
|
-
def _service_client_imports(
|
|
100
|
-
self, global_parameters: ParameterList, mixin_operation_group: Optional[OperationGroup], async_mode: bool
|
|
101
|
-
) -> str:
|
|
102
|
-
file_import = FileImport()
|
|
103
|
-
for gp in global_parameters:
|
|
104
|
-
file_import.merge(gp.imports())
|
|
105
|
-
file_import.add_submodule_import("azure.profiles", "KnownProfiles", import_type=ImportType.AZURECORE)
|
|
106
|
-
file_import.add_submodule_import("azure.profiles", "ProfileDefinition", import_type=ImportType.AZURECORE)
|
|
107
|
-
file_import.add_submodule_import(
|
|
108
|
-
"azure.profiles.multiapiclient", "MultiApiClientMixin", import_type=ImportType.AZURECORE
|
|
109
|
-
)
|
|
110
|
-
file_import.add_submodule_import(
|
|
111
|
-
"._configuration", f"{self.code_model.class_name}Configuration", ImportType.LOCAL
|
|
112
|
-
)
|
|
113
|
-
# api_version and potentially endpoint require Optional typing
|
|
114
|
-
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
115
|
-
if mixin_operation_group:
|
|
116
|
-
file_import.add_submodule_import(
|
|
117
|
-
"._operations_mixin", f"{self.code_model.class_name}OperationsMixin", ImportType.LOCAL
|
|
118
|
-
)
|
|
119
|
-
file_import.merge(self.code_model.service_client.imports_for_multiapi(async_mode=async_mode))
|
|
120
|
-
return _json_serialize_imports(file_import.to_dict())
|
|
121
|
-
|
|
122
92
|
def serialize(self) -> str:
|
|
123
93
|
def _is_lro(operation):
|
|
124
94
|
return isinstance(operation, LROOperation)
|
|
@@ -130,47 +100,26 @@ class MetadataSerializer:
|
|
|
130
100
|
(
|
|
131
101
|
operation_group
|
|
132
102
|
for operation_group in self.code_model.operation_groups
|
|
133
|
-
if operation_group.
|
|
103
|
+
if operation_group.is_mixin
|
|
134
104
|
),
|
|
135
105
|
None,
|
|
136
106
|
)
|
|
137
|
-
mixin_operations =
|
|
107
|
+
mixin_operations = (
|
|
108
|
+
mixin_operation_group.operations if mixin_operation_group else []
|
|
109
|
+
)
|
|
138
110
|
sync_mixin_imports, async_mixin_imports = _mixin_imports(mixin_operation_group)
|
|
139
111
|
|
|
140
112
|
chosen_version, total_api_version_list = self._choose_api_version()
|
|
141
113
|
|
|
142
|
-
# we separate out async and sync for the case of credentials.
|
|
143
|
-
# In this case, we need two copies of the credential global parameter
|
|
144
|
-
# for typing purposes.
|
|
145
|
-
async_global_parameters = self.code_model.global_parameters
|
|
146
|
-
if (
|
|
147
|
-
self.code_model.options['credential'] and
|
|
148
|
-
isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
|
|
149
|
-
):
|
|
150
|
-
# this ensures that the TokenCredentialSchema showing up in the list of code model's global parameters
|
|
151
|
-
# is sync. This way we only have to make a copy for an async_credential
|
|
152
|
-
_correct_credential_parameter(self.code_model.global_parameters, False)
|
|
153
|
-
async_global_parameters = self._make_async_copy_of_global_parameters()
|
|
154
|
-
|
|
155
|
-
sync_client_imports = self._service_client_imports(
|
|
156
|
-
self.code_model.global_parameters, mixin_operation_group, async_mode=False
|
|
157
|
-
)
|
|
158
|
-
async_client_imports = self._service_client_imports(
|
|
159
|
-
async_global_parameters, mixin_operation_group, async_mode=True
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
template = self.env.get_template("metadata.json.jinja2")
|
|
163
|
-
|
|
164
114
|
# setting to true, because for multiapi we always generate with a version file with version 0.1.0
|
|
165
115
|
self.code_model.options["package_version"] = "0.1.0"
|
|
166
|
-
|
|
167
|
-
|
|
116
|
+
template = self.env.get_template("metadata.json.jinja2")
|
|
117
|
+
|
|
168
118
|
return template.render(
|
|
169
119
|
chosen_version=chosen_version,
|
|
170
120
|
total_api_version_list=total_api_version_list,
|
|
171
121
|
code_model=self.code_model,
|
|
172
|
-
|
|
173
|
-
async_global_parameters=async_global_parameters,
|
|
122
|
+
global_parameters=self.code_model.client.parameters,
|
|
174
123
|
mixin_operations=mixin_operations,
|
|
175
124
|
any=any,
|
|
176
125
|
is_lro=_is_lro,
|
|
@@ -178,18 +127,29 @@ class MetadataSerializer:
|
|
|
178
127
|
str=str,
|
|
179
128
|
sync_mixin_imports=sync_mixin_imports,
|
|
180
129
|
async_mixin_imports=async_mixin_imports,
|
|
181
|
-
sync_client_imports=
|
|
182
|
-
|
|
130
|
+
sync_client_imports=_json_serialize_imports(
|
|
131
|
+
self.code_model.client.imports_for_multiapi(async_mode=False).to_dict()
|
|
132
|
+
),
|
|
133
|
+
async_client_imports=_json_serialize_imports(
|
|
134
|
+
self.code_model.client.imports_for_multiapi(async_mode=True).to_dict()
|
|
135
|
+
),
|
|
183
136
|
sync_config_imports=_json_serialize_imports(
|
|
184
|
-
|
|
137
|
+
self.code_model.config.imports(async_mode=False).to_dict()
|
|
185
138
|
),
|
|
186
139
|
async_config_imports=_json_serialize_imports(
|
|
187
|
-
|
|
140
|
+
self.code_model.config.imports(async_mode=True).to_dict()
|
|
188
141
|
),
|
|
189
142
|
get_async_operation_serializer=functools.partial(
|
|
190
|
-
get_operation_serializer,
|
|
143
|
+
get_operation_serializer,
|
|
144
|
+
code_model=self.code_model,
|
|
145
|
+
async_mode=True,
|
|
146
|
+
is_python3_file=True,
|
|
191
147
|
),
|
|
192
148
|
get_sync_operation_serializer=functools.partial(
|
|
193
|
-
get_operation_serializer,
|
|
149
|
+
get_operation_serializer,
|
|
150
|
+
code_model=self.code_model,
|
|
151
|
+
async_mode=False,
|
|
152
|
+
is_python3_file=False,
|
|
194
153
|
),
|
|
154
|
+
has_credential=bool(self.code_model.credential),
|
|
195
155
|
)
|
|
@@ -6,25 +6,31 @@
|
|
|
6
6
|
from abc import abstractmethod
|
|
7
7
|
from typing import cast, List
|
|
8
8
|
from jinja2 import Environment
|
|
9
|
-
from ..models import
|
|
9
|
+
from ..models import ModelType, CodeModel, Property
|
|
10
10
|
from ..models.imports import FileImport, ImportType
|
|
11
11
|
from .import_serializer import FileImportSerializer
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
def _documentation_string(
|
|
14
15
|
prop: Property, description_keyword: str, docstring_type_keyword: str
|
|
15
16
|
) -> List[str]:
|
|
16
17
|
retval: List[str] = []
|
|
17
|
-
sphinx_prefix = f":{description_keyword} {prop.
|
|
18
|
+
sphinx_prefix = f":{description_keyword} {prop.client_name}:"
|
|
18
19
|
retval.append(
|
|
19
|
-
f"{sphinx_prefix} {prop.description}"
|
|
20
|
+
f"{sphinx_prefix} {prop.description(is_operation_file=False)}"
|
|
21
|
+
if prop.description(is_operation_file=False)
|
|
20
22
|
else sphinx_prefix
|
|
21
23
|
)
|
|
22
|
-
retval.append(
|
|
24
|
+
retval.append(
|
|
25
|
+
f":{docstring_type_keyword} {prop.client_name}: {prop.type.docstring_type()}"
|
|
26
|
+
)
|
|
23
27
|
return retval
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
class ModelBaseSerializer:
|
|
27
|
-
def __init__(
|
|
31
|
+
def __init__(
|
|
32
|
+
self, code_model: CodeModel, env: Environment, is_python3_file: bool
|
|
33
|
+
) -> None:
|
|
28
34
|
self.code_model = code_model
|
|
29
35
|
self.env = env
|
|
30
36
|
self.is_python3_file = is_python3_file
|
|
@@ -34,34 +40,44 @@ class ModelBaseSerializer:
|
|
|
34
40
|
template = self.env.get_template("model_container.py.jinja2")
|
|
35
41
|
return template.render(
|
|
36
42
|
code_model=self.code_model,
|
|
37
|
-
imports=FileImportSerializer(
|
|
43
|
+
imports=FileImportSerializer(
|
|
44
|
+
self.imports(), is_python3_file=self.is_python3_file
|
|
45
|
+
),
|
|
38
46
|
str=str,
|
|
39
|
-
|
|
40
|
-
init_args=self.init_args,
|
|
41
|
-
input_documentation_string=ModelBaseSerializer.input_documentation_string,
|
|
42
|
-
variable_documentation_string=ModelBaseSerializer.variable_documentation_string,
|
|
47
|
+
serializer=self,
|
|
43
48
|
)
|
|
44
49
|
|
|
45
50
|
def imports(self) -> FileImport:
|
|
46
51
|
file_import = FileImport()
|
|
47
52
|
file_import.add_import("msrest.serialization", ImportType.AZURECORE)
|
|
48
|
-
for model in self.code_model.
|
|
49
|
-
file_import.merge(model.imports())
|
|
53
|
+
for model in self.code_model.model_types:
|
|
54
|
+
file_import.merge(model.imports(is_operation_file=False))
|
|
50
55
|
return file_import
|
|
51
56
|
|
|
52
57
|
@staticmethod
|
|
53
|
-
def get_properties_to_initialize(model:
|
|
54
|
-
if model.
|
|
55
|
-
properties_to_initialize = list(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
def get_properties_to_initialize(model: ModelType) -> List[Property]:
|
|
59
|
+
if model.parents:
|
|
60
|
+
properties_to_initialize = list(
|
|
61
|
+
{
|
|
62
|
+
p.client_name: p
|
|
63
|
+
for bm in model.parents
|
|
64
|
+
for p in model.properties
|
|
65
|
+
if p not in cast(ModelType, bm).properties
|
|
66
|
+
or p.is_discriminator
|
|
67
|
+
or p.constant
|
|
68
|
+
}.values()
|
|
69
|
+
)
|
|
61
70
|
else:
|
|
62
71
|
properties_to_initialize = model.properties
|
|
63
72
|
return properties_to_initialize
|
|
64
73
|
|
|
74
|
+
@staticmethod
|
|
75
|
+
def declare_model(model: ModelType) -> str:
|
|
76
|
+
basename = "msrest.serialization.Model"
|
|
77
|
+
if model.parents:
|
|
78
|
+
basename = ", ".join([cast(ModelType, m).name for m in model.parents])
|
|
79
|
+
return f"class {model.name}({basename}):{model.pylint_disable}"
|
|
80
|
+
|
|
65
81
|
@staticmethod
|
|
66
82
|
def input_documentation_string(prop: Property) -> List[str]:
|
|
67
83
|
# building the param line of the property doc
|
|
@@ -71,35 +87,55 @@ class ModelBaseSerializer:
|
|
|
71
87
|
def variable_documentation_string(prop: Property) -> List[str]:
|
|
72
88
|
return _documentation_string(prop, "ivar", "vartype")
|
|
73
89
|
|
|
74
|
-
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def super_call_template(self, model: ModelType) -> str:
|
|
92
|
+
...
|
|
93
|
+
|
|
94
|
+
def super_call(self, model: ModelType):
|
|
95
|
+
return self.super_call_template(model).format(
|
|
96
|
+
self.properties_to_pass_to_super(model)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def initialize_properties(self, model: ModelType) -> List[str]:
|
|
75
100
|
init_args = []
|
|
76
|
-
properties_to_pass_to_super = self.properties_to_pass_to_super(model)
|
|
77
|
-
init_args.append(f"super({model.name}, self).__init__({properties_to_pass_to_super})")
|
|
78
101
|
for prop in ModelBaseSerializer.get_properties_to_initialize(model):
|
|
79
102
|
if prop.is_discriminator:
|
|
80
|
-
discriminator_value =
|
|
103
|
+
discriminator_value = (
|
|
104
|
+
f"'{model.discriminator_value}'"
|
|
105
|
+
if model.discriminator_value
|
|
106
|
+
else None
|
|
107
|
+
)
|
|
81
108
|
if not discriminator_value:
|
|
82
109
|
typing = "Optional[str]"
|
|
83
110
|
else:
|
|
84
111
|
typing = "str"
|
|
85
|
-
init_args.append(
|
|
112
|
+
init_args.append(
|
|
113
|
+
f"self.{prop.client_name} = {discriminator_value} # type: {typing}"
|
|
114
|
+
)
|
|
86
115
|
elif prop.readonly:
|
|
87
|
-
init_args.append(f"self.{prop.
|
|
116
|
+
init_args.append(f"self.{prop.client_name} = None")
|
|
88
117
|
elif not prop.constant:
|
|
89
118
|
init_args.append(self.initialize_standard_arg(prop))
|
|
90
119
|
return init_args
|
|
91
120
|
|
|
92
121
|
def initialize_standard_property(self, prop: Property):
|
|
93
|
-
if prop.
|
|
122
|
+
if not (prop.optional or prop.client_default_value is not None):
|
|
94
123
|
return self.required_property_no_default_init(prop)
|
|
95
124
|
return self.optional_property_init(prop)
|
|
96
125
|
|
|
126
|
+
@staticmethod
|
|
127
|
+
def discriminator_docstring(model: ModelType) -> str:
|
|
128
|
+
return (
|
|
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())}"
|
|
131
|
+
)
|
|
132
|
+
|
|
97
133
|
@abstractmethod
|
|
98
|
-
def init_line(self, model:
|
|
134
|
+
def init_line(self, model: ModelType) -> List[str]:
|
|
99
135
|
...
|
|
100
136
|
|
|
101
137
|
@abstractmethod
|
|
102
|
-
def properties_to_pass_to_super(self, model:
|
|
138
|
+
def properties_to_pass_to_super(self, model: ModelType) -> str:
|
|
103
139
|
...
|
|
104
140
|
|
|
105
141
|
@abstractmethod
|
|
@@ -6,28 +6,27 @@
|
|
|
6
6
|
from typing import List
|
|
7
7
|
from jinja2 import Environment
|
|
8
8
|
from .model_base_serializer import ModelBaseSerializer
|
|
9
|
-
from ..models import
|
|
9
|
+
from ..models import ModelType, CodeModel, Property
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ModelGenericSerializer(ModelBaseSerializer):
|
|
13
|
-
|
|
14
13
|
def __init__(self, code_model: CodeModel, env: Environment) -> None:
|
|
15
|
-
super(
|
|
16
|
-
code_model=code_model, env=env, is_python3_file=False
|
|
17
|
-
)
|
|
14
|
+
super().__init__(code_model=code_model, env=env, is_python3_file=False)
|
|
18
15
|
|
|
19
|
-
def init_line(self, model:
|
|
16
|
+
def init_line(self, model: ModelType) -> List[str]:
|
|
20
17
|
return []
|
|
21
18
|
|
|
22
|
-
def properties_to_pass_to_super(self, model:
|
|
19
|
+
def properties_to_pass_to_super(self, model: ModelType) -> str:
|
|
23
20
|
return "**kwargs"
|
|
24
21
|
|
|
25
22
|
def required_property_no_default_init(self, prop: Property) -> str:
|
|
26
|
-
return f"self.{prop.
|
|
23
|
+
return f"self.{prop.client_name} = kwargs['{prop.client_name}']"
|
|
27
24
|
|
|
28
25
|
def optional_property_init(self, prop: Property) -> str:
|
|
29
|
-
|
|
30
|
-
return f"self.{prop.name} = kwargs.get('{prop.name}', {default})"
|
|
26
|
+
return f"self.{prop.client_name} = kwargs.get('{prop.client_name}', {prop.client_default_value_declaration})"
|
|
31
27
|
|
|
32
28
|
def initialize_standard_arg(self, prop: Property) -> str:
|
|
33
29
|
return self.initialize_standard_property(prop)
|
|
30
|
+
|
|
31
|
+
def super_call_template(self, model: ModelType) -> str:
|
|
32
|
+
return "super(" + model.name + ", self).__init__({})"
|
|
@@ -13,9 +13,11 @@ class ModelInitSerializer:
|
|
|
13
13
|
self.env = env
|
|
14
14
|
|
|
15
15
|
def serialize(self) -> str:
|
|
16
|
-
schemas = [s.name for s in self.code_model.
|
|
16
|
+
schemas = [s.name for s in self.code_model.public_model_types]
|
|
17
17
|
schemas.sort()
|
|
18
|
-
enums =
|
|
18
|
+
enums = (
|
|
19
|
+
[e.name for e in self.code_model.enums] if self.code_model.enums else None
|
|
20
|
+
)
|
|
19
21
|
|
|
20
22
|
if enums:
|
|
21
23
|
enums.sort()
|