@autorest/python 5.13.0 → 5.16.0
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 +67 -0
- package/autorest/__init__.py +1 -2
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +239 -105
- package/autorest/codegen/models/__init__.py +29 -18
- package/autorest/codegen/models/base_builder.py +48 -11
- package/autorest/codegen/models/base_model.py +6 -4
- package/autorest/codegen/models/base_schema.py +21 -24
- package/autorest/codegen/models/client.py +70 -20
- package/autorest/codegen/models/code_model.py +144 -129
- package/autorest/codegen/models/constant_schema.py +32 -16
- package/autorest/codegen/models/credential_model.py +55 -0
- package/autorest/codegen/models/credential_schema.py +21 -16
- package/autorest/codegen/models/credential_schema_policy.py +11 -15
- package/autorest/codegen/models/dictionary_schema.py +27 -24
- package/autorest/codegen/models/enum_schema.py +41 -62
- package/autorest/codegen/models/imports.py +72 -41
- package/autorest/codegen/models/list_schema.py +40 -18
- package/autorest/codegen/models/lro_operation.py +61 -25
- package/autorest/codegen/models/lro_paging_operation.py +5 -6
- package/autorest/codegen/models/object_schema.py +113 -59
- package/autorest/codegen/models/operation.py +251 -111
- package/autorest/codegen/models/operation_group.py +67 -32
- package/autorest/codegen/models/paging_operation.py +48 -21
- package/autorest/codegen/models/parameter.py +182 -90
- package/autorest/codegen/models/parameter_list.py +184 -163
- package/autorest/codegen/models/primitive_schemas.py +89 -70
- package/autorest/codegen/models/property.py +49 -31
- package/autorest/codegen/models/request_builder.py +67 -32
- package/autorest/codegen/models/request_builder_parameter.py +54 -23
- package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
- package/autorest/codegen/models/schema_request.py +16 -6
- package/autorest/codegen/models/schema_response.py +35 -17
- package/autorest/codegen/models/utils.py +24 -1
- package/autorest/codegen/serializers/__init__.py +273 -89
- package/autorest/codegen/serializers/builder_serializer.py +711 -333
- package/autorest/codegen/serializers/client_serializer.py +114 -43
- package/autorest/codegen/serializers/general_serializer.py +84 -25
- package/autorest/codegen/serializers/import_serializer.py +93 -31
- package/autorest/codegen/serializers/metadata_serializer.py +73 -24
- package/autorest/codegen/serializers/model_base_serializer.py +42 -14
- package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
- package/autorest/codegen/serializers/model_init_serializer.py +5 -1
- package/autorest/codegen/serializers/model_python3_serializer.py +9 -8
- package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/patch_serializer.py +14 -2
- package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
- package/autorest/codegen/serializers/utils.py +60 -21
- package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
- package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
- package/autorest/codegen/templates/README.md.jinja2 +105 -0
- package/autorest/codegen/templates/config.py.jinja2 +4 -4
- package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
- package/autorest/codegen/templates/enum.py.jinja2 +1 -1
- package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
- package/autorest/codegen/templates/init.py.jinja2 +9 -6
- package/autorest/codegen/templates/keywords.jinja2 +14 -1
- package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
- package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
- package/autorest/codegen/templates/model.py.jinja2 +1 -6
- package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
- package/autorest/codegen/templates/operation.py.jinja2 +8 -11
- package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
- package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/patch.py.jinja2 +18 -29
- package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
- package/autorest/codegen/templates/setup.py.jinja2 +79 -20
- package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +13 -6
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +35 -18
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +18 -23
- package/autorest/multiapi/serializers/import_serializer.py +47 -15
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/namer/__init__.py +2 -4
- package/autorest/namer/name_converter.py +200 -103
- package/autorest/namer/python_mappings.py +10 -22
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/rest.py +0 -42
package/ChangeLog.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
### 2022-04-18 - 5.16.0
|
|
4
|
+
|
|
5
|
+
| Library | Min Version |
|
|
6
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
7
|
+
| `@autorest/core` | `3.6.2` |
|
|
8
|
+
| `@autorest/modelerfour` | `4.19.1` |
|
|
9
|
+
| `azure-core` dep of generated code | `1.23.0` |
|
|
10
|
+
| `msrest` dep of generated code | `0.6.21` |
|
|
11
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
12
|
+
|
|
13
|
+
**Breaking Changes in Version Tolerant Generation**
|
|
14
|
+
|
|
15
|
+
- We no longer generate operations for operations with multipart or urlencoded bodies. SDK writers must implement these operations in their customized patch file. See https://aka.ms/azsdk/python/dpcodegen/python/customize for how to customize generated code #1223
|
|
16
|
+
|
|
17
|
+
**Bug Fixes**
|
|
18
|
+
|
|
19
|
+
- Drop package dependency on "@azure-tools/extension", switch to "@autorest/system-requirements" #1229
|
|
20
|
+
- Fix `content_type` generation in multiapi SDKs with multiple content types for bodies #1232
|
|
21
|
+
|
|
22
|
+
### 2022-04-07 - 5.15.0
|
|
23
|
+
|
|
24
|
+
| Library | Min Version |
|
|
25
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
26
|
+
| `@autorest/core` | `3.6.2` |
|
|
27
|
+
| `@autorest/modelerfour` | `4.19.1` |
|
|
28
|
+
| `azure-core` dep of generated code | `1.23.0` |
|
|
29
|
+
| `msrest` dep of generated code | `0.6.21` |
|
|
30
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
31
|
+
|
|
32
|
+
**New Features**
|
|
33
|
+
|
|
34
|
+
- Add support for security configurations in the swagger. For more information, see https://github.com/Azure/autorest/blob/main/docs/generate/authentication.md #1161
|
|
35
|
+
- Add support for handwritten customizations of generated code. For more information, see https://aka.ms/azsdk/python/dpcodegen/python/customize #1153
|
|
36
|
+
- Allow `header` and `params` as kwargs in operation and request-build function to hand over REST Header and Query parameters case insensitively #1183
|
|
37
|
+
- Typing operation parameters as JSON, Primitives or Any for `--version-tolerant` #1210
|
|
38
|
+
|
|
39
|
+
**Bug Fixes**
|
|
40
|
+
|
|
41
|
+
- Make `--version-tolerant` generated code mypy compatible in the `azure-sdk-for-python` repo. Tested only with the `--black` flag #1185
|
|
42
|
+
- Remove unnecessary vendored code in the `_vendor` file if the SDK has no operations #1196
|
|
43
|
+
- Fix the generation of the root `__init__` files for packages with only models #1195
|
|
44
|
+
- Add pylint and mypy support for `--version-tolerant` generations with `--models-mode=msrest` #1202
|
|
45
|
+
|
|
46
|
+
**Breaking Changes in Version Tolerant Generation**
|
|
47
|
+
|
|
48
|
+
- Change client filenames to `_client.py` #1206
|
|
49
|
+
- Change the models filename from `_models_py3.py` to `_models.py` #1204
|
|
50
|
+
- Change the enums filename to `_enums.py` #1204
|
|
51
|
+
|
|
52
|
+
### 2022-03-08 - 5.14.0
|
|
53
|
+
|
|
54
|
+
| Library | Min Version |
|
|
55
|
+
| ----------------------------------------------------------------------- | ----------- |
|
|
56
|
+
| `@autorest/core` | `3.6.2` |
|
|
57
|
+
| `@autorest/modelerfour` | `4.19.1` |
|
|
58
|
+
| `azure-core` dep of generated code | `1.20.1` |
|
|
59
|
+
| `msrest` dep of generated code | `0.6.21` |
|
|
60
|
+
| `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
|
|
61
|
+
|
|
62
|
+
**New Features**
|
|
63
|
+
|
|
64
|
+
- Add flag `--package-mode=mgmtplane|dataplane|<custom package template folder>` to generate necessary files for package #1154
|
|
65
|
+
|
|
66
|
+
**Bug Fixes**
|
|
67
|
+
|
|
68
|
+
- Improve operation group documentation to prevent users from initializing operation groups themselves #1179
|
|
69
|
+
|
|
3
70
|
### 2022-03-03 - 5.13.0
|
|
4
71
|
|
|
5
72
|
| Library | Min Version |
|
package/autorest/__init__.py
CHANGED
|
@@ -15,20 +15,25 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
15
15
|
_BLACK_MODE = black.Mode()
|
|
16
16
|
_BLACK_MODE.line_length = 120
|
|
17
17
|
|
|
18
|
-
class BlackScriptPlugin(Plugin):
|
|
19
18
|
|
|
19
|
+
class BlackScriptPlugin(Plugin):
|
|
20
20
|
def __init__(self, autorestapi):
|
|
21
|
-
super(
|
|
21
|
+
super().__init__(autorestapi)
|
|
22
22
|
output_folder_uri = self._autorestapi.get_value("outputFolderUri")
|
|
23
23
|
if output_folder_uri.startswith("file:"):
|
|
24
24
|
output_folder_uri = output_folder_uri[5:]
|
|
25
|
-
if os.name ==
|
|
25
|
+
if os.name == "nt" and output_folder_uri.startswith("///"):
|
|
26
26
|
output_folder_uri = output_folder_uri[3:]
|
|
27
27
|
self.output_folder = Path(output_folder_uri)
|
|
28
28
|
|
|
29
29
|
def process(self) -> bool:
|
|
30
30
|
# apply format_file on every file in the output folder
|
|
31
|
-
list(
|
|
31
|
+
list(
|
|
32
|
+
map(
|
|
33
|
+
self.format_file,
|
|
34
|
+
[f for f in self.output_folder.glob("**/*") if f.is_file()],
|
|
35
|
+
)
|
|
36
|
+
)
|
|
32
37
|
return True
|
|
33
38
|
|
|
34
39
|
def format_file(self, full_path) -> None:
|
|
@@ -38,7 +43,9 @@ class BlackScriptPlugin(Plugin):
|
|
|
38
43
|
self._autorestapi.write_file(file, file_content)
|
|
39
44
|
return
|
|
40
45
|
try:
|
|
41
|
-
file_content = black.format_file_contents(
|
|
46
|
+
file_content = black.format_file_contents(
|
|
47
|
+
file_content, fast=True, mode=_BLACK_MODE
|
|
48
|
+
)
|
|
42
49
|
except black.NothingChanged:
|
|
43
50
|
pass
|
|
44
51
|
self._autorestapi.write_file(file, file_content)
|
|
@@ -5,25 +5,37 @@
|
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
7
|
import sys
|
|
8
|
-
from typing import Dict, Any,
|
|
8
|
+
from typing import Dict, Any, Union, Type
|
|
9
|
+
from pathlib import Path
|
|
9
10
|
import yaml
|
|
10
11
|
|
|
11
12
|
from .. import Plugin
|
|
12
13
|
from .models.code_model import CodeModel
|
|
13
|
-
from .models import build_schema
|
|
14
|
+
from .models import build_schema, RequestBuilder
|
|
14
15
|
from .models.operation_group import OperationGroup
|
|
15
16
|
from .models.parameter import Parameter
|
|
16
17
|
from .models.parameter_list import GlobalParameterList
|
|
17
|
-
from .models.rest import Rest
|
|
18
18
|
from .serializers import JinjaSerializer
|
|
19
|
-
from .models.credential_schema_policy import
|
|
20
|
-
|
|
19
|
+
from .models.credential_schema_policy import (
|
|
20
|
+
CredentialSchemaPolicy,
|
|
21
|
+
get_credential_schema_policy_type,
|
|
22
|
+
)
|
|
23
|
+
from .models.credential_schema_policy import (
|
|
24
|
+
BearerTokenCredentialPolicy,
|
|
25
|
+
AzureKeyCredentialPolicy,
|
|
26
|
+
)
|
|
27
|
+
from .models.credential_model import CredentialModel
|
|
28
|
+
|
|
29
|
+
_AAD_TYPE = "AADToken"
|
|
30
|
+
_KEY_TYPE = "AzureKey"
|
|
31
|
+
|
|
21
32
|
|
|
22
33
|
def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
|
|
23
34
|
# Create operations
|
|
24
35
|
if code_model.options["show_operations"] and yaml_data.get("operationGroups"):
|
|
25
36
|
code_model.operation_groups = [
|
|
26
|
-
OperationGroup.from_yaml(
|
|
37
|
+
OperationGroup.from_yaml(op_group, code_model)
|
|
38
|
+
for op_group in yaml_data["operationGroups"]
|
|
27
39
|
]
|
|
28
40
|
if yaml_data.get("schemas"):
|
|
29
41
|
code_model.add_inheritance_to_models()
|
|
@@ -31,13 +43,13 @@ def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -
|
|
|
31
43
|
code_model.sort_schemas()
|
|
32
44
|
|
|
33
45
|
if code_model.options["show_operations"]:
|
|
34
|
-
code_model.add_schema_link_to_operation()
|
|
35
46
|
code_model.generate_single_parameter_from_multiple_content_types_operation()
|
|
36
47
|
code_model.link_operation_to_request_builder()
|
|
37
48
|
# LRO operation
|
|
38
49
|
code_model.format_lro_operations()
|
|
39
50
|
code_model.remove_next_operation()
|
|
40
51
|
|
|
52
|
+
|
|
41
53
|
def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
42
54
|
|
|
43
55
|
if options["builders_visibility"] not in ["public", "hidden", "embedded"]:
|
|
@@ -70,19 +82,40 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
|
|
|
70
82
|
if options["basic_setup_py"] and not options["package_version"]:
|
|
71
83
|
raise ValueError("--basic-setup-py must be used with --package-version")
|
|
72
84
|
|
|
85
|
+
if options["package_mode"] and not options["package_version"]:
|
|
86
|
+
raise ValueError("--package-mode must be used with --package-version")
|
|
87
|
+
|
|
73
88
|
if not options["show_operations"] and options["combine_operation_files"]:
|
|
74
89
|
raise ValueError(
|
|
75
90
|
"Can not combine operation files if you are not showing operations. "
|
|
76
91
|
"If you want operation files, pass in flag --show-operations"
|
|
77
92
|
)
|
|
78
93
|
|
|
94
|
+
if options["package_mode"]:
|
|
95
|
+
if (
|
|
96
|
+
options["package_mode"] not in ("mgmtplane", "dataplane")
|
|
97
|
+
and not Path(options["package_mode"]).exists()
|
|
98
|
+
):
|
|
99
|
+
raise ValueError(
|
|
100
|
+
"--package-mode can only be 'mgmtplane' or 'dataplane' or directory which contains template files"
|
|
101
|
+
)
|
|
102
|
+
|
|
79
103
|
if options["reformat_next_link"] and options["version_tolerant"]:
|
|
80
104
|
raise ValueError(
|
|
81
105
|
"--reformat-next-link can not be true for version tolerant generations. "
|
|
82
106
|
"Please remove --reformat-next-link from your call for version tolerant generations."
|
|
83
107
|
)
|
|
84
108
|
|
|
109
|
+
if options["multiapi"] and options["version_tolerant"]:
|
|
110
|
+
raise ValueError(
|
|
111
|
+
"Can not currently generate version tolerant multiapi SDKs. "
|
|
112
|
+
"We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
85
116
|
_LOGGER = logging.getLogger(__name__)
|
|
117
|
+
|
|
118
|
+
|
|
86
119
|
class CodeGenerator(Plugin):
|
|
87
120
|
@staticmethod
|
|
88
121
|
def remove_cloud_errors(yaml_data: Dict[str, Any]) -> None:
|
|
@@ -93,7 +126,11 @@ class CodeGenerator(Plugin):
|
|
|
93
126
|
i = 0
|
|
94
127
|
while i < len(operation["exceptions"]):
|
|
95
128
|
exception = operation["exceptions"][i]
|
|
96
|
-
if
|
|
129
|
+
if (
|
|
130
|
+
exception.get("schema")
|
|
131
|
+
and exception["schema"]["language"]["default"]["name"]
|
|
132
|
+
== "CloudError"
|
|
133
|
+
):
|
|
97
134
|
del operation["exceptions"][i]
|
|
98
135
|
i -= 1
|
|
99
136
|
i += 1
|
|
@@ -105,40 +142,66 @@ class CodeGenerator(Plugin):
|
|
|
105
142
|
break
|
|
106
143
|
|
|
107
144
|
@staticmethod
|
|
108
|
-
def
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
for exception in operation["exceptions"]:
|
|
115
|
-
if not exception.get("schema"):
|
|
116
|
-
continue
|
|
117
|
-
exceptions_set.add(id(exception["schema"]))
|
|
118
|
-
return exceptions_set
|
|
145
|
+
def _build_package_dependency() -> Dict[str, str]:
|
|
146
|
+
return {
|
|
147
|
+
"dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
|
|
148
|
+
"dependency_azure_core": "azure-core<2.0.0,>=1.23.0",
|
|
149
|
+
"dependency_msrest": "msrest>=0.6.21",
|
|
150
|
+
}
|
|
119
151
|
|
|
120
|
-
|
|
152
|
+
@staticmethod
|
|
153
|
+
def _build_with_security_definition(
|
|
154
|
+
yaml_data: Dict[str, Any], credential_model: CredentialModel
|
|
155
|
+
):
|
|
156
|
+
security_yaml = yaml_data.get("security", {})
|
|
157
|
+
if security_yaml.get("authenticationRequired"):
|
|
158
|
+
for scheme in security_yaml.get("schemes"):
|
|
159
|
+
if _AAD_TYPE == scheme["type"]:
|
|
160
|
+
credential_model.credential_scopes.update(scheme["scopes"])
|
|
161
|
+
elif _KEY_TYPE == scheme["type"]:
|
|
162
|
+
# only accept the last one
|
|
163
|
+
credential_model.key_header_name = scheme["headerName"]
|
|
164
|
+
|
|
165
|
+
if credential_model.credential_scopes:
|
|
166
|
+
credential_model.policy_type = BearerTokenCredentialPolicy
|
|
167
|
+
elif credential_model.key_header_name:
|
|
168
|
+
credential_model.policy_type = AzureKeyCredentialPolicy
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def _build_credential_model(
|
|
172
|
+
code_model: CodeModel, credential_model: CredentialModel
|
|
173
|
+
):
|
|
174
|
+
if credential_model.policy_type:
|
|
175
|
+
code_model.options["credential"] = True
|
|
176
|
+
credential_model.build_authentication_policy()
|
|
177
|
+
code_model.credential_model = credential_model
|
|
178
|
+
|
|
179
|
+
def _handle_credential_model(
|
|
180
|
+
self, yaml_data: Dict[str, Any], code_model: CodeModel
|
|
181
|
+
):
|
|
182
|
+
credential_model = CredentialModel(code_model.options["azure_arm"])
|
|
183
|
+
|
|
184
|
+
# credential info with security definition will be overridded by credential flags
|
|
185
|
+
self._build_with_security_definition(yaml_data, credential_model)
|
|
186
|
+
self._build_with_credential_flags(code_model, credential_model)
|
|
187
|
+
|
|
188
|
+
self._build_credential_model(code_model, credential_model)
|
|
189
|
+
|
|
190
|
+
def _create_code_model(
|
|
191
|
+
self, yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]
|
|
192
|
+
) -> CodeModel:
|
|
121
193
|
# Create a code model
|
|
122
194
|
|
|
123
|
-
code_model = CodeModel(options=options)
|
|
124
|
-
|
|
125
|
-
self._handle_default_authentication_policy(code_model)
|
|
195
|
+
code_model = CodeModel(yaml_data, options=options)
|
|
196
|
+
self._handle_credential_model(yaml_data, code_model)
|
|
126
197
|
code_model.module_name = yaml_data["info"]["python_title"]
|
|
127
198
|
code_model.class_name = yaml_data["info"]["pascal_case_title"]
|
|
128
199
|
code_model.description = (
|
|
129
|
-
yaml_data["info"]["description"]
|
|
200
|
+
yaml_data["info"]["description"]
|
|
201
|
+
if yaml_data["info"].get("description")
|
|
202
|
+
else ""
|
|
130
203
|
)
|
|
131
204
|
|
|
132
|
-
# Global parameters
|
|
133
|
-
code_model.global_parameters = GlobalParameterList(
|
|
134
|
-
code_model,
|
|
135
|
-
[Parameter.from_yaml(param, code_model=code_model) for param in yaml_data.get("globalParameters", [])],
|
|
136
|
-
)
|
|
137
|
-
code_model.global_parameters.code_model = code_model
|
|
138
|
-
|
|
139
|
-
# Custom URL
|
|
140
|
-
code_model.setup_client_input_parameters(yaml_data)
|
|
141
|
-
|
|
142
205
|
# Get my namespace
|
|
143
206
|
namespace = self._autorestapi.get_value("namespace")
|
|
144
207
|
_LOGGER.debug("Namespace parameter was %s", namespace)
|
|
@@ -146,44 +209,74 @@ class CodeGenerator(Plugin):
|
|
|
146
209
|
namespace = yaml_data["info"]["python_title"]
|
|
147
210
|
code_model.namespace = namespace
|
|
148
211
|
|
|
149
|
-
code_model.rest = Rest.from_yaml(yaml_data, code_model=code_model)
|
|
150
212
|
if yaml_data.get("schemas"):
|
|
151
|
-
exceptions_set = CodeGenerator._build_exceptions_set(yaml_data=yaml_data["operationGroups"])
|
|
152
|
-
|
|
153
213
|
for type_list in yaml_data["schemas"].values():
|
|
154
214
|
for schema in type_list:
|
|
155
|
-
build_schema(yaml_data=schema,
|
|
156
|
-
|
|
157
|
-
|
|
215
|
+
build_schema(yaml_data=schema, code_model=code_model)
|
|
216
|
+
|
|
217
|
+
# Global parameters
|
|
218
|
+
code_model.global_parameters = GlobalParameterList(
|
|
219
|
+
code_model,
|
|
220
|
+
[
|
|
221
|
+
Parameter.from_yaml(param, code_model=code_model)
|
|
222
|
+
for param in yaml_data.get("globalParameters", [])
|
|
223
|
+
],
|
|
224
|
+
)
|
|
158
225
|
|
|
226
|
+
# Custom URL
|
|
227
|
+
code_model.setup_client_input_parameters(yaml_data)
|
|
228
|
+
|
|
229
|
+
# Build request builders
|
|
230
|
+
if yaml_data.get("operationGroups"):
|
|
231
|
+
code_model.request_builders = [
|
|
232
|
+
RequestBuilder.from_yaml(operation_yaml, code_model=code_model)
|
|
233
|
+
for og_group in yaml_data["operationGroups"]
|
|
234
|
+
for operation_yaml in og_group["operations"]
|
|
235
|
+
]
|
|
159
236
|
_build_convenience_layer(yaml_data=yaml_data, code_model=code_model)
|
|
160
237
|
|
|
161
238
|
if options["credential"]:
|
|
162
239
|
code_model.global_parameters.add_credential_global_parameter()
|
|
163
240
|
|
|
241
|
+
code_model.package_dependency = self._build_package_dependency()
|
|
164
242
|
return code_model
|
|
165
243
|
|
|
166
244
|
def _get_credential_scopes(self, credential):
|
|
167
245
|
credential_scopes_temp = self._autorestapi.get_value("credential-scopes")
|
|
168
|
-
credential_scopes =
|
|
246
|
+
credential_scopes = (
|
|
247
|
+
credential_scopes_temp.split(",") if credential_scopes_temp else None
|
|
248
|
+
)
|
|
169
249
|
if credential_scopes and not credential:
|
|
170
|
-
raise ValueError(
|
|
250
|
+
raise ValueError(
|
|
251
|
+
"--credential-scopes must be used with the --add-credential flag"
|
|
252
|
+
)
|
|
171
253
|
|
|
172
254
|
# check to see if user just passes in --credential-scopes with no value
|
|
173
|
-
if
|
|
255
|
+
if (
|
|
256
|
+
self._autorestapi.get_boolean_value("credential-scopes", False)
|
|
257
|
+
and not credential_scopes
|
|
258
|
+
):
|
|
174
259
|
raise ValueError(
|
|
175
260
|
"--credential-scopes takes a list of scopes in comma separated format. "
|
|
176
261
|
"For example: --credential-scopes=https://cognitiveservices.azure.com/.default"
|
|
177
262
|
)
|
|
178
263
|
return credential_scopes
|
|
179
264
|
|
|
180
|
-
def
|
|
181
|
-
self,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
265
|
+
def _update_with_credential_flags(
|
|
266
|
+
self,
|
|
267
|
+
code_model: CodeModel,
|
|
268
|
+
credential_schema_policy: Type[CredentialSchemaPolicy],
|
|
269
|
+
credential_model: CredentialModel,
|
|
270
|
+
):
|
|
271
|
+
credential_model.policy_type = credential_schema_policy
|
|
272
|
+
credential_scopes = self._get_credential_scopes(
|
|
273
|
+
code_model.options["credential"]
|
|
274
|
+
)
|
|
275
|
+
credential_key_header_name = self._autorestapi.get_value(
|
|
276
|
+
"credential-key-header-name"
|
|
277
|
+
)
|
|
278
|
+
azure_arm = code_model.options["azure_arm"]
|
|
279
|
+
credential = code_model.options["credential"]
|
|
187
280
|
|
|
188
281
|
if hasattr(credential_schema_policy, "credential_scopes"):
|
|
189
282
|
if not credential_scopes:
|
|
@@ -197,7 +290,7 @@ class CodeGenerator(Plugin):
|
|
|
197
290
|
"but not the --credential-scopes flag set while generating non-management plane code. "
|
|
198
291
|
"This is not recommend because it forces the customer to pass credential scopes "
|
|
199
292
|
"through kwargs if they want to authenticate.",
|
|
200
|
-
credential_schema_policy.name()
|
|
293
|
+
credential_schema_policy.name(),
|
|
201
294
|
)
|
|
202
295
|
credential_scopes = []
|
|
203
296
|
|
|
@@ -208,101 +301,138 @@ class CodeGenerator(Plugin):
|
|
|
208
301
|
"name is tied with AzureKeyCredentialPolicy. Instead, with this policy it is recommend you "
|
|
209
302
|
"pass in --credential-scopes."
|
|
210
303
|
)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
304
|
+
credential_model.credential_scopes = set(credential_scopes)
|
|
305
|
+
else:
|
|
306
|
+
# currently the only other credential policy is AzureKeyCredentialPolicy
|
|
307
|
+
if credential_scopes:
|
|
308
|
+
raise ValueError(
|
|
309
|
+
"You have passed in credential scopes with default credential policy type "
|
|
310
|
+
"AzureKeyCredentialPolicy. This is not allowed, since credential scopes is tied with "
|
|
311
|
+
f"{credential_model.default_authentication_policy.name()}. Instead, with this policy "
|
|
312
|
+
"you must pass in --credential-key-header-name."
|
|
313
|
+
)
|
|
314
|
+
if not credential_key_header_name:
|
|
315
|
+
credential_key_header_name = "api-key"
|
|
316
|
+
_LOGGER.info(
|
|
317
|
+
"Defaulting the AzureKeyCredentialPolicy header's name to 'api-key'"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
credential_model.key_header_name = credential_key_header_name
|
|
321
|
+
|
|
322
|
+
def _build_with_credential_flags(
|
|
323
|
+
self, code_model: CodeModel, credential_model: CredentialModel
|
|
324
|
+
):
|
|
325
|
+
if not code_model.options["credential"]:
|
|
326
|
+
return
|
|
232
327
|
|
|
233
|
-
def _handle_default_authentication_policy(self, code_model: CodeModel):
|
|
234
328
|
credential_schema_policy_name = (
|
|
235
|
-
self._autorestapi.get_value("credential-default-policy-type")
|
|
236
|
-
|
|
329
|
+
self._autorestapi.get_value("credential-default-policy-type")
|
|
330
|
+
or credential_model.default_authentication_policy.name()
|
|
331
|
+
)
|
|
332
|
+
credential_schema_policy_type = get_credential_schema_policy_type(
|
|
333
|
+
credential_schema_policy_name
|
|
237
334
|
)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
code_model, credential_schema_policy_type
|
|
335
|
+
self._update_with_credential_flags(
|
|
336
|
+
code_model, credential_schema_policy_type, credential_model
|
|
241
337
|
)
|
|
242
|
-
code_model.credential_schema_policy = credential_schema_policy
|
|
243
338
|
|
|
244
339
|
def _build_code_model_options(self) -> Dict[str, Any]:
|
|
245
|
-
"""Build en options dict from the user input while running autorest.
|
|
246
|
-
"""
|
|
340
|
+
"""Build en options dict from the user input while running autorest."""
|
|
247
341
|
azure_arm = self._autorestapi.get_boolean_value("azure-arm", False)
|
|
248
|
-
credential = (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
)
|
|
342
|
+
credential = self._autorestapi.get_boolean_value(
|
|
343
|
+
"add-credentials", False
|
|
344
|
+
) or self._autorestapi.get_boolean_value("add-credential", False)
|
|
252
345
|
|
|
253
346
|
license_header = self._autorestapi.get_value("header-text")
|
|
254
347
|
if license_header:
|
|
255
348
|
license_header = license_header.replace("\n", "\n# ")
|
|
256
349
|
license_header = (
|
|
257
|
-
"# --------------------------------------------------------------------------\n# "
|
|
350
|
+
"# --------------------------------------------------------------------------\n# "
|
|
351
|
+
+ license_header
|
|
258
352
|
)
|
|
259
353
|
license_header += "\n# --------------------------------------------------------------------------"
|
|
260
354
|
|
|
261
|
-
low_level_client = self._autorestapi.get_boolean_value(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
355
|
+
low_level_client = self._autorestapi.get_boolean_value(
|
|
356
|
+
"low-level-client", False
|
|
357
|
+
)
|
|
358
|
+
version_tolerant = self._autorestapi.get_boolean_value(
|
|
359
|
+
"version-tolerant", False
|
|
360
|
+
)
|
|
361
|
+
show_operations = self._autorestapi.get_boolean_value(
|
|
362
|
+
"show-operations", not low_level_client
|
|
363
|
+
)
|
|
364
|
+
models_mode_default = (
|
|
365
|
+
"none" if low_level_client or version_tolerant else "msrest"
|
|
366
|
+
)
|
|
367
|
+
python3_only = self._autorestapi.get_boolean_value(
|
|
368
|
+
"python3-only", low_level_client or version_tolerant
|
|
369
|
+
)
|
|
266
370
|
|
|
267
371
|
options: Dict[str, Any] = {
|
|
268
372
|
"azure_arm": azure_arm,
|
|
269
373
|
"credential": credential,
|
|
270
|
-
"head_as_boolean": self._autorestapi.get_boolean_value(
|
|
374
|
+
"head_as_boolean": self._autorestapi.get_boolean_value(
|
|
375
|
+
"head-as-boolean", False
|
|
376
|
+
),
|
|
271
377
|
"license_header": license_header,
|
|
272
|
-
"keep_version_file": self._autorestapi.get_boolean_value(
|
|
378
|
+
"keep_version_file": self._autorestapi.get_boolean_value(
|
|
379
|
+
"keep-version-file", False
|
|
380
|
+
),
|
|
273
381
|
"no_async": self._autorestapi.get_boolean_value("no-async", False),
|
|
274
|
-
"no_namespace_folders": self._autorestapi.get_boolean_value(
|
|
275
|
-
|
|
382
|
+
"no_namespace_folders": self._autorestapi.get_boolean_value(
|
|
383
|
+
"no-namespace-folders", False
|
|
384
|
+
),
|
|
385
|
+
"basic_setup_py": self._autorestapi.get_boolean_value(
|
|
386
|
+
"basic-setup-py", False
|
|
387
|
+
),
|
|
276
388
|
"package_name": self._autorestapi.get_value("package-name"),
|
|
277
389
|
"package_version": self._autorestapi.get_value("package-version"),
|
|
278
|
-
"client_side_validation": self._autorestapi.get_boolean_value(
|
|
390
|
+
"client_side_validation": self._autorestapi.get_boolean_value(
|
|
391
|
+
"client-side-validation", False
|
|
392
|
+
),
|
|
279
393
|
"tracing": self._autorestapi.get_boolean_value("trace", show_operations),
|
|
280
394
|
"multiapi": self._autorestapi.get_boolean_value("multiapi", False),
|
|
281
|
-
"polymorphic_examples": self._autorestapi.get_value("polymorphic-examples")
|
|
282
|
-
|
|
395
|
+
"polymorphic_examples": self._autorestapi.get_value("polymorphic-examples")
|
|
396
|
+
or 5,
|
|
397
|
+
"models_mode": (
|
|
398
|
+
self._autorestapi.get_value("models-mode") or models_mode_default
|
|
399
|
+
).lower(),
|
|
283
400
|
"builders_visibility": self._autorestapi.get_value("builders-visibility"),
|
|
284
401
|
"show_operations": show_operations,
|
|
285
402
|
"show_send_request": self._autorestapi.get_boolean_value(
|
|
286
403
|
"show-send-request", low_level_client or version_tolerant
|
|
287
404
|
),
|
|
288
405
|
"only_path_and_body_params_positional": self._autorestapi.get_boolean_value(
|
|
289
|
-
"only-path-and-body-params-positional",
|
|
406
|
+
"only-path-and-body-params-positional",
|
|
407
|
+
low_level_client or version_tolerant,
|
|
290
408
|
),
|
|
291
409
|
"add_python3_operation_files": self._autorestapi.get_boolean_value(
|
|
292
410
|
"add-python3-operation-files", python3_only and not low_level_client
|
|
293
411
|
),
|
|
294
412
|
"version_tolerant": version_tolerant,
|
|
295
413
|
"low_level_client": low_level_client,
|
|
296
|
-
"combine_operation_files": self._autorestapi.get_boolean_value(
|
|
414
|
+
"combine_operation_files": self._autorestapi.get_boolean_value(
|
|
415
|
+
"combine-operation-files", version_tolerant
|
|
416
|
+
),
|
|
297
417
|
"python3_only": python3_only,
|
|
418
|
+
"package_mode": self._autorestapi.get_value("package-mode"),
|
|
419
|
+
"package_pprint_name": self._autorestapi.get_value("package-pprint-name"),
|
|
420
|
+
"package_configuration": self._autorestapi.get_value(
|
|
421
|
+
"package-configuration"
|
|
422
|
+
),
|
|
298
423
|
"default_optional_constants_to_none": self._autorestapi.get_boolean_value(
|
|
299
|
-
"default-optional-constants-to-none",
|
|
424
|
+
"default-optional-constants-to-none",
|
|
425
|
+
low_level_client or version_tolerant,
|
|
426
|
+
),
|
|
427
|
+
"reformat_next_link": self._autorestapi.get_boolean_value(
|
|
428
|
+
"reformat-next-link", not version_tolerant
|
|
300
429
|
),
|
|
301
|
-
"reformat_next_link": self._autorestapi.get_boolean_value("reformat-next-link", not version_tolerant)
|
|
302
430
|
}
|
|
303
431
|
|
|
304
432
|
if options["builders_visibility"] is None:
|
|
305
|
-
options["builders_visibility"] =
|
|
433
|
+
options["builders_visibility"] = (
|
|
434
|
+
"public" if low_level_client else "embedded"
|
|
435
|
+
)
|
|
306
436
|
else:
|
|
307
437
|
options["builders_visibility"] = options["builders_visibility"].lower()
|
|
308
438
|
|
|
@@ -344,9 +474,13 @@ class CodeGenerator(Plugin):
|
|
|
344
474
|
|
|
345
475
|
|
|
346
476
|
def main(yaml_model_file: str) -> None:
|
|
347
|
-
from ..jsonrpc.localapi import
|
|
477
|
+
from ..jsonrpc.localapi import ( # pylint: disable=import-outside-toplevel
|
|
478
|
+
LocalAutorestAPI,
|
|
479
|
+
)
|
|
348
480
|
|
|
349
|
-
code_generator = CodeGenerator(
|
|
481
|
+
code_generator = CodeGenerator(
|
|
482
|
+
autorestapi=LocalAutorestAPI(reachable_files=[yaml_model_file])
|
|
483
|
+
)
|
|
350
484
|
if not code_generator.process():
|
|
351
485
|
raise SystemExit("Process didn't finish gracefully")
|
|
352
486
|
|