@autorest/python 6.27.4 → 6.28.1
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/generator/build/lib/pygen/black.py +3 -3
- package/generator/build/lib/pygen/codegen/__init__.py +2 -0
- package/generator/build/lib/pygen/codegen/_utils.py +4 -0
- package/generator/build/lib/pygen/codegen/models/base.py +2 -3
- package/generator/build/lib/pygen/codegen/models/base_builder.py +5 -3
- package/generator/build/lib/pygen/codegen/models/client.py +28 -19
- package/generator/build/lib/pygen/codegen/models/code_model.py +204 -33
- package/generator/build/lib/pygen/codegen/models/combined_type.py +12 -8
- package/generator/build/lib/pygen/codegen/models/constant_type.py +2 -3
- package/generator/build/lib/pygen/codegen/models/credential_types.py +6 -3
- package/generator/build/lib/pygen/codegen/models/dictionary_type.py +2 -3
- package/generator/build/lib/pygen/codegen/models/enum_type.py +47 -24
- package/generator/build/lib/pygen/codegen/models/imports.py +14 -12
- package/generator/build/lib/pygen/codegen/models/list_type.py +2 -3
- package/generator/build/lib/pygen/codegen/models/lro_operation.py +8 -4
- package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
- package/generator/build/lib/pygen/codegen/models/model_type.py +34 -19
- package/generator/build/lib/pygen/codegen/models/operation.py +74 -31
- package/generator/build/lib/pygen/codegen/models/operation_group.py +82 -12
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +10 -7
- package/generator/build/lib/pygen/codegen/models/parameter.py +10 -10
- package/generator/build/lib/pygen/codegen/models/parameter_list.py +7 -7
- package/generator/build/lib/pygen/codegen/models/primitive_types.py +23 -43
- package/generator/build/lib/pygen/codegen/models/property.py +9 -9
- package/generator/build/lib/pygen/codegen/models/request_builder.py +9 -15
- package/generator/build/lib/pygen/codegen/models/response.py +6 -8
- package/generator/build/lib/pygen/codegen/models/utils.py +11 -0
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +228 -243
- package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +19 -1
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +58 -36
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +9 -5
- package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +17 -3
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +26 -14
- package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +26 -8
- package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +9 -4
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +65 -24
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +20 -16
- package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -10
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +10 -7
- package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +10 -1
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +7 -10
- package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +24 -28
- package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +6 -1
- package/generator/build/lib/pygen/codegen/serializers/utils.py +1 -15
- package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2 -68
- package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +3 -3
- package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
- package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +4 -4
- package/generator/build/lib/pygen/preprocess/__init__.py +0 -4
- package/generator/component-detection-pip-report.json +2 -2
- package/generator/dev_requirements.txt +2 -2
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/black.py +3 -3
- package/generator/pygen/codegen/__init__.py +2 -0
- package/generator/pygen/codegen/_utils.py +4 -0
- package/generator/pygen/codegen/models/base.py +2 -3
- package/generator/pygen/codegen/models/base_builder.py +5 -3
- package/generator/pygen/codegen/models/client.py +28 -19
- package/generator/pygen/codegen/models/code_model.py +204 -33
- package/generator/pygen/codegen/models/combined_type.py +12 -8
- package/generator/pygen/codegen/models/constant_type.py +2 -3
- package/generator/pygen/codegen/models/credential_types.py +6 -3
- package/generator/pygen/codegen/models/dictionary_type.py +2 -3
- package/generator/pygen/codegen/models/enum_type.py +47 -24
- package/generator/pygen/codegen/models/imports.py +14 -12
- package/generator/pygen/codegen/models/list_type.py +2 -3
- package/generator/pygen/codegen/models/lro_operation.py +8 -4
- package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
- package/generator/pygen/codegen/models/model_type.py +34 -19
- package/generator/pygen/codegen/models/operation.py +74 -31
- package/generator/pygen/codegen/models/operation_group.py +82 -12
- package/generator/pygen/codegen/models/paging_operation.py +10 -7
- package/generator/pygen/codegen/models/parameter.py +10 -10
- package/generator/pygen/codegen/models/parameter_list.py +7 -7
- package/generator/pygen/codegen/models/primitive_types.py +23 -43
- package/generator/pygen/codegen/models/property.py +9 -9
- package/generator/pygen/codegen/models/request_builder.py +9 -15
- package/generator/pygen/codegen/models/response.py +6 -8
- package/generator/pygen/codegen/models/utils.py +11 -0
- package/generator/pygen/codegen/serializers/__init__.py +228 -243
- package/generator/pygen/codegen/serializers/base_serializer.py +19 -1
- package/generator/pygen/codegen/serializers/builder_serializer.py +58 -36
- package/generator/pygen/codegen/serializers/client_serializer.py +9 -5
- package/generator/pygen/codegen/serializers/enum_serializer.py +17 -3
- package/generator/pygen/codegen/serializers/general_serializer.py +26 -14
- package/generator/pygen/codegen/serializers/metadata_serializer.py +26 -8
- package/generator/pygen/codegen/serializers/model_init_serializer.py +9 -4
- package/generator/pygen/codegen/serializers/model_serializer.py +65 -24
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +20 -16
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -10
- package/generator/pygen/codegen/serializers/parameter_serializer.py +10 -7
- package/generator/pygen/codegen/serializers/request_builders_serializer.py +10 -1
- package/generator/pygen/codegen/serializers/sample_serializer.py +7 -10
- package/generator/pygen/codegen/serializers/test_serializer.py +24 -28
- package/generator/pygen/codegen/serializers/types_serializer.py +6 -1
- package/generator/pygen/codegen/serializers/utils.py +1 -15
- package/generator/pygen/codegen/templates/client_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/config_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/init.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/model_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +2 -68
- package/generator/pygen/codegen/templates/test.py.jinja2 +3 -3
- package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
- package/generator/pygen/codegen/templates/vendor.py.jinja2 +4 -4
- package/generator/pygen/preprocess/__init__.py +0 -4
- package/generator/pygen.egg-info/PKG-INFO +10 -1
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
-
from
|
|
7
|
+
from collections import namedtuple
|
|
8
|
+
import re
|
|
9
|
+
from typing import List, Any, Union
|
|
8
10
|
from pathlib import Path
|
|
9
11
|
from jinja2 import PackageLoader, Environment, FileSystemLoader, StrictUndefined
|
|
10
12
|
|
|
@@ -15,6 +17,8 @@ from ..models import (
|
|
|
15
17
|
OverloadedRequestBuilder,
|
|
16
18
|
CodeModel,
|
|
17
19
|
Client,
|
|
20
|
+
ModelType,
|
|
21
|
+
EnumType,
|
|
18
22
|
)
|
|
19
23
|
from .enum_serializer import EnumSerializer
|
|
20
24
|
from .general_serializer import GeneralSerializer
|
|
@@ -34,7 +38,6 @@ from .utils import (
|
|
|
34
38
|
extract_sample_name,
|
|
35
39
|
get_namespace_from_package_name,
|
|
36
40
|
get_namespace_config,
|
|
37
|
-
get_all_operation_groups_recursively,
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -53,6 +56,7 @@ _PACKAGE_FILES = [
|
|
|
53
56
|
]
|
|
54
57
|
|
|
55
58
|
_REGENERATE_FILES = {"setup.py", "MANIFEST.in"}
|
|
59
|
+
AsyncInfo = namedtuple("AsyncInfo", ["async_mode", "async_path"])
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
# extract sub folders. For example, source_file_path is like:
|
|
@@ -85,54 +89,24 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
85
89
|
def has_operations_folder(self) -> bool:
|
|
86
90
|
return self.code_model.options["show_operations"] and bool(self.code_model.has_operations)
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if self.has_operations_folder:
|
|
95
|
-
self._keep_patch_file(
|
|
96
|
-
namespace_path / Path(self.code_model.operations_folder_name) / Path("_patch.py"),
|
|
97
|
-
env,
|
|
98
|
-
)
|
|
99
|
-
if self.has_aio_folder:
|
|
100
|
-
self._keep_patch_file(
|
|
101
|
-
namespace_path / Path("aio") / Path(self.code_model.operations_folder_name) / Path("_patch.py"),
|
|
102
|
-
env,
|
|
103
|
-
)
|
|
104
|
-
self._serialize_and_write_top_level_folder(env=env, namespace_path=namespace_path, clients=clients)
|
|
105
|
-
|
|
106
|
-
if any(c for c in self.code_model.clients if c.operation_groups):
|
|
107
|
-
if self.code_model.options["builders_visibility"] != "embedded":
|
|
108
|
-
self._serialize_and_write_rest_layer(env=env, namespace_path=namespace_path)
|
|
109
|
-
if self.has_aio_folder:
|
|
110
|
-
self._serialize_and_write_aio_top_level_folder(
|
|
111
|
-
env=env,
|
|
112
|
-
namespace_path=namespace_path,
|
|
113
|
-
clients=clients,
|
|
114
|
-
)
|
|
92
|
+
@property
|
|
93
|
+
def serialize_loop(self) -> List[AsyncInfo]:
|
|
94
|
+
sync_loop = AsyncInfo(async_mode=False, async_path="")
|
|
95
|
+
async_loop = AsyncInfo(async_mode=True, async_path="aio/")
|
|
96
|
+
return [sync_loop, async_loop] if self.has_aio_folder else [sync_loop]
|
|
115
97
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
self._serialize_and_write_sample(env, namespace_path)
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
self.code_model.options["show_operations"]
|
|
132
|
-
and self.code_model.has_operations
|
|
133
|
-
and self.code_model.options["generate_test"]
|
|
134
|
-
):
|
|
135
|
-
self._serialize_and_write_test(env, namespace_path)
|
|
98
|
+
@property
|
|
99
|
+
def keep_version_file(self) -> bool:
|
|
100
|
+
if self.options.get("keep_version_file"):
|
|
101
|
+
return True
|
|
102
|
+
# If the version file is already there and the version is greater than the current version, keep it.
|
|
103
|
+
try:
|
|
104
|
+
serialized_version_file = self.read_file(self.exec_path(self.code_model.namespace) / "_version.py")
|
|
105
|
+
match = re.search(r'VERSION\s*=\s*"([^"]+)"', str(serialized_version_file))
|
|
106
|
+
serialized_version = match.group(1) if match else ""
|
|
107
|
+
except (FileNotFoundError, IndexError):
|
|
108
|
+
serialized_version = ""
|
|
109
|
+
return serialized_version > self.code_model.options["package_version"]
|
|
136
110
|
|
|
137
111
|
def serialize(self) -> None:
|
|
138
112
|
env = Environment(
|
|
@@ -144,54 +118,81 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
144
118
|
lstrip_blocks=True,
|
|
145
119
|
)
|
|
146
120
|
|
|
147
|
-
namespace_path = (
|
|
148
|
-
Path(".") if self.code_model.options["no_namespace_folders"] else Path(*self._name_space().split("."))
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
p = namespace_path.parent
|
|
152
121
|
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
122
|
+
for client_namespace, client_namespace_type in self.code_model.client_namespace_types.items():
|
|
123
|
+
exec_path = self.exec_path(client_namespace)
|
|
124
|
+
if client_namespace == "":
|
|
125
|
+
# Write the setup file
|
|
126
|
+
if self.code_model.options["basic_setup_py"]:
|
|
127
|
+
self.write_file(exec_path / Path("setup.py"), general_serializer.serialize_setup_file())
|
|
128
|
+
|
|
129
|
+
# add packaging files in root namespace (e.g. setup.py, README.md, etc.)
|
|
130
|
+
if self.code_model.options["package_mode"]:
|
|
131
|
+
self._serialize_and_write_package_files(client_namespace)
|
|
132
|
+
|
|
133
|
+
# write apiview_mapping_python.json
|
|
134
|
+
if self.code_model.options.get("emit_cross_language_definition_file"):
|
|
135
|
+
self.write_file(
|
|
136
|
+
exec_path / Path("apiview_mapping_python.json"),
|
|
137
|
+
general_serializer.serialize_cross_language_definition_file(),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# add generated samples and generated tests
|
|
141
|
+
if self.code_model.options["show_operations"] and self.code_model.has_operations:
|
|
142
|
+
if self.code_model.options["generate_sample"]:
|
|
143
|
+
self._serialize_and_write_sample(env, namespace=client_namespace)
|
|
144
|
+
if self.code_model.options["generate_test"]:
|
|
145
|
+
self._serialize_and_write_test(env, namespace=client_namespace)
|
|
146
|
+
elif client_namespace_type.clients:
|
|
147
|
+
# add clients folder if there are clients in this namespace
|
|
148
|
+
self._serialize_client_and_config_files(client_namespace, client_namespace_type.clients, env)
|
|
149
|
+
else:
|
|
150
|
+
# add pkgutil init file if no clients in this namespace
|
|
151
|
+
self.write_file(
|
|
152
|
+
exec_path / Path("__init__.py"),
|
|
153
|
+
general_serializer.serialize_pkgutil_init_file(),
|
|
154
|
+
)
|
|
160
155
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
156
|
+
# _model_base.py/_serialization.py/_vendor.py/py.typed/_types.py/_validation.py
|
|
157
|
+
# is always put in top level namespace
|
|
158
|
+
if self.code_model.is_top_namespace(client_namespace):
|
|
159
|
+
self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
|
|
160
|
+
|
|
161
|
+
# add models folder if there are models in this namespace
|
|
162
|
+
if (
|
|
163
|
+
self.code_model.has_non_json_models(client_namespace_type.models) or client_namespace_type.enums
|
|
164
|
+
) and self.code_model.options["models_mode"]:
|
|
165
|
+
self._serialize_and_write_models_folder(
|
|
166
|
+
env=env,
|
|
167
|
+
namespace=client_namespace,
|
|
168
|
+
models=client_namespace_type.models,
|
|
169
|
+
enums=client_namespace_type.enums,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
if not self.code_model.options["models_mode"]:
|
|
173
|
+
# keep models file if users ended up just writing a models file
|
|
174
|
+
model_path = exec_path / Path("models.py")
|
|
175
|
+
if self.read_file(model_path):
|
|
176
|
+
self.write_file(model_path, self.read_file(model_path))
|
|
177
|
+
|
|
178
|
+
# add operations folder if there are operations in this namespace
|
|
179
|
+
if client_namespace_type.operation_groups:
|
|
180
|
+
self._serialize_and_write_operations_folder(
|
|
181
|
+
client_namespace_type.operation_groups, env=env, namespace=client_namespace
|
|
182
|
+
)
|
|
183
|
+
if self.code_model.options["multiapi"]:
|
|
184
|
+
self._serialize_and_write_metadata(env=env, namespace=client_namespace)
|
|
185
|
+
|
|
186
|
+
# if there are only operations under this namespace, we need to add general __init__.py into `aio` folder
|
|
187
|
+
# to make sure all generated files could be packed into .zip/.whl/.tgz package
|
|
188
|
+
if not client_namespace_type.clients and client_namespace_type.operation_groups and self.has_aio_folder:
|
|
183
189
|
self.write_file(
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
exec_path / Path("aio/__init__.py"),
|
|
191
|
+
general_serializer.serialize_pkgutil_init_file(),
|
|
186
192
|
)
|
|
187
|
-
if self.code_model.named_unions:
|
|
188
|
-
self.write_file(
|
|
189
|
-
namespace_path / Path("_types.py"),
|
|
190
|
-
TypesSerializer(code_model=self.code_model, env=env).serialize(),
|
|
191
|
-
)
|
|
192
193
|
|
|
193
|
-
def _serialize_and_write_package_files(self,
|
|
194
|
-
root_of_sdk = self.
|
|
194
|
+
def _serialize_and_write_package_files(self, client_namespace: str) -> None:
|
|
195
|
+
root_of_sdk = self.exec_path(client_namespace)
|
|
195
196
|
if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
|
|
196
197
|
env = Environment(
|
|
197
198
|
loader=PackageLoader("pygen.codegen", "templates/packaging_templates"),
|
|
@@ -216,6 +217,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
216
217
|
file = template_name.replace(".jinja2", "")
|
|
217
218
|
output_name = root_of_sdk / file
|
|
218
219
|
if not self.read_file(output_name) or file in _REGENERATE_FILES:
|
|
220
|
+
if self.keep_version_file and file == "setup.py":
|
|
221
|
+
# don't regenerate setup.py file if the version file is more up to date
|
|
222
|
+
continue
|
|
219
223
|
self.write_file(
|
|
220
224
|
output_name,
|
|
221
225
|
serializer.serialize_package_file(template_name, **params),
|
|
@@ -230,25 +234,31 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
230
234
|
PatchSerializer(env=env, code_model=self.code_model).serialize(),
|
|
231
235
|
)
|
|
232
236
|
|
|
233
|
-
def _serialize_and_write_models_folder(
|
|
237
|
+
def _serialize_and_write_models_folder(
|
|
238
|
+
self, env: Environment, namespace: str, models: List[ModelType], enums: List[EnumType]
|
|
239
|
+
) -> None:
|
|
234
240
|
# Write the models folder
|
|
235
|
-
models_path =
|
|
241
|
+
models_path = self.exec_path(namespace + ".models")
|
|
236
242
|
serializer = DpgModelSerializer if self.code_model.options["models_mode"] == "dpg" else MsrestModelSerializer
|
|
237
|
-
if self.code_model.
|
|
243
|
+
if self.code_model.has_non_json_models(models):
|
|
238
244
|
self.write_file(
|
|
239
245
|
models_path / Path(f"{self.code_model.models_filename}.py"),
|
|
240
|
-
serializer(code_model=self.code_model, env=env).serialize(),
|
|
246
|
+
serializer(code_model=self.code_model, env=env, client_namespace=namespace, models=models).serialize(),
|
|
241
247
|
)
|
|
242
|
-
if
|
|
248
|
+
if enums:
|
|
243
249
|
self.write_file(
|
|
244
250
|
models_path / Path(f"{self.code_model.enums_filename}.py"),
|
|
245
|
-
EnumSerializer(
|
|
251
|
+
EnumSerializer(
|
|
252
|
+
code_model=self.code_model, env=env, client_namespace=namespace, enums=enums
|
|
253
|
+
).serialize(),
|
|
246
254
|
)
|
|
247
255
|
self.write_file(
|
|
248
256
|
models_path / Path("__init__.py"),
|
|
249
|
-
ModelInitSerializer(code_model=self.code_model, env=env).serialize(),
|
|
257
|
+
ModelInitSerializer(code_model=self.code_model, env=env, models=models, enums=enums).serialize(),
|
|
250
258
|
)
|
|
251
259
|
|
|
260
|
+
self._keep_patch_file(models_path / Path("_patch.py"), env)
|
|
261
|
+
|
|
252
262
|
def _serialize_and_write_rest_layer(self, env: Environment, namespace_path: Path) -> None:
|
|
253
263
|
rest_path = namespace_path / Path(self.code_model.rest_layer_name)
|
|
254
264
|
group_names = {rb.group_name for c in self.code_model.clients for rb in c.request_builders}
|
|
@@ -292,196 +302,163 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
292
302
|
).serialize_init(),
|
|
293
303
|
)
|
|
294
304
|
|
|
295
|
-
def _serialize_and_write_operations_file(
|
|
296
|
-
self,
|
|
297
|
-
env: Environment,
|
|
298
|
-
clients: List[Client],
|
|
299
|
-
namespace_path: Path,
|
|
300
|
-
operation_group: Optional[OperationGroup] = None,
|
|
301
|
-
) -> None:
|
|
302
|
-
filename = operation_group.filename if operation_group else "_operations"
|
|
303
|
-
# write first sync file
|
|
304
|
-
operation_group_serializer = OperationGroupsSerializer(
|
|
305
|
-
code_model=self.code_model,
|
|
306
|
-
clients=clients,
|
|
307
|
-
env=env,
|
|
308
|
-
async_mode=False,
|
|
309
|
-
operation_group=operation_group,
|
|
310
|
-
)
|
|
311
|
-
self.write_file(
|
|
312
|
-
namespace_path / Path(self.code_model.operations_folder_name) / Path(f"{filename}.py"),
|
|
313
|
-
operation_group_serializer.serialize(),
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
if self.has_aio_folder:
|
|
317
|
-
# write async operation group and operation files
|
|
318
|
-
operation_group_async_serializer = OperationGroupsSerializer(
|
|
319
|
-
code_model=self.code_model,
|
|
320
|
-
clients=clients,
|
|
321
|
-
env=env,
|
|
322
|
-
async_mode=True,
|
|
323
|
-
operation_group=operation_group,
|
|
324
|
-
)
|
|
325
|
-
self.write_file(
|
|
326
|
-
(namespace_path / Path("aio") / Path(self.code_model.operations_folder_name) / Path(f"{filename}.py")),
|
|
327
|
-
operation_group_async_serializer.serialize(),
|
|
328
|
-
)
|
|
329
|
-
|
|
330
305
|
def _serialize_and_write_operations_folder(
|
|
331
|
-
self,
|
|
306
|
+
self, operation_groups: List[OperationGroup], env: Environment, namespace: str
|
|
332
307
|
) -> None:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
# write async operations init file
|
|
343
|
-
if self.has_aio_folder:
|
|
344
|
-
operations_async_init_serializer = OperationsInitSerializer(
|
|
345
|
-
code_model=self.code_model, clients=clients, env=env, async_mode=True
|
|
308
|
+
operations_folder_name = self.code_model.operations_folder_name(namespace)
|
|
309
|
+
exec_path = self.exec_path(namespace)
|
|
310
|
+
for async_mode, async_path in self.serialize_loop:
|
|
311
|
+
prefix_path = f"{async_path}{operations_folder_name}"
|
|
312
|
+
# write init file
|
|
313
|
+
operations_init_serializer = OperationsInitSerializer(
|
|
314
|
+
code_model=self.code_model, operation_groups=operation_groups, env=env, async_mode=async_mode
|
|
346
315
|
)
|
|
347
316
|
self.write_file(
|
|
348
|
-
|
|
349
|
-
|
|
317
|
+
exec_path / Path(f"{prefix_path}/__init__.py"),
|
|
318
|
+
operations_init_serializer.serialize(),
|
|
350
319
|
)
|
|
351
320
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
321
|
+
# write operations file
|
|
322
|
+
OgLoop = namedtuple("OgLoop", ["operation_groups", "filename"])
|
|
323
|
+
if self.code_model.options["combine_operation_files"]:
|
|
324
|
+
loops = [OgLoop(operation_groups, "_operations")]
|
|
325
|
+
else:
|
|
326
|
+
loops = [OgLoop([og], og.filename) for og in operation_groups]
|
|
327
|
+
for ogs, filename in loops:
|
|
328
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
329
|
+
code_model=self.code_model,
|
|
330
|
+
operation_groups=ogs,
|
|
361
331
|
env=env,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
332
|
+
async_mode=async_mode,
|
|
333
|
+
client_namespace=namespace,
|
|
334
|
+
)
|
|
335
|
+
self.write_file(
|
|
336
|
+
exec_path / Path(f"{prefix_path}/{filename}.py"),
|
|
337
|
+
operation_group_serializer.serialize(),
|
|
365
338
|
)
|
|
366
339
|
|
|
340
|
+
# if there was a patch file before, we keep it
|
|
341
|
+
self._keep_patch_file(exec_path / Path(f"{prefix_path}/_patch.py"), env)
|
|
342
|
+
|
|
367
343
|
def _serialize_and_write_version_file(
|
|
368
344
|
self,
|
|
369
|
-
|
|
345
|
+
namespace: str,
|
|
370
346
|
general_serializer: GeneralSerializer,
|
|
371
347
|
):
|
|
348
|
+
exec_path = self.exec_path(namespace)
|
|
349
|
+
|
|
372
350
|
def _read_version_file(original_version_file_name: str) -> str:
|
|
373
|
-
return self.read_file(
|
|
351
|
+
return self.read_file(exec_path / original_version_file_name)
|
|
374
352
|
|
|
375
353
|
def _write_version_file(original_version_file_name: str) -> None:
|
|
376
354
|
self.write_file(
|
|
377
|
-
|
|
355
|
+
exec_path / Path("_version.py"),
|
|
378
356
|
_read_version_file(original_version_file_name),
|
|
379
357
|
)
|
|
380
358
|
|
|
381
|
-
keep_version_file
|
|
382
|
-
if keep_version_file and _read_version_file("_version.py"):
|
|
359
|
+
if self.keep_version_file and _read_version_file("_version.py"):
|
|
383
360
|
_write_version_file(original_version_file_name="_version.py")
|
|
384
|
-
elif keep_version_file and _read_version_file("version.py"):
|
|
361
|
+
elif self.keep_version_file and _read_version_file("version.py"):
|
|
385
362
|
_write_version_file(original_version_file_name="version.py")
|
|
386
363
|
elif self.code_model.options["package_version"]:
|
|
387
364
|
self.write_file(
|
|
388
|
-
|
|
365
|
+
exec_path / Path("_version.py"),
|
|
389
366
|
general_serializer.serialize_version_file(),
|
|
390
367
|
)
|
|
391
368
|
|
|
392
369
|
def _serialize_client_and_config_files(
|
|
393
370
|
self,
|
|
394
|
-
|
|
395
|
-
general_serializer: GeneralSerializer,
|
|
396
|
-
async_mode: bool,
|
|
371
|
+
namespace: str,
|
|
397
372
|
clients: List[Client],
|
|
373
|
+
env: Environment,
|
|
398
374
|
) -> None:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
general_serializer.serialize_service_client_file(clients),
|
|
375
|
+
exec_path = self.exec_path(namespace)
|
|
376
|
+
for async_mode, async_path in self.serialize_loop:
|
|
377
|
+
general_serializer = GeneralSerializer(
|
|
378
|
+
code_model=self.code_model, env=env, async_mode=async_mode, client_namespace=namespace
|
|
404
379
|
)
|
|
380
|
+
# when there is client.py, there must be __init__.py
|
|
405
381
|
self.write_file(
|
|
406
|
-
|
|
407
|
-
general_serializer.
|
|
382
|
+
exec_path / Path(f"{async_path}__init__.py"),
|
|
383
|
+
general_serializer.serialize_init_file([c for c in clients if c.has_operations]),
|
|
408
384
|
)
|
|
409
385
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
) -> None:
|
|
413
|
-
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
386
|
+
# if there was a patch file before, we keep it
|
|
387
|
+
self._keep_patch_file(exec_path / Path(f"{async_path}_patch.py"), env)
|
|
414
388
|
|
|
415
|
-
|
|
416
|
-
namespace_path / Path("__init__.py"),
|
|
417
|
-
general_serializer.serialize_init_file(clients),
|
|
418
|
-
)
|
|
389
|
+
if self.code_model.clients_has_operations(clients):
|
|
419
390
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
general_serializer.serialize_vendor_file(clients),
|
|
426
|
-
)
|
|
391
|
+
# write client file
|
|
392
|
+
self.write_file(
|
|
393
|
+
exec_path / Path(f"{async_path}{self.code_model.client_filename}.py"),
|
|
394
|
+
general_serializer.serialize_service_client_file(clients),
|
|
395
|
+
)
|
|
427
396
|
|
|
428
|
-
|
|
397
|
+
# write config file
|
|
398
|
+
self.write_file(
|
|
399
|
+
exec_path / Path(f"{async_path}_configuration.py"),
|
|
400
|
+
general_serializer.serialize_config_file(clients),
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
# sometimes we need define additional Mixin class for client in _vendor.py
|
|
404
|
+
self._serialize_and_write_vendor_file(env, namespace)
|
|
405
|
+
|
|
406
|
+
def _serialize_and_write_vendor_file(self, env: Environment, namespace: str) -> None:
|
|
407
|
+
exec_path = self.exec_path(namespace)
|
|
408
|
+
# write _vendor.py
|
|
409
|
+
for async_mode, async_path in self.serialize_loop:
|
|
410
|
+
if self.code_model.need_vendored_code(async_mode=async_mode, client_namespace=namespace):
|
|
411
|
+
self.write_file(
|
|
412
|
+
exec_path / Path(f"{async_path}_vendor.py"),
|
|
413
|
+
GeneralSerializer(
|
|
414
|
+
code_model=self.code_model, env=env, async_mode=async_mode, client_namespace=namespace
|
|
415
|
+
).serialize_vendor_file(),
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
def _serialize_and_write_top_level_folder(self, env: Environment, namespace: str) -> None:
|
|
419
|
+
exec_path = self.exec_path(namespace)
|
|
420
|
+
# write _vendor.py
|
|
421
|
+
self._serialize_and_write_vendor_file(env, namespace)
|
|
422
|
+
|
|
423
|
+
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
424
|
+
|
|
425
|
+
# write _version.py
|
|
426
|
+
self._serialize_and_write_version_file(namespace, general_serializer)
|
|
429
427
|
|
|
430
428
|
# write the empty py.typed file
|
|
431
|
-
self.write_file(
|
|
429
|
+
self.write_file(exec_path / Path("py.typed"), "# Marker file for PEP 561.")
|
|
432
430
|
|
|
431
|
+
# write _serialization.py
|
|
433
432
|
if not self.code_model.options["client_side_validation"] and not self.code_model.options["multiapi"]:
|
|
434
433
|
self.write_file(
|
|
435
|
-
|
|
434
|
+
exec_path / Path("_serialization.py"),
|
|
436
435
|
general_serializer.serialize_serialization_file(),
|
|
437
436
|
)
|
|
437
|
+
|
|
438
|
+
# write _model_base.py
|
|
438
439
|
if self.code_model.options["models_mode"] == "dpg":
|
|
439
440
|
self.write_file(
|
|
440
|
-
|
|
441
|
+
exec_path / Path("_model_base.py"),
|
|
441
442
|
general_serializer.serialize_model_base_file(),
|
|
442
443
|
)
|
|
443
444
|
|
|
445
|
+
# write _validation.py
|
|
444
446
|
if any(og for client in self.code_model.clients for og in client.operation_groups if og.need_validation):
|
|
445
447
|
self.write_file(
|
|
446
|
-
|
|
448
|
+
exec_path / Path("_validation.py"),
|
|
447
449
|
general_serializer.serialize_validation_file(),
|
|
448
450
|
)
|
|
449
|
-
if self.code_model.options.get("emit_cross_language_definition_file"):
|
|
450
|
-
self.write_file(
|
|
451
|
-
Path("./apiview_mapping_python.json"),
|
|
452
|
-
general_serializer.serialize_cross_language_definition_file(),
|
|
453
|
-
)
|
|
454
|
-
|
|
455
|
-
# Write the setup file
|
|
456
|
-
if self.code_model.options["basic_setup_py"]:
|
|
457
|
-
self.write_file(Path("setup.py"), general_serializer.serialize_setup_file())
|
|
458
|
-
|
|
459
|
-
def _serialize_and_write_aio_top_level_folder(
|
|
460
|
-
self, env: Environment, namespace_path: Path, clients: List[Client]
|
|
461
|
-
) -> None:
|
|
462
|
-
aio_general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=True)
|
|
463
|
-
|
|
464
|
-
aio_path = namespace_path / Path("aio")
|
|
465
|
-
|
|
466
|
-
# Write the __init__ file
|
|
467
|
-
self.write_file(
|
|
468
|
-
aio_path / Path("__init__.py"),
|
|
469
|
-
aio_general_serializer.serialize_init_file(clients),
|
|
470
|
-
)
|
|
471
451
|
|
|
472
|
-
#
|
|
473
|
-
self.
|
|
474
|
-
namespace_path, aio_general_serializer, async_mode=True, clients=clients
|
|
475
|
-
)
|
|
476
|
-
if self.code_model.need_vendored_code(async_mode=True):
|
|
452
|
+
# write _types.py
|
|
453
|
+
if self.code_model.named_unions:
|
|
477
454
|
self.write_file(
|
|
478
|
-
|
|
479
|
-
|
|
455
|
+
exec_path / Path("_types.py"),
|
|
456
|
+
TypesSerializer(code_model=self.code_model, env=env).serialize(),
|
|
480
457
|
)
|
|
481
458
|
|
|
482
|
-
def _serialize_and_write_metadata(self, env: Environment,
|
|
483
|
-
metadata_serializer = MetadataSerializer(self.code_model, env)
|
|
484
|
-
self.write_file(
|
|
459
|
+
def _serialize_and_write_metadata(self, env: Environment, namespace: str) -> None:
|
|
460
|
+
metadata_serializer = MetadataSerializer(self.code_model, env, client_namespace=namespace)
|
|
461
|
+
self.write_file(self.exec_path(namespace) / Path("_metadata.json"), metadata_serializer.serialize())
|
|
485
462
|
|
|
486
463
|
@property
|
|
487
464
|
def _namespace_from_package_name(self) -> str:
|
|
@@ -493,9 +470,17 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
493
470
|
|
|
494
471
|
return self._namespace_from_package_name
|
|
495
472
|
|
|
496
|
-
|
|
497
|
-
def
|
|
498
|
-
|
|
473
|
+
@property
|
|
474
|
+
def exec_path_compensation(self) -> Path:
|
|
475
|
+
"""Assume the process is running in the root folder of the package. If not, we need the path compensation."""
|
|
476
|
+
return (
|
|
477
|
+
Path("../" * (self._name_space().count(".") + 1))
|
|
478
|
+
if self.code_model.options["no_namespace_folders"]
|
|
479
|
+
else Path(".")
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
def exec_path(self, namespace: str) -> Path:
|
|
483
|
+
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
499
484
|
|
|
500
485
|
@property
|
|
501
486
|
def _additional_folder(self) -> Path:
|
|
@@ -506,8 +491,8 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
506
491
|
return Path("/".join(namespace_config.split(".")[num_of_package_namespace:]))
|
|
507
492
|
return Path("")
|
|
508
493
|
|
|
509
|
-
def _serialize_and_write_sample(self, env: Environment,
|
|
510
|
-
out_path = self.
|
|
494
|
+
def _serialize_and_write_sample(self, env: Environment, namespace: str):
|
|
495
|
+
out_path = self.exec_path(namespace) / Path("generated_samples")
|
|
511
496
|
for client in self.code_model.clients:
|
|
512
497
|
for op_group in client.operation_groups:
|
|
513
498
|
for operation in op_group.operations:
|
|
@@ -539,15 +524,15 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
539
524
|
log_error = f"error happens in sample {file}: {e}"
|
|
540
525
|
_LOGGER.error(log_error)
|
|
541
526
|
|
|
542
|
-
def _serialize_and_write_test(self, env: Environment,
|
|
527
|
+
def _serialize_and_write_test(self, env: Environment, namespace: str):
|
|
543
528
|
self.code_model.for_test = True
|
|
544
|
-
out_path = self.
|
|
529
|
+
out_path = self.exec_path(namespace) / Path("generated_tests")
|
|
545
530
|
general_serializer = TestGeneralSerializer(code_model=self.code_model, env=env)
|
|
546
531
|
self.write_file(out_path / "conftest.py", general_serializer.serialize_conftest())
|
|
547
532
|
if not self.code_model.options["azure_arm"]:
|
|
548
|
-
for
|
|
549
|
-
async_suffix = "_async" if
|
|
550
|
-
general_serializer.
|
|
533
|
+
for async_mode in (True, False):
|
|
534
|
+
async_suffix = "_async" if async_mode else ""
|
|
535
|
+
general_serializer.async_mode = async_mode
|
|
551
536
|
self.write_file(
|
|
552
537
|
out_path / f"testpreparer{async_suffix}.py",
|
|
553
538
|
general_serializer.serialize_testpreparer(),
|
|
@@ -560,9 +545,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
560
545
|
):
|
|
561
546
|
continue
|
|
562
547
|
test_serializer = TestSerializer(self.code_model, env, client=client, operation_group=og)
|
|
563
|
-
for
|
|
548
|
+
for async_mode in (True, False):
|
|
564
549
|
try:
|
|
565
|
-
test_serializer.
|
|
550
|
+
test_serializer.async_mode = async_mode
|
|
566
551
|
self.write_file(
|
|
567
552
|
out_path / f"{to_snake_case(test_serializer.test_class_name)}.py",
|
|
568
553
|
test_serializer.serialize_test(),
|