@autorest/python 6.46.1 → 6.48.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/generator/build/lib/pygen/codegen/models/paging_operation.py +10 -0
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +24 -2
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +20 -10
- package/generator/component-detection-pip-report.json +4 -4
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/paging_operation.py +10 -0
- package/generator/pygen/codegen/serializers/builder_serializer.py +24 -2
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +20 -10
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
|
@@ -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
|
|
|
@@ -1372,10 +1372,15 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1372
1372
|
def _function_def(self) -> str:
|
|
1373
1373
|
return "def"
|
|
1374
1374
|
|
|
1375
|
-
def _extract_data_callback(
|
|
1375
|
+
def _extract_data_callback( # pylint: disable=too-many-statements,too-many-branches
|
|
1376
|
+
self, builder: PagingOperationType
|
|
1377
|
+
) -> list[str]:
|
|
1376
1378
|
retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
|
|
1377
1379
|
response = builder.responses[0]
|
|
1378
|
-
|
|
1380
|
+
if builder.is_xml_paging:
|
|
1381
|
+
deserialized = "ET.fromstring(pipeline_response.http_response.text())"
|
|
1382
|
+
else:
|
|
1383
|
+
deserialized = "pipeline_response.http_response.json()"
|
|
1379
1384
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1380
1385
|
suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
|
|
1381
1386
|
deserialize_type = response.serialization_type(serialize_namespace=self.serialize_namespace)
|
|
@@ -1395,6 +1400,10 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1395
1400
|
item_name = builder.item_name
|
|
1396
1401
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1397
1402
|
access = f".{item_name}"
|
|
1403
|
+
elif builder.is_xml_paging:
|
|
1404
|
+
# For XML, use .find() to navigate the element tree
|
|
1405
|
+
item_name_array = item_name.split(".")
|
|
1406
|
+
access = "".join([f'.find("{i}")' for i in item_name_array])
|
|
1398
1407
|
else:
|
|
1399
1408
|
item_name_array = item_name.split(".")
|
|
1400
1409
|
access = (
|
|
@@ -1412,11 +1421,17 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1412
1421
|
retval.append(" if cls:")
|
|
1413
1422
|
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1414
1423
|
|
|
1424
|
+
cont_token_expr: Optional[str] = None # For XML, we need to extract find() result first
|
|
1415
1425
|
if builder.has_continuation_token:
|
|
1416
1426
|
location = builder.continuation_token.get("output", {}).get("location")
|
|
1417
1427
|
wire_name = builder.continuation_token.get("output", {}).get("wireName") or ""
|
|
1418
1428
|
if location == "header":
|
|
1419
1429
|
cont_token_property = f'pipeline_response.http_response.headers.get("{wire_name}") or None'
|
|
1430
|
+
elif builder.is_xml_paging:
|
|
1431
|
+
wire_name_array = wire_name.split(".")
|
|
1432
|
+
wire_name_call = "".join([f'.find("{i}")' for i in wire_name_array])
|
|
1433
|
+
cont_token_expr = f"deserialized{wire_name_call}"
|
|
1434
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1420
1435
|
else:
|
|
1421
1436
|
wire_name_array = wire_name.split(".")
|
|
1422
1437
|
wire_name_call = (
|
|
@@ -1429,6 +1444,11 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1429
1444
|
cont_token_property = "None"
|
|
1430
1445
|
elif self.code_model.options["models-mode"] == "msrest":
|
|
1431
1446
|
cont_token_property = f"deserialized.{next_link_name} or None"
|
|
1447
|
+
elif builder.is_xml_paging:
|
|
1448
|
+
next_link_name_array = next_link_name.split(".")
|
|
1449
|
+
access = "".join([f'.find("{i}")' for i in next_link_name_array])
|
|
1450
|
+
cont_token_expr = f"deserialized{access}"
|
|
1451
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1432
1452
|
elif builder.next_link_is_nested:
|
|
1433
1453
|
next_link_name_array = next_link_name.split(".")
|
|
1434
1454
|
access = (
|
|
@@ -1439,6 +1459,8 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1439
1459
|
else:
|
|
1440
1460
|
cont_token_property = f'deserialized.get("{next_link_name}") or None'
|
|
1441
1461
|
list_type = "AsyncList" if self.async_mode else "iter"
|
|
1462
|
+
if cont_token_expr:
|
|
1463
|
+
retval.append(f" _cont_token_elem = {cont_token_expr}")
|
|
1442
1464
|
retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
|
|
1443
1465
|
return retval
|
|
1444
1466
|
|
|
@@ -848,6 +848,14 @@ def _deserialize_multiple_sequence(
|
|
|
848
848
|
return type(obj)(_deserialize(deserializer, entry, module) for entry, deserializer in zip(obj, entry_deserializers))
|
|
849
849
|
|
|
850
850
|
|
|
851
|
+
def _is_array_encoded_deserializer(deserializer: functools.partial) -> bool:
|
|
852
|
+
return (
|
|
853
|
+
isinstance(deserializer, functools.partial)
|
|
854
|
+
and isinstance(deserializer.args[0], functools.partial)
|
|
855
|
+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
|
|
851
859
|
def _deserialize_sequence(
|
|
852
860
|
deserializer: typing.Optional[typing.Callable],
|
|
853
861
|
module: typing.Optional[str],
|
|
@@ -857,17 +865,19 @@ def _deserialize_sequence(
|
|
|
857
865
|
return obj
|
|
858
866
|
if isinstance(obj, ET.Element):
|
|
859
867
|
obj = list(obj)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
|
|
866
|
-
):
|
|
867
|
-
# encoded string may be deserialized to sequence
|
|
868
|
+
|
|
869
|
+
# encoded string may be deserialized to sequence
|
|
870
|
+
if isinstance(obj, str) and isinstance(deserializer, functools.partial):
|
|
871
|
+
# for list[str]
|
|
872
|
+
if _is_array_encoded_deserializer(deserializer):
|
|
868
873
|
return deserializer(obj)
|
|
869
|
-
|
|
870
|
-
|
|
874
|
+
|
|
875
|
+
# for list[Union[...]]
|
|
876
|
+
if isinstance(deserializer.args[0], list):
|
|
877
|
+
for sub_deserializer in deserializer.args[0]:
|
|
878
|
+
if _is_array_encoded_deserializer(sub_deserializer):
|
|
879
|
+
return sub_deserializer(obj)
|
|
880
|
+
|
|
871
881
|
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
|
|
872
882
|
|
|
873
883
|
|
|
@@ -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.
|
|
21
|
+
"version": "80.10.2",
|
|
22
22
|
"dynamic": [
|
|
23
23
|
"license-file"
|
|
24
24
|
],
|
|
Binary file
|
|
@@ -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
|
|
|
@@ -1372,10 +1372,15 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1372
1372
|
def _function_def(self) -> str:
|
|
1373
1373
|
return "def"
|
|
1374
1374
|
|
|
1375
|
-
def _extract_data_callback(
|
|
1375
|
+
def _extract_data_callback( # pylint: disable=too-many-statements,too-many-branches
|
|
1376
|
+
self, builder: PagingOperationType
|
|
1377
|
+
) -> list[str]:
|
|
1376
1378
|
retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
|
|
1377
1379
|
response = builder.responses[0]
|
|
1378
|
-
|
|
1380
|
+
if builder.is_xml_paging:
|
|
1381
|
+
deserialized = "ET.fromstring(pipeline_response.http_response.text())"
|
|
1382
|
+
else:
|
|
1383
|
+
deserialized = "pipeline_response.http_response.json()"
|
|
1379
1384
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1380
1385
|
suffix = ".http_response" if hasattr(builder, "initial_operation") else ""
|
|
1381
1386
|
deserialize_type = response.serialization_type(serialize_namespace=self.serialize_namespace)
|
|
@@ -1395,6 +1400,10 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1395
1400
|
item_name = builder.item_name
|
|
1396
1401
|
if self.code_model.options["models-mode"] == "msrest":
|
|
1397
1402
|
access = f".{item_name}"
|
|
1403
|
+
elif builder.is_xml_paging:
|
|
1404
|
+
# For XML, use .find() to navigate the element tree
|
|
1405
|
+
item_name_array = item_name.split(".")
|
|
1406
|
+
access = "".join([f'.find("{i}")' for i in item_name_array])
|
|
1398
1407
|
else:
|
|
1399
1408
|
item_name_array = item_name.split(".")
|
|
1400
1409
|
access = (
|
|
@@ -1412,11 +1421,17 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1412
1421
|
retval.append(" if cls:")
|
|
1413
1422
|
retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
|
|
1414
1423
|
|
|
1424
|
+
cont_token_expr: Optional[str] = None # For XML, we need to extract find() result first
|
|
1415
1425
|
if builder.has_continuation_token:
|
|
1416
1426
|
location = builder.continuation_token.get("output", {}).get("location")
|
|
1417
1427
|
wire_name = builder.continuation_token.get("output", {}).get("wireName") or ""
|
|
1418
1428
|
if location == "header":
|
|
1419
1429
|
cont_token_property = f'pipeline_response.http_response.headers.get("{wire_name}") or None'
|
|
1430
|
+
elif builder.is_xml_paging:
|
|
1431
|
+
wire_name_array = wire_name.split(".")
|
|
1432
|
+
wire_name_call = "".join([f'.find("{i}")' for i in wire_name_array])
|
|
1433
|
+
cont_token_expr = f"deserialized{wire_name_call}"
|
|
1434
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1420
1435
|
else:
|
|
1421
1436
|
wire_name_array = wire_name.split(".")
|
|
1422
1437
|
wire_name_call = (
|
|
@@ -1429,6 +1444,11 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1429
1444
|
cont_token_property = "None"
|
|
1430
1445
|
elif self.code_model.options["models-mode"] == "msrest":
|
|
1431
1446
|
cont_token_property = f"deserialized.{next_link_name} or None"
|
|
1447
|
+
elif builder.is_xml_paging:
|
|
1448
|
+
next_link_name_array = next_link_name.split(".")
|
|
1449
|
+
access = "".join([f'.find("{i}")' for i in next_link_name_array])
|
|
1450
|
+
cont_token_expr = f"deserialized{access}"
|
|
1451
|
+
cont_token_property = "_cont_token_elem.text if _cont_token_elem is not None else None"
|
|
1432
1452
|
elif builder.next_link_is_nested:
|
|
1433
1453
|
next_link_name_array = next_link_name.split(".")
|
|
1434
1454
|
access = (
|
|
@@ -1439,6 +1459,8 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1439
1459
|
else:
|
|
1440
1460
|
cont_token_property = f'deserialized.get("{next_link_name}") or None'
|
|
1441
1461
|
list_type = "AsyncList" if self.async_mode else "iter"
|
|
1462
|
+
if cont_token_expr:
|
|
1463
|
+
retval.append(f" _cont_token_elem = {cont_token_expr}")
|
|
1442
1464
|
retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
|
|
1443
1465
|
return retval
|
|
1444
1466
|
|
|
@@ -848,6 +848,14 @@ def _deserialize_multiple_sequence(
|
|
|
848
848
|
return type(obj)(_deserialize(deserializer, entry, module) for entry, deserializer in zip(obj, entry_deserializers))
|
|
849
849
|
|
|
850
850
|
|
|
851
|
+
def _is_array_encoded_deserializer(deserializer: functools.partial) -> bool:
|
|
852
|
+
return (
|
|
853
|
+
isinstance(deserializer, functools.partial)
|
|
854
|
+
and isinstance(deserializer.args[0], functools.partial)
|
|
855
|
+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
|
|
851
859
|
def _deserialize_sequence(
|
|
852
860
|
deserializer: typing.Optional[typing.Callable],
|
|
853
861
|
module: typing.Optional[str],
|
|
@@ -857,17 +865,19 @@ def _deserialize_sequence(
|
|
|
857
865
|
return obj
|
|
858
866
|
if isinstance(obj, ET.Element):
|
|
859
867
|
obj = list(obj)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
|
|
866
|
-
):
|
|
867
|
-
# encoded string may be deserialized to sequence
|
|
868
|
+
|
|
869
|
+
# encoded string may be deserialized to sequence
|
|
870
|
+
if isinstance(obj, str) and isinstance(deserializer, functools.partial):
|
|
871
|
+
# for list[str]
|
|
872
|
+
if _is_array_encoded_deserializer(deserializer):
|
|
868
873
|
return deserializer(obj)
|
|
869
|
-
|
|
870
|
-
|
|
874
|
+
|
|
875
|
+
# for list[Union[...]]
|
|
876
|
+
if isinstance(deserializer.args[0], list):
|
|
877
|
+
for sub_deserializer in deserializer.args[0]:
|
|
878
|
+
if _is_array_encoded_deserializer(sub_deserializer):
|
|
879
|
+
return sub_deserializer(obj)
|
|
880
|
+
|
|
871
881
|
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
|
|
872
882
|
|
|
873
883
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autorest/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.48.0",
|
|
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.0",
|
|
23
23
|
"@autorest/system-requirements": "~1.0.2",
|
|
24
24
|
"fs-extra": "~11.2.0",
|
|
25
25
|
"tsx": "~4.19.1"
|
|
Binary file
|