@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
package/ChangeLog.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### 2022-07-20 - 6.1.1
|
|
4
|
+
|
|
5
|
+
| Library | Min Version |
|
|
6
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
7
|
+
| `@autorest/core` | `3.8.1` |
|
|
8
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
9
|
+
| `azure-core` dep of generated code | `1.24.0` |
|
|
10
|
+
| `isodate` dep of generated code | `0.6.1` |
|
|
11
|
+
| `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
|
|
12
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
13
|
+
|
|
14
|
+
**Other Changes**
|
|
15
|
+
|
|
16
|
+
- Get skeleton for cadl generation released #1358
|
|
17
|
+
|
|
18
|
+
### 2022-07-20 - 6.1.0
|
|
19
|
+
|
|
20
|
+
| Library | Min Version |
|
|
21
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
22
|
+
| `@autorest/core` | `3.8.1` |
|
|
23
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
24
|
+
| `azure-core` dep of generated code | `1.24.0` |
|
|
25
|
+
| `isodate` dep of generated code | `0.6.1` |
|
|
26
|
+
| `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
|
|
27
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
28
|
+
|
|
29
|
+
**New Features**
|
|
30
|
+
|
|
31
|
+
- Add new plugin `MultiClient` and new flag `--multiclientscript` to handle package structure of multi client #1328
|
|
32
|
+
|
|
33
|
+
**Bug Fixes**
|
|
34
|
+
|
|
35
|
+
- Fallback unrecognized type as string to avoid a fatal error. #1341
|
|
36
|
+
- Fix regression in default namespace for SDKs generated without `--namespace` flag #1354
|
|
37
|
+
|
|
38
|
+
**Other Changes**
|
|
39
|
+
|
|
40
|
+
- Generated code no longer supports Python 3.6 #1353
|
|
41
|
+
- Order json input and response template entries by whether they are required or not #1335
|
|
42
|
+
- Reduce extreme amount of `black` logs when running in `--debug` mode to just log errors
|
|
43
|
+
|
|
44
|
+
### 2022-06-29 - 6.0.1
|
|
45
|
+
|
|
46
|
+
| Library | Min Version |
|
|
47
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
48
|
+
| `@autorest/core` | `3.8.1` |
|
|
49
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
50
|
+
| `azure-core` dep of generated code | `1.24.0` |
|
|
51
|
+
| `isodate` dep of generated code | `0.6.1` |
|
|
52
|
+
| `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
|
|
53
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
54
|
+
|
|
55
|
+
**Bug Fixes**
|
|
56
|
+
|
|
57
|
+
- Ignore linting error for clients with no credentials #1333
|
|
58
|
+
|
|
3
59
|
### 2022-06-24 - 6.0.0
|
|
4
60
|
|
|
5
61
|
| Library | Min Version |
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
|
|
|
23
23
|
|
|
24
24
|
#### Python code gen
|
|
25
25
|
|
|
26
|
-
```yaml !$(multiapiscript)
|
|
26
|
+
```yaml !$(multiapiscript) && !$(multiclientscript)
|
|
27
27
|
# default values for version tolerant and black
|
|
28
28
|
black: true
|
|
29
29
|
```
|
|
@@ -43,7 +43,7 @@ modelerfour:
|
|
|
43
43
|
allow-no-input: true
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
```yaml !$(multiapiscript)
|
|
46
|
+
```yaml !$(multiapiscript) && !$(multiclientscript)
|
|
47
47
|
pass-thru:
|
|
48
48
|
- model-deduplicator
|
|
49
49
|
- subset-reducer
|
|
@@ -161,6 +161,25 @@ scope-postprocess/emitter:
|
|
|
161
161
|
output-artifact: python-files
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
+
# Multi Client pipeline
|
|
165
|
+
|
|
166
|
+
```yaml $(multiclientscript)
|
|
167
|
+
pipeline:
|
|
168
|
+
python/multiclientscript:
|
|
169
|
+
scope: multiclientscript
|
|
170
|
+
output-artifact: python-files
|
|
171
|
+
|
|
172
|
+
python/multiclientscript/emitter:
|
|
173
|
+
input: multiclientscript
|
|
174
|
+
scope: scope-multiclientscript/emitter
|
|
175
|
+
|
|
176
|
+
scope-multiclientscript/emitter:
|
|
177
|
+
input-artifact: python-files
|
|
178
|
+
output-uri-expr: $key
|
|
179
|
+
|
|
180
|
+
output-artifact: python-files
|
|
181
|
+
```
|
|
182
|
+
|
|
164
183
|
# Help
|
|
165
184
|
|
|
166
185
|
```yaml
|
package/autorest/__init__.py
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
+
from pathlib import Path
|
|
7
8
|
from abc import ABC, abstractmethod
|
|
8
|
-
from typing import Any, Dict
|
|
9
|
+
from typing import Any, Dict, Union
|
|
9
10
|
|
|
10
11
|
import yaml
|
|
11
12
|
|
|
@@ -17,15 +18,49 @@ __version__ = VERSION
|
|
|
17
18
|
_LOGGER = logging.getLogger(__name__)
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class
|
|
21
|
+
class ReaderAndWriter:
|
|
22
|
+
def __init__(self, *, output_folder: Union[str, Path], **kwargs: Any) -> None:
|
|
23
|
+
self.output_folder = Path(output_folder)
|
|
24
|
+
self.options = kwargs
|
|
25
|
+
|
|
26
|
+
def read_file(self, path: Union[str, Path]) -> str:
|
|
27
|
+
"""How does one read a file in cadl?"""
|
|
28
|
+
# make path relative to output folder
|
|
29
|
+
try:
|
|
30
|
+
with open(self.output_folder / Path(path), "r") as fd:
|
|
31
|
+
return fd.read()
|
|
32
|
+
except FileNotFoundError:
|
|
33
|
+
return ""
|
|
34
|
+
|
|
35
|
+
def write_file(self, filename: Union[str, Path], file_content: str) -> None:
|
|
36
|
+
"""How does writing work in cadl?"""
|
|
37
|
+
file_folder = Path(filename).parent
|
|
38
|
+
if not Path.is_dir(self.output_folder / file_folder):
|
|
39
|
+
Path.mkdir(self.output_folder / file_folder, parents=True)
|
|
40
|
+
with open(self.output_folder / Path(filename), "w") as fd:
|
|
41
|
+
fd.write(file_content)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ReaderAndWriterAutorest(ReaderAndWriter):
|
|
45
|
+
def __init__(
|
|
46
|
+
self, *, output_folder: Union[str, Path], autorestapi: AutorestAPI
|
|
47
|
+
) -> None:
|
|
48
|
+
super().__init__(output_folder=output_folder)
|
|
49
|
+
self._autorestapi = autorestapi
|
|
50
|
+
|
|
51
|
+
def read_file(self, path: Union[str, Path]) -> str:
|
|
52
|
+
return self._autorestapi.read_file(path)
|
|
53
|
+
|
|
54
|
+
def write_file(self, filename: Union[str, Path], file_content: str) -> None:
|
|
55
|
+
return self._autorestapi.write_file(filename, file_content)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Plugin(ReaderAndWriter, ABC):
|
|
21
59
|
"""A base class for autorest plugin.
|
|
22
60
|
|
|
23
61
|
:param autorestapi: An autorest API instance
|
|
24
62
|
"""
|
|
25
63
|
|
|
26
|
-
def __init__(self, autorestapi: AutorestAPI) -> None:
|
|
27
|
-
self._autorestapi = autorestapi
|
|
28
|
-
|
|
29
64
|
@abstractmethod
|
|
30
65
|
def process(self) -> bool:
|
|
31
66
|
"""The plugin process.
|
|
@@ -37,24 +72,41 @@ class Plugin(ABC):
|
|
|
37
72
|
raise NotImplementedError()
|
|
38
73
|
|
|
39
74
|
|
|
75
|
+
class PluginAutorest(Plugin, ReaderAndWriterAutorest):
|
|
76
|
+
"""For our Autorest plugins, we want to take autorest api as input as options, then pass it to the Plugin"""
|
|
77
|
+
|
|
78
|
+
def __init__(
|
|
79
|
+
self, autorestapi: AutorestAPI, *, output_folder: Union[str, Path]
|
|
80
|
+
) -> None:
|
|
81
|
+
super().__init__(autorestapi=autorestapi, output_folder=output_folder)
|
|
82
|
+
self.options = self.get_options()
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def get_options(self) -> Dict[str, Any]:
|
|
86
|
+
"""Get the options bag using the AutorestAPI that we send to the parent plugin"""
|
|
87
|
+
|
|
88
|
+
|
|
40
89
|
class YamlUpdatePlugin(Plugin):
|
|
41
90
|
"""A plugin that update the YAML as input."""
|
|
42
91
|
|
|
92
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
93
|
+
# cadl file doesn't have to be relative to output folder
|
|
94
|
+
with open(self.options["cadl_file"], "r") as fd:
|
|
95
|
+
return yaml.safe_load(fd.read())
|
|
96
|
+
|
|
97
|
+
def write_yaml(self, yaml_string: str) -> None:
|
|
98
|
+
with open(self.options["cadl_file"], "w") as fd:
|
|
99
|
+
fd.write(yaml_string)
|
|
100
|
+
|
|
43
101
|
def process(self) -> bool:
|
|
44
102
|
# List the input file, should be only one
|
|
45
|
-
|
|
46
|
-
_LOGGER.debug("Possible Inputs: %s", inputs)
|
|
47
|
-
if "code-model-v4-no-tags.yaml" not in inputs:
|
|
48
|
-
raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
|
|
49
|
-
|
|
50
|
-
file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
|
|
51
|
-
yaml_data = yaml.safe_load(file_content)
|
|
103
|
+
yaml_data = self.get_yaml()
|
|
52
104
|
|
|
53
105
|
self.update_yaml(yaml_data)
|
|
54
106
|
|
|
55
107
|
yaml_string = yaml.safe_dump(yaml_data)
|
|
56
108
|
|
|
57
|
-
self.
|
|
109
|
+
self.write_yaml(yaml_string)
|
|
58
110
|
return True
|
|
59
111
|
|
|
60
112
|
@abstractmethod
|
|
@@ -67,4 +119,18 @@ class YamlUpdatePlugin(Plugin):
|
|
|
67
119
|
raise NotImplementedError()
|
|
68
120
|
|
|
69
121
|
|
|
70
|
-
|
|
122
|
+
class YamlUpdatePluginAutorest( # pylint: disable=abstract-method
|
|
123
|
+
YamlUpdatePlugin, PluginAutorest
|
|
124
|
+
):
|
|
125
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
126
|
+
return yaml.safe_load(self.read_file("code-model-v4-no-tags.yaml"))
|
|
127
|
+
|
|
128
|
+
def write_yaml(self, yaml_string: str) -> None:
|
|
129
|
+
self.write_file("code-model-v4-no-tags.yaml", yaml_string)
|
|
130
|
+
|
|
131
|
+
def get_options(self) -> Dict[str, Any]:
|
|
132
|
+
inputs = self._autorestapi.list_inputs()
|
|
133
|
+
_LOGGER.debug("Possible Inputs: %s", inputs)
|
|
134
|
+
if "code-model-v4-no-tags.yaml" not in inputs:
|
|
135
|
+
raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
|
|
136
|
+
return {}
|
|
@@ -0,0 +1,56 @@
|
|
|
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 re
|
|
7
|
+
import argparse
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def to_snake_case(name: str) -> str:
|
|
11
|
+
def replace_upper_characters(m) -> str:
|
|
12
|
+
match_str = m.group().lower()
|
|
13
|
+
if m.start() > 0 and name[m.start() - 1] == "_":
|
|
14
|
+
# we are good if a '_' already exists
|
|
15
|
+
return match_str
|
|
16
|
+
# the first letter should not have _
|
|
17
|
+
prefix = "_" if m.start() > 0 else ""
|
|
18
|
+
|
|
19
|
+
# we will add an extra _ if there are multiple upper case chars together
|
|
20
|
+
next_non_upper_case_char_location = m.start() + len(match_str)
|
|
21
|
+
if (
|
|
22
|
+
len(match_str) > 2
|
|
23
|
+
and len(name) - next_non_upper_case_char_location > 1
|
|
24
|
+
and name[next_non_upper_case_char_location].isalpha()
|
|
25
|
+
):
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
prefix
|
|
29
|
+
+ match_str[: len(match_str) - 1]
|
|
30
|
+
+ "_"
|
|
31
|
+
+ match_str[len(match_str) - 1]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return prefix + match_str
|
|
35
|
+
|
|
36
|
+
return re.sub("[A-Z]+", replace_upper_characters, name)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def parse_args(need_cadl_file: bool = True):
|
|
40
|
+
parser = argparse.ArgumentParser(
|
|
41
|
+
description="Run mypy against target folder. Add a local custom plugin to the path prior to execution. "
|
|
42
|
+
)
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--output-folder",
|
|
45
|
+
dest="output_folder",
|
|
46
|
+
help="Output folder for generated SDK",
|
|
47
|
+
required=True,
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--cadl-file",
|
|
51
|
+
dest="cadl_file",
|
|
52
|
+
help="Serialized cadl file",
|
|
53
|
+
required=need_cadl_file,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return parser.parse_args()
|
|
@@ -6,25 +6,27 @@
|
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
import os
|
|
9
|
+
from typing import Any, Dict
|
|
9
10
|
import black
|
|
10
11
|
|
|
11
|
-
from .. import Plugin
|
|
12
|
+
from .. import Plugin, PluginAutorest
|
|
13
|
+
from .._utils import parse_args
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
logging.getLogger("blib2to3").setLevel(logging.ERROR)
|
|
14
16
|
|
|
15
17
|
_BLACK_MODE = black.Mode()
|
|
16
18
|
_BLACK_MODE.line_length = 120
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
class BlackScriptPlugin(Plugin):
|
|
20
|
-
def __init__(self,
|
|
21
|
-
super().__init__(
|
|
22
|
-
|
|
23
|
-
if
|
|
24
|
-
|
|
25
|
-
if os.name == "nt" and
|
|
26
|
-
|
|
27
|
-
self.output_folder = Path(
|
|
21
|
+
class BlackScriptPlugin(Plugin): # pylint: disable=abstract-method
|
|
22
|
+
def __init__(self, **kwargs):
|
|
23
|
+
super().__init__(**kwargs)
|
|
24
|
+
output_folder = self.options.get("output_folder", str(self.output_folder))
|
|
25
|
+
if output_folder.startswith("file:"):
|
|
26
|
+
output_folder = output_folder[5:]
|
|
27
|
+
if os.name == "nt" and output_folder.startswith("///"):
|
|
28
|
+
output_folder = output_folder[3:]
|
|
29
|
+
self.output_folder = Path(output_folder)
|
|
28
30
|
|
|
29
31
|
def process(self) -> bool:
|
|
30
32
|
# apply format_file on every file in the output folder
|
|
@@ -38,9 +40,9 @@ class BlackScriptPlugin(Plugin):
|
|
|
38
40
|
|
|
39
41
|
def format_file(self, full_path) -> None:
|
|
40
42
|
file = full_path.relative_to(self.output_folder)
|
|
41
|
-
file_content = self.
|
|
43
|
+
file_content = self.read_file(file)
|
|
42
44
|
if not file.suffix == ".py":
|
|
43
|
-
self.
|
|
45
|
+
self.write_file(file, file_content)
|
|
44
46
|
return
|
|
45
47
|
try:
|
|
46
48
|
file_content = black.format_file_contents(
|
|
@@ -48,4 +50,15 @@ class BlackScriptPlugin(Plugin):
|
|
|
48
50
|
)
|
|
49
51
|
except black.NothingChanged:
|
|
50
52
|
pass
|
|
51
|
-
self.
|
|
53
|
+
self.write_file(file, file_content)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BlackScriptPluginAutorest(BlackScriptPlugin, PluginAutorest):
|
|
57
|
+
def get_options(self) -> Dict[str, Any]:
|
|
58
|
+
return {"output_folder": self._autorestapi.get_value("outputFolderUri")}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
# CADL pipeline will call this
|
|
63
|
+
args = parse_args(need_cadl_file=False)
|
|
64
|
+
BlackScriptPlugin(output_folder=args.output_folder).process()
|
|
@@ -4,19 +4,20 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
-
import sys
|
|
8
7
|
from typing import Dict, Any, Union, cast
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
import yaml
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
from .. import Plugin
|
|
12
|
+
from .. import Plugin, PluginAutorest
|
|
13
|
+
from .._utils import parse_args
|
|
14
14
|
from .models.client import Client, Config
|
|
15
15
|
from .models.code_model import CodeModel
|
|
16
16
|
from .models import build_type
|
|
17
17
|
from .models.request_builder import get_request_builder
|
|
18
18
|
from .models.operation_group import OperationGroup
|
|
19
|
-
from .serializers import JinjaSerializer
|
|
19
|
+
from .serializers import JinjaSerializer, JinjaSerializerAutorest
|
|
20
|
+
from ._utils import DEFAULT_HEADER_TEXT
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
|
|
@@ -162,8 +163,8 @@ class CodeGenerator(Plugin):
|
|
|
162
163
|
|
|
163
164
|
def _build_code_model_options(self) -> Dict[str, Any]:
|
|
164
165
|
"""Build en options dict from the user input while running autorest."""
|
|
165
|
-
azure_arm = self.
|
|
166
|
-
license_header = self.
|
|
166
|
+
azure_arm = self.options.get("azure-arm", False)
|
|
167
|
+
license_header = self.options.get("header-text", DEFAULT_HEADER_TEXT)
|
|
167
168
|
if license_header:
|
|
168
169
|
license_header = license_header.replace("\n", "\n# ")
|
|
169
170
|
license_header = (
|
|
@@ -172,83 +173,46 @@ class CodeGenerator(Plugin):
|
|
|
172
173
|
)
|
|
173
174
|
license_header += "\n# --------------------------------------------------------------------------"
|
|
174
175
|
|
|
175
|
-
low_level_client = cast(
|
|
176
|
-
|
|
177
|
-
)
|
|
178
|
-
version_tolerant = cast(
|
|
179
|
-
bool, self._autorestapi.get_boolean_value("version-tolerant")
|
|
180
|
-
)
|
|
181
|
-
show_operations = self._autorestapi.get_boolean_value(
|
|
182
|
-
"show-operations", not low_level_client
|
|
183
|
-
)
|
|
176
|
+
low_level_client = cast(bool, self.options.get("low-level-client", False))
|
|
177
|
+
version_tolerant = cast(bool, self.options.get("version-tolerant", True))
|
|
178
|
+
show_operations = self.options.get("show-operations", not low_level_client)
|
|
184
179
|
models_mode_default = (
|
|
185
180
|
"none" if low_level_client or version_tolerant else "msrest"
|
|
186
181
|
)
|
|
187
|
-
if self._autorestapi.get_boolean_value("python3-only") is False:
|
|
188
|
-
_LOGGER.warning(
|
|
189
|
-
"You have passed in --python3-only=False. We have force overriden "
|
|
190
|
-
"this to True."
|
|
191
|
-
)
|
|
192
|
-
if self._autorestapi.get_boolean_value("add-python3-operation-files"):
|
|
193
|
-
_LOGGER.warning(
|
|
194
|
-
"You have passed in --add-python3-operation-files. "
|
|
195
|
-
"This flag no longer has an effect bc all SDKs are now Python3 only."
|
|
196
|
-
)
|
|
197
|
-
if self._autorestapi.get_boolean_value("reformat-next-link"):
|
|
198
|
-
_LOGGER.warning(
|
|
199
|
-
"You have passed in --reformat-next-link. We have force overriden "
|
|
200
|
-
"this to False because we no longer reformat initial query parameters into next "
|
|
201
|
-
"calls unless explicitly defined in the service definition."
|
|
202
|
-
)
|
|
203
182
|
|
|
204
183
|
options: Dict[str, Any] = {
|
|
205
184
|
"azure_arm": azure_arm,
|
|
206
|
-
"head_as_boolean": self.
|
|
207
|
-
"head-as-boolean", False
|
|
208
|
-
),
|
|
185
|
+
"head_as_boolean": self.options.get("head-as-boolean", True),
|
|
209
186
|
"license_header": license_header,
|
|
210
|
-
"keep_version_file": self.
|
|
211
|
-
|
|
212
|
-
),
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
|
|
216
|
-
),
|
|
217
|
-
"
|
|
218
|
-
|
|
219
|
-
),
|
|
220
|
-
"
|
|
221
|
-
"
|
|
222
|
-
"client_side_validation": self._autorestapi.get_boolean_value(
|
|
223
|
-
"client-side-validation", False
|
|
224
|
-
),
|
|
225
|
-
"tracing": self._autorestapi.get_boolean_value("trace", show_operations),
|
|
226
|
-
"multiapi": self._autorestapi.get_boolean_value("multiapi", False),
|
|
227
|
-
"polymorphic_examples": self._autorestapi.get_value("polymorphic-examples")
|
|
228
|
-
or 5,
|
|
229
|
-
"models_mode": (
|
|
230
|
-
self._autorestapi.get_value("models-mode") or models_mode_default
|
|
231
|
-
).lower(),
|
|
232
|
-
"builders_visibility": self._autorestapi.get_value("builders-visibility"),
|
|
187
|
+
"keep_version_file": self.options.get("keep-version-file", False),
|
|
188
|
+
"no_async": self.options.get("no-async", False),
|
|
189
|
+
"no_namespace_folders": self.options.get("no-namespace-folders", False),
|
|
190
|
+
"basic_setup_py": self.options.get("basic-setup-py", False),
|
|
191
|
+
"package_name": self.options.get("package-name"),
|
|
192
|
+
"package_version": self.options.get("package-version"),
|
|
193
|
+
"client_side_validation": self.options.get("client-side-validation", False),
|
|
194
|
+
"tracing": self.options.get("tracing", show_operations),
|
|
195
|
+
"multiapi": self.options.get("multiapi", False),
|
|
196
|
+
"polymorphic_examples": self.options.get("polymorphic-examples", 5),
|
|
197
|
+
"models_mode": self.options.get("models-mode", models_mode_default).lower(),
|
|
198
|
+
"builders_visibility": self.options.get("builders-visibility"),
|
|
233
199
|
"show_operations": show_operations,
|
|
234
|
-
"show_send_request": self.
|
|
200
|
+
"show_send_request": self.options.get(
|
|
235
201
|
"show-send-request", low_level_client or version_tolerant
|
|
236
202
|
),
|
|
237
|
-
"only_path_and_body_params_positional": self.
|
|
203
|
+
"only_path_and_body_params_positional": self.options.get(
|
|
238
204
|
"only-path-and-body-params-positional",
|
|
239
205
|
low_level_client or version_tolerant,
|
|
240
206
|
),
|
|
241
207
|
"version_tolerant": version_tolerant,
|
|
242
208
|
"low_level_client": low_level_client,
|
|
243
|
-
"combine_operation_files": self.
|
|
209
|
+
"combine_operation_files": self.options.get(
|
|
244
210
|
"combine-operation-files", version_tolerant
|
|
245
211
|
),
|
|
246
|
-
"package_mode": self.
|
|
247
|
-
"package_pprint_name": self.
|
|
248
|
-
"package_configuration": self.
|
|
249
|
-
|
|
250
|
-
),
|
|
251
|
-
"default_optional_constants_to_none": self._autorestapi.get_boolean_value(
|
|
212
|
+
"package_mode": self.options.get("package-mode"),
|
|
213
|
+
"package_pprint_name": self.options.get("package-pprint-name"),
|
|
214
|
+
"package_configuration": self.options.get("package-configuration"),
|
|
215
|
+
"default_optional_constants_to_none": self.options.get(
|
|
252
216
|
"default-optional-constants-to-none",
|
|
253
217
|
low_level_client or version_tolerant,
|
|
254
218
|
),
|
|
@@ -272,8 +236,102 @@ class CodeGenerator(Plugin):
|
|
|
272
236
|
options["head_as_boolean"] = True
|
|
273
237
|
return options
|
|
274
238
|
|
|
239
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
240
|
+
# cadl file doesn't have to be relative to output folder
|
|
241
|
+
with open(self.options["cadl_file"], "r") as fd:
|
|
242
|
+
return yaml.safe_load(fd.read())
|
|
243
|
+
|
|
244
|
+
def get_serializer(self, code_model: CodeModel):
|
|
245
|
+
return JinjaSerializer(code_model, output_folder=self.output_folder)
|
|
246
|
+
|
|
275
247
|
def process(self) -> bool:
|
|
276
248
|
# List the input file, should be only one
|
|
249
|
+
|
|
250
|
+
options = self._build_code_model_options()
|
|
251
|
+
yaml_data = self.get_yaml()
|
|
252
|
+
|
|
253
|
+
if options["azure_arm"]:
|
|
254
|
+
self.remove_cloud_errors(yaml_data)
|
|
255
|
+
|
|
256
|
+
code_model = self._create_code_model(yaml_data=yaml_data, options=options)
|
|
257
|
+
|
|
258
|
+
serializer = self.get_serializer(code_model)
|
|
259
|
+
serializer.serialize()
|
|
260
|
+
|
|
261
|
+
return True
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
|
|
265
|
+
def get_options(self) -> Dict[str, Any]:
|
|
266
|
+
if self._autorestapi.get_boolean_value("python3-only") is False:
|
|
267
|
+
_LOGGER.warning(
|
|
268
|
+
"You have passed in --python3-only=False. We have force overriden "
|
|
269
|
+
"this to True."
|
|
270
|
+
)
|
|
271
|
+
if self._autorestapi.get_boolean_value("add-python3-operation-files"):
|
|
272
|
+
_LOGGER.warning(
|
|
273
|
+
"You have passed in --add-python3-operation-files. "
|
|
274
|
+
"This flag no longer has an effect bc all SDKs are now Python3 only."
|
|
275
|
+
)
|
|
276
|
+
if self._autorestapi.get_boolean_value("reformat-next-link"):
|
|
277
|
+
_LOGGER.warning(
|
|
278
|
+
"You have passed in --reformat-next-link. We have force overriden "
|
|
279
|
+
"this to False because we no longer reformat initial query parameters into next "
|
|
280
|
+
"calls unless explicitly defined in the service definition."
|
|
281
|
+
)
|
|
282
|
+
options = {
|
|
283
|
+
"azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
|
|
284
|
+
"header-text": self._autorestapi.get_value("header-text"),
|
|
285
|
+
"low-level-client": self._autorestapi.get_boolean_value(
|
|
286
|
+
"low-level-client", False
|
|
287
|
+
),
|
|
288
|
+
"version-tolerant": self._autorestapi.get_boolean_value(
|
|
289
|
+
"version-tolerant", True
|
|
290
|
+
),
|
|
291
|
+
"show-operations": self._autorestapi.get_boolean_value("show-operations"),
|
|
292
|
+
"python3-only": self._autorestapi.get_boolean_value("python3-only"),
|
|
293
|
+
"head-as-boolean": self._autorestapi.get_boolean_value(
|
|
294
|
+
"head-as-boolean", False
|
|
295
|
+
),
|
|
296
|
+
"keep-version-file": self._autorestapi.get_boolean_value(
|
|
297
|
+
"keep-version-file"
|
|
298
|
+
),
|
|
299
|
+
"no-async": self._autorestapi.get_boolean_value("no-async"),
|
|
300
|
+
"no-namespace-folders": self._autorestapi.get_boolean_value(
|
|
301
|
+
"no-namespace-folders"
|
|
302
|
+
),
|
|
303
|
+
"basic-setup-py": self._autorestapi.get_boolean_value("basic-setup-py"),
|
|
304
|
+
"package-name": self._autorestapi.get_value("package-name"),
|
|
305
|
+
"package-version": self._autorestapi.get_value("package-version"),
|
|
306
|
+
"client-side-validation": self._autorestapi.get_boolean_value(
|
|
307
|
+
"client-side-validation"
|
|
308
|
+
),
|
|
309
|
+
"tracing": self._autorestapi.get_boolean_value("trace"),
|
|
310
|
+
"multiapi": self._autorestapi.get_boolean_value("multiapi", False),
|
|
311
|
+
"polymorphic-examples": self._autorestapi.get_value("polymorphic-examples"),
|
|
312
|
+
"models-mode": self._autorestapi.get_value("models-mode"),
|
|
313
|
+
"builders-visibility": self._autorestapi.get_value("builders-visibility"),
|
|
314
|
+
"show-send-request": self._autorestapi.get_boolean_value(
|
|
315
|
+
"show-send-request"
|
|
316
|
+
),
|
|
317
|
+
"only-path-and-body-params-positional": self._autorestapi.get_boolean_value(
|
|
318
|
+
"only-path-and-body-params-positional"
|
|
319
|
+
),
|
|
320
|
+
"combine-operation-files": self._autorestapi.get_boolean_value(
|
|
321
|
+
"combine-operation-files"
|
|
322
|
+
),
|
|
323
|
+
"package-mode": self._autorestapi.get_value("package-mode"),
|
|
324
|
+
"package-pprint-name": self._autorestapi.get_value("package-pprint-name"),
|
|
325
|
+
"package-configuration": self._autorestapi.get_value(
|
|
326
|
+
"package-configuration"
|
|
327
|
+
),
|
|
328
|
+
"default-optional-constants-to-none": self._autorestapi.get_boolean_value(
|
|
329
|
+
"default-optional-constants-to-none"
|
|
330
|
+
),
|
|
331
|
+
}
|
|
332
|
+
return {k: v for k, v in options.items() if v is not None}
|
|
333
|
+
|
|
334
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
277
335
|
inputs = self._autorestapi.list_inputs()
|
|
278
336
|
_LOGGER.debug("Possible Inputs: %s", inputs)
|
|
279
337
|
if "code-model-v4-no-tags.yaml" not in inputs:
|
|
@@ -291,32 +349,15 @@ class CodeGenerator(Plugin):
|
|
|
291
349
|
file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
|
|
292
350
|
|
|
293
351
|
# Parse the received YAML
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
options = self._build_code_model_options()
|
|
297
|
-
|
|
298
|
-
if options["azure_arm"]:
|
|
299
|
-
self.remove_cloud_errors(yaml_data)
|
|
300
|
-
|
|
301
|
-
code_model = self._create_code_model(yaml_data=yaml_data, options=options)
|
|
302
|
-
|
|
303
|
-
serializer = JinjaSerializer(self._autorestapi, code_model)
|
|
304
|
-
serializer.serialize()
|
|
352
|
+
return yaml.safe_load(file_content)
|
|
305
353
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
from ..jsonrpc.localapi import ( # pylint: disable=import-outside-toplevel
|
|
311
|
-
LocalAutorestAPI,
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
code_generator = CodeGenerator(
|
|
315
|
-
autorestapi=LocalAutorestAPI(reachable_files=[yaml_model_file])
|
|
316
|
-
)
|
|
317
|
-
if not code_generator.process():
|
|
318
|
-
raise SystemExit("Process didn't finish gracefully")
|
|
354
|
+
def get_serializer(self, code_model: CodeModel): # type: ignore
|
|
355
|
+
return JinjaSerializerAutorest(
|
|
356
|
+
self._autorestapi, code_model, output_folder=self.output_folder
|
|
357
|
+
)
|
|
319
358
|
|
|
320
359
|
|
|
321
360
|
if __name__ == "__main__":
|
|
322
|
-
|
|
361
|
+
# CADL pipeline will call this
|
|
362
|
+
args = parse_args()
|
|
363
|
+
CodeGenerator(output_folder=args.output_folder, cadl_file=args.cadl_file).process()
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
|
|
7
|
+
DEFAULT_HEADER_TEXT = (
|
|
8
|
+
"# --------------------------------------------------------------------------\n"
|
|
9
|
+
"# Copyright (c) Microsoft Corporation. All rights reserved.\n"
|
|
10
|
+
"# Licensed under the MIT License. See License.txt in the project root for license information.\n"
|
|
11
|
+
"# Code generated by Microsoft (R) Python Code Generator.\n"
|
|
12
|
+
"# Changes may cause incorrect behavior and will be lost if the code is regenerated.\n"
|
|
13
|
+
"# --------------------------------------------------------------------------"
|
|
14
|
+
)
|