@autorest/python 6.47.0 → 6.48.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/generator/build/lib/pygen/codegen/models/operation.py +13 -1
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +10 -0
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +38 -7
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +5 -3
- package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +54 -9
- package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +32 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +7 -3
- package/generator/component-detection-pip-report.json +4 -5
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/operation.py +13 -1
- package/generator/pygen/codegen/models/paging_operation.py +10 -0
- package/generator/pygen/codegen/serializers/builder_serializer.py +38 -7
- package/generator/pygen/codegen/serializers/general_serializer.py +5 -3
- package/generator/pygen/codegen/templates/macros.jinja2 +54 -9
- package/generator/pygen/codegen/templates/operation_tools.jinja2 +32 -1
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +7 -3
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
|
@@ -448,7 +448,19 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
448
448
|
elif self.need_deserialize:
|
|
449
449
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
450
450
|
if self.default_error_deserialization(serialize_namespace) or self.non_default_errors:
|
|
451
|
-
|
|
451
|
+
xml_non_default_errors = any(
|
|
452
|
+
xml_serializable(str(e.default_content_type)) for e in self.non_default_errors
|
|
453
|
+
)
|
|
454
|
+
try:
|
|
455
|
+
default_error = next(e for e in self.exceptions if "default" in e.status_codes and e.type)
|
|
456
|
+
except StopIteration:
|
|
457
|
+
default_error = None
|
|
458
|
+
if xml_non_default_errors or (
|
|
459
|
+
default_error and xml_serializable(str(default_error.default_content_type))
|
|
460
|
+
):
|
|
461
|
+
file_import.add_submodule_import(relative_path, "_failsafe_deserialize_xml", ImportType.LOCAL)
|
|
462
|
+
else:
|
|
463
|
+
file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
|
|
452
464
|
return file_import
|
|
453
465
|
|
|
454
466
|
def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType:
|
|
@@ -73,6 +73,13 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
73
73
|
def next_variable_name(self) -> str:
|
|
74
74
|
return "_continuation_token" if self.has_continuation_token else "next_link"
|
|
75
75
|
|
|
76
|
+
@property
|
|
77
|
+
def is_xml_paging(self) -> bool:
|
|
78
|
+
try:
|
|
79
|
+
return bool(self.responses[0].item_type.xml_metadata)
|
|
80
|
+
except KeyError:
|
|
81
|
+
return False
|
|
82
|
+
|
|
76
83
|
def _get_attr_name(self, wire_name: str) -> str:
|
|
77
84
|
response_type = self.responses[0].type
|
|
78
85
|
if not response_type:
|
|
@@ -176,6 +183,9 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
176
183
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
177
184
|
if self.default_error_deserialization(serialize_namespace) or self.need_deserialize:
|
|
178
185
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
186
|
+
if self.is_xml_paging:
|
|
187
|
+
file_import.add_submodule_import("xml.etree", "ElementTree", ImportType.STDLIB, alias="ET")
|
|
188
|
+
file_import.add_submodule_import(relative_path, "_convert_element", ImportType.LOCAL)
|
|
179
189
|
return file_import
|
|
180
190
|
|
|
181
191
|
|
|
@@ -1045,7 +1045,9 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1045
1045
|
retval.extend([f" {l}" for l in response_read])
|
|
1046
1046
|
retval.append(" map_error(status_code=response.status_code, response=response, error_map=error_map)")
|
|
1047
1047
|
error_model = ""
|
|
1048
|
-
if
|
|
1048
|
+
if ( # pylint: disable=too-many-nested-blocks
|
|
1049
|
+
builder.non_default_errors and self.code_model.options["models-mode"]
|
|
1050
|
+
):
|
|
1049
1051
|
error_model = ", model=error"
|
|
1050
1052
|
condition = "if"
|
|
1051
1053
|
retval.append(" error = None")
|
|
@@ -1062,9 +1064,11 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1062
1064
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1063
1065
|
)
|
|
1064
1066
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1067
|
+
if xml_serializable(str(e.default_content_type)):
|
|
1068
|
+
fn = "_failsafe_deserialize_xml"
|
|
1069
|
+
else:
|
|
1070
|
+
fn = "_failsafe_deserialize"
|
|
1071
|
+
retval.append(f" error = {fn}({type_annotation},{pylint_disable}\n response)")
|
|
1068
1072
|
else:
|
|
1069
1073
|
retval.extend(
|
|
1070
1074
|
[
|
|
@@ -1130,9 +1134,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1130
1134
|
if builder.non_default_errors:
|
|
1131
1135
|
retval.append(" else:")
|
|
1132
1136
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1137
|
+
default_exception = next(e for e in builder.exceptions if "default" in e.status_codes and e.type)
|
|
1138
|
+
if xml_serializable(str(default_exception.default_content_type)):
|
|
1139
|
+
fn = "_failsafe_deserialize_xml"
|
|
1140
|
+
else:
|
|
1141
|
+
fn = "_failsafe_deserialize"
|
|
1133
1142
|
retval.extend(
|
|
1134
1143
|
[
|
|
1135
|
-
f"{indent}error =
|
|
1144
|
+
f"{indent}error = {fn}(",
|
|
1136
1145
|
f"{indent} {default_error_deserialization}",
|
|
1137
1146
|
f"{indent} response,",
|
|
1138
1147
|
f"{indent})",
|
|
@@ -1372,10 +1381,15 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1372
1381
|
def _function_def(self) -> str:
|
|
1373
1382
|
return "def"
|
|
1374
1383
|
|
|
1375
|
-
def _extract_data_callback(
|
|
1384
|
+
def _extract_data_callback( # pylint: disable=too-many-statements,too-many-branches
|
|
1385
|
+
self, builder: PagingOperationType
|
|
1386
|
+
) -> list[str]:
|
|
1376
1387
|
retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
|
|
1377
1388
|
response = builder.responses[0]
|
|
1378
|
-
|
|
1389
|
+
if builder.is_xml_paging:
|
|
1390
|
+
deserialized = "ET.fromstring(pipeline_response.http_response.text())"
|
|
1391
|
+
else:
|
|
1392
|
+
deserialized = "pipeline_response.http_response.json()"
|
|
1379
1393
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1380
1394
|
suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
|
|
1381
1395
|
deserialize_type = response.serialization_type(serialize_namespace=self.serialize_namespace)
|
|
@@ -1395,6 +1409,10 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1395
1409
|
item_name = builder.item_name
|
|
1396
1410
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1397
1411
|
access = f".{item_name}"
|
|
1412
|
+
elif builder.is_xml_paging:
|
|
1413
|
+
# For XML, use .find() to navigate the element tree
|
|
1414
|
+
item_name_array = item_name.split(".")
|
|
1415
|
+
access = "".join([f'.find("{i}")' for i in item_name_array])
|
|
1398
1416
|
else:
|
|
1399
1417
|
item_name_array = item_name.split(".")
|
|
1400
1418
|
access = (
|
|
@@ -1412,11 +1430,17 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1412
1430
|
retval.append(" if cls:")
|
|
1413
1431
|
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1414
1432
|
|
|
1433
|
+
cont_token_expr: Optional[str] = None # For XML, we need to extract find() result first
|
|
1415
1434
|
if builder.has_continuation_token:
|
|
1416
1435
|
location = builder.continuation_token.get("output", {}).get("location")
|
|
1417
1436
|
wire_name = builder.continuation_token.get("output", {}).get("wireName") or ""
|
|
1418
1437
|
if location == "header":
|
|
1419
1438
|
cont_token_property = f'pipeline_response.http_response.headers.get("{wire_name}") or None'
|
|
1439
|
+
elif builder.is_xml_paging:
|
|
1440
|
+
wire_name_array = wire_name.split(".")
|
|
1441
|
+
wire_name_call = "".join([f'.find("{i}")' for i in wire_name_array])
|
|
1442
|
+
cont_token_expr = f"deserialized{wire_name_call}"
|
|
1443
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1420
1444
|
else:
|
|
1421
1445
|
wire_name_array = wire_name.split(".")
|
|
1422
1446
|
wire_name_call = (
|
|
@@ -1429,6 +1453,11 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1429
1453
|
cont_token_property = "None"
|
|
1430
1454
|
elif self.code_model.options["models-mode"] == "msrest":
|
|
1431
1455
|
cont_token_property = f"deserialized.{next_link_name} or None"
|
|
1456
|
+
elif builder.is_xml_paging:
|
|
1457
|
+
next_link_name_array = next_link_name.split(".")
|
|
1458
|
+
access = "".join([f'.find("{i}")' for i in next_link_name_array])
|
|
1459
|
+
cont_token_expr = f"deserialized{access}"
|
|
1460
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1432
1461
|
elif builder.next_link_is_nested:
|
|
1433
1462
|
next_link_name_array = next_link_name.split(".")
|
|
1434
1463
|
access = (
|
|
@@ -1439,6 +1468,8 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1439
1468
|
else:
|
|
1440
1469
|
cont_token_property = f'deserialized.get("{next_link_name}") or None'
|
|
1441
1470
|
list_type = "AsyncList" if self.async_mode else "iter"
|
|
1471
|
+
if cont_token_expr:
|
|
1472
|
+
retval.append(f" _cont_token_elem = {cont_token_expr}")
|
|
1442
1473
|
retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
|
|
1443
1474
|
return retval
|
|
1444
1475
|
|
|
@@ -75,9 +75,11 @@ class GeneralSerializer(BaseSerializer):
|
|
|
75
75
|
# If parsing the pyproject.toml fails, we assume the it does not exist or is incorrectly formatted.
|
|
76
76
|
return result
|
|
77
77
|
|
|
78
|
-
# Keep "azure-sdk
|
|
79
|
-
if "tool" in loaded_pyproject_toml
|
|
80
|
-
|
|
78
|
+
# Keep "azure-sdk-*" and "packaging" configuration
|
|
79
|
+
if "tool" in loaded_pyproject_toml:
|
|
80
|
+
for key in loaded_pyproject_toml["tool"]:
|
|
81
|
+
if key.startswith("azure-sdk"):
|
|
82
|
+
result["KEEP_FIELDS"][f"tool.{key}"] = loaded_pyproject_toml["tool"][key]
|
|
81
83
|
if "packaging" in loaded_pyproject_toml:
|
|
82
84
|
result["KEEP_FIELDS"]["packaging"] = loaded_pyproject_toml["packaging"]
|
|
83
85
|
|
|
@@ -3,24 +3,69 @@
|
|
|
3
3
|
{%- set is_sphinx_doc = doc_string.strip().startswith(':ivar') or doc_string.strip().startswith(':vartype') or doc_string.strip().startswith(':param') or doc_string.strip().startswith(':type') -%}
|
|
4
4
|
{# Custom handling for bullet points - normalization is now done in preprocessing #}
|
|
5
5
|
{% set enable_custom_handling = "\n* " in doc_string or doc_string.startswith("* ") %}
|
|
6
|
+
{# Normalize multi-line descriptions by collapsing internal new_lines to spaces, but preserve special blocks #}
|
|
7
|
+
{%- if not enable_custom_handling -%}
|
|
8
|
+
{%- if '.. code-block::' in doc_string -%}
|
|
9
|
+
{# Split at code block and only normalize the prose before it #}
|
|
10
|
+
{%- set parts = doc_string.split('.. code-block::') -%}
|
|
11
|
+
{%- set prose = parts[0].rstrip() -%}
|
|
12
|
+
{%- set code_block = '.. code-block::' + parts[1:] | join('.. code-block::') -%}
|
|
13
|
+
{%- if '\n\n' not in prose -%}
|
|
14
|
+
{%- set normalized_lines = [] -%}
|
|
15
|
+
{%- for line in prose.split('\n') -%}
|
|
16
|
+
{%- set stripped = line.strip() -%}
|
|
17
|
+
{%- if stripped -%}
|
|
18
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
19
|
+
{%- endif -%}
|
|
20
|
+
{%- endfor -%}
|
|
21
|
+
{%- set doc_string = normalized_lines | join(' ') + '\n\n' + code_block -%}
|
|
22
|
+
{%- endif -%}
|
|
23
|
+
{%- elif '\n\n' not in doc_string -%}
|
|
24
|
+
{%- set normalized_lines = [] -%}
|
|
25
|
+
{%- for line in doc_string.split('\n') -%}
|
|
26
|
+
{%- set stripped = line.strip() -%}
|
|
27
|
+
{%- if stripped -%}
|
|
28
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
29
|
+
{%- endif -%}
|
|
30
|
+
{%- endfor -%}
|
|
31
|
+
{%- set doc_string = normalized_lines | join(' ') -%}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- endif -%}
|
|
6
34
|
{%- if enable_custom_handling -%}
|
|
7
|
-
{
|
|
35
|
+
{# First, normalize prose before bullet points by splitting at first bullet #}
|
|
36
|
+
{%- set normalized_doc = doc_string -%}
|
|
37
|
+
{%- if '\n* ' in doc_string -%}
|
|
38
|
+
{%- set parts = doc_string.split('\n* ', 1) -%}
|
|
39
|
+
{%- set prose_part = parts[0] -%}
|
|
40
|
+
{%- set bullet_part = '* ' + parts[1] -%}
|
|
41
|
+
{# Normalize the prose part #}
|
|
42
|
+
{%- set prose_lines = [] -%}
|
|
43
|
+
{%- for line in prose_part.split('\n') -%}
|
|
44
|
+
{%- set stripped = line.strip() -%}
|
|
45
|
+
{%- if stripped -%}
|
|
46
|
+
{%- set _ = prose_lines.append(stripped) -%}
|
|
47
|
+
{%- endif -%}
|
|
48
|
+
{%- endfor -%}
|
|
49
|
+
{%- set normalized_doc = prose_lines | join(' ') + '\n\n' + bullet_part -%}
|
|
50
|
+
{%- endif -%}
|
|
51
|
+
{%- set lines = normalized_doc.split('\n') -%}
|
|
8
52
|
{%- set base_indent = wrap_string.lstrip('\n') -%}
|
|
9
53
|
{%- set result_lines = [] -%}
|
|
10
54
|
{%- for line in lines -%}
|
|
11
|
-
{%- if line.startswith('* ') -%}
|
|
55
|
+
{%- if line.strip().startswith('* ') -%}
|
|
12
56
|
{# Handle bullet points with proper continuation alignment #}
|
|
13
|
-
{%- set bullet_content = line[2:] -%}
|
|
57
|
+
{%- set bullet_content = line.strip()[2:] -%}
|
|
14
58
|
{%- set bullet_line = base_indent + ' * ' + bullet_content -%}
|
|
15
59
|
{%- set continuation_spaces = base_indent + ' ' -%}
|
|
16
60
|
{%- set wrapped = bullet_line | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n' + continuation_spaces) -%}
|
|
17
61
|
{%- set _ = result_lines.append(wrapped) -%}
|
|
18
62
|
{%- elif line.strip() -%}
|
|
19
|
-
{%- set
|
|
20
|
-
{%- set
|
|
21
|
-
{%-
|
|
22
|
-
{%-
|
|
23
|
-
|
|
63
|
+
{%- set stripped_line = line.strip() -%}
|
|
64
|
+
{%- set line_indent = '' if stripped_line.startswith(':') or loop.index == 1 else (base_indent + ' ') -%}
|
|
65
|
+
{%- set wrapped = (line_indent + stripped_line) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
|
|
66
|
+
{%- for w_line in wrapped.split('\n') -%}
|
|
67
|
+
{%- set prefix = "" if loop.index == 1 else " " -%}
|
|
68
|
+
{%- set _ = result_lines.append(prefix + w_line) -%}
|
|
24
69
|
{%- endfor -%}
|
|
25
70
|
{%- else -%}
|
|
26
71
|
{# Do not add continuous blank lines #}
|
|
@@ -44,4 +89,4 @@
|
|
|
44
89
|
{% set suffix = suffix_string if list_result | length == loop.index %}
|
|
45
90
|
{{ prefix }}{{ line }}{{ suffix }}
|
|
46
91
|
{% endfor %}
|
|
47
|
-
{% endmacro %}
|
|
92
|
+
{% endmacro %}
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
{% macro wrap_string(string, wrapstring, width=95) %}
|
|
1
|
+
{% macro wrap_string(string, wrapstring, width=95) %}
|
|
2
|
+
{%- set normalized_string = string -%}
|
|
3
|
+
{# Normalize multi-line descriptions by collapsing internal newlines to spaces, but preserve special blocks #}
|
|
4
|
+
{# Skip normalization for pre-formatted content (strings starting with whitespace like code examples) #}
|
|
5
|
+
{%- if '\n* ' not in string and string == string.lstrip() -%}
|
|
6
|
+
{%- if '.. code-block::' in string -%}
|
|
7
|
+
{# Split at code block and only normalize the prose before it #}
|
|
8
|
+
{%- set parts = string.split('.. code-block::') -%}
|
|
9
|
+
{%- set prose = parts[0].rstrip() -%}
|
|
10
|
+
{%- set code_block = '.. code-block::' + parts[1:] | join('.. code-block::') -%}
|
|
11
|
+
{%- if '\n\n' not in prose -%}
|
|
12
|
+
{%- set normalized_lines = [] -%}
|
|
13
|
+
{%- for line in prose.split('\n') -%}
|
|
14
|
+
{%- set stripped = line.strip() -%}
|
|
15
|
+
{%- if stripped -%}
|
|
16
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
17
|
+
{%- endif -%}
|
|
18
|
+
{%- endfor -%}
|
|
19
|
+
{%- set normalized_string = normalized_lines | join(' ') + '\n\n' + code_block -%}
|
|
20
|
+
{%- endif -%}
|
|
21
|
+
{%- elif '\n\n' not in string -%}
|
|
22
|
+
{%- set normalized_lines = [] -%}
|
|
23
|
+
{%- for line in string.split('\n') -%}
|
|
24
|
+
{%- set stripped = line.strip() -%}
|
|
25
|
+
{%- if stripped -%}
|
|
26
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
27
|
+
{%- endif -%}
|
|
28
|
+
{%- endfor -%}
|
|
29
|
+
{%- set normalized_string = normalized_lines | join(' ') -%}
|
|
30
|
+
{%- endif -%}
|
|
31
|
+
{%- endif -%}
|
|
32
|
+
{{ normalized_string | replace("\\", "\\\\") | wordwrap(width=width, break_long_words=False, break_on_hyphens=False, wrapstring=wrapstring)}}{% endmacro %}
|
|
2
33
|
|
|
3
34
|
{% macro description(builder, serializer) %}
|
|
4
35
|
{% set example_template = serializer.example_template(builder) %}
|
package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2
CHANGED
|
@@ -109,13 +109,17 @@ exclude = [
|
|
|
109
109
|
[tool.setuptools.package-data]
|
|
110
110
|
pytyped = ["py.typed"]
|
|
111
111
|
{% endif %}
|
|
112
|
-
{% if KEEP_FIELDS
|
|
112
|
+
{% if KEEP_FIELDS %}
|
|
113
|
+
{% for field_key, field_val in KEEP_FIELDS.items() %}
|
|
114
|
+
{% if field_key.startswith('tool.azure-sdk') %}
|
|
113
115
|
|
|
114
|
-
[
|
|
115
|
-
{% for key, val in
|
|
116
|
+
[{{ field_key }}]
|
|
117
|
+
{% for key, val in field_val.items() %}
|
|
116
118
|
{{ key }} = {{ val|tojson }}
|
|
117
119
|
{% endfor %}
|
|
118
120
|
{% endif %}
|
|
121
|
+
{% endfor %}
|
|
122
|
+
{% endif %}
|
|
119
123
|
{% if KEEP_FIELDS and KEEP_FIELDS.get('packaging') %}
|
|
120
124
|
|
|
121
125
|
[packaging]
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
"install": [
|
|
5
5
|
{
|
|
6
6
|
"download_info": {
|
|
7
|
-
"url": "https://files.pythonhosted.org/packages/
|
|
7
|
+
"url": "https://files.pythonhosted.org/packages/94/b8/f1f62a5e3c0ad2ff1d189590bfa4c46b4f3b6e49cef6f26c6ee4e575394d/setuptools-80.10.2-py3-none-any.whl",
|
|
8
8
|
"archive_info": {
|
|
9
|
-
"hash": "sha256=
|
|
9
|
+
"hash": "sha256=95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173",
|
|
10
10
|
"hashes": {
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
},
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"metadata": {
|
|
19
19
|
"metadata_version": "2.4",
|
|
20
20
|
"name": "setuptools",
|
|
21
|
-
"version": "80.10.
|
|
21
|
+
"version": "80.10.2",
|
|
22
22
|
"dynamic": [
|
|
23
23
|
"license-file"
|
|
24
24
|
],
|
|
@@ -63,7 +63,6 @@
|
|
|
63
63
|
"tomli-w>=1.0.0; extra == \"test\"",
|
|
64
64
|
"pytest-timeout; extra == \"test\"",
|
|
65
65
|
"pytest-perf; sys_platform != \"cygwin\" and extra == \"test\"",
|
|
66
|
-
"pyobjc<12; (sys_platform == \"darwin\" and python_version <= \"3.9\") and extra == \"test\"",
|
|
67
66
|
"jaraco.develop>=7.21; (python_version >= \"3.9\" and sys_platform != \"cygwin\") and extra == \"test\"",
|
|
68
67
|
"pytest-home>=0.5; extra == \"test\"",
|
|
69
68
|
"pytest-subprocess; extra == \"test\"",
|
|
Binary file
|
|
@@ -448,7 +448,19 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
448
448
|
elif self.need_deserialize:
|
|
449
449
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
450
450
|
if self.default_error_deserialization(serialize_namespace) or self.non_default_errors:
|
|
451
|
-
|
|
451
|
+
xml_non_default_errors = any(
|
|
452
|
+
xml_serializable(str(e.default_content_type)) for e in self.non_default_errors
|
|
453
|
+
)
|
|
454
|
+
try:
|
|
455
|
+
default_error = next(e for e in self.exceptions if "default" in e.status_codes and e.type)
|
|
456
|
+
except StopIteration:
|
|
457
|
+
default_error = None
|
|
458
|
+
if xml_non_default_errors or (
|
|
459
|
+
default_error and xml_serializable(str(default_error.default_content_type))
|
|
460
|
+
):
|
|
461
|
+
file_import.add_submodule_import(relative_path, "_failsafe_deserialize_xml", ImportType.LOCAL)
|
|
462
|
+
else:
|
|
463
|
+
file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
|
|
452
464
|
return file_import
|
|
453
465
|
|
|
454
466
|
def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType:
|
|
@@ -73,6 +73,13 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
73
73
|
def next_variable_name(self) -> str:
|
|
74
74
|
return "_continuation_token" if self.has_continuation_token else "next_link"
|
|
75
75
|
|
|
76
|
+
@property
|
|
77
|
+
def is_xml_paging(self) -> bool:
|
|
78
|
+
try:
|
|
79
|
+
return bool(self.responses[0].item_type.xml_metadata)
|
|
80
|
+
except KeyError:
|
|
81
|
+
return False
|
|
82
|
+
|
|
76
83
|
def _get_attr_name(self, wire_name: str) -> str:
|
|
77
84
|
response_type = self.responses[0].type
|
|
78
85
|
if not response_type:
|
|
@@ -176,6 +183,9 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
176
183
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
177
184
|
if self.default_error_deserialization(serialize_namespace) or self.need_deserialize:
|
|
178
185
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
186
|
+
if self.is_xml_paging:
|
|
187
|
+
file_import.add_submodule_import("xml.etree", "ElementTree", ImportType.STDLIB, alias="ET")
|
|
188
|
+
file_import.add_submodule_import(relative_path, "_convert_element", ImportType.LOCAL)
|
|
179
189
|
return file_import
|
|
180
190
|
|
|
181
191
|
|
|
@@ -1045,7 +1045,9 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1045
1045
|
retval.extend([f" {l}" for l in response_read])
|
|
1046
1046
|
retval.append(" map_error(status_code=response.status_code, response=response, error_map=error_map)")
|
|
1047
1047
|
error_model = ""
|
|
1048
|
-
if
|
|
1048
|
+
if ( # pylint: disable=too-many-nested-blocks
|
|
1049
|
+
builder.non_default_errors and self.code_model.options["models-mode"]
|
|
1050
|
+
):
|
|
1049
1051
|
error_model = ", model=error"
|
|
1050
1052
|
condition = "if"
|
|
1051
1053
|
retval.append(" error = None")
|
|
@@ -1062,9 +1064,11 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1062
1064
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1063
1065
|
)
|
|
1064
1066
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1067
|
+
if xml_serializable(str(e.default_content_type)):
|
|
1068
|
+
fn = "_failsafe_deserialize_xml"
|
|
1069
|
+
else:
|
|
1070
|
+
fn = "_failsafe_deserialize"
|
|
1071
|
+
retval.append(f" error = {fn}({type_annotation},{pylint_disable}\n response)")
|
|
1068
1072
|
else:
|
|
1069
1073
|
retval.extend(
|
|
1070
1074
|
[
|
|
@@ -1130,9 +1134,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1130
1134
|
if builder.non_default_errors:
|
|
1131
1135
|
retval.append(" else:")
|
|
1132
1136
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1137
|
+
default_exception = next(e for e in builder.exceptions if "default" in e.status_codes and e.type)
|
|
1138
|
+
if xml_serializable(str(default_exception.default_content_type)):
|
|
1139
|
+
fn = "_failsafe_deserialize_xml"
|
|
1140
|
+
else:
|
|
1141
|
+
fn = "_failsafe_deserialize"
|
|
1133
1142
|
retval.extend(
|
|
1134
1143
|
[
|
|
1135
|
-
f"{indent}error =
|
|
1144
|
+
f"{indent}error = {fn}(",
|
|
1136
1145
|
f"{indent} {default_error_deserialization}",
|
|
1137
1146
|
f"{indent} response,",
|
|
1138
1147
|
f"{indent})",
|
|
@@ -1372,10 +1381,15 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1372
1381
|
def _function_def(self) -> str:
|
|
1373
1382
|
return "def"
|
|
1374
1383
|
|
|
1375
|
-
def _extract_data_callback(
|
|
1384
|
+
def _extract_data_callback( # pylint: disable=too-many-statements,too-many-branches
|
|
1385
|
+
self, builder: PagingOperationType
|
|
1386
|
+
) -> list[str]:
|
|
1376
1387
|
retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
|
|
1377
1388
|
response = builder.responses[0]
|
|
1378
|
-
|
|
1389
|
+
if builder.is_xml_paging:
|
|
1390
|
+
deserialized = "ET.fromstring(pipeline_response.http_response.text())"
|
|
1391
|
+
else:
|
|
1392
|
+
deserialized = "pipeline_response.http_response.json()"
|
|
1379
1393
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1380
1394
|
suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
|
|
1381
1395
|
deserialize_type = response.serialization_type(serialize_namespace=self.serialize_namespace)
|
|
@@ -1395,6 +1409,10 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1395
1409
|
item_name = builder.item_name
|
|
1396
1410
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1397
1411
|
access = f".{item_name}"
|
|
1412
|
+
elif builder.is_xml_paging:
|
|
1413
|
+
# For XML, use .find() to navigate the element tree
|
|
1414
|
+
item_name_array = item_name.split(".")
|
|
1415
|
+
access = "".join([f'.find("{i}")' for i in item_name_array])
|
|
1398
1416
|
else:
|
|
1399
1417
|
item_name_array = item_name.split(".")
|
|
1400
1418
|
access = (
|
|
@@ -1412,11 +1430,17 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1412
1430
|
retval.append(" if cls:")
|
|
1413
1431
|
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1414
1432
|
|
|
1433
|
+
cont_token_expr: Optional[str] = None # For XML, we need to extract find() result first
|
|
1415
1434
|
if builder.has_continuation_token:
|
|
1416
1435
|
location = builder.continuation_token.get("output", {}).get("location")
|
|
1417
1436
|
wire_name = builder.continuation_token.get("output", {}).get("wireName") or ""
|
|
1418
1437
|
if location == "header":
|
|
1419
1438
|
cont_token_property = f'pipeline_response.http_response.headers.get("{wire_name}") or None'
|
|
1439
|
+
elif builder.is_xml_paging:
|
|
1440
|
+
wire_name_array = wire_name.split(".")
|
|
1441
|
+
wire_name_call = "".join([f'.find("{i}")' for i in wire_name_array])
|
|
1442
|
+
cont_token_expr = f"deserialized{wire_name_call}"
|
|
1443
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1420
1444
|
else:
|
|
1421
1445
|
wire_name_array = wire_name.split(".")
|
|
1422
1446
|
wire_name_call = (
|
|
@@ -1429,6 +1453,11 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1429
1453
|
cont_token_property = "None"
|
|
1430
1454
|
elif self.code_model.options["models-mode"] == "msrest":
|
|
1431
1455
|
cont_token_property = f"deserialized.{next_link_name} or None"
|
|
1456
|
+
elif builder.is_xml_paging:
|
|
1457
|
+
next_link_name_array = next_link_name.split(".")
|
|
1458
|
+
access = "".join([f'.find("{i}")' for i in next_link_name_array])
|
|
1459
|
+
cont_token_expr = f"deserialized{access}"
|
|
1460
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1432
1461
|
elif builder.next_link_is_nested:
|
|
1433
1462
|
next_link_name_array = next_link_name.split(".")
|
|
1434
1463
|
access = (
|
|
@@ -1439,6 +1468,8 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1439
1468
|
else:
|
|
1440
1469
|
cont_token_property = f'deserialized.get("{next_link_name}") or None'
|
|
1441
1470
|
list_type = "AsyncList" if self.async_mode else "iter"
|
|
1471
|
+
if cont_token_expr:
|
|
1472
|
+
retval.append(f" _cont_token_elem = {cont_token_expr}")
|
|
1442
1473
|
retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
|
|
1443
1474
|
return retval
|
|
1444
1475
|
|
|
@@ -75,9 +75,11 @@ class GeneralSerializer(BaseSerializer):
|
|
|
75
75
|
# If parsing the pyproject.toml fails, we assume the it does not exist or is incorrectly formatted.
|
|
76
76
|
return result
|
|
77
77
|
|
|
78
|
-
# Keep "azure-sdk
|
|
79
|
-
if "tool" in loaded_pyproject_toml
|
|
80
|
-
|
|
78
|
+
# Keep "azure-sdk-*" and "packaging" configuration
|
|
79
|
+
if "tool" in loaded_pyproject_toml:
|
|
80
|
+
for key in loaded_pyproject_toml["tool"]:
|
|
81
|
+
if key.startswith("azure-sdk"):
|
|
82
|
+
result["KEEP_FIELDS"][f"tool.{key}"] = loaded_pyproject_toml["tool"][key]
|
|
81
83
|
if "packaging" in loaded_pyproject_toml:
|
|
82
84
|
result["KEEP_FIELDS"]["packaging"] = loaded_pyproject_toml["packaging"]
|
|
83
85
|
|
|
@@ -3,24 +3,69 @@
|
|
|
3
3
|
{%- set is_sphinx_doc = doc_string.strip().startswith(':ivar') or doc_string.strip().startswith(':vartype') or doc_string.strip().startswith(':param') or doc_string.strip().startswith(':type') -%}
|
|
4
4
|
{# Custom handling for bullet points - normalization is now done in preprocessing #}
|
|
5
5
|
{% set enable_custom_handling = "\n* " in doc_string or doc_string.startswith("* ") %}
|
|
6
|
+
{# Normalize multi-line descriptions by collapsing internal new_lines to spaces, but preserve special blocks #}
|
|
7
|
+
{%- if not enable_custom_handling -%}
|
|
8
|
+
{%- if '.. code-block::' in doc_string -%}
|
|
9
|
+
{# Split at code block and only normalize the prose before it #}
|
|
10
|
+
{%- set parts = doc_string.split('.. code-block::') -%}
|
|
11
|
+
{%- set prose = parts[0].rstrip() -%}
|
|
12
|
+
{%- set code_block = '.. code-block::' + parts[1:] | join('.. code-block::') -%}
|
|
13
|
+
{%- if '\n\n' not in prose -%}
|
|
14
|
+
{%- set normalized_lines = [] -%}
|
|
15
|
+
{%- for line in prose.split('\n') -%}
|
|
16
|
+
{%- set stripped = line.strip() -%}
|
|
17
|
+
{%- if stripped -%}
|
|
18
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
19
|
+
{%- endif -%}
|
|
20
|
+
{%- endfor -%}
|
|
21
|
+
{%- set doc_string = normalized_lines | join(' ') + '\n\n' + code_block -%}
|
|
22
|
+
{%- endif -%}
|
|
23
|
+
{%- elif '\n\n' not in doc_string -%}
|
|
24
|
+
{%- set normalized_lines = [] -%}
|
|
25
|
+
{%- for line in doc_string.split('\n') -%}
|
|
26
|
+
{%- set stripped = line.strip() -%}
|
|
27
|
+
{%- if stripped -%}
|
|
28
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
29
|
+
{%- endif -%}
|
|
30
|
+
{%- endfor -%}
|
|
31
|
+
{%- set doc_string = normalized_lines | join(' ') -%}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- endif -%}
|
|
6
34
|
{%- if enable_custom_handling -%}
|
|
7
|
-
{
|
|
35
|
+
{# First, normalize prose before bullet points by splitting at first bullet #}
|
|
36
|
+
{%- set normalized_doc = doc_string -%}
|
|
37
|
+
{%- if '\n* ' in doc_string -%}
|
|
38
|
+
{%- set parts = doc_string.split('\n* ', 1) -%}
|
|
39
|
+
{%- set prose_part = parts[0] -%}
|
|
40
|
+
{%- set bullet_part = '* ' + parts[1] -%}
|
|
41
|
+
{# Normalize the prose part #}
|
|
42
|
+
{%- set prose_lines = [] -%}
|
|
43
|
+
{%- for line in prose_part.split('\n') -%}
|
|
44
|
+
{%- set stripped = line.strip() -%}
|
|
45
|
+
{%- if stripped -%}
|
|
46
|
+
{%- set _ = prose_lines.append(stripped) -%}
|
|
47
|
+
{%- endif -%}
|
|
48
|
+
{%- endfor -%}
|
|
49
|
+
{%- set normalized_doc = prose_lines | join(' ') + '\n\n' + bullet_part -%}
|
|
50
|
+
{%- endif -%}
|
|
51
|
+
{%- set lines = normalized_doc.split('\n') -%}
|
|
8
52
|
{%- set base_indent = wrap_string.lstrip('\n') -%}
|
|
9
53
|
{%- set result_lines = [] -%}
|
|
10
54
|
{%- for line in lines -%}
|
|
11
|
-
{%- if line.startswith('* ') -%}
|
|
55
|
+
{%- if line.strip().startswith('* ') -%}
|
|
12
56
|
{# Handle bullet points with proper continuation alignment #}
|
|
13
|
-
{%- set bullet_content = line[2:] -%}
|
|
57
|
+
{%- set bullet_content = line.strip()[2:] -%}
|
|
14
58
|
{%- set bullet_line = base_indent + ' * ' + bullet_content -%}
|
|
15
59
|
{%- set continuation_spaces = base_indent + ' ' -%}
|
|
16
60
|
{%- set wrapped = bullet_line | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n' + continuation_spaces) -%}
|
|
17
61
|
{%- set _ = result_lines.append(wrapped) -%}
|
|
18
62
|
{%- elif line.strip() -%}
|
|
19
|
-
{%- set
|
|
20
|
-
{%- set
|
|
21
|
-
{%-
|
|
22
|
-
{%-
|
|
23
|
-
|
|
63
|
+
{%- set stripped_line = line.strip() -%}
|
|
64
|
+
{%- set line_indent = '' if stripped_line.startswith(':') or loop.index == 1 else (base_indent + ' ') -%}
|
|
65
|
+
{%- set wrapped = (line_indent + stripped_line) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
|
|
66
|
+
{%- for w_line in wrapped.split('\n') -%}
|
|
67
|
+
{%- set prefix = "" if loop.index == 1 else " " -%}
|
|
68
|
+
{%- set _ = result_lines.append(prefix + w_line) -%}
|
|
24
69
|
{%- endfor -%}
|
|
25
70
|
{%- else -%}
|
|
26
71
|
{# Do not add continuous blank lines #}
|
|
@@ -44,4 +89,4 @@
|
|
|
44
89
|
{% set suffix = suffix_string if list_result | length == loop.index %}
|
|
45
90
|
{{ prefix }}{{ line }}{{ suffix }}
|
|
46
91
|
{% endfor %}
|
|
47
|
-
{% endmacro %}
|
|
92
|
+
{% endmacro %}
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
{% macro wrap_string(string, wrapstring, width=95) %}
|
|
1
|
+
{% macro wrap_string(string, wrapstring, width=95) %}
|
|
2
|
+
{%- set normalized_string = string -%}
|
|
3
|
+
{# Normalize multi-line descriptions by collapsing internal newlines to spaces, but preserve special blocks #}
|
|
4
|
+
{# Skip normalization for pre-formatted content (strings starting with whitespace like code examples) #}
|
|
5
|
+
{%- if '\n* ' not in string and string == string.lstrip() -%}
|
|
6
|
+
{%- if '.. code-block::' in string -%}
|
|
7
|
+
{# Split at code block and only normalize the prose before it #}
|
|
8
|
+
{%- set parts = string.split('.. code-block::') -%}
|
|
9
|
+
{%- set prose = parts[0].rstrip() -%}
|
|
10
|
+
{%- set code_block = '.. code-block::' + parts[1:] | join('.. code-block::') -%}
|
|
11
|
+
{%- if '\n\n' not in prose -%}
|
|
12
|
+
{%- set normalized_lines = [] -%}
|
|
13
|
+
{%- for line in prose.split('\n') -%}
|
|
14
|
+
{%- set stripped = line.strip() -%}
|
|
15
|
+
{%- if stripped -%}
|
|
16
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
17
|
+
{%- endif -%}
|
|
18
|
+
{%- endfor -%}
|
|
19
|
+
{%- set normalized_string = normalized_lines | join(' ') + '\n\n' + code_block -%}
|
|
20
|
+
{%- endif -%}
|
|
21
|
+
{%- elif '\n\n' not in string -%}
|
|
22
|
+
{%- set normalized_lines = [] -%}
|
|
23
|
+
{%- for line in string.split('\n') -%}
|
|
24
|
+
{%- set stripped = line.strip() -%}
|
|
25
|
+
{%- if stripped -%}
|
|
26
|
+
{%- set _ = normalized_lines.append(stripped) -%}
|
|
27
|
+
{%- endif -%}
|
|
28
|
+
{%- endfor -%}
|
|
29
|
+
{%- set normalized_string = normalized_lines | join(' ') -%}
|
|
30
|
+
{%- endif -%}
|
|
31
|
+
{%- endif -%}
|
|
32
|
+
{{ normalized_string | replace("\\", "\\\\") | wordwrap(width=width, break_long_words=False, break_on_hyphens=False, wrapstring=wrapstring)}}{% endmacro %}
|
|
2
33
|
|
|
3
34
|
{% macro description(builder, serializer) %}
|
|
4
35
|
{% set example_template = serializer.example_template(builder) %}
|
|
@@ -109,13 +109,17 @@ exclude = [
|
|
|
109
109
|
[tool.setuptools.package-data]
|
|
110
110
|
pytyped = ["py.typed"]
|
|
111
111
|
{% endif %}
|
|
112
|
-
{% if KEEP_FIELDS
|
|
112
|
+
{% if KEEP_FIELDS %}
|
|
113
|
+
{% for field_key, field_val in KEEP_FIELDS.items() %}
|
|
114
|
+
{% if field_key.startswith('tool.azure-sdk') %}
|
|
113
115
|
|
|
114
|
-
[
|
|
115
|
-
{% for key, val in
|
|
116
|
+
[{{ field_key }}]
|
|
117
|
+
{% for key, val in field_val.items() %}
|
|
116
118
|
{{ key }} = {{ val|tojson }}
|
|
117
119
|
{% endfor %}
|
|
118
120
|
{% endif %}
|
|
121
|
+
{% endfor %}
|
|
122
|
+
{% endif %}
|
|
119
123
|
{% if KEEP_FIELDS and KEEP_FIELDS.get('packaging') %}
|
|
120
124
|
|
|
121
125
|
[packaging]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autorest/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.48.1",
|
|
4
4
|
"description": "The Python extension for generators in AutoRest.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"homepage": "https://github.com/Azure/autorest.python/blob/main/README.md",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@typespec/http-client-python": "~0.
|
|
22
|
+
"@typespec/http-client-python": "~0.26.1",
|
|
23
23
|
"@autorest/system-requirements": "~1.0.2",
|
|
24
24
|
"fs-extra": "~11.2.0",
|
|
25
25
|
"tsx": "~4.19.1"
|
|
Binary file
|