@typespec/http-client-python 0.6.10 → 0.7.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/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +80 -50
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +28 -1
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +21 -1
- package/dist/emitter/lib.js.map +1 -1
- package/emitter/src/emitter.ts +84 -53
- package/emitter/src/lib.ts +22 -1
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/Build-Packages.ps1 +3 -2
- package/eng/scripts/ci/regenerate.ts +34 -4
- package/eng/scripts/ci/run_apiview.py +5 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/generator/build/lib/pygen/black.py +13 -2
- package/generator/build/lib/pygen/codegen/models/client.py +0 -8
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +18 -33
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +1 -7
- package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +0 -4
- package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +0 -10
- package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +0 -3
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2 -2
- package/generator/component-detection-pip-report.json +3 -3
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/black.py +13 -2
- package/generator/pygen/codegen/models/client.py +0 -8
- package/generator/pygen/codegen/serializers/builder_serializer.py +18 -33
- package/generator/pygen/codegen/serializers/model_serializer.py +1 -7
- package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
- package/generator/pygen/codegen/templates/macros.jinja2 +0 -4
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +0 -10
- package/generator/pygen/codegen/templates/operation_tools.jinja2 +0 -3
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +2 -2
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +92 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py +199 -3
- package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +80 -0
- package/generator/test/azure/mock_api_tests/test_azure_arm_resource.py +187 -3
- package/generator/test/azure/requirements.txt +1 -0
- package/package.json +30 -28
|
@@ -58,6 +58,7 @@ const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, st
|
|
|
58
58
|
},
|
|
59
59
|
"type/array": {
|
|
60
60
|
"package-name": "typetest-array",
|
|
61
|
+
"use-pyodide": "true",
|
|
61
62
|
},
|
|
62
63
|
"type/dictionary": {
|
|
63
64
|
"package-name": "typetest-dictionary",
|
|
@@ -85,6 +86,7 @@ const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, st
|
|
|
85
86
|
},
|
|
86
87
|
"type/model/inheritance/recursive": {
|
|
87
88
|
"package-name": "typetest-model-recursive",
|
|
89
|
+
"use-pyodide": "true",
|
|
88
90
|
},
|
|
89
91
|
"type/model/usage": {
|
|
90
92
|
"package-name": "typetest-model-usage",
|
|
@@ -220,6 +222,9 @@ async function getSubdirectories(baseDir: string, flags: RegenerateFlags): Promi
|
|
|
220
222
|
// after fix test generation for nested operation group, remove this check
|
|
221
223
|
if (mainTspRelativePath.includes("client-operation-group")) return;
|
|
222
224
|
|
|
225
|
+
// after https://github.com/Azure/autorest.python/issues/3043 fixed, remove this check
|
|
226
|
+
if (mainTspRelativePath.includes("azure/client-generator-core/api-version")) return;
|
|
227
|
+
|
|
223
228
|
const hasMainTsp = await promises
|
|
224
229
|
.access(mainTspPath)
|
|
225
230
|
.then(() => true)
|
|
@@ -311,10 +316,24 @@ function _getCmdList(spec: string, flags: RegenerateFlags): TspCommand[] {
|
|
|
311
316
|
});
|
|
312
317
|
}
|
|
313
318
|
|
|
319
|
+
async function runTaskPool(tasks: Array<() => Promise<void>>, poolLimit: number): Promise<void> {
|
|
320
|
+
let currentIndex = 0;
|
|
321
|
+
|
|
322
|
+
async function worker() {
|
|
323
|
+
while (currentIndex < tasks.length) {
|
|
324
|
+
const index = currentIndex++;
|
|
325
|
+
await tasks[index]();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const workers = new Array(Math.min(poolLimit, tasks.length)).fill(null).map(() => worker());
|
|
330
|
+
await Promise.all(workers);
|
|
331
|
+
}
|
|
332
|
+
|
|
314
333
|
async function regenerate(flags: RegenerateFlagsInput): Promise<void> {
|
|
315
334
|
if (flags.flavor === undefined) {
|
|
316
335
|
await regenerate({ flavor: "azure", ...flags });
|
|
317
|
-
await regenerate({ flavor: "unbranded",
|
|
336
|
+
await regenerate({ flavor: "unbranded", ...flags });
|
|
318
337
|
} else {
|
|
319
338
|
const flagsResolved = { debug: false, flavor: flags.flavor, ...flags };
|
|
320
339
|
const subdirectoriesForAzure = await getSubdirectories(AZURE_HTTP_SPECS, flagsResolved);
|
|
@@ -326,11 +345,22 @@ async function regenerate(flags: RegenerateFlagsInput): Promise<void> {
|
|
|
326
345
|
const cmdList: TspCommand[] = subdirectories.flatMap((subdirectory) =>
|
|
327
346
|
_getCmdList(subdirectory, flagsResolved),
|
|
328
347
|
);
|
|
329
|
-
|
|
330
|
-
|
|
348
|
+
|
|
349
|
+
// Create tasks as functions for the pool
|
|
350
|
+
const tasks: Array<() => Promise<void>> = cmdList.map((tspCommand) => {
|
|
351
|
+
return () => executeCommand(tspCommand);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Run tasks with a concurrency limit
|
|
355
|
+
await runTaskPool(tasks, 30);
|
|
331
356
|
}
|
|
332
357
|
}
|
|
333
358
|
|
|
359
|
+
const start = performance.now();
|
|
334
360
|
regenerate(argv.values)
|
|
335
|
-
.then(() =>
|
|
361
|
+
.then(() =>
|
|
362
|
+
console.log(
|
|
363
|
+
`Regeneration successful, time taken: ${Math.round((performance.now() - start) / 1000)} s`,
|
|
364
|
+
),
|
|
365
|
+
)
|
|
336
366
|
.catch((error) => console.error(`Regeneration failed: ${error.message}`));
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
# This script is used to execute apiview generation within a tox environment. Depending on which package is being executed against,
|
|
9
9
|
# a failure may be suppressed.
|
|
10
10
|
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
11
13
|
from subprocess import check_call, CalledProcessError
|
|
12
14
|
import logging
|
|
13
15
|
from util import run_check
|
|
@@ -37,4 +39,7 @@ def _single_dir_apiview(mod):
|
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
if __name__ == "__main__":
|
|
42
|
+
if os.name == "nt":
|
|
43
|
+
logging.info("Skip running ApiView on Windows for now to reduce time cost in CI")
|
|
44
|
+
sys.exit(0)
|
|
40
45
|
run_check("apiview", _single_dir_apiview, "APIView")
|
|
Binary file
|
|
@@ -60,8 +60,19 @@ class BlackScriptPlugin(Plugin):
|
|
|
60
60
|
except:
|
|
61
61
|
_LOGGER.error("Error: failed to format %s", file)
|
|
62
62
|
raise
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
pylint_disables = []
|
|
64
|
+
lines = file_content.splitlines()
|
|
65
|
+
if len(lines) > 0:
|
|
66
|
+
if "line-too-long" not in lines[0] and any(len(line) > 120 for line in lines):
|
|
67
|
+
pylint_disables.extend(["line-too-long", "useless-suppression"])
|
|
68
|
+
if "too-many-lines" not in lines[0] and len(lines) > 1000:
|
|
69
|
+
pylint_disables.append("too-many-lines")
|
|
70
|
+
if pylint_disables:
|
|
71
|
+
file_content = (
|
|
72
|
+
"\n".join([lines[0] + ",".join([""] + pylint_disables)] + lines[1:])
|
|
73
|
+
if "pylint: disable=" in lines[0]
|
|
74
|
+
else f"# pylint: disable={','.join(pylint_disables)}\n" + file_content
|
|
75
|
+
)
|
|
65
76
|
self.write_file(file, file_content)
|
|
66
77
|
|
|
67
78
|
|
|
@@ -161,14 +161,6 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
161
161
|
retval = add_to_pylint_disable(retval, "name-too-long")
|
|
162
162
|
return retval
|
|
163
163
|
|
|
164
|
-
@property
|
|
165
|
-
def url_pylint_disable(self) -> str:
|
|
166
|
-
# if the url is too long
|
|
167
|
-
retval = ""
|
|
168
|
-
if len(self.url) > 85:
|
|
169
|
-
retval = add_to_pylint_disable(retval, "line-too-long")
|
|
170
|
-
return retval
|
|
171
|
-
|
|
172
164
|
@property
|
|
173
165
|
def filename(self) -> str:
|
|
174
166
|
"""Name of the file for the client"""
|
|
@@ -498,11 +498,7 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
|
|
|
498
498
|
url_value = _escape_str(builder.url)
|
|
499
499
|
else:
|
|
500
500
|
url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
|
|
501
|
-
|
|
502
|
-
# there will be always 4 spaces before the url
|
|
503
|
-
if len(result) + 4 > 120:
|
|
504
|
-
return result + " # pylint: disable=line-too-long"
|
|
505
|
-
return result
|
|
501
|
+
return "_url = " + url_value
|
|
506
502
|
|
|
507
503
|
|
|
508
504
|
############################## NORMAL OPERATIONS ##############################
|
|
@@ -1005,7 +1001,9 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1005
1001
|
retval.extend(deserialize_code)
|
|
1006
1002
|
return retval
|
|
1007
1003
|
|
|
1008
|
-
def handle_error_response(
|
|
1004
|
+
def handle_error_response( # pylint: disable=too-many-statements, too-many-branches
|
|
1005
|
+
self, builder: OperationType
|
|
1006
|
+
) -> List[str]:
|
|
1009
1007
|
async_await = "await " if self.async_mode else ""
|
|
1010
1008
|
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
1011
1009
|
response_read = [
|
|
@@ -1042,34 +1040,23 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1042
1040
|
)
|
|
1043
1041
|
# add build-in error type
|
|
1044
1042
|
# TODO: we should decide whether need to this wrapper for customized error type
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
elif status_code == 404:
|
|
1053
|
-
retval.append(
|
|
1054
|
-
" raise ResourceNotFoundError(response=response{}{})".format(
|
|
1055
|
-
error_model,
|
|
1056
|
-
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1057
|
-
)
|
|
1058
|
-
)
|
|
1059
|
-
elif status_code == 409:
|
|
1060
|
-
retval.append(
|
|
1061
|
-
" raise ResourceExistsError(response=response{}{})".format(
|
|
1062
|
-
error_model,
|
|
1063
|
-
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1064
|
-
)
|
|
1065
|
-
)
|
|
1066
|
-
elif status_code == 304:
|
|
1043
|
+
status_code_error_map = {
|
|
1044
|
+
401: "ClientAuthenticationError",
|
|
1045
|
+
404: "ResourceNotFoundError",
|
|
1046
|
+
409: "ResourceExistsError",
|
|
1047
|
+
304: "ResourceNotModifiedError",
|
|
1048
|
+
}
|
|
1049
|
+
if status_code in status_code_error_map:
|
|
1067
1050
|
retval.append(
|
|
1068
|
-
" raise
|
|
1051
|
+
" raise {}(response=response{}{})".format(
|
|
1052
|
+
status_code_error_map[cast(int, status_code)],
|
|
1069
1053
|
error_model,
|
|
1070
1054
|
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1071
1055
|
)
|
|
1072
1056
|
)
|
|
1057
|
+
condition = "if"
|
|
1058
|
+
else:
|
|
1059
|
+
condition = "elif"
|
|
1073
1060
|
# ranged status code only exist in typespec and will not have multiple status codes
|
|
1074
1061
|
else:
|
|
1075
1062
|
retval.append(
|
|
@@ -1084,15 +1071,13 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1084
1071
|
f" error = _failsafe_deserialize_xml({type_annotation}, response.text())"
|
|
1085
1072
|
)
|
|
1086
1073
|
else:
|
|
1087
|
-
retval.append(
|
|
1088
|
-
f" error = _failsafe_deserialize({type_annotation}, response.json())"
|
|
1089
|
-
)
|
|
1074
|
+
retval.append(f" error = _failsafe_deserialize({type_annotation}, response.json())")
|
|
1090
1075
|
else:
|
|
1091
1076
|
retval.append(
|
|
1092
1077
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|
|
1093
1078
|
"pipeline_response)"
|
|
1094
1079
|
)
|
|
1095
|
-
|
|
1080
|
+
condition = "elif"
|
|
1096
1081
|
# default error handling
|
|
1097
1082
|
if builder.default_error_deserialization and self.code_model.options["models_mode"]:
|
|
1098
1083
|
error_model = ", model=error"
|
|
@@ -325,13 +325,7 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
325
325
|
)
|
|
326
326
|
type_annotation = prop.type_annotation(serialize_namespace=self.serialize_namespace)
|
|
327
327
|
generated_code = f'{prop.client_name}: {type_annotation} = {field}({", ".join(args)})'
|
|
328
|
-
|
|
329
|
-
pylint_disable = (
|
|
330
|
-
" # pylint: disable=line-too-long"
|
|
331
|
-
if len(generated_code) <= 116 < (len(generated_code) + len(type_ignore))
|
|
332
|
-
else ""
|
|
333
|
-
)
|
|
334
|
-
return f"{generated_code}{type_ignore}{pylint_disable}"
|
|
328
|
+
return f"{generated_code}{type_ignore}"
|
|
335
329
|
|
|
336
330
|
def initialize_properties(self, model: ModelType) -> List[str]:
|
|
337
331
|
init_args = []
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
super().__init__()
|
|
8
8
|
{% endif %}
|
|
9
9
|
{% if client.has_parameterized_host %}
|
|
10
|
-
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
10
|
+
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
11
11
|
{% endif %}
|
|
12
12
|
{{ serializer.initialize_config() }}
|
|
13
13
|
{{ op_tools.serialize(serializer.initialize_pipeline_client(async_mode)) | indent(8) }}
|
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
{% for line in list_result %}
|
|
5
5
|
{% set prefix = "" if loop.index == 1 else " " %}
|
|
6
6
|
{% set suffix = suffix_string if list_result | length == loop.index %}
|
|
7
|
-
{% if line | length > 120 %}
|
|
8
|
-
{{ prefix }}{{ line + " # pylint: disable=line-too-long" }}{{ suffix }}
|
|
9
|
-
{% else %}
|
|
10
7
|
{{ prefix }}{{ line }}{{ suffix }}
|
|
11
|
-
{% endif %}
|
|
12
8
|
{% endfor %}
|
|
13
9
|
{% endmacro %}
|
|
@@ -8,16 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
{{ serializer.discriminator_docstring(model) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n ') }}
|
|
10
10
|
{% endif %}
|
|
11
|
-
{% if model.has_readonly_or_constant_property %}
|
|
12
|
-
|
|
13
|
-
Readonly variables are only populated by the server, and will be ignored when sending a request.
|
|
14
|
-
{% endif %}
|
|
15
|
-
{% if (model.properties | selectattr('optional', "equalto", false) | first) is defined %}
|
|
16
|
-
|
|
17
|
-
{% if not model.is_usage_output %}
|
|
18
|
-
All required parameters must be populated in order to send to server.
|
|
19
|
-
{% endif %}
|
|
20
|
-
{% endif %}
|
|
21
11
|
|
|
22
12
|
{% if model.properties != None %}
|
|
23
13
|
{% for p in model.properties %}
|
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
{% for description in serializer.description_and_summary(builder) %}
|
|
13
13
|
{% if description %}
|
|
14
14
|
{% set description = wrap_string(description, wrapstring='\n') %}
|
|
15
|
-
{% if (serializer.line_too_long(example_template) or ns.line_too_long) and loop.first %}
|
|
16
|
-
# pylint: disable=line-too-long
|
|
17
|
-
{% endif %}
|
|
18
15
|
{{ '"""' + description if loop.first else description }}
|
|
19
16
|
{% else %}
|
|
20
17
|
|
|
@@ -410,7 +410,7 @@ class Model:
|
|
|
410
410
|
:param function key_extractors: A key extractor function.
|
|
411
411
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
412
412
|
:returns: An instance of this model
|
|
413
|
-
:raises
|
|
413
|
+
:raises DeserializationError: if something went wrong
|
|
414
414
|
:rtype: Self
|
|
415
415
|
"""
|
|
416
416
|
deserializer = Deserializer(cls._infer_class_models())
|
|
@@ -1360,7 +1360,7 @@ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
|
1360
1360
|
# Iter and wrapped, should have found one node only (the wrap one)
|
|
1361
1361
|
if len(children) != 1:
|
|
1362
1362
|
raise DeserializationError(
|
|
1363
|
-
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
|
|
1363
|
+
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
|
|
1364
1364
|
xml_name
|
|
1365
1365
|
)
|
|
1366
1366
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1",
|
|
3
|
-
"pip_version": "25.0",
|
|
3
|
+
"pip_version": "25.0.1",
|
|
4
4
|
"install": [
|
|
5
5
|
{
|
|
6
6
|
"download_info": {
|
|
@@ -126,9 +126,9 @@
|
|
|
126
126
|
"implementation_version": "3.8.10",
|
|
127
127
|
"os_name": "posix",
|
|
128
128
|
"platform_machine": "x86_64",
|
|
129
|
-
"platform_release": "5.15.0-
|
|
129
|
+
"platform_release": "5.15.0-1081-azure",
|
|
130
130
|
"platform_system": "Linux",
|
|
131
|
-
"platform_version": "#
|
|
131
|
+
"platform_version": "#90~20.04.1-Ubuntu SMP Tue Jan 28 05:34:18 UTC 2025",
|
|
132
132
|
"python_full_version": "3.8.10",
|
|
133
133
|
"platform_python_implementation": "CPython",
|
|
134
134
|
"python_version": "3.8",
|
|
Binary file
|
package/generator/pygen/black.py
CHANGED
|
@@ -60,8 +60,19 @@ class BlackScriptPlugin(Plugin):
|
|
|
60
60
|
except:
|
|
61
61
|
_LOGGER.error("Error: failed to format %s", file)
|
|
62
62
|
raise
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
pylint_disables = []
|
|
64
|
+
lines = file_content.splitlines()
|
|
65
|
+
if len(lines) > 0:
|
|
66
|
+
if "line-too-long" not in lines[0] and any(len(line) > 120 for line in lines):
|
|
67
|
+
pylint_disables.extend(["line-too-long", "useless-suppression"])
|
|
68
|
+
if "too-many-lines" not in lines[0] and len(lines) > 1000:
|
|
69
|
+
pylint_disables.append("too-many-lines")
|
|
70
|
+
if pylint_disables:
|
|
71
|
+
file_content = (
|
|
72
|
+
"\n".join([lines[0] + ",".join([""] + pylint_disables)] + lines[1:])
|
|
73
|
+
if "pylint: disable=" in lines[0]
|
|
74
|
+
else f"# pylint: disable={','.join(pylint_disables)}\n" + file_content
|
|
75
|
+
)
|
|
65
76
|
self.write_file(file, file_content)
|
|
66
77
|
|
|
67
78
|
|
|
@@ -161,14 +161,6 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
|
|
|
161
161
|
retval = add_to_pylint_disable(retval, "name-too-long")
|
|
162
162
|
return retval
|
|
163
163
|
|
|
164
|
-
@property
|
|
165
|
-
def url_pylint_disable(self) -> str:
|
|
166
|
-
# if the url is too long
|
|
167
|
-
retval = ""
|
|
168
|
-
if len(self.url) > 85:
|
|
169
|
-
retval = add_to_pylint_disable(retval, "line-too-long")
|
|
170
|
-
return retval
|
|
171
|
-
|
|
172
164
|
@property
|
|
173
165
|
def filename(self) -> str:
|
|
174
166
|
"""Name of the file for the client"""
|
|
@@ -498,11 +498,7 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
|
|
|
498
498
|
url_value = _escape_str(builder.url)
|
|
499
499
|
else:
|
|
500
500
|
url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
|
|
501
|
-
|
|
502
|
-
# there will be always 4 spaces before the url
|
|
503
|
-
if len(result) + 4 > 120:
|
|
504
|
-
return result + " # pylint: disable=line-too-long"
|
|
505
|
-
return result
|
|
501
|
+
return "_url = " + url_value
|
|
506
502
|
|
|
507
503
|
|
|
508
504
|
############################## NORMAL OPERATIONS ##############################
|
|
@@ -1005,7 +1001,9 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1005
1001
|
retval.extend(deserialize_code)
|
|
1006
1002
|
return retval
|
|
1007
1003
|
|
|
1008
|
-
def handle_error_response(
|
|
1004
|
+
def handle_error_response( # pylint: disable=too-many-statements, too-many-branches
|
|
1005
|
+
self, builder: OperationType
|
|
1006
|
+
) -> List[str]:
|
|
1009
1007
|
async_await = "await " if self.async_mode else ""
|
|
1010
1008
|
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
1011
1009
|
response_read = [
|
|
@@ -1042,34 +1040,23 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1042
1040
|
)
|
|
1043
1041
|
# add build-in error type
|
|
1044
1042
|
# TODO: we should decide whether need to this wrapper for customized error type
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
elif status_code == 404:
|
|
1053
|
-
retval.append(
|
|
1054
|
-
" raise ResourceNotFoundError(response=response{}{})".format(
|
|
1055
|
-
error_model,
|
|
1056
|
-
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1057
|
-
)
|
|
1058
|
-
)
|
|
1059
|
-
elif status_code == 409:
|
|
1060
|
-
retval.append(
|
|
1061
|
-
" raise ResourceExistsError(response=response{}{})".format(
|
|
1062
|
-
error_model,
|
|
1063
|
-
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1064
|
-
)
|
|
1065
|
-
)
|
|
1066
|
-
elif status_code == 304:
|
|
1043
|
+
status_code_error_map = {
|
|
1044
|
+
401: "ClientAuthenticationError",
|
|
1045
|
+
404: "ResourceNotFoundError",
|
|
1046
|
+
409: "ResourceExistsError",
|
|
1047
|
+
304: "ResourceNotModifiedError",
|
|
1048
|
+
}
|
|
1049
|
+
if status_code in status_code_error_map:
|
|
1067
1050
|
retval.append(
|
|
1068
|
-
" raise
|
|
1051
|
+
" raise {}(response=response{}{})".format(
|
|
1052
|
+
status_code_error_map[cast(int, status_code)],
|
|
1069
1053
|
error_model,
|
|
1070
1054
|
(", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""),
|
|
1071
1055
|
)
|
|
1072
1056
|
)
|
|
1057
|
+
condition = "if"
|
|
1058
|
+
else:
|
|
1059
|
+
condition = "elif"
|
|
1073
1060
|
# ranged status code only exist in typespec and will not have multiple status codes
|
|
1074
1061
|
else:
|
|
1075
1062
|
retval.append(
|
|
@@ -1084,15 +1071,13 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1084
1071
|
f" error = _failsafe_deserialize_xml({type_annotation}, response.text())"
|
|
1085
1072
|
)
|
|
1086
1073
|
else:
|
|
1087
|
-
retval.append(
|
|
1088
|
-
f" error = _failsafe_deserialize({type_annotation}, response.json())"
|
|
1089
|
-
)
|
|
1074
|
+
retval.append(f" error = _failsafe_deserialize({type_annotation}, response.json())")
|
|
1090
1075
|
else:
|
|
1091
1076
|
retval.append(
|
|
1092
1077
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|
|
1093
1078
|
"pipeline_response)"
|
|
1094
1079
|
)
|
|
1095
|
-
|
|
1080
|
+
condition = "elif"
|
|
1096
1081
|
# default error handling
|
|
1097
1082
|
if builder.default_error_deserialization and self.code_model.options["models_mode"]:
|
|
1098
1083
|
error_model = ", model=error"
|
|
@@ -325,13 +325,7 @@ class DpgModelSerializer(_ModelSerializer):
|
|
|
325
325
|
)
|
|
326
326
|
type_annotation = prop.type_annotation(serialize_namespace=self.serialize_namespace)
|
|
327
327
|
generated_code = f'{prop.client_name}: {type_annotation} = {field}({", ".join(args)})'
|
|
328
|
-
|
|
329
|
-
pylint_disable = (
|
|
330
|
-
" # pylint: disable=line-too-long"
|
|
331
|
-
if len(generated_code) <= 116 < (len(generated_code) + len(type_ignore))
|
|
332
|
-
else ""
|
|
333
|
-
)
|
|
334
|
-
return f"{generated_code}{type_ignore}{pylint_disable}"
|
|
328
|
+
return f"{generated_code}{type_ignore}"
|
|
335
329
|
|
|
336
330
|
def initialize_properties(self, model: ModelType) -> List[str]:
|
|
337
331
|
init_args = []
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
super().__init__()
|
|
8
8
|
{% endif %}
|
|
9
9
|
{% if client.has_parameterized_host %}
|
|
10
|
-
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
10
|
+
{{ serializer.host_variable_name }} = {{ keywords.escape_str(client.url) }}
|
|
11
11
|
{% endif %}
|
|
12
12
|
{{ serializer.initialize_config() }}
|
|
13
13
|
{{ op_tools.serialize(serializer.initialize_pipeline_client(async_mode)) | indent(8) }}
|
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
{% for line in list_result %}
|
|
5
5
|
{% set prefix = "" if loop.index == 1 else " " %}
|
|
6
6
|
{% set suffix = suffix_string if list_result | length == loop.index %}
|
|
7
|
-
{% if line | length > 120 %}
|
|
8
|
-
{{ prefix }}{{ line + " # pylint: disable=line-too-long" }}{{ suffix }}
|
|
9
|
-
{% else %}
|
|
10
7
|
{{ prefix }}{{ line }}{{ suffix }}
|
|
11
|
-
{% endif %}
|
|
12
8
|
{% endfor %}
|
|
13
9
|
{% endmacro %}
|
|
@@ -8,16 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
{{ serializer.discriminator_docstring(model) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n ') }}
|
|
10
10
|
{% endif %}
|
|
11
|
-
{% if model.has_readonly_or_constant_property %}
|
|
12
|
-
|
|
13
|
-
Readonly variables are only populated by the server, and will be ignored when sending a request.
|
|
14
|
-
{% endif %}
|
|
15
|
-
{% if (model.properties | selectattr('optional', "equalto", false) | first) is defined %}
|
|
16
|
-
|
|
17
|
-
{% if not model.is_usage_output %}
|
|
18
|
-
All required parameters must be populated in order to send to server.
|
|
19
|
-
{% endif %}
|
|
20
|
-
{% endif %}
|
|
21
11
|
|
|
22
12
|
{% if model.properties != None %}
|
|
23
13
|
{% for p in model.properties %}
|
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
{% for description in serializer.description_and_summary(builder) %}
|
|
13
13
|
{% if description %}
|
|
14
14
|
{% set description = wrap_string(description, wrapstring='\n') %}
|
|
15
|
-
{% if (serializer.line_too_long(example_template) or ns.line_too_long) and loop.first %}
|
|
16
|
-
# pylint: disable=line-too-long
|
|
17
|
-
{% endif %}
|
|
18
15
|
{{ '"""' + description if loop.first else description }}
|
|
19
16
|
{% else %}
|
|
20
17
|
|
|
@@ -410,7 +410,7 @@ class Model:
|
|
|
410
410
|
:param function key_extractors: A key extractor function.
|
|
411
411
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
412
412
|
:returns: An instance of this model
|
|
413
|
-
:raises
|
|
413
|
+
:raises DeserializationError: if something went wrong
|
|
414
414
|
:rtype: Self
|
|
415
415
|
"""
|
|
416
416
|
deserializer = Deserializer(cls._infer_class_models())
|
|
@@ -1360,7 +1360,7 @@ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
|
|
|
1360
1360
|
# Iter and wrapped, should have found one node only (the wrap one)
|
|
1361
1361
|
if len(children) != 1:
|
|
1362
1362
|
raise DeserializationError(
|
|
1363
|
-
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
|
|
1363
|
+
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
|
|
1364
1364
|
xml_name
|
|
1365
1365
|
)
|
|
1366
1366
|
)
|
package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
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 azure.resourcemanager.operationtemplates.aio import OperationTemplatesClient
|
|
8
|
+
from azure.resourcemanager.operationtemplates import models
|
|
9
|
+
|
|
10
|
+
SUBSCRIPTION_ID = "00000000-0000-0000-0000-000000000000"
|
|
11
|
+
RESOURCE_GROUP_NAME = "test-rg"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
async def client(credential, authentication_policy):
|
|
16
|
+
async with OperationTemplatesClient(
|
|
17
|
+
credential,
|
|
18
|
+
SUBSCRIPTION_ID,
|
|
19
|
+
"http://localhost:3000",
|
|
20
|
+
authentication_policy=authentication_policy,
|
|
21
|
+
) as client:
|
|
22
|
+
yield client
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.asyncio
|
|
26
|
+
async def test_check_name_availability_check_global(client):
|
|
27
|
+
result = await client.check_name_availability.check_global(
|
|
28
|
+
body=models.CheckNameAvailabilityRequest(name="checkName", type="Microsoft.Web/site")
|
|
29
|
+
)
|
|
30
|
+
assert result.name_available == False
|
|
31
|
+
assert result.reason == models.CheckNameAvailabilityReason.ALREADY_EXISTS
|
|
32
|
+
assert result.message == "Hostname 'checkName' already exists. Please select a different name."
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.asyncio
|
|
36
|
+
async def test_check_name_availability_check_local(client):
|
|
37
|
+
result = await client.check_name_availability.check_local(
|
|
38
|
+
location="westus",
|
|
39
|
+
body=models.CheckNameAvailabilityRequest(name="checkName", type="Microsoft.Web/site"),
|
|
40
|
+
)
|
|
41
|
+
assert result.name_available == False
|
|
42
|
+
assert result.reason == models.CheckNameAvailabilityReason.ALREADY_EXISTS
|
|
43
|
+
assert result.message == "Hostname 'checkName' already exists. Please select a different name."
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.asyncio
|
|
47
|
+
async def test_operations_list(client):
|
|
48
|
+
result = client.operations.list()
|
|
49
|
+
assert result
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.asyncio
|
|
53
|
+
async def test_lro_begin_create_or_replace(client):
|
|
54
|
+
result = await (
|
|
55
|
+
await client.lro.begin_create_or_replace(
|
|
56
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
57
|
+
order_name="order1",
|
|
58
|
+
resource=models.Order(
|
|
59
|
+
location="eastus",
|
|
60
|
+
properties=models.OrderProperties(product_id="product1", amount=1),
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
).result()
|
|
64
|
+
assert result.name == "order1"
|
|
65
|
+
assert (
|
|
66
|
+
result.id
|
|
67
|
+
== "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.OperationTemplates/orders/order1"
|
|
68
|
+
)
|
|
69
|
+
assert result.type == "Azure.ResourceManager.Resources/orders"
|
|
70
|
+
assert result.location == "eastus"
|
|
71
|
+
assert result.system_data.created_by == "AzureSDK"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.asyncio
|
|
75
|
+
async def test_lro_begin_export(client):
|
|
76
|
+
await (
|
|
77
|
+
await client.lro.begin_export(
|
|
78
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
79
|
+
order_name="order1",
|
|
80
|
+
body=models.ExportRequest(format="csv"),
|
|
81
|
+
)
|
|
82
|
+
).result()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@pytest.mark.asyncio
|
|
86
|
+
async def test_lro_begin_delete(client):
|
|
87
|
+
await (
|
|
88
|
+
await client.lro.begin_delete(
|
|
89
|
+
resource_group_name=RESOURCE_GROUP_NAME,
|
|
90
|
+
order_name="order1",
|
|
91
|
+
)
|
|
92
|
+
).result()
|