@typespec/http-client-python 0.13.0-dev.3 → 0.14.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/dist/emitter/http.d.ts.map +1 -1
- package/dist/emitter/http.js +13 -3
- package/dist/emitter/http.js.map +1 -1
- package/emitter/src/http.ts +20 -2
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/regenerate.ts +7 -5
- package/eng/scripts/setup/__pycache__/package_manager.cpython-39.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
- package/eng/scripts/setup/build_pygen_wheel.py +1 -0
- package/eng/scripts/setup/install.py +4 -2
- package/eng/scripts/setup/package_manager.py +24 -22
- package/eng/scripts/setup/prepare.py +1 -1
- package/eng/scripts/setup/venvtools.py +1 -3
- package/generator/build/lib/pygen/codegen/models/client.py +3 -1
- package/generator/build/lib/pygen/codegen/models/operation_group.py +8 -2
- package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +2 -1
- package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -1
- package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -0
- package/generator/component-detection-pip-report.json +2 -2
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/client.py +3 -1
- package/generator/pygen/codegen/models/operation_group.py +8 -2
- package/generator/pygen/codegen/serializers/client_serializer.py +2 -1
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -1
- package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -0
- package/generator/pygen.egg-info/PKG-INFO +1 -1
- package/generator/pygen.egg-info/requires.txt +1 -1
- package/generator/setup.py +1 -1
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +5 -1
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py +48 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py +23 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py +5 -5
- package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +23 -20
- package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +5 -2
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py +41 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_override.py +21 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py +2 -2
- package/generator/test/azure/mock_api_tests/test_client_namespace.py +21 -18
- package/generator/test/azure/requirements.txt +4 -1
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +16 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py +38 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py +7 -0
- package/generator/test/generic_mock_api_tests/test_payload_xml.py +14 -0
- package/generator/test/generic_mock_api_tests/test_response_status_code_range.py +36 -0
- package/generator/test/generic_mock_api_tests/test_versioning_removed.py +6 -0
- package/generator/test/unbranded/requirements.txt +1 -0
- package/package.json +33 -33
|
@@ -58,6 +58,9 @@ const AZURE_EMITTER_OPTIONS: Record<string, Record<string, string> | Record<stri
|
|
|
58
58
|
"azure/client-generator-core/usage": {
|
|
59
59
|
namespace: "specs.azure.clientgenerator.core.usage",
|
|
60
60
|
},
|
|
61
|
+
"azure/client-generator-core/override": {
|
|
62
|
+
namespace: "specs.azure.clientgenerator.core.override",
|
|
63
|
+
},
|
|
61
64
|
"azure/core/basic": {
|
|
62
65
|
namespace: "specs.azure.core.basic",
|
|
63
66
|
},
|
|
@@ -259,17 +262,13 @@ function getEmitterOption(spec: string, flavor: string): Record<string, string>[
|
|
|
259
262
|
|
|
260
263
|
// Function to execute CLI commands asynchronously
|
|
261
264
|
async function executeCommand(tspCommand: TspCommand): Promise<void> {
|
|
262
|
-
try {
|
|
263
|
-
rmSync(tspCommand.outputDir, { recursive: true, force: true });
|
|
264
|
-
} catch (error) {
|
|
265
|
-
console.error(chalk.red(`rm error: ${error}`));
|
|
266
|
-
}
|
|
267
265
|
const execFileAsync = promisify(execFile);
|
|
268
266
|
try {
|
|
269
267
|
console.log(chalk.green(`start tsp ${tspCommand.command.join(" ")}`));
|
|
270
268
|
await execFileAsync("tsp", tspCommand.command, { shell: true });
|
|
271
269
|
console.log(chalk.green(`tsp ${tspCommand.command.join(" ")} succeeded`));
|
|
272
270
|
} catch (err) {
|
|
271
|
+
rmSync(tspCommand.outputDir, { recursive: true, force: true });
|
|
273
272
|
console.error(chalk.red(`exec error: ${err}`));
|
|
274
273
|
throw err;
|
|
275
274
|
}
|
|
@@ -310,6 +309,9 @@ async function getSubdirectories(baseDir: string, flags: RegenerateFlags): Promi
|
|
|
310
309
|
|
|
311
310
|
const mainTspRelativePath = toPosix(relative(baseDir, mainTspPath));
|
|
312
311
|
|
|
312
|
+
// after support discriminated union, remove this check
|
|
313
|
+
if (mainTspRelativePath.includes("type/union/discriminated")) return;
|
|
314
|
+
|
|
313
315
|
// after fix test generation for nested operation group, remove this check
|
|
314
316
|
if (mainTspRelativePath.includes("client-operation-group")) return;
|
|
315
317
|
|
|
Binary file
|
|
Binary file
|
|
@@ -12,6 +12,7 @@ if not sys.version_info >= (3, 9, 0):
|
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
14
|
from package_manager import detect_package_manager, PackageManagerNotFoundError
|
|
15
|
+
|
|
15
16
|
detect_package_manager() # Just check if we have a package manager
|
|
16
17
|
except (ImportError, ModuleNotFoundError, PackageManagerNotFoundError):
|
|
17
18
|
raise Exception("Your Python installation doesn't have a suitable package manager (pip or uv) available")
|
|
@@ -14,6 +14,7 @@ if not sys.version_info >= (3, 9, 0):
|
|
|
14
14
|
|
|
15
15
|
try:
|
|
16
16
|
from package_manager import detect_package_manager, PackageManagerNotFoundError
|
|
17
|
+
|
|
17
18
|
detect_package_manager() # Just check if we have a package manager
|
|
18
19
|
except (ImportError, ModuleNotFoundError, PackageManagerNotFoundError):
|
|
19
20
|
raise Warning(
|
|
@@ -37,11 +38,12 @@ _ROOT_DIR = Path(__file__).parent.parent.parent.parent
|
|
|
37
38
|
|
|
38
39
|
def main():
|
|
39
40
|
venv_path = _ROOT_DIR / "venv"
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
# Create virtual environment using package manager abstraction
|
|
42
43
|
from package_manager import create_venv_with_package_manager, install_packages
|
|
44
|
+
|
|
43
45
|
venv_context = create_venv_with_package_manager(venv_path)
|
|
44
|
-
|
|
46
|
+
|
|
45
47
|
# Install required packages - install_packages handles package manager logic
|
|
46
48
|
install_packages(["-U", "black"], venv_context)
|
|
47
49
|
install_packages(["-e", f"{_ROOT_DIR}/generator"], venv_context)
|
|
@@ -16,6 +16,7 @@ from venvtools import ExtendedEnvBuilder
|
|
|
16
16
|
|
|
17
17
|
class PackageManagerNotFoundError(Exception):
|
|
18
18
|
"""Raised when no suitable package manager is found."""
|
|
19
|
+
|
|
19
20
|
pass
|
|
20
21
|
|
|
21
22
|
|
|
@@ -30,41 +31,38 @@ def _check_command_available(command: str) -> bool:
|
|
|
30
31
|
|
|
31
32
|
def detect_package_manager() -> str:
|
|
32
33
|
"""Detect the best available package manager.
|
|
33
|
-
|
|
34
|
+
|
|
34
35
|
Returns:
|
|
35
36
|
str: The package manager command ('uv' or 'pip')
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
Raises:
|
|
38
39
|
PackageManagerNotFoundError: If no suitable package manager is found
|
|
39
40
|
"""
|
|
40
41
|
# Check for uv first since it's more modern and faster
|
|
41
42
|
if _check_command_available("uv"):
|
|
42
43
|
return "uv"
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
# Fall back to pip
|
|
45
46
|
if _check_command_available("pip"):
|
|
46
47
|
return "pip"
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
# As a last resort, try using python -m pip
|
|
49
50
|
try:
|
|
50
|
-
subprocess.run([sys.executable, "-m", "pip", "--version"],
|
|
51
|
-
capture_output=True, check=True)
|
|
51
|
+
subprocess.run([sys.executable, "-m", "pip", "--version"], capture_output=True, check=True)
|
|
52
52
|
return "python -m pip"
|
|
53
53
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
54
54
|
pass
|
|
55
|
-
|
|
56
|
-
raise PackageManagerNotFoundError(
|
|
57
|
-
"No suitable package manager found. Please install either uv or pip."
|
|
58
|
-
)
|
|
55
|
+
|
|
56
|
+
raise PackageManagerNotFoundError("No suitable package manager found. Please install either uv or pip.")
|
|
59
57
|
|
|
60
58
|
|
|
61
59
|
def get_install_command(package_manager: str, venv_context=None) -> list:
|
|
62
60
|
"""Get the install command for the given package manager.
|
|
63
|
-
|
|
61
|
+
|
|
64
62
|
Args:
|
|
65
63
|
package_manager: The package manager command ('uv', 'pip', or 'python -m pip')
|
|
66
64
|
venv_context: The virtual environment context (optional, used for pip)
|
|
67
|
-
|
|
65
|
+
|
|
68
66
|
Returns:
|
|
69
67
|
list: The base install command as a list
|
|
70
68
|
"""
|
|
@@ -89,7 +87,7 @@ def get_install_command(package_manager: str, venv_context=None) -> list:
|
|
|
89
87
|
|
|
90
88
|
def install_packages(packages: list, venv_context=None, package_manager: str = None) -> None:
|
|
91
89
|
"""Install packages using the available package manager.
|
|
92
|
-
|
|
90
|
+
|
|
93
91
|
Args:
|
|
94
92
|
packages: List of packages to install
|
|
95
93
|
venv_context: Virtual environment context (optional)
|
|
@@ -97,9 +95,9 @@ def install_packages(packages: list, venv_context=None, package_manager: str = N
|
|
|
97
95
|
"""
|
|
98
96
|
if package_manager is None:
|
|
99
97
|
package_manager = detect_package_manager()
|
|
100
|
-
|
|
98
|
+
|
|
101
99
|
install_cmd = get_install_command(package_manager, venv_context)
|
|
102
|
-
|
|
100
|
+
|
|
103
101
|
try:
|
|
104
102
|
subprocess.check_call(install_cmd + packages)
|
|
105
103
|
except subprocess.CalledProcessError as e:
|
|
@@ -108,25 +106,29 @@ def install_packages(packages: list, venv_context=None, package_manager: str = N
|
|
|
108
106
|
|
|
109
107
|
def create_venv_with_package_manager(venv_path):
|
|
110
108
|
"""Create virtual environment using the best available package manager.
|
|
111
|
-
|
|
109
|
+
|
|
112
110
|
Args:
|
|
113
111
|
venv_path: Path where to create the virtual environment
|
|
114
|
-
|
|
112
|
+
|
|
115
113
|
Returns:
|
|
116
114
|
venv_context: Virtual environment context object
|
|
117
115
|
"""
|
|
118
116
|
package_manager = detect_package_manager()
|
|
119
|
-
|
|
117
|
+
|
|
120
118
|
if package_manager == "uv":
|
|
121
119
|
# Use uv to create and manage the virtual environment
|
|
122
120
|
if not venv_path.exists():
|
|
123
121
|
subprocess.check_call(["uv", "venv", str(venv_path)])
|
|
124
|
-
|
|
122
|
+
|
|
125
123
|
# Create a mock venv_context for compatibility
|
|
126
124
|
class MockVenvContext:
|
|
127
125
|
def __init__(self, venv_path):
|
|
128
|
-
self.env_exe =
|
|
129
|
-
|
|
126
|
+
self.env_exe = (
|
|
127
|
+
str(venv_path / "bin" / "python")
|
|
128
|
+
if sys.platform != "win32"
|
|
129
|
+
else str(venv_path / "Scripts" / "python.exe")
|
|
130
|
+
)
|
|
131
|
+
|
|
130
132
|
return MockVenvContext(venv_path)
|
|
131
133
|
else:
|
|
132
134
|
# Use standard venv for pip
|
|
@@ -136,4 +138,4 @@ def create_venv_with_package_manager(venv_path):
|
|
|
136
138
|
else:
|
|
137
139
|
env_builder = ExtendedEnvBuilder(with_pip=True, upgrade_deps=True)
|
|
138
140
|
env_builder.create(venv_path)
|
|
139
|
-
return env_builder.context
|
|
141
|
+
return env_builder.context
|
|
@@ -25,7 +25,7 @@ def main():
|
|
|
25
25
|
assert venv_preexists # Otherwise install was not done
|
|
26
26
|
|
|
27
27
|
venv_context = create_venv_with_package_manager(venv_path)
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
try:
|
|
30
30
|
install_packages(["-r", f"{_ROOT_DIR}/generator/dev_requirements.txt"], venv_context)
|
|
31
31
|
except FileNotFoundError as e:
|
|
@@ -29,12 +29,10 @@ class ExtendedEnvBuilder(venv.EnvBuilder):
|
|
|
29
29
|
return self.context
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
32
|
def python_run(venv_context, module, command=None, *, additional_dir="."):
|
|
35
33
|
try:
|
|
36
34
|
cmd_line = [venv_context.env_exe, "-m", module] + (command if command else [])
|
|
37
|
-
|
|
35
|
+
|
|
38
36
|
print("Executing: {}".format(" ".join(cmd_line)))
|
|
39
37
|
subprocess.run(
|
|
40
38
|
cmd_line,
|
|
@@ -322,11 +322,13 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
322
322
|
)
|
|
323
323
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
324
324
|
for og in self.operation_groups:
|
|
325
|
+
suffix = f".{og.filename}" if (not self.code_model.options["multiapi"]) and og.is_mixin else ""
|
|
325
326
|
file_import.add_submodule_import(
|
|
326
327
|
self.code_model.get_relative_import_path(
|
|
327
328
|
serialize_namespace,
|
|
328
329
|
self.code_model.get_imported_namespace_for_operation(og.client_namespace, async_mode),
|
|
329
|
-
)
|
|
330
|
+
)
|
|
331
|
+
+ suffix,
|
|
330
332
|
og.class_name,
|
|
331
333
|
ImportType.LOCAL,
|
|
332
334
|
)
|
|
@@ -34,7 +34,6 @@ class OperationGroup(BaseModel):
|
|
|
34
34
|
) -> None:
|
|
35
35
|
super().__init__(yaml_data, code_model)
|
|
36
36
|
self.client = client
|
|
37
|
-
self.class_name: str = yaml_data["className"]
|
|
38
37
|
self.identify_name: str = yaml_data["identifyName"]
|
|
39
38
|
self.property_name: str = yaml_data["propertyName"]
|
|
40
39
|
self.operations = operations
|
|
@@ -51,6 +50,13 @@ class OperationGroup(BaseModel):
|
|
|
51
50
|
for og in self.operation_groups:
|
|
52
51
|
og.has_parent_operation_group = True
|
|
53
52
|
|
|
53
|
+
@property
|
|
54
|
+
def class_name(self) -> str:
|
|
55
|
+
"""The class name of the operation group."""
|
|
56
|
+
if self.is_mixin and not self.code_model.options["multiapi"]:
|
|
57
|
+
return "_" + self.yaml_data["className"]
|
|
58
|
+
return self.yaml_data["className"]
|
|
59
|
+
|
|
54
60
|
@property
|
|
55
61
|
def has_abstract_operations(self) -> bool:
|
|
56
62
|
return any(o for o in self.operations if o.abstract) or any(
|
|
@@ -89,7 +95,7 @@ class OperationGroup(BaseModel):
|
|
|
89
95
|
retval = add_to_pylint_disable(retval, "abstract-class-instantiated")
|
|
90
96
|
if len(self.operations) > 20:
|
|
91
97
|
retval = add_to_pylint_disable(retval, "too-many-public-methods")
|
|
92
|
-
if len(self.class_name) > NAME_LENGTH_LIMIT:
|
|
98
|
+
if len(self.class_name) > NAME_LENGTH_LIMIT and self.class_name[0] != "_":
|
|
93
99
|
retval = add_to_pylint_disable(retval, "name-too-long")
|
|
94
100
|
if len(self.operation_groups) > 6:
|
|
95
101
|
retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
|
|
@@ -50,7 +50,8 @@ class ClientSerializer:
|
|
|
50
50
|
class_name = self.client.name
|
|
51
51
|
base_class = ""
|
|
52
52
|
if self.client.has_mixin:
|
|
53
|
-
|
|
53
|
+
prefix = "" if self.client.code_model.options["multiapi"] else "_"
|
|
54
|
+
base_class = f"{prefix}{class_name}OperationsMixin"
|
|
54
55
|
pylint_disable = self.client.pylint_disable()
|
|
55
56
|
if base_class:
|
|
56
57
|
return f"class {class_name}({base_class}):{pylint_disable}"
|
|
@@ -26,7 +26,11 @@ class OperationsInitSerializer:
|
|
|
26
26
|
def _get_filename(operation_group: OperationGroup) -> str:
|
|
27
27
|
return "_operations" if self.code_model.options["combine-operation-files"] else operation_group.filename
|
|
28
28
|
|
|
29
|
-
return [
|
|
29
|
+
return [
|
|
30
|
+
f"from .{_get_filename(og)} import {og.class_name} # type: ignore"
|
|
31
|
+
for og in self.operation_groups
|
|
32
|
+
if not og.is_mixin or self.code_model.options["multiapi"]
|
|
33
|
+
]
|
|
30
34
|
|
|
31
35
|
def serialize(self) -> str:
|
|
32
36
|
operation_group_init_template = self.env.get_template("operations_folder_init.py.jinja2")
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
{{ keywords.patch_imports() }}
|
|
11
11
|
__all__ = [
|
|
12
12
|
{% for operation_group in operation_groups %}
|
|
13
|
+
{% if not operation_group.is_mixin or code_model.options["multiapi"] %}
|
|
13
14
|
'{{ operation_group.class_name }}',
|
|
15
|
+
{% endif %}
|
|
14
16
|
{% endfor %}
|
|
15
17
|
]
|
|
16
18
|
{{ keywords.extend_all }}
|
|
@@ -126,9 +126,9 @@
|
|
|
126
126
|
"implementation_version": "3.9.23",
|
|
127
127
|
"os_name": "posix",
|
|
128
128
|
"platform_machine": "x86_64",
|
|
129
|
-
"platform_release": "6.11.0-
|
|
129
|
+
"platform_release": "6.11.0-1018-azure",
|
|
130
130
|
"platform_system": "Linux",
|
|
131
|
-
"platform_version": "#
|
|
131
|
+
"platform_version": "#18~24.04.1-Ubuntu SMP Sat Jun 28 04:46:03 UTC 2025",
|
|
132
132
|
"python_full_version": "3.9.23",
|
|
133
133
|
"platform_python_implementation": "CPython",
|
|
134
134
|
"python_version": "3.9",
|
|
Binary file
|
|
@@ -322,11 +322,13 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=t
|
|
|
322
322
|
)
|
|
323
323
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
324
324
|
for og in self.operation_groups:
|
|
325
|
+
suffix = f".{og.filename}" if (not self.code_model.options["multiapi"]) and og.is_mixin else ""
|
|
325
326
|
file_import.add_submodule_import(
|
|
326
327
|
self.code_model.get_relative_import_path(
|
|
327
328
|
serialize_namespace,
|
|
328
329
|
self.code_model.get_imported_namespace_for_operation(og.client_namespace, async_mode),
|
|
329
|
-
)
|
|
330
|
+
)
|
|
331
|
+
+ suffix,
|
|
330
332
|
og.class_name,
|
|
331
333
|
ImportType.LOCAL,
|
|
332
334
|
)
|
|
@@ -34,7 +34,6 @@ class OperationGroup(BaseModel):
|
|
|
34
34
|
) -> None:
|
|
35
35
|
super().__init__(yaml_data, code_model)
|
|
36
36
|
self.client = client
|
|
37
|
-
self.class_name: str = yaml_data["className"]
|
|
38
37
|
self.identify_name: str = yaml_data["identifyName"]
|
|
39
38
|
self.property_name: str = yaml_data["propertyName"]
|
|
40
39
|
self.operations = operations
|
|
@@ -51,6 +50,13 @@ class OperationGroup(BaseModel):
|
|
|
51
50
|
for og in self.operation_groups:
|
|
52
51
|
og.has_parent_operation_group = True
|
|
53
52
|
|
|
53
|
+
@property
|
|
54
|
+
def class_name(self) -> str:
|
|
55
|
+
"""The class name of the operation group."""
|
|
56
|
+
if self.is_mixin and not self.code_model.options["multiapi"]:
|
|
57
|
+
return "_" + self.yaml_data["className"]
|
|
58
|
+
return self.yaml_data["className"]
|
|
59
|
+
|
|
54
60
|
@property
|
|
55
61
|
def has_abstract_operations(self) -> bool:
|
|
56
62
|
return any(o for o in self.operations if o.abstract) or any(
|
|
@@ -89,7 +95,7 @@ class OperationGroup(BaseModel):
|
|
|
89
95
|
retval = add_to_pylint_disable(retval, "abstract-class-instantiated")
|
|
90
96
|
if len(self.operations) > 20:
|
|
91
97
|
retval = add_to_pylint_disable(retval, "too-many-public-methods")
|
|
92
|
-
if len(self.class_name) > NAME_LENGTH_LIMIT:
|
|
98
|
+
if len(self.class_name) > NAME_LENGTH_LIMIT and self.class_name[0] != "_":
|
|
93
99
|
retval = add_to_pylint_disable(retval, "name-too-long")
|
|
94
100
|
if len(self.operation_groups) > 6:
|
|
95
101
|
retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
|
|
@@ -50,7 +50,8 @@ class ClientSerializer:
|
|
|
50
50
|
class_name = self.client.name
|
|
51
51
|
base_class = ""
|
|
52
52
|
if self.client.has_mixin:
|
|
53
|
-
|
|
53
|
+
prefix = "" if self.client.code_model.options["multiapi"] else "_"
|
|
54
|
+
base_class = f"{prefix}{class_name}OperationsMixin"
|
|
54
55
|
pylint_disable = self.client.pylint_disable()
|
|
55
56
|
if base_class:
|
|
56
57
|
return f"class {class_name}({base_class}):{pylint_disable}"
|
|
@@ -26,7 +26,11 @@ class OperationsInitSerializer:
|
|
|
26
26
|
def _get_filename(operation_group: OperationGroup) -> str:
|
|
27
27
|
return "_operations" if self.code_model.options["combine-operation-files"] else operation_group.filename
|
|
28
28
|
|
|
29
|
-
return [
|
|
29
|
+
return [
|
|
30
|
+
f"from .{_get_filename(og)} import {og.class_name} # type: ignore"
|
|
31
|
+
for og in self.operation_groups
|
|
32
|
+
if not og.is_mixin or self.code_model.options["multiapi"]
|
|
33
|
+
]
|
|
30
34
|
|
|
31
35
|
def serialize(self) -> str:
|
|
32
36
|
operation_group_init_template = self.env.get_template("operations_folder_init.py.jinja2")
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
{{ keywords.patch_imports() }}
|
|
11
11
|
__all__ = [
|
|
12
12
|
{% for operation_group in operation_groups %}
|
|
13
|
+
{% if not operation_group.is_mixin or code_model.options["multiapi"] %}
|
|
13
14
|
'{{ operation_group.class_name }}',
|
|
15
|
+
{% endif %}
|
|
14
16
|
{% endfor %}
|
|
15
17
|
]
|
|
16
18
|
{{ keywords.extend_all }}
|
|
@@ -21,7 +21,7 @@ Requires-Dist: docutils>=0.20.1
|
|
|
21
21
|
Requires-Dist: Jinja2==3.1.6
|
|
22
22
|
Requires-Dist: PyYAML==6.0.1
|
|
23
23
|
Requires-Dist: tomli==2.0.1
|
|
24
|
-
Requires-Dist: setuptools==
|
|
24
|
+
Requires-Dist: setuptools==75.3.2
|
|
25
25
|
Dynamic: author
|
|
26
26
|
Dynamic: author-email
|
|
27
27
|
Dynamic: classifier
|
package/generator/setup.py
CHANGED
package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py
CHANGED
|
@@ -47,7 +47,11 @@ async def test_check_name_availability_check_local(client):
|
|
|
47
47
|
@pytest.mark.asyncio
|
|
48
48
|
async def test_operations_list(client):
|
|
49
49
|
result = client.operations.list()
|
|
50
|
-
|
|
50
|
+
async for operation in result:
|
|
51
|
+
assert operation.name == "Microsoft.Compute/virtualMachines/write"
|
|
52
|
+
assert operation.display.operation == "Create or Update Virtual Machine."
|
|
53
|
+
assert operation.origin == "user,system"
|
|
54
|
+
assert operation.action_type == "Internal"
|
|
51
55
|
|
|
52
56
|
|
|
53
57
|
@pytest.mark.asyncio
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import pytest
|
|
7
|
+
from specs.azure.clientgenerator.core.clientlocation.aio import ClientLocationClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
async def client():
|
|
12
|
+
async with ClientLocationClient() as client:
|
|
13
|
+
yield client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.asyncio
|
|
17
|
+
async def test_get_health_status(client: ClientLocationClient):
|
|
18
|
+
await client.get_health_status()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.asyncio
|
|
22
|
+
async def test_archive_operations_archive_product(client: ClientLocationClient):
|
|
23
|
+
await client.archive_operations.archive_product()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.mark.asyncio
|
|
27
|
+
async def test_move_to_existing_sub_client_admin_operations_get_admin_info(client: ClientLocationClient):
|
|
28
|
+
await client.move_to_existing_sub_client.admin_operations.get_admin_info()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.asyncio
|
|
32
|
+
async def test_move_to_existing_sub_client_admin_operations_delete_user(client: ClientLocationClient):
|
|
33
|
+
await client.move_to_existing_sub_client.admin_operations.delete_user()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.mark.asyncio
|
|
37
|
+
async def test_move_to_existing_sub_client_user_operations_get_user(client: ClientLocationClient):
|
|
38
|
+
await client.move_to_existing_sub_client.user_operations.get_user()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pytest.mark.asyncio
|
|
42
|
+
async def test_move_to_new_sub_client_product_operations_list_products(client: ClientLocationClient):
|
|
43
|
+
await client.move_to_new_sub_client.product_operations.list_products()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.asyncio
|
|
47
|
+
async def test_move_to_root_client_resource_operations_get_resource(client: ClientLocationClient):
|
|
48
|
+
await client.move_to_root_client.resource_operations.get_resource()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import pytest
|
|
7
|
+
from specs.azure.clientgenerator.core.override.aio import OverrideClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
async def client():
|
|
12
|
+
async with OverrideClient() as client:
|
|
13
|
+
yield client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.asyncio
|
|
17
|
+
async def test_reorder_parameters(client: OverrideClient):
|
|
18
|
+
await client.reorder_parameters.reorder("param1", "param2")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.asyncio
|
|
22
|
+
async def test_group_parameters(client: OverrideClient):
|
|
23
|
+
await client.group_parameters.group(param1="param1", param2="param2")
|
|
@@ -31,8 +31,8 @@ async def test_model_usage(client: UsageClient):
|
|
|
31
31
|
) == await client.model_in_operation.model_in_read_only_property(body=models.RoundTripModel())
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
@pytest.mark.asyncio
|
|
35
|
+
async def test_orphan_model_serializable(client: UsageClient):
|
|
36
|
+
await client.model_in_operation.orphan_model_serializable(
|
|
37
|
+
body=models.OrphanModel(model_name="name", description="desc")
|
|
38
|
+
)
|
|
@@ -3,29 +3,32 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import pytest
|
|
7
|
+
from client.clientnamespace.aio import ClientNamespaceFirstClient
|
|
8
|
+
from client.clientnamespace.first.models import FirstClientResult
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
from client.clientnamespace.second.aio import ClientNamespaceSecondClient
|
|
11
|
+
from client.clientnamespace.second.models import SecondClientResult
|
|
12
|
+
from client.clientnamespace.second.sub.models import SecondClientEnumType
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
async def first_client():
|
|
17
|
+
async with ClientNamespaceFirstClient() as client:
|
|
18
|
+
yield client
|
|
19
19
|
|
|
20
|
-
# @pytest.fixture
|
|
21
|
-
# async def second_client():
|
|
22
|
-
# async with ClientNamespaceSecondClient() as client:
|
|
23
|
-
# yield client
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
async def second_client():
|
|
23
|
+
async with ClientNamespaceSecondClient() as client:
|
|
24
|
+
yield client
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
|
|
27
|
+
@pytest.mark.asyncio
|
|
28
|
+
async def test_get_first(first_client: ClientNamespaceFirstClient):
|
|
29
|
+
assert await first_client.get_first() == FirstClientResult(name="first")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.asyncio
|
|
33
|
+
async def test_get_second(second_client: ClientNamespaceSecondClient):
|
|
34
|
+
assert await second_client.get_second() == SecondClientResult(type=SecondClientEnumType.SECOND)
|
|
@@ -43,8 +43,11 @@ def test_check_name_availability_check_local(client):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def test_operations_list(client):
|
|
46
|
-
result = client.operations.list()
|
|
47
|
-
assert result
|
|
46
|
+
result = client.operations.list().next()
|
|
47
|
+
assert result.name == "Microsoft.Compute/virtualMachines/write"
|
|
48
|
+
assert result.display.operation == "Create or Update Virtual Machine."
|
|
49
|
+
assert result.origin == "user,system"
|
|
50
|
+
assert result.action_type == "Internal"
|
|
48
51
|
|
|
49
52
|
|
|
50
53
|
def test_lro_begin_create_or_replace(client):
|
package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import pytest
|
|
7
|
+
from specs.azure.clientgenerator.core.clientlocation import ClientLocationClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def client():
|
|
12
|
+
with ClientLocationClient() as client:
|
|
13
|
+
yield client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_get_health_status(client: ClientLocationClient):
|
|
17
|
+
client.get_health_status()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_archive_operations_archive_product(client: ClientLocationClient):
|
|
21
|
+
client.archive_operations.archive_product()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_move_to_existing_sub_client_admin_operations_get_admin_info(client: ClientLocationClient):
|
|
25
|
+
client.move_to_existing_sub_client.admin_operations.get_admin_info()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_move_to_existing_sub_client_admin_operations_delete_user(client: ClientLocationClient):
|
|
29
|
+
client.move_to_existing_sub_client.admin_operations.delete_user()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_move_to_existing_sub_client_user_operations_get_user(client: ClientLocationClient):
|
|
33
|
+
client.move_to_existing_sub_client.user_operations.get_user()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_move_to_new_sub_client_product_operations_list_products(client: ClientLocationClient):
|
|
37
|
+
client.move_to_new_sub_client.product_operations.list_products()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_move_to_root_client_resource_operations_get_resource(client: ClientLocationClient):
|
|
41
|
+
client.move_to_root_client.resource_operations.get_resource()
|