@typespec/http-client-python 0.5.1 → 0.6.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/dist/emitter/code-model.d.ts.map +1 -1
- package/dist/emitter/code-model.js +10 -7
- package/dist/emitter/code-model.js.map +1 -1
- package/dist/emitter/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +4 -1
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +1 -0
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +1 -0
- package/dist/emitter/lib.js.map +1 -1
- package/dist/emitter/types.d.ts.map +1 -1
- package/dist/emitter/types.js +7 -4
- package/dist/emitter/types.js.map +1 -1
- package/dist/emitter/utils.d.ts +1 -0
- package/dist/emitter/utils.d.ts.map +1 -1
- package/dist/emitter/utils.js +19 -0
- package/dist/emitter/utils.js.map +1 -1
- package/emitter/src/code-model.ts +16 -6
- package/emitter/src/emitter.ts +4 -1
- package/emitter/src/lib.ts +4 -0
- package/emitter/src/types.ts +16 -4
- package/emitter/src/utils.ts +27 -0
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/regenerate.ts +7 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/generator/build/lib/pygen/black.py +2 -2
- 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 +200 -33
- package/generator/build/lib/pygen/codegen/models/combined_type.py +8 -5
- package/generator/build/lib/pygen/codegen/models/constant_type.py +2 -3
- package/generator/build/lib/pygen/codegen/models/credential_types.py +2 -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 +66 -29
- package/generator/build/lib/pygen/codegen/models/operation_group.py +56 -11
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +9 -6
- 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 +7 -7
- 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 +201 -242
- package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +19 -1
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +53 -35
- 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 +63 -23
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +19 -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/operations_folder_init.py.jinja2 +2 -4
- 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 +2 -2
- 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 +200 -33
- package/generator/pygen/codegen/models/combined_type.py +8 -5
- package/generator/pygen/codegen/models/constant_type.py +2 -3
- package/generator/pygen/codegen/models/credential_types.py +2 -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 +66 -29
- package/generator/pygen/codegen/models/operation_group.py +56 -11
- package/generator/pygen/codegen/models/paging_operation.py +9 -6
- 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 +7 -7
- 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 +201 -242
- package/generator/pygen/codegen/serializers/base_serializer.py +19 -1
- package/generator/pygen/codegen/serializers/builder_serializer.py +53 -35
- 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 +63 -23
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +19 -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/operations_folder_init.py.jinja2 +2 -4
- 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/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +1 -1
- package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +31 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py +1 -1
- package/generator/test/azure/mock_api_tests/test_client_namespace.py +29 -0
- package/generator/test/azure/mock_api_tests/test_resiliency_srv_driven_async.py +1 -0
- package/generator/test/azure/requirements.txt +3 -2
- package/generator/test/azure/tox.ini +2 -2
- package/generator/test/unbranded/requirements.txt +2 -2
- package/generator/test/unbranded/tox.ini +2 -2
- package/package.json +1 -1
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
-
from
|
|
7
|
+
from collections import namedtuple
|
|
8
|
+
from typing import List, Any, Union
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from jinja2 import PackageLoader, Environment, FileSystemLoader, StrictUndefined
|
|
10
11
|
|
|
@@ -15,6 +16,8 @@ from ..models import (
|
|
|
15
16
|
OverloadedRequestBuilder,
|
|
16
17
|
CodeModel,
|
|
17
18
|
Client,
|
|
19
|
+
ModelType,
|
|
20
|
+
EnumType,
|
|
18
21
|
)
|
|
19
22
|
from .enum_serializer import EnumSerializer
|
|
20
23
|
from .general_serializer import GeneralSerializer
|
|
@@ -34,7 +37,6 @@ from .utils import (
|
|
|
34
37
|
extract_sample_name,
|
|
35
38
|
get_namespace_from_package_name,
|
|
36
39
|
get_namespace_config,
|
|
37
|
-
get_all_operation_groups_recursively,
|
|
38
40
|
)
|
|
39
41
|
|
|
40
42
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -53,6 +55,7 @@ _PACKAGE_FILES = [
|
|
|
53
55
|
]
|
|
54
56
|
|
|
55
57
|
_REGENERATE_FILES = {"setup.py", "MANIFEST.in"}
|
|
58
|
+
AsyncInfo = namedtuple("AsyncInfo", ["async_mode", "async_path"])
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
# extract sub folders. For example, source_file_path is like:
|
|
@@ -85,54 +88,11 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
85
88
|
def has_operations_folder(self) -> bool:
|
|
86
89
|
return self.code_model.options["show_operations"] and bool(self.code_model.has_operations)
|
|
87
90
|
|
|
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
|
-
)
|
|
115
|
-
|
|
116
|
-
if self.has_operations_folder:
|
|
117
|
-
self._serialize_and_write_operations_folder(clients, env=env, namespace_path=namespace_path)
|
|
118
|
-
if self.code_model.options["multiapi"]:
|
|
119
|
-
self._serialize_and_write_metadata(env=env, namespace_path=namespace_path)
|
|
120
|
-
if self.code_model.options["package_mode"]:
|
|
121
|
-
self._serialize_and_write_package_files(namespace_path=namespace_path)
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
self.code_model.options["show_operations"]
|
|
125
|
-
and self.code_model.has_operations
|
|
126
|
-
and self.code_model.options["generate_sample"]
|
|
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)
|
|
91
|
+
@property
|
|
92
|
+
def serialize_loop(self) -> List[AsyncInfo]:
|
|
93
|
+
sync_loop = AsyncInfo(async_mode=False, async_path="")
|
|
94
|
+
async_loop = AsyncInfo(async_mode=True, async_path="aio/")
|
|
95
|
+
return [sync_loop, async_loop] if self.has_aio_folder else [sync_loop]
|
|
136
96
|
|
|
137
97
|
def serialize(self) -> None:
|
|
138
98
|
env = Environment(
|
|
@@ -144,54 +104,71 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
144
104
|
lstrip_blocks=True,
|
|
145
105
|
)
|
|
146
106
|
|
|
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
107
|
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if self.read_file(namespace_path / Path("models.py")):
|
|
108
|
+
for client_namespace, client_namespace_type in self.code_model.client_namespace_types.items():
|
|
109
|
+
exec_path = self.exec_path(client_namespace)
|
|
110
|
+
if client_namespace == "":
|
|
111
|
+
# Write the setup file
|
|
112
|
+
if self.code_model.options["basic_setup_py"]:
|
|
113
|
+
self.write_file(exec_path / Path("setup.py"), general_serializer.serialize_setup_file())
|
|
114
|
+
|
|
115
|
+
# add packaging files in root namespace (e.g. setup.py, README.md, etc.)
|
|
116
|
+
if self.code_model.options["package_mode"]:
|
|
117
|
+
self._serialize_and_write_package_files(client_namespace)
|
|
118
|
+
|
|
119
|
+
# write apiview_mapping_python.json
|
|
120
|
+
if self.code_model.options.get("emit_cross_language_definition_file"):
|
|
121
|
+
self.write_file(
|
|
122
|
+
exec_path / Path("apiview_mapping_python.json"),
|
|
123
|
+
general_serializer.serialize_cross_language_definition_file(),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# add generated samples and generated tests
|
|
127
|
+
if self.code_model.options["show_operations"] and self.code_model.has_operations:
|
|
128
|
+
if self.code_model.options["generate_sample"]:
|
|
129
|
+
self._serialize_and_write_sample(env, namespace=client_namespace)
|
|
130
|
+
if self.code_model.options["generate_test"]:
|
|
131
|
+
self._serialize_and_write_test(env, namespace=client_namespace)
|
|
132
|
+
elif client_namespace_type.clients:
|
|
133
|
+
# add clients folder if there are clients in this namespace
|
|
134
|
+
self._serialize_client_and_config_files(client_namespace, client_namespace_type.clients, env)
|
|
135
|
+
else:
|
|
136
|
+
# add pkgutil init file if no clients in this namespace
|
|
183
137
|
self.write_file(
|
|
184
|
-
|
|
185
|
-
|
|
138
|
+
exec_path / Path("__init__.py"),
|
|
139
|
+
general_serializer.serialize_pkgutil_init_file(),
|
|
186
140
|
)
|
|
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
141
|
|
|
193
|
-
|
|
194
|
-
|
|
142
|
+
# _model_base.py/_serialization.py/_vendor.py/py.typed/_types.py/_validation.py
|
|
143
|
+
# is always put in top level namespace
|
|
144
|
+
if self.code_model.is_top_namespace(client_namespace):
|
|
145
|
+
self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
|
|
146
|
+
|
|
147
|
+
# add models folder if there are models in this namespace
|
|
148
|
+
if (client_namespace_type.models or client_namespace_type.enums) and self.code_model.options["models_mode"]:
|
|
149
|
+
self._serialize_and_write_models_folder(
|
|
150
|
+
env=env,
|
|
151
|
+
namespace=client_namespace,
|
|
152
|
+
models=client_namespace_type.models,
|
|
153
|
+
enums=client_namespace_type.enums,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
if not self.code_model.options["models_mode"]:
|
|
157
|
+
# keep models file if users ended up just writing a models file
|
|
158
|
+
model_path = exec_path / Path("models.py")
|
|
159
|
+
if self.read_file(model_path):
|
|
160
|
+
self.write_file(model_path, self.read_file(model_path))
|
|
161
|
+
|
|
162
|
+
# add operations folder if there are operations in this namespace
|
|
163
|
+
if client_namespace_type.operation_groups:
|
|
164
|
+
self._serialize_and_write_operations_folder(
|
|
165
|
+
client_namespace_type.operation_groups, env=env, namespace=client_namespace
|
|
166
|
+
)
|
|
167
|
+
if self.code_model.options["multiapi"]:
|
|
168
|
+
self._serialize_and_write_metadata(env=env, namespace=client_namespace)
|
|
169
|
+
|
|
170
|
+
def _serialize_and_write_package_files(self, client_namespace: str) -> None:
|
|
171
|
+
root_of_sdk = self.exec_path(client_namespace)
|
|
195
172
|
if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
|
|
196
173
|
env = Environment(
|
|
197
174
|
loader=PackageLoader("pygen.codegen", "templates/packaging_templates"),
|
|
@@ -230,25 +207,31 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
230
207
|
PatchSerializer(env=env, code_model=self.code_model).serialize(),
|
|
231
208
|
)
|
|
232
209
|
|
|
233
|
-
def _serialize_and_write_models_folder(
|
|
210
|
+
def _serialize_and_write_models_folder(
|
|
211
|
+
self, env: Environment, namespace: str, models: List[ModelType], enums: List[EnumType]
|
|
212
|
+
) -> None:
|
|
234
213
|
# Write the models folder
|
|
235
|
-
models_path =
|
|
214
|
+
models_path = self.exec_path(namespace + ".models")
|
|
236
215
|
serializer = DpgModelSerializer if self.code_model.options["models_mode"] == "dpg" else MsrestModelSerializer
|
|
237
|
-
if
|
|
216
|
+
if models:
|
|
238
217
|
self.write_file(
|
|
239
218
|
models_path / Path(f"{self.code_model.models_filename}.py"),
|
|
240
|
-
serializer(code_model=self.code_model, env=env).serialize(),
|
|
219
|
+
serializer(code_model=self.code_model, env=env, client_namespace=namespace, models=models).serialize(),
|
|
241
220
|
)
|
|
242
|
-
if
|
|
221
|
+
if enums:
|
|
243
222
|
self.write_file(
|
|
244
223
|
models_path / Path(f"{self.code_model.enums_filename}.py"),
|
|
245
|
-
EnumSerializer(
|
|
224
|
+
EnumSerializer(
|
|
225
|
+
code_model=self.code_model, env=env, client_namespace=namespace, enums=enums
|
|
226
|
+
).serialize(),
|
|
246
227
|
)
|
|
247
228
|
self.write_file(
|
|
248
229
|
models_path / Path("__init__.py"),
|
|
249
|
-
ModelInitSerializer(code_model=self.code_model, env=env).serialize(),
|
|
230
|
+
ModelInitSerializer(code_model=self.code_model, env=env, models=models, enums=enums).serialize(),
|
|
250
231
|
)
|
|
251
232
|
|
|
233
|
+
self._keep_patch_file(models_path / Path("_patch.py"), env)
|
|
234
|
+
|
|
252
235
|
def _serialize_and_write_rest_layer(self, env: Environment, namespace_path: Path) -> None:
|
|
253
236
|
rest_path = namespace_path / Path(self.code_model.rest_layer_name)
|
|
254
237
|
group_names = {rb.group_name for c in self.code_model.clients for rb in c.request_builders}
|
|
@@ -292,89 +275,57 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
292
275
|
).serialize_init(),
|
|
293
276
|
)
|
|
294
277
|
|
|
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
278
|
def _serialize_and_write_operations_folder(
|
|
331
|
-
self,
|
|
279
|
+
self, operation_groups: List[OperationGroup], env: Environment, namespace: str
|
|
332
280
|
) -> 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
|
|
281
|
+
operations_folder_name = self.code_model.operations_folder_name(namespace)
|
|
282
|
+
exec_path = self.exec_path(namespace)
|
|
283
|
+
for async_mode, async_path in self.serialize_loop:
|
|
284
|
+
prefix_path = f"{async_path}{operations_folder_name}"
|
|
285
|
+
# write init file
|
|
286
|
+
operations_init_serializer = OperationsInitSerializer(
|
|
287
|
+
code_model=self.code_model, operation_groups=operation_groups, env=env, async_mode=async_mode
|
|
346
288
|
)
|
|
347
289
|
self.write_file(
|
|
348
|
-
|
|
349
|
-
|
|
290
|
+
exec_path / Path(f"{prefix_path}/__init__.py"),
|
|
291
|
+
operations_init_serializer.serialize(),
|
|
350
292
|
)
|
|
351
293
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
294
|
+
# write operations file
|
|
295
|
+
OgLoop = namedtuple("OgLoop", ["operation_groups", "filename"])
|
|
296
|
+
if self.code_model.options["combine_operation_files"]:
|
|
297
|
+
loops = [OgLoop(operation_groups, "_operations")]
|
|
298
|
+
else:
|
|
299
|
+
loops = [OgLoop([og], og.filename) for og in operation_groups]
|
|
300
|
+
for ogs, filename in loops:
|
|
301
|
+
operation_group_serializer = OperationGroupsSerializer(
|
|
302
|
+
code_model=self.code_model,
|
|
303
|
+
operation_groups=ogs,
|
|
361
304
|
env=env,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
clients=clients,
|
|
305
|
+
async_mode=async_mode,
|
|
306
|
+
client_namespace=namespace,
|
|
365
307
|
)
|
|
308
|
+
self.write_file(
|
|
309
|
+
exec_path / Path(f"{prefix_path}/{filename}.py"),
|
|
310
|
+
operation_group_serializer.serialize(),
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# if there was a patch file before, we keep it
|
|
314
|
+
self._keep_patch_file(exec_path / Path(f"{prefix_path}/_patch.py"), env)
|
|
366
315
|
|
|
367
316
|
def _serialize_and_write_version_file(
|
|
368
317
|
self,
|
|
369
|
-
|
|
318
|
+
namespace: str,
|
|
370
319
|
general_serializer: GeneralSerializer,
|
|
371
320
|
):
|
|
321
|
+
exec_path = self.exec_path(namespace)
|
|
322
|
+
|
|
372
323
|
def _read_version_file(original_version_file_name: str) -> str:
|
|
373
|
-
return self.read_file(
|
|
324
|
+
return self.read_file(exec_path / original_version_file_name)
|
|
374
325
|
|
|
375
326
|
def _write_version_file(original_version_file_name: str) -> None:
|
|
376
327
|
self.write_file(
|
|
377
|
-
|
|
328
|
+
exec_path / Path("_version.py"),
|
|
378
329
|
_read_version_file(original_version_file_name),
|
|
379
330
|
)
|
|
380
331
|
|
|
@@ -385,103 +336,103 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
385
336
|
_write_version_file(original_version_file_name="version.py")
|
|
386
337
|
elif self.code_model.options["package_version"]:
|
|
387
338
|
self.write_file(
|
|
388
|
-
|
|
339
|
+
exec_path / Path("_version.py"),
|
|
389
340
|
general_serializer.serialize_version_file(),
|
|
390
341
|
)
|
|
391
342
|
|
|
392
343
|
def _serialize_client_and_config_files(
|
|
393
344
|
self,
|
|
394
|
-
|
|
395
|
-
general_serializer: GeneralSerializer,
|
|
396
|
-
async_mode: bool,
|
|
345
|
+
namespace: str,
|
|
397
346
|
clients: List[Client],
|
|
347
|
+
env: Environment,
|
|
398
348
|
) -> None:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
general_serializer.serialize_service_client_file(clients),
|
|
349
|
+
exec_path = self.exec_path(namespace)
|
|
350
|
+
for async_mode, async_path in self.serialize_loop:
|
|
351
|
+
general_serializer = GeneralSerializer(
|
|
352
|
+
code_model=self.code_model, env=env, async_mode=async_mode, client_namespace=namespace
|
|
404
353
|
)
|
|
354
|
+
# when there is client.py, there must be __init__.py
|
|
405
355
|
self.write_file(
|
|
406
|
-
|
|
407
|
-
general_serializer.
|
|
356
|
+
exec_path / Path(f"{async_path}__init__.py"),
|
|
357
|
+
general_serializer.serialize_init_file([c for c in clients if c.has_operations]),
|
|
408
358
|
)
|
|
409
359
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
) -> None:
|
|
413
|
-
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
360
|
+
# if there was a patch file before, we keep it
|
|
361
|
+
self._keep_patch_file(exec_path / Path(f"{async_path}_patch.py"), env)
|
|
414
362
|
|
|
415
|
-
|
|
416
|
-
namespace_path / Path("__init__.py"),
|
|
417
|
-
general_serializer.serialize_init_file(clients),
|
|
418
|
-
)
|
|
363
|
+
if self.code_model.clients_has_operations(clients):
|
|
419
364
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
365
|
+
# write client file
|
|
366
|
+
self.write_file(
|
|
367
|
+
exec_path / Path(f"{async_path}{self.code_model.client_filename}.py"),
|
|
368
|
+
general_serializer.serialize_service_client_file(clients),
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
# write config file
|
|
372
|
+
self.write_file(
|
|
373
|
+
exec_path / Path(f"{async_path}_configuration.py"),
|
|
374
|
+
general_serializer.serialize_config_file(clients),
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
# sometimes we need define additional Mixin class for client in _vendor.py
|
|
378
|
+
self._serialize_and_write_vendor_file(env, namespace)
|
|
427
379
|
|
|
428
|
-
|
|
380
|
+
def _serialize_and_write_vendor_file(self, env: Environment, namespace: str) -> None:
|
|
381
|
+
exec_path = self.exec_path(namespace)
|
|
382
|
+
# write _vendor.py
|
|
383
|
+
for async_mode, async_path in self.serialize_loop:
|
|
384
|
+
if self.code_model.need_vendored_code(async_mode=async_mode, client_namespace=namespace):
|
|
385
|
+
self.write_file(
|
|
386
|
+
exec_path / Path(f"{async_path}_vendor.py"),
|
|
387
|
+
GeneralSerializer(
|
|
388
|
+
code_model=self.code_model, env=env, async_mode=async_mode, client_namespace=namespace
|
|
389
|
+
).serialize_vendor_file(),
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
def _serialize_and_write_top_level_folder(self, env: Environment, namespace: str) -> None:
|
|
393
|
+
exec_path = self.exec_path(namespace)
|
|
394
|
+
# write _vendor.py
|
|
395
|
+
self._serialize_and_write_vendor_file(env, namespace)
|
|
396
|
+
|
|
397
|
+
general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
|
|
398
|
+
|
|
399
|
+
# write _version.py
|
|
400
|
+
self._serialize_and_write_version_file(namespace, general_serializer)
|
|
429
401
|
|
|
430
402
|
# write the empty py.typed file
|
|
431
|
-
self.write_file(
|
|
403
|
+
self.write_file(exec_path / Path("py.typed"), "# Marker file for PEP 561.")
|
|
432
404
|
|
|
405
|
+
# write _serialization.py
|
|
433
406
|
if not self.code_model.options["client_side_validation"] and not self.code_model.options["multiapi"]:
|
|
434
407
|
self.write_file(
|
|
435
|
-
|
|
408
|
+
exec_path / Path("_serialization.py"),
|
|
436
409
|
general_serializer.serialize_serialization_file(),
|
|
437
410
|
)
|
|
411
|
+
|
|
412
|
+
# write _model_base.py
|
|
438
413
|
if self.code_model.options["models_mode"] == "dpg":
|
|
439
414
|
self.write_file(
|
|
440
|
-
|
|
415
|
+
exec_path / Path("_model_base.py"),
|
|
441
416
|
general_serializer.serialize_model_base_file(),
|
|
442
417
|
)
|
|
443
418
|
|
|
419
|
+
# write _validation.py
|
|
444
420
|
if any(og for client in self.code_model.clients for og in client.operation_groups if og.need_validation):
|
|
445
421
|
self.write_file(
|
|
446
|
-
|
|
422
|
+
exec_path / Path("_validation.py"),
|
|
447
423
|
general_serializer.serialize_validation_file(),
|
|
448
424
|
)
|
|
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
425
|
|
|
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):
|
|
426
|
+
# write _types.py
|
|
427
|
+
if self.code_model.named_unions:
|
|
477
428
|
self.write_file(
|
|
478
|
-
|
|
479
|
-
|
|
429
|
+
exec_path / Path("_types.py"),
|
|
430
|
+
TypesSerializer(code_model=self.code_model, env=env).serialize(),
|
|
480
431
|
)
|
|
481
432
|
|
|
482
|
-
def _serialize_and_write_metadata(self, env: Environment,
|
|
483
|
-
metadata_serializer = MetadataSerializer(self.code_model, env)
|
|
484
|
-
self.write_file(
|
|
433
|
+
def _serialize_and_write_metadata(self, env: Environment, namespace: str) -> None:
|
|
434
|
+
metadata_serializer = MetadataSerializer(self.code_model, env, client_namespace=namespace)
|
|
435
|
+
self.write_file(self.exec_path(namespace) / Path("_metadata.json"), metadata_serializer.serialize())
|
|
485
436
|
|
|
486
437
|
@property
|
|
487
438
|
def _namespace_from_package_name(self) -> str:
|
|
@@ -493,9 +444,17 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
493
444
|
|
|
494
445
|
return self._namespace_from_package_name
|
|
495
446
|
|
|
496
|
-
|
|
497
|
-
def
|
|
498
|
-
|
|
447
|
+
@property
|
|
448
|
+
def exec_path_compensation(self) -> Path:
|
|
449
|
+
"""Assume the process is running in the root folder of the package. If not, we need the path compensation."""
|
|
450
|
+
return (
|
|
451
|
+
Path("../" * (self._name_space().count(".") + 1))
|
|
452
|
+
if self.code_model.options["no_namespace_folders"]
|
|
453
|
+
else Path(".")
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
def exec_path(self, namespace: str) -> Path:
|
|
457
|
+
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
499
458
|
|
|
500
459
|
@property
|
|
501
460
|
def _additional_folder(self) -> Path:
|
|
@@ -506,8 +465,8 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
506
465
|
return Path("/".join(namespace_config.split(".")[num_of_package_namespace:]))
|
|
507
466
|
return Path("")
|
|
508
467
|
|
|
509
|
-
def _serialize_and_write_sample(self, env: Environment,
|
|
510
|
-
out_path = self.
|
|
468
|
+
def _serialize_and_write_sample(self, env: Environment, namespace: str):
|
|
469
|
+
out_path = self.exec_path(namespace) / Path("generated_samples")
|
|
511
470
|
for client in self.code_model.clients:
|
|
512
471
|
for op_group in client.operation_groups:
|
|
513
472
|
for operation in op_group.operations:
|
|
@@ -539,15 +498,15 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
539
498
|
log_error = f"error happens in sample {file}: {e}"
|
|
540
499
|
_LOGGER.error(log_error)
|
|
541
500
|
|
|
542
|
-
def _serialize_and_write_test(self, env: Environment,
|
|
501
|
+
def _serialize_and_write_test(self, env: Environment, namespace: str):
|
|
543
502
|
self.code_model.for_test = True
|
|
544
|
-
out_path = self.
|
|
503
|
+
out_path = self.exec_path(namespace) / Path("generated_tests")
|
|
545
504
|
general_serializer = TestGeneralSerializer(code_model=self.code_model, env=env)
|
|
546
505
|
self.write_file(out_path / "conftest.py", general_serializer.serialize_conftest())
|
|
547
506
|
if not self.code_model.options["azure_arm"]:
|
|
548
|
-
for
|
|
549
|
-
async_suffix = "_async" if
|
|
550
|
-
general_serializer.
|
|
507
|
+
for async_mode in (True, False):
|
|
508
|
+
async_suffix = "_async" if async_mode else ""
|
|
509
|
+
general_serializer.async_mode = async_mode
|
|
551
510
|
self.write_file(
|
|
552
511
|
out_path / f"testpreparer{async_suffix}.py",
|
|
553
512
|
general_serializer.serialize_testpreparer(),
|
|
@@ -560,9 +519,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
560
519
|
):
|
|
561
520
|
continue
|
|
562
521
|
test_serializer = TestSerializer(self.code_model, env, client=client, operation_group=og)
|
|
563
|
-
for
|
|
522
|
+
for async_mode in (True, False):
|
|
564
523
|
try:
|
|
565
|
-
test_serializer.
|
|
524
|
+
test_serializer.async_mode = async_mode
|
|
566
525
|
self.write_file(
|
|
567
526
|
out_path / f"{to_snake_case(test_serializer.test_class_name)}.py",
|
|
568
527
|
test_serializer.serialize_test(),
|
|
@@ -3,6 +3,7 @@
|
|
|
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 Optional
|
|
6
7
|
from jinja2 import Environment
|
|
7
8
|
from ..models import (
|
|
8
9
|
FileImport,
|
|
@@ -13,9 +14,26 @@ from ..models import (
|
|
|
13
14
|
class BaseSerializer:
|
|
14
15
|
"""Base serializer for SDK root level files"""
|
|
15
16
|
|
|
16
|
-
def __init__(
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
code_model: CodeModel,
|
|
20
|
+
env: Environment,
|
|
21
|
+
async_mode: bool = False,
|
|
22
|
+
*,
|
|
23
|
+
client_namespace: Optional[str] = None
|
|
24
|
+
):
|
|
17
25
|
self.code_model = code_model
|
|
18
26
|
self.env = env
|
|
27
|
+
self.async_mode = async_mode
|
|
28
|
+
self.client_namespace = code_model.namespace if client_namespace is None else client_namespace
|
|
19
29
|
|
|
20
30
|
def init_file_import(self) -> FileImport:
|
|
21
31
|
return FileImport(self.code_model)
|
|
32
|
+
|
|
33
|
+
# get namespace of serialize file from client namespace.
|
|
34
|
+
# For async API, serialize namespace will have additional suffix '.aio' compared with client namespace;
|
|
35
|
+
# For models, there will be additional '.models';
|
|
36
|
+
# For operations, there will be additional '.operations' or '._operations';
|
|
37
|
+
@property
|
|
38
|
+
def serialize_namespace(self) -> str:
|
|
39
|
+
return self.code_model.get_serialize_namespace(self.client_namespace, async_mode=self.async_mode)
|