@typespec/http-client-python 0.13.0-dev.2 → 0.13.0-dev.3
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/eng/scripts/setup/__pycache__/package_manager.cpython-39.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
- package/generator/build/lib/pygen/__init__.py +176 -2
- package/generator/build/lib/pygen/black.py +1 -1
- package/generator/build/lib/pygen/codegen/__init__.py +4 -256
- package/generator/build/lib/pygen/codegen/_utils.py +0 -3
- package/generator/build/lib/pygen/codegen/models/__init__.py +1 -1
- package/generator/build/lib/pygen/codegen/models/base_builder.py +1 -1
- package/generator/build/lib/pygen/codegen/models/client.py +12 -12
- package/generator/build/lib/pygen/codegen/models/code_model.py +10 -9
- package/generator/build/lib/pygen/codegen/models/enum_type.py +4 -4
- package/generator/build/lib/pygen/codegen/models/imports.py +1 -1
- package/generator/build/lib/pygen/codegen/models/list_type.py +6 -6
- package/generator/build/lib/pygen/codegen/models/lro_operation.py +1 -1
- package/generator/build/lib/pygen/codegen/models/operation.py +16 -16
- package/generator/build/lib/pygen/codegen/models/operation_group.py +4 -4
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +4 -4
- package/generator/build/lib/pygen/codegen/models/parameter.py +8 -8
- package/generator/build/lib/pygen/codegen/models/property.py +1 -1
- package/generator/build/lib/pygen/codegen/models/request_builder.py +2 -2
- package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +2 -2
- package/generator/build/lib/pygen/codegen/models/response.py +3 -3
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +27 -28
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +31 -31
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +4 -4
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +4 -4
- package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +5 -5
- package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +2 -2
- package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +2 -2
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +38 -7
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +9 -9
- package/generator/build/lib/pygen/codegen/templates/request_builder.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +6 -6
- package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +1 -1
- package/generator/build/lib/pygen/preprocess/__init__.py +1 -1
- package/generator/build/lib/pygen/utils.py +4 -0
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +176 -2
- package/generator/pygen/black.py +1 -1
- package/generator/pygen/codegen/__init__.py +4 -256
- package/generator/pygen/codegen/_utils.py +0 -3
- package/generator/pygen/codegen/models/__init__.py +1 -1
- package/generator/pygen/codegen/models/base_builder.py +1 -1
- package/generator/pygen/codegen/models/client.py +12 -12
- package/generator/pygen/codegen/models/code_model.py +10 -9
- package/generator/pygen/codegen/models/enum_type.py +4 -4
- package/generator/pygen/codegen/models/imports.py +1 -1
- package/generator/pygen/codegen/models/list_type.py +6 -6
- package/generator/pygen/codegen/models/lro_operation.py +1 -1
- package/generator/pygen/codegen/models/operation.py +16 -16
- package/generator/pygen/codegen/models/operation_group.py +4 -4
- package/generator/pygen/codegen/models/paging_operation.py +4 -4
- package/generator/pygen/codegen/models/parameter.py +8 -8
- package/generator/pygen/codegen/models/property.py +1 -1
- package/generator/pygen/codegen/models/request_builder.py +2 -2
- package/generator/pygen/codegen/models/request_builder_parameter.py +2 -2
- package/generator/pygen/codegen/models/response.py +3 -3
- package/generator/pygen/codegen/serializers/__init__.py +27 -28
- package/generator/pygen/codegen/serializers/builder_serializer.py +31 -31
- package/generator/pygen/codegen/serializers/client_serializer.py +4 -4
- package/generator/pygen/codegen/serializers/general_serializer.py +4 -4
- package/generator/pygen/codegen/serializers/metadata_serializer.py +1 -1
- package/generator/pygen/codegen/serializers/model_serializer.py +1 -1
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +1 -1
- package/generator/pygen/codegen/serializers/sample_serializer.py +1 -1
- package/generator/pygen/codegen/serializers/test_serializer.py +5 -5
- package/generator/pygen/codegen/templates/config.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/config_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/conftest.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/init.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/metadata.json.jinja2 +2 -2
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +2 -2
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/operation_tools.jinja2 +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +38 -7
- package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +9 -9
- package/generator/pygen/codegen/templates/request_builder.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/sample.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/test.py.jinja2 +6 -6
- package/generator/pygen/codegen/templates/version.py.jinja2 +1 -1
- package/generator/pygen/preprocess/__init__.py +1 -1
- package/generator/pygen/utils.py +4 -0
- package/generator/test/unittests/test_optional_return_type.py +5 -5
- package/generator/test/unittests/test_parameter_ordering.py +5 -5
- package/generator/test/unittests/test_sort_schema.py +4 -4
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
from collections.abc import ItemsView, KeysView, MutableMapping, ValuesView
|
|
6
7
|
import logging
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
import json
|
|
9
10
|
from abc import ABC, abstractmethod
|
|
10
|
-
from typing import Any, Dict, Union, List
|
|
11
|
+
from typing import Any, Dict, Iterator, Optional, Union, List
|
|
11
12
|
|
|
12
13
|
import yaml
|
|
14
|
+
from .utils import TYPESPEC_PACKAGE_MODE, VALID_PACKAGE_MODE
|
|
13
15
|
|
|
14
16
|
from ._version import VERSION
|
|
15
17
|
|
|
@@ -18,6 +20,177 @@ __version__ = VERSION
|
|
|
18
20
|
_LOGGER = logging.getLogger(__name__)
|
|
19
21
|
|
|
20
22
|
|
|
23
|
+
class OptionsDict(MutableMapping):
|
|
24
|
+
DEFAULTS = {
|
|
25
|
+
"azure-arm": False,
|
|
26
|
+
"basic-setup-py": False,
|
|
27
|
+
"client-side-validation": False,
|
|
28
|
+
"emit-cross-language-definition-file": False,
|
|
29
|
+
"flavor": "azure", # need to default to azure in shared code so we don't break swagger generation
|
|
30
|
+
"from-typespec": False,
|
|
31
|
+
"generate-sample": False,
|
|
32
|
+
"generate-test": False,
|
|
33
|
+
"head-as-boolean": True,
|
|
34
|
+
"keep-version-file": False,
|
|
35
|
+
"low-level-client": False,
|
|
36
|
+
"multiapi": False,
|
|
37
|
+
"no-async": False,
|
|
38
|
+
"no-namespace-folders": False,
|
|
39
|
+
"polymorphic-examples": 5,
|
|
40
|
+
"validate-versioning": True,
|
|
41
|
+
"version-tolerant": True,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
|
|
45
|
+
self._data = options.copy() if options else {}
|
|
46
|
+
self._validate_combinations()
|
|
47
|
+
|
|
48
|
+
def __getitem__(self, key: str) -> Any:
|
|
49
|
+
if key == "head-as-boolean" and self.get("azure-arm"):
|
|
50
|
+
# override to always true if azure-arm is set
|
|
51
|
+
return True
|
|
52
|
+
if key in self._data:
|
|
53
|
+
retval = self._data[key]
|
|
54
|
+
if key == "package-files-config":
|
|
55
|
+
try:
|
|
56
|
+
return {k.strip(): v.strip() for k, v in [i.split(":") for i in retval.split("|")]}
|
|
57
|
+
except AttributeError:
|
|
58
|
+
return retval
|
|
59
|
+
return retval
|
|
60
|
+
if key == "package-mode" and self._data.get("packaging-files-dir"):
|
|
61
|
+
# if packaging-files-dir is set, use it as package-mode
|
|
62
|
+
return self._data["packaging-files-dir"]
|
|
63
|
+
return self._get_default(key)
|
|
64
|
+
|
|
65
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
66
|
+
validated_value = self._validate_and_transform(key, value)
|
|
67
|
+
self._data[key] = validated_value
|
|
68
|
+
|
|
69
|
+
def __delitem__(self, key: str) -> None:
|
|
70
|
+
if key in self._data:
|
|
71
|
+
del self._data[key]
|
|
72
|
+
else:
|
|
73
|
+
raise KeyError(f"Option '{key}' not found")
|
|
74
|
+
|
|
75
|
+
def __iter__(self) -> Iterator[str]:
|
|
76
|
+
# Return both explicitly set keys and all possible default keys
|
|
77
|
+
return iter(set(self.keys()))
|
|
78
|
+
|
|
79
|
+
def __len__(self) -> int:
|
|
80
|
+
return len(set(self._data.keys()).union(self.DEFAULTS.keys()))
|
|
81
|
+
|
|
82
|
+
def __contains__(self, key: str) -> bool: # type: ignore
|
|
83
|
+
return key in self._data or key in self.DEFAULTS
|
|
84
|
+
|
|
85
|
+
def __repr__(self) -> str:
|
|
86
|
+
"""String representation."""
|
|
87
|
+
return f"OptionsDict({dict(self.items())})"
|
|
88
|
+
|
|
89
|
+
def _get_default(self, key: str) -> Any: # pylint: disable=too-many-return-statements
|
|
90
|
+
if key == "show-operations":
|
|
91
|
+
return not self.get("low-level-client")
|
|
92
|
+
if key == "tracing":
|
|
93
|
+
return self.get("show-operations") and self.get("flavor") == "azure"
|
|
94
|
+
if key in ["show-send-request", "only-path-and-body-params-positional", "default-optional-constants-to-none"]:
|
|
95
|
+
return self.get("low-level-client") or self.get("version-tolerant")
|
|
96
|
+
if key == "combine-operation-files":
|
|
97
|
+
return self.get("version-tolerant")
|
|
98
|
+
if key == "package-pprint-name":
|
|
99
|
+
return " ".join([i.capitalize() for i in str(self.get("package-name", "")).split("-")])
|
|
100
|
+
if key == "builders-visibility":
|
|
101
|
+
# Default to public if low-level client is not set, otherwise embedded
|
|
102
|
+
return "embedded" if not self.get("low-level-client") else "public"
|
|
103
|
+
if key == "models-mode":
|
|
104
|
+
models_mode_default = False if self.get("low-level-client") or self.get("version-tolerant") else "msrest"
|
|
105
|
+
if self.get("tsp_file") is not None:
|
|
106
|
+
models_mode_default = "dpg"
|
|
107
|
+
# switch to falsy value for easier code writing
|
|
108
|
+
return models_mode_default
|
|
109
|
+
return self.DEFAULTS[key]
|
|
110
|
+
|
|
111
|
+
def _validate_combinations(self) -> None:
|
|
112
|
+
if not self.get("show-operations") and self.get("builders-visibility") == "embedded":
|
|
113
|
+
raise ValueError(
|
|
114
|
+
"Can not embed builders without operations. "
|
|
115
|
+
"Either set --show-operations to True, or change the value of --builders-visibility "
|
|
116
|
+
"to 'public' or 'hidden'."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
if self.get("basic-setup-py") and not self.get("package-version"):
|
|
120
|
+
raise ValueError("--basic-setup-py must be used with --package-version")
|
|
121
|
+
|
|
122
|
+
if self.get("package-mode") and not self.get("package-version"):
|
|
123
|
+
raise ValueError("--package-mode must be used with --package-version")
|
|
124
|
+
|
|
125
|
+
if not self.get("show-operations") and self.get("combine-operation-files"):
|
|
126
|
+
raise ValueError(
|
|
127
|
+
"Can not combine operation files if you are not showing operations. "
|
|
128
|
+
"If you want operation files, pass in flag --show-operations"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if self.get("multiapi") and self.get("version-tolerant"):
|
|
132
|
+
raise ValueError(
|
|
133
|
+
"Can not currently generate version tolerant multiapi SDKs. "
|
|
134
|
+
"We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if self.get("client-side-validation") and self.get("version-tolerant"):
|
|
138
|
+
raise ValueError("Can not generate version tolerant with --client-side-validation. ")
|
|
139
|
+
|
|
140
|
+
if not (self.get("azure-arm") or self.get("version-tolerant")):
|
|
141
|
+
_LOGGER.warning(
|
|
142
|
+
"You are generating with options that would not allow the SDK to be shipped as an official Azure SDK. "
|
|
143
|
+
"Please read https://aka.ms/azsdk/dpcodegen for more details."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if self.get("flavor") != "azure" and self.get("tracing"):
|
|
147
|
+
raise ValueError("Can only have tracing turned on for Azure SDKs.")
|
|
148
|
+
|
|
149
|
+
def _validate_and_transform(self, key: str, value: Any) -> Any:
|
|
150
|
+
if key == "builders-visibility" and value not in ["public", "hidden", "embedded"]:
|
|
151
|
+
raise ValueError("The value of --builders-visibility must be either 'public', 'hidden', or 'embedded'")
|
|
152
|
+
|
|
153
|
+
if key == "models-mode" and value == "none":
|
|
154
|
+
value = False # switch to falsy value for easier code writing
|
|
155
|
+
|
|
156
|
+
if key == "models-mode" and value not in ["msrest", "dpg", False]:
|
|
157
|
+
raise ValueError(
|
|
158
|
+
"--models-mode can only be 'msrest', 'dpg' or 'none'. "
|
|
159
|
+
"Pass in 'msrest' if you want msrest models, or "
|
|
160
|
+
"'none' if you don't want any."
|
|
161
|
+
)
|
|
162
|
+
if key == "package-mode":
|
|
163
|
+
if (
|
|
164
|
+
(value not in TYPESPEC_PACKAGE_MODE and self.get("from-typespec"))
|
|
165
|
+
or (value not in VALID_PACKAGE_MODE and not self.get("from-typespec"))
|
|
166
|
+
) and not Path(value).exists():
|
|
167
|
+
raise ValueError(
|
|
168
|
+
f"--package-mode can only be {' or '.join(TYPESPEC_PACKAGE_MODE)} or directory which contains template files" # pylint: disable=line-too-long
|
|
169
|
+
)
|
|
170
|
+
return value
|
|
171
|
+
|
|
172
|
+
def setdefault(self, key: str, default: Any, /) -> Any: # type: ignore # pylint: disable=arguments-differ
|
|
173
|
+
"""Set a default value for a key if it does not exist."""
|
|
174
|
+
if key not in self._data:
|
|
175
|
+
self[key] = default
|
|
176
|
+
return self[key]
|
|
177
|
+
|
|
178
|
+
def keys(self) -> KeysView[str]:
|
|
179
|
+
"""Return all keys, including defaults."""
|
|
180
|
+
all_keys = set(self._data.keys())
|
|
181
|
+
for key in self.DEFAULTS:
|
|
182
|
+
if key not in all_keys:
|
|
183
|
+
all_keys.add(key)
|
|
184
|
+
all_keys.update(self.DEFAULTS.keys())
|
|
185
|
+
return KeysView({key: None for key in all_keys})
|
|
186
|
+
|
|
187
|
+
def values(self) -> ValuesView[Any]:
|
|
188
|
+
return {key: self[key] for key in self.keys()}.values() # pylint: disable=consider-using-dict-items
|
|
189
|
+
|
|
190
|
+
def items(self) -> ItemsView[str, Any]:
|
|
191
|
+
return {key: self[key] for key in self.keys()}.items() # pylint: disable=consider-using-dict-items
|
|
192
|
+
|
|
193
|
+
|
|
21
194
|
class ReaderAndWriter:
|
|
22
195
|
def __init__(self, *, output_folder: Union[str, Path], **kwargs: Any) -> None:
|
|
23
196
|
self.output_folder = Path(output_folder)
|
|
@@ -31,7 +204,8 @@ class ReaderAndWriter:
|
|
|
31
204
|
python_json = json.load(fd)
|
|
32
205
|
except Exception: # pylint: disable=broad-except
|
|
33
206
|
python_json = {}
|
|
34
|
-
|
|
207
|
+
kwargs["output-folder"] = str(self.output_folder)
|
|
208
|
+
self.options = OptionsDict(kwargs)
|
|
35
209
|
if python_json:
|
|
36
210
|
_LOGGER.warning("Loading python.json file. This behavior will be depreacted")
|
|
37
211
|
self.options.update(python_json)
|
|
@@ -21,7 +21,7 @@ _BLACK_MODE.line_length = 120
|
|
|
21
21
|
class BlackScriptPlugin(Plugin):
|
|
22
22
|
def __init__(self, **kwargs):
|
|
23
23
|
super().__init__(**kwargs)
|
|
24
|
-
output_folder = self.options.get("
|
|
24
|
+
output_folder = self.options.get("output-folder", str(self.output_folder))
|
|
25
25
|
if output_folder.startswith("file:"):
|
|
26
26
|
output_folder = output_folder[5:]
|
|
27
27
|
if os.name == "nt" and output_folder.startswith("///"):
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import logging
|
|
7
|
-
from typing import Dict, Any
|
|
8
|
-
from pathlib import Path
|
|
7
|
+
from typing import Dict, Any
|
|
9
8
|
import yaml
|
|
10
9
|
|
|
11
10
|
|
|
@@ -13,223 +12,12 @@ from .. import Plugin
|
|
|
13
12
|
from ..utils import parse_args
|
|
14
13
|
from .models.code_model import CodeModel
|
|
15
14
|
from .serializers import JinjaSerializer
|
|
16
|
-
from ._utils import VALID_PACKAGE_MODE, TYPESPEC_PACKAGE_MODE
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def _default_pprint(package_name: str) -> str:
|
|
20
|
-
return " ".join([i.capitalize() for i in package_name.split("-")])
|
|
21
15
|
|
|
22
16
|
|
|
23
17
|
_LOGGER = logging.getLogger(__name__)
|
|
24
18
|
|
|
25
19
|
|
|
26
|
-
class OptionsRetriever:
|
|
27
|
-
OPTIONS_TO_DEFAULT = {
|
|
28
|
-
"azure-arm": False,
|
|
29
|
-
"flavor": "azure", # need to default to azure in shared code so we don't break swagger generation
|
|
30
|
-
"no-async": False,
|
|
31
|
-
"low-level-client": False,
|
|
32
|
-
"version-tolerant": True,
|
|
33
|
-
"keep-version-file": False,
|
|
34
|
-
"no-namespace-folders": False,
|
|
35
|
-
"basic-setup-py": False,
|
|
36
|
-
"client-side-validation": False,
|
|
37
|
-
"multiapi": False,
|
|
38
|
-
"polymorphic-examples": 5,
|
|
39
|
-
"generate-sample": False,
|
|
40
|
-
"generate-test": False,
|
|
41
|
-
"from-typespec": False,
|
|
42
|
-
"emit-cross-language-definition-file": False,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def is_azure_flavor(self) -> bool:
|
|
47
|
-
return self.flavor == "azure"
|
|
48
|
-
|
|
49
|
-
def __init__(self, options: Dict[str, Any]) -> None:
|
|
50
|
-
self.options = options
|
|
51
|
-
|
|
52
|
-
def __getattr__(self, prop: str) -> Any:
|
|
53
|
-
key = prop.replace("_", "-")
|
|
54
|
-
return self.options.get(key, self.OPTIONS_TO_DEFAULT.get(key))
|
|
55
|
-
|
|
56
|
-
@property
|
|
57
|
-
def show_operations(self) -> bool:
|
|
58
|
-
return self.options.get("show-operations", not self.low_level_client)
|
|
59
|
-
|
|
60
|
-
@property
|
|
61
|
-
def _models_mode_default(self) -> str:
|
|
62
|
-
models_mode_default = "none" if self.low_level_client or self.version_tolerant else "msrest"
|
|
63
|
-
if self.options.get("tsp_file") is not None:
|
|
64
|
-
models_mode_default = "dpg"
|
|
65
|
-
return models_mode_default
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def original_models_mode(self) -> str:
|
|
69
|
-
return self.options.get("models-mode", self._models_mode_default)
|
|
70
|
-
|
|
71
|
-
@property
|
|
72
|
-
def models_mode(self) -> Union[str, bool]:
|
|
73
|
-
# switch to falsy value for easier code writing
|
|
74
|
-
return False if self.original_models_mode == "none" else self.original_models_mode
|
|
75
|
-
|
|
76
|
-
@property
|
|
77
|
-
def tracing(self) -> bool:
|
|
78
|
-
return self.options.get(
|
|
79
|
-
"tracing",
|
|
80
|
-
self.show_operations and self.is_azure_flavor,
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
@property
|
|
84
|
-
def show_send_request(self) -> bool:
|
|
85
|
-
return self.options.get(
|
|
86
|
-
"show-send-request",
|
|
87
|
-
self._low_level_or_version_tolerant,
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
@property
|
|
91
|
-
def _low_level_or_version_tolerant(self) -> bool:
|
|
92
|
-
return self.low_level_client or self.version_tolerant
|
|
93
|
-
|
|
94
|
-
@property
|
|
95
|
-
def only_path_and_body_params_positional(self) -> bool:
|
|
96
|
-
return self.options.get(
|
|
97
|
-
"only-path-and-body-params-positional",
|
|
98
|
-
self._low_level_or_version_tolerant,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def combine_operation_files(self) -> bool:
|
|
103
|
-
return self.options.get(
|
|
104
|
-
"combine-operation-files",
|
|
105
|
-
self.version_tolerant,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
@property
|
|
109
|
-
def package_pprint_name(self) -> str:
|
|
110
|
-
return self.options.get("package-pprint-name") or _default_pprint(str(self.package_name))
|
|
111
|
-
|
|
112
|
-
@property
|
|
113
|
-
def validate_versioning(self) -> bool:
|
|
114
|
-
return self.options.get("validate-versioning", True)
|
|
115
|
-
|
|
116
|
-
@property
|
|
117
|
-
def default_optional_constants_to_none(self) -> bool:
|
|
118
|
-
return self.options.get(
|
|
119
|
-
"default-optional-constants-to-none",
|
|
120
|
-
self._low_level_or_version_tolerant,
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
@property
|
|
124
|
-
def builders_visibility(self) -> str:
|
|
125
|
-
builders_visibility = self.options.get("builders-visibility")
|
|
126
|
-
if builders_visibility is None:
|
|
127
|
-
return "public" if self.low_level_client else "embedded"
|
|
128
|
-
return builders_visibility.lower()
|
|
129
|
-
|
|
130
|
-
@property
|
|
131
|
-
def head_as_boolean(self) -> bool:
|
|
132
|
-
head_as_boolean = self.options.get("head-as-boolean", True)
|
|
133
|
-
# Force some options in ARM MODE
|
|
134
|
-
return True if self.azure_arm else head_as_boolean
|
|
135
|
-
|
|
136
|
-
@property
|
|
137
|
-
def package_mode(self) -> str:
|
|
138
|
-
return self.options.get("packaging-files-dir") or self.options.get("package-mode", "")
|
|
139
|
-
|
|
140
|
-
@property
|
|
141
|
-
def packaging_files_config(self) -> Optional[Dict[str, Any]]:
|
|
142
|
-
packaging_files_config = self.options.get("packaging-files-config")
|
|
143
|
-
if packaging_files_config is None:
|
|
144
|
-
return None
|
|
145
|
-
# packaging-files-config is either a string or a dict
|
|
146
|
-
# if it's a string, we can split on the comma to get the dict
|
|
147
|
-
# otherwise we just return
|
|
148
|
-
try:
|
|
149
|
-
return {k.strip(): v.strip() for k, v in [i.split(":") for i in packaging_files_config.split("|")]}
|
|
150
|
-
except AttributeError:
|
|
151
|
-
return packaging_files_config
|
|
152
|
-
|
|
153
|
-
@property
|
|
154
|
-
def package_version(self) -> Optional[str]:
|
|
155
|
-
return str(self.options.get("package-version", ""))
|
|
156
|
-
|
|
157
|
-
@property
|
|
158
|
-
def header_text(self) -> Optional[str]:
|
|
159
|
-
return self.options.get("header-text")
|
|
160
|
-
|
|
161
|
-
|
|
162
20
|
class CodeGenerator(Plugin):
|
|
163
|
-
def __init__(self, *args, **kwargs: Any) -> None:
|
|
164
|
-
super().__init__(*args, **kwargs)
|
|
165
|
-
self.options_retriever = OptionsRetriever(self.options)
|
|
166
|
-
|
|
167
|
-
def _validate_code_model_options(self) -> None:
|
|
168
|
-
if self.options_retriever.builders_visibility not in [
|
|
169
|
-
"public",
|
|
170
|
-
"hidden",
|
|
171
|
-
"embedded",
|
|
172
|
-
]:
|
|
173
|
-
raise ValueError("The value of --builders-visibility must be either 'public', 'hidden', or 'embedded'")
|
|
174
|
-
|
|
175
|
-
if self.options_retriever.original_models_mode not in ["msrest", "dpg", "none"]:
|
|
176
|
-
raise ValueError(
|
|
177
|
-
"--models-mode can only be 'msrest', 'dpg' or 'none'. "
|
|
178
|
-
"Pass in 'msrest' if you want msrest models, or "
|
|
179
|
-
"'none' if you don't want any."
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
if not self.options_retriever.show_operations and self.options_retriever.builders_visibility == "embedded":
|
|
183
|
-
raise ValueError(
|
|
184
|
-
"Can not embed builders without operations. "
|
|
185
|
-
"Either set --show-operations to True, or change the value of --builders-visibility "
|
|
186
|
-
"to 'public' or 'hidden'."
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
if self.options_retriever.basic_setup_py and not self.options_retriever.package_version:
|
|
190
|
-
raise ValueError("--basic-setup-py must be used with --package-version")
|
|
191
|
-
|
|
192
|
-
if self.options_retriever.package_mode and not self.options_retriever.package_version:
|
|
193
|
-
raise ValueError("--package-mode must be used with --package-version")
|
|
194
|
-
|
|
195
|
-
if not self.options_retriever.show_operations and self.options_retriever.combine_operation_files:
|
|
196
|
-
raise ValueError(
|
|
197
|
-
"Can not combine operation files if you are not showing operations. "
|
|
198
|
-
"If you want operation files, pass in flag --show-operations"
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
if self.options_retriever.package_mode:
|
|
202
|
-
if (
|
|
203
|
-
(
|
|
204
|
-
self.options_retriever.package_mode not in TYPESPEC_PACKAGE_MODE
|
|
205
|
-
and self.options_retriever.from_typespec
|
|
206
|
-
)
|
|
207
|
-
or (
|
|
208
|
-
self.options_retriever.package_mode not in VALID_PACKAGE_MODE
|
|
209
|
-
and not self.options_retriever.from_typespec
|
|
210
|
-
)
|
|
211
|
-
) and not Path(self.options_retriever.package_mode).exists():
|
|
212
|
-
raise ValueError(
|
|
213
|
-
f"--package-mode can only be {' or '.join(TYPESPEC_PACKAGE_MODE)} or directory which contains template files" # pylint: disable=line-too-long
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
if self.options_retriever.multiapi and self.options_retriever.version_tolerant:
|
|
217
|
-
raise ValueError(
|
|
218
|
-
"Can not currently generate version tolerant multiapi SDKs. "
|
|
219
|
-
"We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
if self.options_retriever.client_side_validation and self.options_retriever.version_tolerant:
|
|
223
|
-
raise ValueError("Can not generate version tolerant with --client-side-validation. ")
|
|
224
|
-
|
|
225
|
-
if not (self.options_retriever.azure_arm or self.options_retriever.version_tolerant):
|
|
226
|
-
_LOGGER.warning(
|
|
227
|
-
"You are generating with options that would not allow the SDK to be shipped as an official Azure SDK. "
|
|
228
|
-
"Please read https://aka.ms/azsdk/dpcodegen for more details."
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
if not self.options_retriever.is_azure_flavor and self.options_retriever.tracing:
|
|
232
|
-
raise ValueError("Can only have tracing turned on for Azure SDKs.")
|
|
233
21
|
|
|
234
22
|
@staticmethod
|
|
235
23
|
def sort_exceptions(yaml_data: Dict[str, Any]) -> None:
|
|
@@ -272,43 +60,6 @@ class CodeGenerator(Plugin):
|
|
|
272
60
|
del yaml_data["schemas"]["objects"][i]
|
|
273
61
|
break
|
|
274
62
|
|
|
275
|
-
def _build_code_model_options(self) -> Dict[str, Any]:
|
|
276
|
-
flags = [
|
|
277
|
-
"azure_arm",
|
|
278
|
-
"head_as_boolean",
|
|
279
|
-
"header_text",
|
|
280
|
-
"keep_version_file",
|
|
281
|
-
"no_async",
|
|
282
|
-
"no_namespace_folders",
|
|
283
|
-
"basic_setup_py",
|
|
284
|
-
"package_name",
|
|
285
|
-
"package_version",
|
|
286
|
-
"client_side_validation",
|
|
287
|
-
"tracing",
|
|
288
|
-
"multiapi",
|
|
289
|
-
"polymorphic_examples",
|
|
290
|
-
"models_mode",
|
|
291
|
-
"builders_visibility",
|
|
292
|
-
"show_operations",
|
|
293
|
-
"show_send_request",
|
|
294
|
-
"only_path_and_body_params_positional",
|
|
295
|
-
"version_tolerant",
|
|
296
|
-
"low_level_client",
|
|
297
|
-
"combine_operation_files",
|
|
298
|
-
"package_mode",
|
|
299
|
-
"package_pprint_name",
|
|
300
|
-
"packaging_files_config",
|
|
301
|
-
"default_optional_constants_to_none",
|
|
302
|
-
"generate_sample",
|
|
303
|
-
"generate_test",
|
|
304
|
-
"default_api_version",
|
|
305
|
-
"from_typespec",
|
|
306
|
-
"flavor",
|
|
307
|
-
"emit_cross_language_definition_file",
|
|
308
|
-
"validate_versioning",
|
|
309
|
-
]
|
|
310
|
-
return {f: getattr(self.options_retriever, f) for f in flags}
|
|
311
|
-
|
|
312
63
|
def get_yaml(self) -> Dict[str, Any]:
|
|
313
64
|
# tsp file doesn't have to be relative to output folder
|
|
314
65
|
with open(self.options["tsp_file"], "r", encoding="utf-8-sig") as fd:
|
|
@@ -319,21 +70,18 @@ class CodeGenerator(Plugin):
|
|
|
319
70
|
|
|
320
71
|
def process(self) -> bool:
|
|
321
72
|
# List the input file, should be only one
|
|
322
|
-
self._validate_code_model_options()
|
|
323
|
-
options = self._build_code_model_options()
|
|
324
73
|
yaml_data = self.get_yaml()
|
|
325
74
|
|
|
326
75
|
self.sort_exceptions(yaml_data)
|
|
327
76
|
|
|
328
|
-
if self.
|
|
77
|
+
if self.options["azure-arm"]:
|
|
329
78
|
self.remove_cloud_errors(yaml_data)
|
|
330
79
|
|
|
331
|
-
code_model = CodeModel(yaml_data=yaml_data, options=options)
|
|
332
|
-
if
|
|
80
|
+
code_model = CodeModel(yaml_data=yaml_data, options=self.options)
|
|
81
|
+
if self.options["flavor"] != "azure" and any(client.lro_operations for client in code_model.clients):
|
|
333
82
|
raise ValueError("Only support LROs for Azure SDKs")
|
|
334
83
|
serializer = self.get_serializer(code_model)
|
|
335
84
|
serializer.serialize()
|
|
336
|
-
|
|
337
85
|
return True
|
|
338
86
|
|
|
339
87
|
|
|
@@ -35,9 +35,6 @@ DEFAULT_LICENSE_DESCRIPTION = (
|
|
|
35
35
|
"SOFTWARE."
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
|
|
39
|
-
TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
|
|
40
|
-
VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
|
|
41
38
|
NAME_LENGTH_LIMIT = 40
|
|
42
39
|
|
|
43
40
|
|
|
@@ -165,7 +165,7 @@ def build_type(yaml_data: Dict[str, Any], code_model: CodeModel) -> BaseType:
|
|
|
165
165
|
response: Optional[BaseType] = None
|
|
166
166
|
if yaml_data["type"] == "model":
|
|
167
167
|
# need to special case model to avoid recursion
|
|
168
|
-
if yaml_data["base"] == "json" or not code_model.options["
|
|
168
|
+
if yaml_data["base"] == "json" or not code_model.options["models-mode"]:
|
|
169
169
|
model_type = JSONModelType
|
|
170
170
|
elif yaml_data["base"] == "dpg":
|
|
171
171
|
model_type = DPGModelType # type: ignore
|
|
@@ -75,7 +75,7 @@ class BaseBuilder(
|
|
|
75
75
|
self.external_docs: Optional[Dict[str, Any]] = yaml_data.get("externalDocs")
|
|
76
76
|
self.client_namespace: str = yaml_data.get("clientNamespace", code_model.namespace)
|
|
77
77
|
|
|
78
|
-
if code_model.options["
|
|
78
|
+
if code_model.options["version-tolerant"] and yaml_data.get("abstract"):
|
|
79
79
|
_LOGGER.warning(
|
|
80
80
|
'Not going to generate operation "%s" because we are unable to generate this '
|
|
81
81
|
"type of operation right now. "
|
|
@@ -70,7 +70,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
70
70
|
self.config = Config.from_yaml(yaml_data, self.code_model)
|
|
71
71
|
self.is_subclient = is_subclient
|
|
72
72
|
self.request_builders = self._build_request_builders()
|
|
73
|
-
if self.code_model.options["
|
|
73
|
+
if self.code_model.options["show-operations"]:
|
|
74
74
|
self.operation_groups = [
|
|
75
75
|
OperationGroup.from_yaml(op_group, code_model, self)
|
|
76
76
|
for op_group in self.yaml_data.get("operationGroups", [])
|
|
@@ -91,7 +91,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
91
91
|
@property
|
|
92
92
|
def need_cloud_setting(self) -> bool:
|
|
93
93
|
return bool(
|
|
94
|
-
self.code_model.options.get("
|
|
94
|
+
self.code_model.options.get("azure-arm", False)
|
|
95
95
|
and self.credential_scopes is not None
|
|
96
96
|
and self.endpoint_parameter is not None
|
|
97
97
|
)
|
|
@@ -144,7 +144,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
144
144
|
return request_builders
|
|
145
145
|
|
|
146
146
|
def pipeline_class(self, async_mode: bool) -> str:
|
|
147
|
-
if self.code_model.options["
|
|
147
|
+
if self.code_model.options["azure-arm"]:
|
|
148
148
|
if async_mode:
|
|
149
149
|
return "AsyncARMPipelineClient"
|
|
150
150
|
return "ARMPipelineClient"
|
|
@@ -160,7 +160,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
160
160
|
@property
|
|
161
161
|
def send_request_name(self) -> str:
|
|
162
162
|
"""Name of the send request function"""
|
|
163
|
-
return "send_request" if self.code_model.options["
|
|
163
|
+
return "send_request" if self.code_model.options["show-send-request"] else "_send_request"
|
|
164
164
|
|
|
165
165
|
@property
|
|
166
166
|
def has_parameterized_host(self) -> bool:
|
|
@@ -186,7 +186,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
186
186
|
@property
|
|
187
187
|
def filename(self) -> str:
|
|
188
188
|
"""Name of the file for the client"""
|
|
189
|
-
if self.code_model.options["
|
|
189
|
+
if self.code_model.options["version-tolerant"] or self.code_model.options["low-level-client"]:
|
|
190
190
|
return "_client"
|
|
191
191
|
return f"_{self.legacy_filename}"
|
|
192
192
|
|
|
@@ -206,7 +206,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
206
206
|
def _imports_shared(self, async_mode: bool, **kwargs) -> FileImport:
|
|
207
207
|
file_import = FileImport(self.code_model)
|
|
208
208
|
file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
209
|
-
if self.code_model.options["
|
|
209
|
+
if self.code_model.options["azure-arm"]:
|
|
210
210
|
file_import.add_submodule_import("azure.mgmt.core", self.pipeline_class(async_mode), ImportType.SDKCORE)
|
|
211
211
|
else:
|
|
212
212
|
file_import.add_submodule_import(
|
|
@@ -241,7 +241,7 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
241
241
|
"policies",
|
|
242
242
|
ImportType.SDKCORE,
|
|
243
243
|
)
|
|
244
|
-
if self.code_model.options["
|
|
244
|
+
if self.code_model.options["azure-arm"]:
|
|
245
245
|
async_prefix = "Async" if async_mode else ""
|
|
246
246
|
file_import.add_submodule_import(
|
|
247
247
|
"azure.mgmt.core.policies",
|
|
@@ -331,10 +331,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
331
331
|
ImportType.LOCAL,
|
|
332
332
|
)
|
|
333
333
|
|
|
334
|
-
if self.code_model.model_types and self.code_model.options["
|
|
334
|
+
if self.code_model.model_types and self.code_model.options["models-mode"] == "msrest":
|
|
335
335
|
path_to_models = ".." if async_mode else "."
|
|
336
336
|
file_import.add_submodule_import(path_to_models, "models", ImportType.LOCAL, alias="_models")
|
|
337
|
-
elif self.code_model.options["
|
|
337
|
+
elif self.code_model.options["models-mode"] == "msrest":
|
|
338
338
|
# in this case, we have client_models = {} in the service client, which needs a type annotation
|
|
339
339
|
# this import will always be commented, so will always add it to the typing section
|
|
340
340
|
file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB)
|
|
@@ -404,7 +404,7 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
|
|
|
404
404
|
|
|
405
405
|
@property
|
|
406
406
|
def sdk_moniker(self) -> str:
|
|
407
|
-
package_name = self.code_model.options
|
|
407
|
+
package_name = self.code_model.options.get("package-name")
|
|
408
408
|
if package_name and package_name.startswith("azure-"):
|
|
409
409
|
package_name = package_name[len("azure-") :]
|
|
410
410
|
return package_name if package_name else self.yaml_data["name"].lower()
|
|
@@ -421,14 +421,14 @@ class Config(_ClientConfigBase[ConfigGlobalParameterList]):
|
|
|
421
421
|
ImportType.SDKCORE,
|
|
422
422
|
)
|
|
423
423
|
file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
|
|
424
|
-
if self.code_model.options
|
|
424
|
+
if self.code_model.options.get("package-version"):
|
|
425
425
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
426
426
|
file_import.add_submodule_import(
|
|
427
427
|
self.code_model.get_relative_import_path(serialize_namespace, module_name="_version"),
|
|
428
428
|
"VERSION",
|
|
429
429
|
ImportType.LOCAL,
|
|
430
430
|
)
|
|
431
|
-
if self.code_model.options["
|
|
431
|
+
if self.code_model.options["azure-arm"]:
|
|
432
432
|
policy = "AsyncARMChallengeAuthenticationPolicy" if async_mode else "ARMChallengeAuthenticationPolicy"
|
|
433
433
|
file_import.add_submodule_import("azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.SDKCORE)
|
|
434
434
|
file_import.add_submodule_import("azure.mgmt.core.policies", policy, ImportType.SDKCORE)
|