@autorest/python 6.0.0 → 6.1.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/ChangeLog.md +56 -0
- package/README.md +21 -2
- package/autorest/__init__.py +80 -14
- package/autorest/_utils.py +56 -0
- package/autorest/black/__init__.py +27 -14
- package/autorest/codegen/__init__.py +131 -90
- package/autorest/codegen/_utils.py +14 -0
- package/autorest/codegen/models/__init__.py +10 -1
- package/autorest/codegen/models/model_type.py +12 -1
- package/autorest/codegen/serializers/__init__.py +58 -58
- package/autorest/codegen/serializers/builder_serializer.py +1 -3
- package/autorest/codegen/serializers/client_serializer.py +6 -0
- package/autorest/codegen/templates/README.md.jinja2 +3 -3
- package/autorest/codegen/templates/setup.py.jinja2 +1 -2
- package/autorest/jsonrpc/server.py +13 -7
- package/autorest/m2r/__init__.py +18 -6
- package/autorest/m4reformatter/__init__.py +6 -3
- package/autorest/multiapi/__init__.py +57 -31
- package/autorest/multiapi/serializers/__init__.py +26 -24
- package/autorest/multiclient/__init__.py +50 -0
- package/autorest/multiclient/templates/init.py.jinja2 +8 -0
- package/autorest/multiclient/templates/version.py.jinja2 +8 -0
- package/autorest/postprocess/__init__.py +15 -12
- package/autorest/preprocess/__init__.py +24 -5
- package/autorest/preprocess/helpers.py +0 -30
- package/install.py +3 -3
- package/package.json +3 -2
- package/prepare.py +2 -2
- package/requirements.txt +8 -9
- package/run-python3.js +2 -2
- package/run_cadl.py +26 -0
- package/setup.py +2 -3
- package/start.py +2 -2
- package/autorest/multiapi/serializers/multiapi_serializer.py +0 -114
|
@@ -11,53 +11,70 @@ import shutil
|
|
|
11
11
|
from collections import defaultdict
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Dict, List, Optional, cast, Any
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
from .serializers import MultiAPISerializer, MultiAPISerializerAutorest
|
|
15
16
|
from .models import CodeModel
|
|
16
17
|
from .utils import _get_default_api_version_from_list
|
|
17
|
-
from ..jsonrpc import AutorestAPI
|
|
18
18
|
|
|
19
|
-
from .. import Plugin
|
|
19
|
+
from .. import Plugin, PluginAutorest, ReaderAndWriter, ReaderAndWriterAutorest
|
|
20
20
|
|
|
21
21
|
_LOGGER = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class MultiApiScriptPlugin(Plugin):
|
|
24
|
+
class MultiApiScriptPlugin(Plugin): # pylint: disable=abstract-method
|
|
25
25
|
def process(self) -> bool:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
input_package_name,
|
|
32
|
-
output_folder,
|
|
33
|
-
self.
|
|
34
|
-
no_async,
|
|
35
|
-
|
|
26
|
+
return self.generator.process()
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def generator(self) -> "MultiAPI":
|
|
30
|
+
return MultiAPI(
|
|
31
|
+
input_package_name=self.options.get("package-name"),
|
|
32
|
+
output_folder=self.options["output-folder"],
|
|
33
|
+
user_specified_default_api=self.options.get("default-api"),
|
|
34
|
+
no_async=self.options.get("no-async", False),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MultiApiScriptPluginAutorest(MultiApiScriptPlugin, PluginAutorest):
|
|
39
|
+
@property
|
|
40
|
+
def generator(self) -> "MultiAPI":
|
|
41
|
+
return MultiAPIAutorest(
|
|
42
|
+
autorestapi=self._autorestapi,
|
|
43
|
+
input_package_name=self.options.get("package-name"),
|
|
44
|
+
output_folder=self.output_folder,
|
|
45
|
+
user_specified_default_api=self.options.get("default-api"),
|
|
46
|
+
no_async=self.options.get("no-async", False),
|
|
36
47
|
)
|
|
37
|
-
return generator.process()
|
|
38
48
|
|
|
49
|
+
def get_options(self) -> Dict[str, Any]:
|
|
50
|
+
options = {
|
|
51
|
+
"package-name": self._autorestapi.get_value("package-name"),
|
|
52
|
+
"default-api": self._autorestapi.get_value("default-api"),
|
|
53
|
+
"no-async": self._autorestapi.get_value("no-async"),
|
|
54
|
+
}
|
|
55
|
+
return {k: v for k, v in options.items() if v is not None}
|
|
39
56
|
|
|
40
|
-
|
|
57
|
+
|
|
58
|
+
class MultiAPI(ReaderAndWriter): # pylint: disable=abstract-method
|
|
41
59
|
def __init__(
|
|
42
60
|
self,
|
|
43
|
-
|
|
61
|
+
*,
|
|
62
|
+
input_package_name: Optional[str] = None,
|
|
44
63
|
output_folder: str,
|
|
45
|
-
autorestapi: AutorestAPI,
|
|
46
64
|
no_async: Optional[bool] = False,
|
|
47
65
|
user_specified_default_api: Optional[str] = None,
|
|
66
|
+
**kwargs: Any,
|
|
48
67
|
) -> None:
|
|
68
|
+
super().__init__(output_folder=Path(output_folder).resolve(), **kwargs)
|
|
49
69
|
if input_package_name is None:
|
|
50
70
|
raise ValueError(
|
|
51
71
|
"package-name is required, either provide it as args or check your readme configuration"
|
|
52
72
|
)
|
|
53
73
|
self.input_package_name = input_package_name
|
|
54
74
|
_LOGGER.debug("Received package name %s", input_package_name)
|
|
55
|
-
|
|
56
|
-
self.output_folder = Path(output_folder).resolve()
|
|
57
75
|
_LOGGER.debug("Received output-folder %s", output_folder)
|
|
58
76
|
self.output_package_name: str = ""
|
|
59
77
|
self.no_async = no_async
|
|
60
|
-
self._autorestapi = autorestapi
|
|
61
78
|
self.user_specified_default_api = user_specified_default_api
|
|
62
79
|
|
|
63
80
|
@property
|
|
@@ -77,9 +94,7 @@ class MultiAPI:
|
|
|
77
94
|
if self.default_api_version.replace("-", "_") == path_to_version.stem:
|
|
78
95
|
path_to_default_version = path_to_version
|
|
79
96
|
break
|
|
80
|
-
return json.loads(
|
|
81
|
-
self._autorestapi.read_file(path_to_default_version / "_metadata.json")
|
|
82
|
-
)
|
|
97
|
+
return json.loads(self.read_file(path_to_default_version / "_metadata.json"))
|
|
83
98
|
|
|
84
99
|
@property
|
|
85
100
|
def module_name(self) -> str:
|
|
@@ -120,9 +135,7 @@ class MultiAPI:
|
|
|
120
135
|
@property
|
|
121
136
|
def version_path_to_metadata(self) -> Dict[Path, Dict[str, Any]]:
|
|
122
137
|
return {
|
|
123
|
-
version_path: json.loads(
|
|
124
|
-
self._autorestapi.read_file(version_path / "_metadata.json")
|
|
125
|
-
)
|
|
138
|
+
version_path: json.loads(self.read_file(version_path / "_metadata.json"))
|
|
126
139
|
for version_path in self.paths_to_versions
|
|
127
140
|
}
|
|
128
141
|
|
|
@@ -130,9 +143,7 @@ class MultiAPI:
|
|
|
130
143
|
def mod_to_api_version(self) -> Dict[str, str]:
|
|
131
144
|
mod_to_api_version: Dict[str, str] = defaultdict(str)
|
|
132
145
|
for version_path in self.paths_to_versions:
|
|
133
|
-
metadata_json = json.loads(
|
|
134
|
-
self._autorestapi.read_file(version_path / "_metadata.json")
|
|
135
|
-
)
|
|
146
|
+
metadata_json = json.loads(self.read_file(version_path / "_metadata.json"))
|
|
136
147
|
version = metadata_json["chosen_version"]
|
|
137
148
|
total_api_version_list = metadata_json["total_api_version_list"]
|
|
138
149
|
if not version:
|
|
@@ -145,6 +156,10 @@ class MultiAPI:
|
|
|
145
156
|
mod_to_api_version[version_path.name] = version
|
|
146
157
|
return mod_to_api_version
|
|
147
158
|
|
|
159
|
+
@property
|
|
160
|
+
def serializer(self) -> MultiAPISerializer:
|
|
161
|
+
return MultiAPISerializer()
|
|
162
|
+
|
|
148
163
|
def process(self) -> bool:
|
|
149
164
|
_LOGGER.info("Generating multiapi client")
|
|
150
165
|
|
|
@@ -163,8 +178,19 @@ class MultiAPI:
|
|
|
163
178
|
shutil.rmtree(str(self.output_folder / "operations"), ignore_errors=True)
|
|
164
179
|
shutil.rmtree(str(self.output_folder / "models"), ignore_errors=True)
|
|
165
180
|
|
|
166
|
-
multiapi_serializer =
|
|
181
|
+
multiapi_serializer = self.serializer
|
|
167
182
|
multiapi_serializer.serialize(code_model, self.no_async)
|
|
168
183
|
|
|
169
184
|
_LOGGER.info("Done!")
|
|
170
185
|
return True
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class MultiAPIAutorest(MultiAPI, ReaderAndWriterAutorest):
|
|
189
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
190
|
+
super().__init__(**kwargs)
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def serializer(self) -> MultiAPISerializer:
|
|
194
|
+
return MultiAPISerializerAutorest(
|
|
195
|
+
self._autorestapi, output_folder=self.output_folder
|
|
196
|
+
)
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Any, Optional
|
|
7
|
+
from typing import Any, Optional, Union
|
|
8
8
|
from jinja2 import PackageLoader, Environment
|
|
9
9
|
|
|
10
10
|
from .import_serializer import FileImportSerializer
|
|
11
11
|
|
|
12
12
|
from ...jsonrpc import AutorestAPI
|
|
13
13
|
from ..models import CodeModel
|
|
14
|
+
from ... import ReaderAndWriter, ReaderAndWriterAutorest
|
|
14
15
|
|
|
15
16
|
__all__ = [
|
|
16
17
|
"MultiAPISerializer",
|
|
@@ -32,9 +33,9 @@ def _get_file_path(filename: str, async_mode: bool) -> Path:
|
|
|
32
33
|
return Path(filename)
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
class MultiAPISerializer(
|
|
36
|
-
def __init__(self,
|
|
37
|
-
|
|
36
|
+
class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
|
|
37
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
38
|
+
super().__init__(**kwargs)
|
|
38
39
|
self.env = Environment(
|
|
39
40
|
loader=PackageLoader("autorest.multiapi", "templates"),
|
|
40
41
|
keep_trailing_newline=True,
|
|
@@ -52,20 +53,20 @@ class MultiAPISerializer(object):
|
|
|
52
53
|
)
|
|
53
54
|
|
|
54
55
|
# serialize init file
|
|
55
|
-
self.
|
|
56
|
+
self.write_file(
|
|
56
57
|
_get_file_path("__init__", async_mode), _render_template("init")
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
# serialize service client file
|
|
60
61
|
imports = FileImportSerializer(code_model.client.imports(async_mode))
|
|
61
|
-
self.
|
|
62
|
+
self.write_file(
|
|
62
63
|
_get_file_path(code_model.client.filename, async_mode),
|
|
63
64
|
_render_template("client", imports=imports),
|
|
64
65
|
)
|
|
65
66
|
|
|
66
67
|
# serialize config file
|
|
67
68
|
imports = FileImportSerializer(code_model.config.imports(async_mode))
|
|
68
|
-
self.
|
|
69
|
+
self.write_file(
|
|
69
70
|
_get_file_path("_configuration", async_mode),
|
|
70
71
|
_render_template("config", imports=imports),
|
|
71
72
|
)
|
|
@@ -75,26 +76,22 @@ class MultiAPISerializer(object):
|
|
|
75
76
|
imports = FileImportSerializer(
|
|
76
77
|
code_model.operation_mixin_group.imports(async_mode)
|
|
77
78
|
)
|
|
78
|
-
self.
|
|
79
|
+
self.write_file(
|
|
79
80
|
_get_file_path("_operations_mixin", async_mode),
|
|
80
81
|
_render_template("operations_mixin", imports=imports),
|
|
81
82
|
)
|
|
82
83
|
|
|
83
84
|
# serialize models
|
|
84
|
-
self.
|
|
85
|
+
self.write_file(Path("models.py"), _render_template("models"))
|
|
85
86
|
|
|
86
87
|
def _serialize_version_file(self) -> None:
|
|
87
|
-
if self.
|
|
88
|
-
self.
|
|
89
|
-
|
|
90
|
-
)
|
|
91
|
-
elif self._autorestapi.read_file("version.py"):
|
|
92
|
-
self._autorestapi.write_file(
|
|
93
|
-
"_version.py", self._autorestapi.read_file("version.py")
|
|
94
|
-
)
|
|
88
|
+
if self.read_file("_version.py"):
|
|
89
|
+
self.write_file("_version.py", self.read_file("_version.py"))
|
|
90
|
+
elif self.read_file("version.py"):
|
|
91
|
+
self.write_file("_version.py", self.read_file("version.py"))
|
|
95
92
|
else:
|
|
96
93
|
template = self.env.get_template("multiapi_version.py.jinja2")
|
|
97
|
-
self.
|
|
94
|
+
self.write_file(Path("_version.py"), template.render())
|
|
98
95
|
|
|
99
96
|
def serialize(self, code_model: CodeModel, no_async: Optional[bool]) -> None:
|
|
100
97
|
self._serialize_helper(code_model, async_mode=False)
|
|
@@ -104,12 +101,10 @@ class MultiAPISerializer(object):
|
|
|
104
101
|
self._serialize_version_file()
|
|
105
102
|
|
|
106
103
|
# don't erase patch file
|
|
107
|
-
if self.
|
|
108
|
-
self.
|
|
109
|
-
"_patch.py", self._autorestapi.read_file("_patch.py")
|
|
110
|
-
)
|
|
104
|
+
if self.read_file("_patch.py"):
|
|
105
|
+
self.write_file("_patch.py", self.read_file("_patch.py"))
|
|
111
106
|
|
|
112
|
-
self.
|
|
107
|
+
self.write_file(Path("py.typed"), "# Marker file for PEP 561.")
|
|
113
108
|
|
|
114
109
|
if not code_model.client.client_side_validation:
|
|
115
110
|
codegen_env = Environment(
|
|
@@ -120,7 +115,14 @@ class MultiAPISerializer(object):
|
|
|
120
115
|
trim_blocks=True,
|
|
121
116
|
lstrip_blocks=True,
|
|
122
117
|
)
|
|
123
|
-
self.
|
|
118
|
+
self.write_file(
|
|
124
119
|
Path("_serialization.py"),
|
|
125
120
|
codegen_env.get_template("serialization.py.jinja2").render(),
|
|
126
121
|
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class MultiAPISerializerAutorest(MultiAPISerializer, ReaderAndWriterAutorest):
|
|
125
|
+
def __init__(
|
|
126
|
+
self, autorestapi: AutorestAPI, *, output_folder: Union[str, Path]
|
|
127
|
+
) -> None:
|
|
128
|
+
super().__init__(autorestapi=autorestapi, output_folder=output_folder)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Any, Dict
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from jinja2 import Environment, PackageLoader
|
|
10
|
+
from .. import Plugin, PluginAutorest
|
|
11
|
+
|
|
12
|
+
_LOGGER = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MultiClientPlugin(Plugin): # pylint: disable=abstract-method
|
|
16
|
+
def process(self) -> bool:
|
|
17
|
+
_LOGGER.info("Generating files for multi client")
|
|
18
|
+
|
|
19
|
+
env = Environment(
|
|
20
|
+
loader=PackageLoader("autorest.multiclient", "templates"),
|
|
21
|
+
keep_trailing_newline=True,
|
|
22
|
+
line_statement_prefix="##",
|
|
23
|
+
line_comment_prefix="###",
|
|
24
|
+
trim_blocks=True,
|
|
25
|
+
lstrip_blocks=True,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# __init__.py
|
|
29
|
+
template = env.get_template("init.py.jinja2")
|
|
30
|
+
self.write_file(Path("__init__.py"), template.render())
|
|
31
|
+
|
|
32
|
+
# _version.py
|
|
33
|
+
template = env.get_template("version.py.jinja2")
|
|
34
|
+
self.write_file(
|
|
35
|
+
Path("_version.py"),
|
|
36
|
+
template.render(
|
|
37
|
+
package_version=self.options.get("package-version") or "1.0.0b1"
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# py.typed
|
|
42
|
+
self.write_file(Path("py.typed"), "# Marker file for PEP 561.")
|
|
43
|
+
|
|
44
|
+
_LOGGER.info("Generating Done for multi client!")
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class MultiClientPluginAutorest(MultiClientPlugin, PluginAutorest):
|
|
49
|
+
def get_options(self) -> Dict[str, Any]:
|
|
50
|
+
return {"package-version": self._autorestapi.get_value("package-version")}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
|
+
# Code generated by Microsoft (R) AutoRest Code Generator.
|
|
5
|
+
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
6
|
+
# --------------------------------------------------------------------------
|
|
7
|
+
from ._version import VERSION
|
|
8
|
+
__version__ = VERSION
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# --------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
5
|
+
# license information.
|
|
6
|
+
# --------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
VERSION = "{{ package_version }}"
|
|
@@ -3,7 +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 Tuple
|
|
6
|
+
from typing import Tuple, Any, Dict
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
import os
|
|
9
9
|
import shutil
|
|
@@ -11,7 +11,7 @@ from venv import EnvBuilder
|
|
|
11
11
|
import black
|
|
12
12
|
from .venvtools import ExtendedEnvBuilder, python_run
|
|
13
13
|
|
|
14
|
-
from .. import Plugin
|
|
14
|
+
from .. import Plugin, PluginAutorest
|
|
15
15
|
|
|
16
16
|
_BLACK_MODE = black.Mode()
|
|
17
17
|
_BLACK_MODE.line_length = 120
|
|
@@ -29,10 +29,10 @@ def format_file(file: Path, file_content: str) -> str:
|
|
|
29
29
|
return file_content
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class PostProcessPlugin(Plugin):
|
|
33
|
-
def __init__(self,
|
|
34
|
-
super().__init__(
|
|
35
|
-
output_folder_uri = self.
|
|
32
|
+
class PostProcessPlugin(Plugin): # pylint: disable=abstract-method
|
|
33
|
+
def __init__(self, **kwargs: Any):
|
|
34
|
+
super().__init__(**kwargs)
|
|
35
|
+
output_folder_uri = self.options["outputFolderUri"]
|
|
36
36
|
if output_folder_uri.startswith("file:"):
|
|
37
37
|
output_folder_uri = output_folder_uri[5:]
|
|
38
38
|
if os.name == "nt" and output_folder_uri.startswith("///"):
|
|
@@ -65,10 +65,8 @@ class PostProcessPlugin(Plugin):
|
|
|
65
65
|
try:
|
|
66
66
|
init_file = next(d for d in dir.iterdir() if d.name == "__init__.py")
|
|
67
67
|
# we don't care about pkgutil inits, we skip over them
|
|
68
|
-
file_content = self.
|
|
69
|
-
|
|
70
|
-
)
|
|
71
|
-
if not "pkgutil" in file_content:
|
|
68
|
+
file_content = self.read_file(init_file.relative_to(self.output_folder))
|
|
69
|
+
if "pkgutil" not in file_content:
|
|
72
70
|
return dir, namespace
|
|
73
71
|
except StopIteration:
|
|
74
72
|
pass
|
|
@@ -157,7 +155,7 @@ class PostProcessPlugin(Plugin):
|
|
|
157
155
|
k: None for k in customized_objects_str.split(",")
|
|
158
156
|
}.keys() # filter out duplicates
|
|
159
157
|
file = (folder_path / "__init__.py").relative_to(self.output_folder)
|
|
160
|
-
file_content = self.
|
|
158
|
+
file_content = self.read_file(file)
|
|
161
159
|
added_objs = []
|
|
162
160
|
for obj in customized_objects:
|
|
163
161
|
if f" import {obj}\n" in file_content:
|
|
@@ -199,4 +197,9 @@ class PostProcessPlugin(Plugin):
|
|
|
199
197
|
"__all__ = [", f"__all__ = [\n{added_objs_all}", 1
|
|
200
198
|
)
|
|
201
199
|
formatted_file = format_file(file, file_content)
|
|
202
|
-
self.
|
|
200
|
+
self.write_file(file, formatted_file)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class PostProcessPluginAutorest(PostProcessPlugin, PluginAutorest):
|
|
204
|
+
def get_options(self) -> Dict[str, Any]:
|
|
205
|
+
return {"outputFolderUri": self._autorestapi.get_value("outputFolderUri")}
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
"""The preprocessing autorest plugin.
|
|
7
7
|
"""
|
|
8
8
|
from typing import Callable, Dict, Any, List, Optional
|
|
9
|
-
from
|
|
9
|
+
from .._utils import to_snake_case
|
|
10
|
+
from .helpers import pad_reserved_words, add_redefined_builtin_info
|
|
10
11
|
from .python_mappings import PadType
|
|
11
12
|
|
|
12
|
-
from .. import YamlUpdatePlugin
|
|
13
|
+
from .. import YamlUpdatePlugin, YamlUpdatePluginAutorest
|
|
14
|
+
from .._utils import parse_args
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def _remove_paging_maxpagesize(yaml_data: Dict[str, Any]) -> None:
|
|
@@ -92,12 +94,12 @@ def update_paging_response(yaml_data: Dict[str, Any]) -> None:
|
|
|
92
94
|
)
|
|
93
95
|
|
|
94
96
|
|
|
95
|
-
class PreProcessPlugin(YamlUpdatePlugin):
|
|
97
|
+
class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
|
|
96
98
|
"""Add Python naming information."""
|
|
97
99
|
|
|
98
100
|
@property
|
|
99
101
|
def version_tolerant(self) -> bool:
|
|
100
|
-
return
|
|
102
|
+
return self.options.get("version-tolerant", True)
|
|
101
103
|
|
|
102
104
|
def get_operation_updater(
|
|
103
105
|
self, yaml_data: Dict[str, Any]
|
|
@@ -133,7 +135,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
133
135
|
response["discriminator"] = "operation"
|
|
134
136
|
|
|
135
137
|
def _update_lro_operation_helper(self, yaml_data: Dict[str, Any]) -> None:
|
|
136
|
-
azure_arm = self.
|
|
138
|
+
azure_arm = self.options.get("azure-arm", False)
|
|
137
139
|
for response in yaml_data.get("responses", []):
|
|
138
140
|
response["discriminator"] = "lro"
|
|
139
141
|
response["pollerSync"] = (
|
|
@@ -228,3 +230,20 @@ class PreProcessPlugin(YamlUpdatePlugin):
|
|
|
228
230
|
update_client(yaml_data["client"])
|
|
229
231
|
update_types(yaml_data["types"])
|
|
230
232
|
self.update_operation_groups(yaml_data)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class PreProcessPluginAutorest(YamlUpdatePluginAutorest, PreProcessPlugin):
|
|
236
|
+
def get_options(self) -> Dict[str, Any]:
|
|
237
|
+
options = {
|
|
238
|
+
"version-tolerant": self._autorestapi.get_boolean_value("version-tolerant"),
|
|
239
|
+
"azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
|
|
240
|
+
}
|
|
241
|
+
return {k: v for k, v in options.items() if v is not None}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
# CADL pipeline will call this
|
|
246
|
+
args = parse_args()
|
|
247
|
+
PreProcessPlugin(
|
|
248
|
+
output_folder=args.output_folder, cadl_file=args.cadl_file
|
|
249
|
+
).process()
|
|
@@ -4,39 +4,9 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
from typing import Any, Dict
|
|
7
|
-
import re
|
|
8
7
|
from .python_mappings import PadType, RESERVED_WORDS, REDEFINED_BUILTINS
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
def to_snake_case(name: str) -> str:
|
|
12
|
-
def replace_upper_characters(m) -> str:
|
|
13
|
-
match_str = m.group().lower()
|
|
14
|
-
if m.start() > 0 and name[m.start() - 1] == "_":
|
|
15
|
-
# we are good if a '_' already exists
|
|
16
|
-
return match_str
|
|
17
|
-
# the first letter should not have _
|
|
18
|
-
prefix = "_" if m.start() > 0 else ""
|
|
19
|
-
|
|
20
|
-
# we will add an extra _ if there are multiple upper case chars together
|
|
21
|
-
next_non_upper_case_char_location = m.start() + len(match_str)
|
|
22
|
-
if (
|
|
23
|
-
len(match_str) > 2
|
|
24
|
-
and len(name) - next_non_upper_case_char_location > 1
|
|
25
|
-
and name[next_non_upper_case_char_location].isalpha()
|
|
26
|
-
):
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
prefix
|
|
30
|
-
+ match_str[: len(match_str) - 1]
|
|
31
|
-
+ "_"
|
|
32
|
-
+ match_str[len(match_str) - 1]
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
return prefix + match_str
|
|
36
|
-
|
|
37
|
-
return re.sub("[A-Z]+", replace_upper_characters, name)
|
|
38
|
-
|
|
39
|
-
|
|
40
10
|
def pad_reserved_words(name: str, pad_type: PadType):
|
|
41
11
|
# we want to pad hidden variables as well
|
|
42
12
|
if not name:
|
package/install.py
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
# license information.
|
|
7
7
|
# --------------------------------------------------------------------------
|
|
8
8
|
import sys
|
|
9
|
-
if not sys.version_info >= (3,
|
|
10
|
-
raise Exception("Autorest for Python extension requires Python 3.
|
|
9
|
+
if not sys.version_info >= (3, 7, 0):
|
|
10
|
+
raise Exception("Autorest for Python extension requires Python 3.7 at least")
|
|
11
11
|
|
|
12
12
|
try:
|
|
13
13
|
import pip
|
|
@@ -20,7 +20,7 @@ except ImportError:
|
|
|
20
20
|
raise Exception("Your Python installation doesn't have venv available")
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
# Now we have pip and Py >= 3.
|
|
23
|
+
# Now we have pip and Py >= 3.7, go to work
|
|
24
24
|
|
|
25
25
|
import subprocess
|
|
26
26
|
from pathlib import Path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autorest/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "The Python extension for generators in AutoRest.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepare": "node run-python3.js prepare.py",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"start.py",
|
|
39
39
|
"venvtools.py",
|
|
40
40
|
"run-python3.js",
|
|
41
|
-
"requirements.txt"
|
|
41
|
+
"requirements.txt",
|
|
42
|
+
"run_cadl.py"
|
|
42
43
|
]
|
|
43
44
|
}
|
package/prepare.py
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
# license information.
|
|
7
7
|
# --------------------------------------------------------------------------
|
|
8
8
|
import sys
|
|
9
|
-
if not sys.version_info >= (3,
|
|
10
|
-
raise Exception("Autorest for Python extension requires Python 3.
|
|
9
|
+
if not sys.version_info >= (3, 7, 0):
|
|
10
|
+
raise Exception("Autorest for Python extension requires Python 3.7 at least")
|
|
11
11
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
import venv
|
package/requirements.txt
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
black==
|
|
2
|
-
click==8.
|
|
3
|
-
docutils==0.18
|
|
4
|
-
Jinja2==3.
|
|
1
|
+
black==22.6.0
|
|
2
|
+
click==8.1.3
|
|
3
|
+
docutils==0.18
|
|
4
|
+
Jinja2==3.1.2
|
|
5
5
|
json-rpc==1.13.0
|
|
6
|
-
|
|
7
|
-
MarkupSafe==2.
|
|
6
|
+
m2r2==0.3.2
|
|
7
|
+
MarkupSafe==2.1.1
|
|
8
8
|
mistune==0.8.4
|
|
9
9
|
mypy-extensions==0.4.3
|
|
10
10
|
pathspec==0.9.0
|
|
11
|
-
platformdirs==2.
|
|
11
|
+
platformdirs==2.5.2
|
|
12
12
|
PyYAML==6.0
|
|
13
|
-
tomli==
|
|
14
|
-
typing-extensions==4.0.1
|
|
13
|
+
tomli==2.0.1
|
package/run-python3.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
const cp = require("child_process");
|
|
10
10
|
const extension = require("@autorest/system-requirements");
|
|
11
11
|
|
|
12
|
-
async function runPython3(scriptName,
|
|
13
|
-
const command = await extension.patchPythonPath(["python", scriptName,
|
|
12
|
+
async function runPython3(scriptName, ...args) {
|
|
13
|
+
const command = await extension.patchPythonPath(["python", scriptName, ...args], { version: ">=3.7", environmentVariable: "AUTOREST_PYTHON_EXE" });
|
|
14
14
|
cp.execSync(command.join(" "), {
|
|
15
15
|
stdio: [0, 1, 2]
|
|
16
16
|
});
|
package/run_cadl.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import sys
|
|
7
|
+
import venv
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from venvtools import python_run
|
|
10
|
+
|
|
11
|
+
_ROOT_DIR = Path(__file__).parent
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
venv_path = _ROOT_DIR / "venv"
|
|
15
|
+
venv_prexists = venv_path.exists()
|
|
16
|
+
|
|
17
|
+
assert venv_prexists # Otherwise install was not done
|
|
18
|
+
|
|
19
|
+
env_builder = venv.EnvBuilder(with_pip=True)
|
|
20
|
+
venv_context = env_builder.ensure_directories(venv_path)
|
|
21
|
+
|
|
22
|
+
# run m2r
|
|
23
|
+
python_run(venv_context, "autorest.m2r.__init__", command=sys.argv[1:])
|
|
24
|
+
python_run(venv_context, "autorest.preprocess.__init__", command=sys.argv[1:])
|
|
25
|
+
python_run(venv_context, "autorest.codegen.__init__", command=sys.argv[1:])
|
|
26
|
+
python_run(venv_context, "autorest.black.__init__", command=sys.argv[1:])
|
package/setup.py
CHANGED
|
@@ -36,7 +36,6 @@ setup(
|
|
|
36
36
|
'Development Status :: 4 - Beta',
|
|
37
37
|
'Programming Language :: Python',
|
|
38
38
|
'Programming Language :: Python :: 3',
|
|
39
|
-
'Programming Language :: Python :: 3.6',
|
|
40
39
|
'Programming Language :: Python :: 3.7',
|
|
41
40
|
'Programming Language :: Python :: 3.8',
|
|
42
41
|
'License :: OSI Approved :: MIT License',
|
|
@@ -48,8 +47,8 @@ setup(
|
|
|
48
47
|
"json-rpc",
|
|
49
48
|
"Jinja2 >= 2.11", # I need "include" and auto-context + blank line are not indented by default
|
|
50
49
|
"pyyaml",
|
|
51
|
-
"
|
|
52
|
-
"m2r",
|
|
50
|
+
"m2r2",
|
|
53
51
|
"black",
|
|
52
|
+
"docutils<0.19", # m2r2 fails with docutils 0.19
|
|
54
53
|
],
|
|
55
54
|
)
|
package/start.py
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
# license information.
|
|
7
7
|
# --------------------------------------------------------------------------
|
|
8
8
|
import sys
|
|
9
|
-
if not sys.version_info >= (3,
|
|
10
|
-
raise Exception("Autorest for Python extension requires Python 3.
|
|
9
|
+
if not sys.version_info >= (3, 7, 0):
|
|
10
|
+
raise Exception("Autorest for Python extension requires Python 3.7 at least")
|
|
11
11
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
import venv
|