@autorest/python 5.19.0 → 6.0.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 +61 -2
- package/README.md +9 -0
- package/autorest/__init__.py +54 -13
- package/autorest/black/__init__.py +14 -8
- package/autorest/codegen/__init__.py +126 -89
- package/autorest/codegen/models/base_builder.py +17 -6
- package/autorest/codegen/models/client.py +1 -1
- package/autorest/codegen/models/code_model.py +7 -12
- package/autorest/codegen/models/lro_operation.py +2 -6
- package/autorest/codegen/models/lro_paging_operation.py +3 -9
- package/autorest/codegen/models/model_type.py +1 -6
- package/autorest/codegen/models/operation.py +6 -37
- package/autorest/codegen/models/operation_group.py +4 -7
- package/autorest/codegen/models/paging_operation.py +17 -7
- package/autorest/codegen/models/parameter.py +3 -7
- package/autorest/codegen/models/parameter_list.py +20 -36
- package/autorest/codegen/models/request_builder.py +0 -22
- package/autorest/codegen/serializers/__init__.py +46 -98
- package/autorest/codegen/serializers/builder_serializer.py +53 -36
- package/autorest/codegen/serializers/client_serializer.py +20 -31
- package/autorest/codegen/serializers/general_serializer.py +2 -7
- package/autorest/codegen/serializers/import_serializer.py +11 -22
- package/autorest/codegen/serializers/metadata_serializer.py +0 -2
- package/autorest/codegen/serializers/{model_base_serializer.py → model_serializer.py} +47 -38
- package/autorest/codegen/serializers/operation_groups_serializer.py +0 -7
- package/autorest/codegen/serializers/operations_init_serializer.py +2 -23
- package/autorest/codegen/serializers/patch_serializer.py +1 -3
- package/autorest/codegen/serializers/request_builders_serializer.py +1 -4
- package/autorest/codegen/serializers/utils.py +1 -4
- package/autorest/codegen/templates/client.py.jinja2 +3 -3
- package/autorest/codegen/templates/config.py.jinja2 +2 -2
- package/autorest/codegen/templates/metadata.json.jinja2 +4 -4
- package/autorest/codegen/templates/model_init.py.jinja2 +5 -12
- package/autorest/codegen/templates/operation_group.py.jinja2 +1 -1
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -6
- package/autorest/codegen/templates/patch.py.jinja2 +1 -2
- package/autorest/codegen/templates/request_builders.py.jinja2 +0 -3
- package/autorest/codegen/templates/rest_init.py.jinja2 +3 -8
- package/autorest/codegen/templates/serialization.py.jinja2 +3 -3
- package/autorest/codegen/templates/setup.py.jinja2 +1 -1
- package/autorest/jsonrpc/server.py +7 -7
- package/autorest/m2r/__init__.py +7 -2
- package/autorest/m4reformatter/__init__.py +13 -5
- package/autorest/multiapi/__init__.py +56 -29
- package/autorest/multiapi/serializers/__init__.py +26 -31
- package/autorest/multiapi/serializers/import_serializer.py +4 -8
- package/autorest/multiapi/serializers/multiapi_serializer.py +33 -26
- package/autorest/postprocess/__init__.py +14 -11
- package/autorest/preprocess/__init__.py +36 -7
- package/package.json +2 -2
- package/autorest/codegen/serializers/model_generic_serializer.py +0 -32
- package/autorest/codegen/serializers/model_python3_serializer.py +0 -72
package/ChangeLog.md
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
-
### 2022-
|
|
3
|
+
### 2022-06-29 - 6.0.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
|
+
**Bug Fixes**
|
|
15
|
+
|
|
16
|
+
- Ignore linting error for clients with no credentials #1333
|
|
17
|
+
|
|
18
|
+
### 2022-06-24 - 6.0.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
|
+
**Breaking Changes**
|
|
30
|
+
|
|
31
|
+
- Don't generate paging variables `maxpagesize` for DPG generations. Users should pass in `maxpagesize` to the `by_page` method of their
|
|
32
|
+
pager #1320
|
|
33
|
+
|
|
34
|
+
### 2022-06-17 - 6.0.0-rc.1
|
|
35
|
+
|
|
36
|
+
| Library | Min Version |
|
|
37
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
38
|
+
| `@autorest/core` | `3.8.1` |
|
|
39
|
+
| `@autorest/modelerfour` | `4.23.5` |
|
|
40
|
+
| `azure-core` dep of generated code | `1.24.0` |
|
|
41
|
+
| `isodate` dep of generated code | `0.6.1` |
|
|
42
|
+
| `msrest` dep of generated code (If generating legacy code) | `0.7.1` |
|
|
43
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
44
|
+
|
|
45
|
+
**Breaking Changes**
|
|
46
|
+
|
|
47
|
+
- Default to generating DPG SDKs with `--version-tolerant` now defaulting to `true`. For a list of flag default changes, please
|
|
48
|
+
see [here](https://github.com/Azure/autorest.python/issues/1186) #1304
|
|
49
|
+
- Only generate Python3 SDKs #1297
|
|
50
|
+
- Don't reformat initial query parameters into the next link. However, we do append `api-version` parameters if they are not present in the next link #1297 #1309
|
|
51
|
+
- Don't generate operations with more than two body types. SDK authors need to implement this operation themselves #1300
|
|
52
|
+
|
|
53
|
+
**New Features**
|
|
54
|
+
|
|
55
|
+
- Automatically format generated code with `black`. To not format, pass in `--black=false` #1304
|
|
56
|
+
|
|
57
|
+
**Other**
|
|
58
|
+
|
|
59
|
+
- Remove testing support for `--low-level-client` SDKs #1303
|
|
60
|
+
|
|
61
|
+
### 2022-06-13 - 5.19.0
|
|
4
62
|
|
|
5
63
|
| Library | Min Version |
|
|
6
64
|
| ----------------------------------------------------------------------- | ----------- |
|
|
@@ -11,9 +69,10 @@
|
|
|
11
69
|
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
12
70
|
|
|
13
71
|
**New Features**
|
|
72
|
+
|
|
14
73
|
- Add _serialization.py for `--client-side-validation=false` generation, and migrate serilization from msrest to _serialization.py #1236
|
|
15
74
|
|
|
16
|
-
### 2022-
|
|
75
|
+
### 2022-06-09 - 5.18.0
|
|
17
76
|
|
|
18
77
|
| Library | Min Version |
|
|
19
78
|
| ----------------------------------------------------------------------- | ----------- |
|
package/README.md
CHANGED
|
@@ -23,6 +23,15 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
|
|
|
23
23
|
|
|
24
24
|
#### Python code gen
|
|
25
25
|
|
|
26
|
+
```yaml !$(multiapiscript)
|
|
27
|
+
# default values for version tolerant and black
|
|
28
|
+
black: true
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```yaml !$(low-level-client)
|
|
32
|
+
version-tolerant: true
|
|
33
|
+
```
|
|
34
|
+
|
|
26
35
|
```yaml !$(low-level-client) && !$(version-tolerant)
|
|
27
36
|
modelerfour:
|
|
28
37
|
group-parameters: true
|
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,14 +18,40 @@ __version__ = VERSION
|
|
|
17
18
|
_LOGGER = logging.getLogger(__name__)
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class
|
|
21
|
+
class ReaderAndWriter:
|
|
22
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def read_file(self, path: Union[str, Path]) -> str:
|
|
26
|
+
"""How does one read a file in cadl?"""
|
|
27
|
+
raise NotImplementedError("Haven't plugged in Cadl yet")
|
|
28
|
+
|
|
29
|
+
def write_file(self, filename: Union[str, Path], file_content: str) -> None:
|
|
30
|
+
"""How does writing work in cadl?"""
|
|
31
|
+
raise NotImplementedError("Haven't plugged in Cadl yet")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ReaderAndWriterAutorest(ReaderAndWriter):
|
|
35
|
+
def __init__(self, *, autorestapi: AutorestAPI) -> None:
|
|
36
|
+
super().__init__()
|
|
37
|
+
self._autorestapi = autorestapi
|
|
38
|
+
|
|
39
|
+
def read_file(self, path: Union[str, Path]) -> str:
|
|
40
|
+
return self._autorestapi.read_file(path)
|
|
41
|
+
|
|
42
|
+
def write_file(self, filename: Union[str, Path], file_content: str) -> None:
|
|
43
|
+
return self._autorestapi.write_file(filename, file_content)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Plugin(ReaderAndWriter, ABC):
|
|
21
47
|
"""A base class for autorest plugin.
|
|
22
48
|
|
|
23
49
|
:param autorestapi: An autorest API instance
|
|
24
50
|
"""
|
|
25
51
|
|
|
26
|
-
def __init__(self,
|
|
27
|
-
|
|
52
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
53
|
+
super().__init__(**kwargs)
|
|
54
|
+
self.options: Dict[str, Any] = {}
|
|
28
55
|
|
|
29
56
|
@abstractmethod
|
|
30
57
|
def process(self) -> bool:
|
|
@@ -37,24 +64,30 @@ class Plugin(ABC):
|
|
|
37
64
|
raise NotImplementedError()
|
|
38
65
|
|
|
39
66
|
|
|
67
|
+
class PluginAutorest(Plugin, ReaderAndWriterAutorest):
|
|
68
|
+
"""For our Autorest plugins, we want to take autorest api as input as options, then pass it to the Plugin"""
|
|
69
|
+
|
|
70
|
+
def __init__(self, autorestapi: AutorestAPI) -> None:
|
|
71
|
+
super().__init__(autorestapi=autorestapi)
|
|
72
|
+
self.options = self.get_options()
|
|
73
|
+
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def get_options(self) -> Dict[str, Any]:
|
|
76
|
+
"""Get the options bag using the AutorestAPI that we send to the parent plugin"""
|
|
77
|
+
|
|
78
|
+
|
|
40
79
|
class YamlUpdatePlugin(Plugin):
|
|
41
80
|
"""A plugin that update the YAML as input."""
|
|
42
81
|
|
|
43
82
|
def process(self) -> bool:
|
|
44
83
|
# 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)
|
|
84
|
+
yaml_data = yaml.safe_load(self.read_file("code-model-v4-no-tags.yaml"))
|
|
52
85
|
|
|
53
86
|
self.update_yaml(yaml_data)
|
|
54
87
|
|
|
55
88
|
yaml_string = yaml.safe_dump(yaml_data)
|
|
56
89
|
|
|
57
|
-
self.
|
|
90
|
+
self.write_file("code-model-v4-no-tags.yaml", yaml_string)
|
|
58
91
|
return True
|
|
59
92
|
|
|
60
93
|
@abstractmethod
|
|
@@ -67,4 +100,12 @@ class YamlUpdatePlugin(Plugin):
|
|
|
67
100
|
raise NotImplementedError()
|
|
68
101
|
|
|
69
102
|
|
|
70
|
-
|
|
103
|
+
class YamlUpdatePluginAutorest( # pylint: disable=abstract-method
|
|
104
|
+
YamlUpdatePlugin, PluginAutorest
|
|
105
|
+
):
|
|
106
|
+
def get_options(self) -> Dict[str, Any]:
|
|
107
|
+
inputs = self._autorestapi.list_inputs()
|
|
108
|
+
_LOGGER.debug("Possible Inputs: %s", inputs)
|
|
109
|
+
if "code-model-v4-no-tags.yaml" not in inputs:
|
|
110
|
+
raise ValueError("code-model-v4-no-tags.yaml must be a possible input")
|
|
111
|
+
return {}
|
|
@@ -6,9 +6,10 @@
|
|
|
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
|
|
12
13
|
|
|
13
14
|
_LOGGER = logging.getLogger(__name__)
|
|
14
15
|
|
|
@@ -16,10 +17,10 @@ _BLACK_MODE = black.Mode()
|
|
|
16
17
|
_BLACK_MODE.line_length = 120
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class BlackScriptPlugin(Plugin):
|
|
20
|
-
def __init__(self,
|
|
21
|
-
super().__init__(
|
|
22
|
-
output_folder_uri = self.
|
|
20
|
+
class BlackScriptPlugin(Plugin): # pylint: disable=abstract-method
|
|
21
|
+
def __init__(self, **kwargs):
|
|
22
|
+
super().__init__(**kwargs)
|
|
23
|
+
output_folder_uri = self.options["outputFolderUri"]
|
|
23
24
|
if output_folder_uri.startswith("file:"):
|
|
24
25
|
output_folder_uri = output_folder_uri[5:]
|
|
25
26
|
if os.name == "nt" and output_folder_uri.startswith("///"):
|
|
@@ -38,9 +39,9 @@ class BlackScriptPlugin(Plugin):
|
|
|
38
39
|
|
|
39
40
|
def format_file(self, full_path) -> None:
|
|
40
41
|
file = full_path.relative_to(self.output_folder)
|
|
41
|
-
file_content = self.
|
|
42
|
+
file_content = self.read_file(file)
|
|
42
43
|
if not file.suffix == ".py":
|
|
43
|
-
self.
|
|
44
|
+
self.write_file(file, file_content)
|
|
44
45
|
return
|
|
45
46
|
try:
|
|
46
47
|
file_content = black.format_file_contents(
|
|
@@ -48,4 +49,9 @@ class BlackScriptPlugin(Plugin):
|
|
|
48
49
|
)
|
|
49
50
|
except black.NothingChanged:
|
|
50
51
|
pass
|
|
51
|
-
self.
|
|
52
|
+
self.write_file(file, file_content)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class BlackScriptPluginAutorest(BlackScriptPlugin, PluginAutorest):
|
|
56
|
+
def get_options(self) -> Dict[str, Any]:
|
|
57
|
+
return {"outputFolderUri": self._autorestapi.get_value("outputFolderUri")}
|
|
@@ -10,13 +10,13 @@ from pathlib import Path
|
|
|
10
10
|
import yaml
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
from .. import Plugin
|
|
13
|
+
from .. import Plugin, PluginAutorest
|
|
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
20
|
|
|
21
21
|
|
|
22
22
|
def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
|
|
@@ -57,13 +57,6 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
|
57
57
|
"to 'public' or 'hidden'."
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
-
if not options["show_operations"] and options["add_python3_operation_files"]:
|
|
61
|
-
raise ValueError(
|
|
62
|
-
"Can not add typed sync operation files if you are not showing operations. "
|
|
63
|
-
"If you want typed synced operation files, you have to add flag "
|
|
64
|
-
"--show-operations"
|
|
65
|
-
)
|
|
66
|
-
|
|
67
60
|
if options["basic_setup_py"] and not options["package_version"]:
|
|
68
61
|
raise ValueError("--basic-setup-py must be used with --package-version")
|
|
69
62
|
|
|
@@ -85,12 +78,6 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
|
85
78
|
"--package-mode can only be 'mgmtplane' or 'dataplane' or directory which contains template files"
|
|
86
79
|
)
|
|
87
80
|
|
|
88
|
-
if options["reformat_next_link"] and options["version_tolerant"]:
|
|
89
|
-
raise ValueError(
|
|
90
|
-
"--reformat-next-link can not be true for version tolerant generations. "
|
|
91
|
-
"Please remove --reformat-next-link from your call for version tolerant generations."
|
|
92
|
-
)
|
|
93
|
-
|
|
94
81
|
if options["multiapi"] and options["version_tolerant"]:
|
|
95
82
|
raise ValueError(
|
|
96
83
|
"Can not currently generate version tolerant multiapi SDKs. "
|
|
@@ -136,7 +123,7 @@ class CodeGenerator(Plugin):
|
|
|
136
123
|
return {
|
|
137
124
|
"dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
|
|
138
125
|
"dependency_azure_core": "azure-core<2.0.0,>=1.24.0",
|
|
139
|
-
"dependency_msrest": "msrest>=0.7.
|
|
126
|
+
"dependency_msrest": "msrest>=0.7.1",
|
|
140
127
|
}
|
|
141
128
|
|
|
142
129
|
def _create_code_model(
|
|
@@ -175,8 +162,8 @@ class CodeGenerator(Plugin):
|
|
|
175
162
|
|
|
176
163
|
def _build_code_model_options(self) -> Dict[str, Any]:
|
|
177
164
|
"""Build en options dict from the user input while running autorest."""
|
|
178
|
-
azure_arm = self.
|
|
179
|
-
license_header = self.
|
|
165
|
+
azure_arm = self.options.get("azure-arm", False)
|
|
166
|
+
license_header = self.options["header-text"]
|
|
180
167
|
if license_header:
|
|
181
168
|
license_header = license_header.replace("\n", "\n# ")
|
|
182
169
|
license_header = (
|
|
@@ -185,84 +172,49 @@ class CodeGenerator(Plugin):
|
|
|
185
172
|
)
|
|
186
173
|
license_header += "\n# --------------------------------------------------------------------------"
|
|
187
174
|
|
|
188
|
-
low_level_client = cast(
|
|
189
|
-
|
|
190
|
-
)
|
|
191
|
-
version_tolerant = cast(
|
|
192
|
-
bool, self._autorestapi.get_boolean_value("version-tolerant", False)
|
|
193
|
-
)
|
|
194
|
-
show_operations = self._autorestapi.get_boolean_value(
|
|
195
|
-
"show-operations", not low_level_client
|
|
196
|
-
)
|
|
175
|
+
low_level_client = cast(bool, self.options.get("low-level-client", False))
|
|
176
|
+
version_tolerant = cast(bool, self.options.get("version-tolerant", True))
|
|
177
|
+
show_operations = self.options.get("show-operations", not low_level_client)
|
|
197
178
|
models_mode_default = (
|
|
198
179
|
"none" if low_level_client or version_tolerant else "msrest"
|
|
199
180
|
)
|
|
200
|
-
python3_only = cast(
|
|
201
|
-
bool,
|
|
202
|
-
self._autorestapi.get_boolean_value(
|
|
203
|
-
"python3-only", low_level_client or version_tolerant
|
|
204
|
-
),
|
|
205
|
-
)
|
|
206
181
|
|
|
207
182
|
options: Dict[str, Any] = {
|
|
208
183
|
"azure_arm": azure_arm,
|
|
209
|
-
"head_as_boolean": self.
|
|
210
|
-
"head-as-boolean", False
|
|
211
|
-
),
|
|
184
|
+
"head_as_boolean": self.options.get("head-as-boolean", True),
|
|
212
185
|
"license_header": license_header,
|
|
213
|
-
"keep_version_file": self.
|
|
214
|
-
|
|
215
|
-
),
|
|
216
|
-
"
|
|
217
|
-
"
|
|
218
|
-
|
|
219
|
-
),
|
|
220
|
-
"
|
|
221
|
-
|
|
222
|
-
),
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"client_side_validation": self._autorestapi.get_boolean_value(
|
|
226
|
-
"client-side-validation", False
|
|
227
|
-
),
|
|
228
|
-
"tracing": self._autorestapi.get_boolean_value("trace", show_operations),
|
|
229
|
-
"multiapi": self._autorestapi.get_boolean_value("multiapi", False),
|
|
230
|
-
"polymorphic_examples": self._autorestapi.get_value("polymorphic-examples")
|
|
231
|
-
or 5,
|
|
232
|
-
"models_mode": (
|
|
233
|
-
self._autorestapi.get_value("models-mode") or models_mode_default
|
|
234
|
-
).lower(),
|
|
235
|
-
"builders_visibility": self._autorestapi.get_value("builders-visibility"),
|
|
186
|
+
"keep_version_file": self.options.get("keep-version-file", False),
|
|
187
|
+
"no_async": self.options.get("no-async", False),
|
|
188
|
+
"no_namespace_folders": self.options.get("no-namespace-folders", False),
|
|
189
|
+
"basic_setup_py": self.options.get("basic-setup-py", False),
|
|
190
|
+
"package_name": self.options.get("package-name"),
|
|
191
|
+
"package_version": self.options.get("package-version"),
|
|
192
|
+
"client_side_validation": self.options.get("client-side-validation", False),
|
|
193
|
+
"tracing": self.options.get("tracing", show_operations),
|
|
194
|
+
"multiapi": self.options.get("multiapi", False),
|
|
195
|
+
"polymorphic_examples": self.options.get("polymorphic-examples", 5),
|
|
196
|
+
"models_mode": self.options.get("models-mode", models_mode_default).lower(),
|
|
197
|
+
"builders_visibility": self.options.get("builders-visibility"),
|
|
236
198
|
"show_operations": show_operations,
|
|
237
|
-
"show_send_request": self.
|
|
199
|
+
"show_send_request": self.options.get(
|
|
238
200
|
"show-send-request", low_level_client or version_tolerant
|
|
239
201
|
),
|
|
240
|
-
"only_path_and_body_params_positional": self.
|
|
202
|
+
"only_path_and_body_params_positional": self.options.get(
|
|
241
203
|
"only-path-and-body-params-positional",
|
|
242
204
|
low_level_client or version_tolerant,
|
|
243
205
|
),
|
|
244
|
-
"add_python3_operation_files": self._autorestapi.get_boolean_value(
|
|
245
|
-
"add-python3-operation-files",
|
|
246
|
-
python3_only and not (low_level_client or version_tolerant),
|
|
247
|
-
),
|
|
248
206
|
"version_tolerant": version_tolerant,
|
|
249
207
|
"low_level_client": low_level_client,
|
|
250
|
-
"combine_operation_files": self.
|
|
208
|
+
"combine_operation_files": self.options.get(
|
|
251
209
|
"combine-operation-files", version_tolerant
|
|
252
210
|
),
|
|
253
|
-
"
|
|
254
|
-
"
|
|
255
|
-
"
|
|
256
|
-
"
|
|
257
|
-
"package-configuration"
|
|
258
|
-
),
|
|
259
|
-
"default_optional_constants_to_none": self._autorestapi.get_boolean_value(
|
|
211
|
+
"package_mode": self.options.get("package-mode"),
|
|
212
|
+
"package_pprint_name": self.options.get("package-pprint-name"),
|
|
213
|
+
"package_configuration": self.options.get("package-configuration"),
|
|
214
|
+
"default_optional_constants_to_none": self.options.get(
|
|
260
215
|
"default-optional-constants-to-none",
|
|
261
216
|
low_level_client or version_tolerant,
|
|
262
217
|
),
|
|
263
|
-
"reformat_next_link": self._autorestapi.get_boolean_value(
|
|
264
|
-
"reformat-next-link", not version_tolerant
|
|
265
|
-
),
|
|
266
218
|
}
|
|
267
219
|
|
|
268
220
|
if options["builders_visibility"] is None:
|
|
@@ -283,8 +235,102 @@ class CodeGenerator(Plugin):
|
|
|
283
235
|
options["head_as_boolean"] = True
|
|
284
236
|
return options
|
|
285
237
|
|
|
238
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
239
|
+
# cadl should call this one
|
|
240
|
+
raise NotImplementedError()
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def get_serializer(code_model: CodeModel):
|
|
244
|
+
return JinjaSerializer(code_model)
|
|
245
|
+
|
|
286
246
|
def process(self) -> bool:
|
|
287
247
|
# List the input file, should be only one
|
|
248
|
+
|
|
249
|
+
options = self._build_code_model_options()
|
|
250
|
+
yaml_data = self.get_yaml()
|
|
251
|
+
|
|
252
|
+
if options["azure_arm"]:
|
|
253
|
+
self.remove_cloud_errors(yaml_data)
|
|
254
|
+
|
|
255
|
+
code_model = self._create_code_model(yaml_data=yaml_data, options=options)
|
|
256
|
+
|
|
257
|
+
serializer = self.get_serializer(code_model)
|
|
258
|
+
serializer.serialize()
|
|
259
|
+
|
|
260
|
+
return True
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class CodeGeneratorAutorest(CodeGenerator, PluginAutorest):
|
|
264
|
+
def get_options(self) -> Dict[str, Any]:
|
|
265
|
+
if self._autorestapi.get_boolean_value("python3-only") is False:
|
|
266
|
+
_LOGGER.warning(
|
|
267
|
+
"You have passed in --python3-only=False. We have force overriden "
|
|
268
|
+
"this to True."
|
|
269
|
+
)
|
|
270
|
+
if self._autorestapi.get_boolean_value("add-python3-operation-files"):
|
|
271
|
+
_LOGGER.warning(
|
|
272
|
+
"You have passed in --add-python3-operation-files. "
|
|
273
|
+
"This flag no longer has an effect bc all SDKs are now Python3 only."
|
|
274
|
+
)
|
|
275
|
+
if self._autorestapi.get_boolean_value("reformat-next-link"):
|
|
276
|
+
_LOGGER.warning(
|
|
277
|
+
"You have passed in --reformat-next-link. We have force overriden "
|
|
278
|
+
"this to False because we no longer reformat initial query parameters into next "
|
|
279
|
+
"calls unless explicitly defined in the service definition."
|
|
280
|
+
)
|
|
281
|
+
options = {
|
|
282
|
+
"azure-arm": self._autorestapi.get_boolean_value("azure-arm"),
|
|
283
|
+
"header-text": self._autorestapi.get_value("header-text"),
|
|
284
|
+
"low-level-client": self._autorestapi.get_boolean_value(
|
|
285
|
+
"low-level-client", False
|
|
286
|
+
),
|
|
287
|
+
"version-tolerant": self._autorestapi.get_boolean_value(
|
|
288
|
+
"version-tolerant", True
|
|
289
|
+
),
|
|
290
|
+
"show-operations": self._autorestapi.get_boolean_value("show-operations"),
|
|
291
|
+
"python3-only": self._autorestapi.get_boolean_value("python3-only"),
|
|
292
|
+
"head-as-boolean": self._autorestapi.get_boolean_value(
|
|
293
|
+
"head-as-boolean", False
|
|
294
|
+
),
|
|
295
|
+
"keep-version-file": self._autorestapi.get_boolean_value(
|
|
296
|
+
"keep-version-file"
|
|
297
|
+
),
|
|
298
|
+
"no-async": self._autorestapi.get_boolean_value("no-async"),
|
|
299
|
+
"no-namespace-folders": self._autorestapi.get_boolean_value(
|
|
300
|
+
"no-namespace-folders"
|
|
301
|
+
),
|
|
302
|
+
"basic-setup-py": self._autorestapi.get_boolean_value("basic-setup-py"),
|
|
303
|
+
"package-name": self._autorestapi.get_value("package-name"),
|
|
304
|
+
"package-version": self._autorestapi.get_value("package-version"),
|
|
305
|
+
"client-side-validation": self._autorestapi.get_boolean_value(
|
|
306
|
+
"client-side-validation"
|
|
307
|
+
),
|
|
308
|
+
"tracing": self._autorestapi.get_boolean_value("trace"),
|
|
309
|
+
"multiapi": self._autorestapi.get_boolean_value("multiapi", False),
|
|
310
|
+
"polymorphic-examples": self._autorestapi.get_value("polymorphic-examples"),
|
|
311
|
+
"models-mode": self._autorestapi.get_value("models-mode"),
|
|
312
|
+
"builders-visibility": self._autorestapi.get_value("builders-visibility"),
|
|
313
|
+
"show-send-request": self._autorestapi.get_boolean_value(
|
|
314
|
+
"show-send-request"
|
|
315
|
+
),
|
|
316
|
+
"only-path-and-body-params-positional": self._autorestapi.get_boolean_value(
|
|
317
|
+
"only-path-and-body-params-positional"
|
|
318
|
+
),
|
|
319
|
+
"combine-operation-files": self._autorestapi.get_boolean_value(
|
|
320
|
+
"combine-operation-files"
|
|
321
|
+
),
|
|
322
|
+
"package-mode": self._autorestapi.get_value("package-mode"),
|
|
323
|
+
"package-pprint-name": self._autorestapi.get_value("package-pprint-name"),
|
|
324
|
+
"package-configuration": self._autorestapi.get_value(
|
|
325
|
+
"package-configuration"
|
|
326
|
+
),
|
|
327
|
+
"default-optional-constants-to-none": self._autorestapi.get_boolean_value(
|
|
328
|
+
"default-optional-constants-to-none"
|
|
329
|
+
),
|
|
330
|
+
}
|
|
331
|
+
return {k: v for k, v in options.items() if v is not None}
|
|
332
|
+
|
|
333
|
+
def get_yaml(self) -> Dict[str, Any]:
|
|
288
334
|
inputs = self._autorestapi.list_inputs()
|
|
289
335
|
_LOGGER.debug("Possible Inputs: %s", inputs)
|
|
290
336
|
if "code-model-v4-no-tags.yaml" not in inputs:
|
|
@@ -302,19 +348,10 @@ class CodeGenerator(Plugin):
|
|
|
302
348
|
file_content = self._autorestapi.read_file("code-model-v4-no-tags.yaml")
|
|
303
349
|
|
|
304
350
|
# Parse the received YAML
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
options = self._build_code_model_options()
|
|
351
|
+
return yaml.safe_load(file_content)
|
|
308
352
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
code_model = self._create_code_model(yaml_data=yaml_data, options=options)
|
|
313
|
-
|
|
314
|
-
serializer = JinjaSerializer(self._autorestapi, code_model)
|
|
315
|
-
serializer.serialize()
|
|
316
|
-
|
|
317
|
-
return True
|
|
353
|
+
def get_serializer(self, code_model: CodeModel): # type: ignore
|
|
354
|
+
return JinjaSerializerAutorest(self._autorestapi, code_model)
|
|
318
355
|
|
|
319
356
|
|
|
320
357
|
def main(yaml_model_file: str) -> None:
|
|
@@ -322,7 +359,7 @@ def main(yaml_model_file: str) -> None:
|
|
|
322
359
|
LocalAutorestAPI,
|
|
323
360
|
)
|
|
324
361
|
|
|
325
|
-
code_generator =
|
|
362
|
+
code_generator = CodeGeneratorAutorest(
|
|
326
363
|
autorestapi=LocalAutorestAPI(reachable_files=[yaml_model_file])
|
|
327
364
|
)
|
|
328
365
|
if not code_generator.process():
|
|
@@ -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
|
+
import logging
|
|
6
7
|
from abc import abstractmethod
|
|
7
8
|
from typing import Any, Dict, List, Optional, TypeVar, Union, TYPE_CHECKING, Generic
|
|
8
9
|
from .base_model import BaseModel
|
|
@@ -27,6 +28,8 @@ if TYPE_CHECKING:
|
|
|
27
28
|
from .operation import Operation
|
|
28
29
|
from .request_builder import RequestBuilder
|
|
29
30
|
|
|
31
|
+
_LOGGER = logging.getLogger(__name__)
|
|
32
|
+
|
|
30
33
|
|
|
31
34
|
class BaseBuilder(Generic[ParameterListType], BaseModel):
|
|
32
35
|
"""Base class for Operations and Request Builders"""
|
|
@@ -39,7 +42,6 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
|
|
|
39
42
|
parameters: ParameterListType,
|
|
40
43
|
*,
|
|
41
44
|
overloads=None,
|
|
42
|
-
abstract: bool = False,
|
|
43
45
|
want_tracing: bool = True,
|
|
44
46
|
) -> None:
|
|
45
47
|
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
@@ -50,14 +52,23 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
|
|
|
50
52
|
overloads or []
|
|
51
53
|
)
|
|
52
54
|
self._summary: str = yaml_data.get("summary", "")
|
|
53
|
-
# for operations where we don't know what to do, we mark them as abstract so users implement
|
|
54
|
-
# in patch.py
|
|
55
|
-
self.abstract = abstract
|
|
56
55
|
self.want_tracing = want_tracing
|
|
57
56
|
self.group_name: str = yaml_data["groupName"]
|
|
58
57
|
self.is_overload: bool = yaml_data["isOverload"]
|
|
59
58
|
self.api_versions: List[str] = yaml_data["apiVersions"]
|
|
60
59
|
|
|
60
|
+
if code_model.options["version_tolerant"] and yaml_data.get("abstract"):
|
|
61
|
+
_LOGGER.warning(
|
|
62
|
+
'Not going to generate operation "%s" because we are unable to generate this '
|
|
63
|
+
"type of operation right now. "
|
|
64
|
+
'Please write your own custom operation in the "_patch.py" file '
|
|
65
|
+
"following https://aka.ms/azsdk/python/dpcodegen/python/customize",
|
|
66
|
+
name,
|
|
67
|
+
)
|
|
68
|
+
self.abstract = True
|
|
69
|
+
else:
|
|
70
|
+
self.abstract = False
|
|
71
|
+
|
|
61
72
|
@property
|
|
62
73
|
def summary(self) -> Optional[str]:
|
|
63
74
|
if self.abstract:
|
|
@@ -89,7 +100,7 @@ class BaseBuilder(Generic[ParameterListType], BaseModel):
|
|
|
89
100
|
)
|
|
90
101
|
return self._description or self.name
|
|
91
102
|
|
|
92
|
-
def method_signature(self,
|
|
103
|
+
def method_signature(self, async_mode: bool) -> List[str]:
|
|
93
104
|
if self.abstract:
|
|
94
105
|
return ["*args,", "**kwargs"]
|
|
95
|
-
return self.parameters.method_signature(
|
|
106
|
+
return self.parameters.method_signature(async_mode)
|
|
@@ -159,7 +159,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
159
159
|
# Also in this case, we're in version tolerant, so python3 only is true
|
|
160
160
|
file_import.add_submodule_import(
|
|
161
161
|
f"{path_to_models}models",
|
|
162
|
-
|
|
162
|
+
self.code_model.models_filename,
|
|
163
163
|
ImportType.LOCAL,
|
|
164
164
|
alias="models",
|
|
165
165
|
)
|
|
@@ -235,11 +235,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
235
235
|
@property
|
|
236
236
|
def need_mixin_abc(self) -> bool:
|
|
237
237
|
"""Do we want a mixin ABC class for typing purposes?"""
|
|
238
|
-
return any(
|
|
239
|
-
o
|
|
240
|
-
for o in self.operation_groups
|
|
241
|
-
if o.is_mixin and self.options["python3_only"]
|
|
242
|
-
)
|
|
238
|
+
return any(o for o in self.operation_groups if o.is_mixin)
|
|
243
239
|
|
|
244
240
|
@property
|
|
245
241
|
def has_lro_operations(self) -> bool:
|
|
@@ -252,20 +248,19 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
|
|
|
252
248
|
]
|
|
253
249
|
)
|
|
254
250
|
|
|
255
|
-
|
|
251
|
+
@property
|
|
252
|
+
def models_filename(self) -> str:
|
|
256
253
|
"""Get the names of the model file(s)"""
|
|
257
|
-
if
|
|
258
|
-
return "_models"
|
|
259
|
-
if is_python3_file:
|
|
254
|
+
if self.is_legacy:
|
|
260
255
|
return "_models_py3"
|
|
261
256
|
return "_models"
|
|
262
257
|
|
|
263
258
|
@property
|
|
264
259
|
def enums_filename(self) -> str:
|
|
265
260
|
"""The name of the enums file"""
|
|
266
|
-
if
|
|
267
|
-
return "_enums"
|
|
268
|
-
return
|
|
261
|
+
if self.is_legacy:
|
|
262
|
+
return f"_{self.module_name}_enums"
|
|
263
|
+
return "_enums"
|
|
269
264
|
|
|
270
265
|
@property
|
|
271
266
|
def is_legacy(self) -> bool:
|