From 371f8d2df4f1f1a6cc84827b8ed1252f74cdf777 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 05:41:31 +0000 Subject: [PATCH 1/2] Initial plan From 40df10d74880ab17d30b226cf262bd0de0199593 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 06:02:53 +0000 Subject: [PATCH 2/2] feat: add XML enum/datetime mock API tests and fix XML deserialization for enum/datetime types Co-authored-by: msyyc <70930885+msyyc@users.noreply.github.com> --- ...ml-enum-datetime-tests-2026-2-14-5-42-5.md | 7 +++++++ .../codegen/templates/model_base.py.jinja2 | 8 +++++-- .../asynctests/test_payload_xml_async.py | 21 +++++++++++++++++++ .../test_payload_xml.py | 19 +++++++++++++++++ packages/http-client-python/package-lock.json | 19 +++++++++-------- packages/http-client-python/package.json | 2 +- 6 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 .chronus/changes/http-client-python-xml-enum-datetime-tests-2026-2-14-5-42-5.md diff --git a/.chronus/changes/http-client-python-xml-enum-datetime-tests-2026-2-14-5-42-5.md b/.chronus/changes/http-client-python-xml-enum-datetime-tests-2026-2-14-5-42-5.md new file mode 100644 index 00000000000..f378830d95b --- /dev/null +++ b/.chronus/changes/http-client-python-xml-enum-datetime-tests-2026-2-14-5-42-5.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/http-client-python" +--- + +Add mock API tests for XML model with enum and datetime properties, and fix XML deserialization for enum and datetime types diff --git a/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 b/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 index b42f50ef661..81f51a33e44 100644 --- a/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 +++ b/packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2 @@ -1020,16 +1020,20 @@ def _deserialize_with_callable( return float(value.text) if value.text else None if deserializer is bool: return value.text == "true" if value.text else None + if callable(deserializer) and deserializer in _DESERIALIZE_MAPPING.values(): + return deserializer(value.text) + if callable(deserializer) and deserializer in _DESERIALIZE_MAPPING_WITHFORMAT.values(): + return deserializer(value.text) if deserializer is None: return value if deserializer in [int, float, bool]: return deserializer(value) if isinstance(deserializer, CaseInsensitiveEnumMeta): try: - return deserializer(value) + return deserializer(value.text if isinstance(value, ET.Element) else value) except ValueError: # for unknown value, return raw value - return value + return value.text if isinstance(value, ET.Element) else value if isinstance(deserializer, type) and issubclass(deserializer, Model): return deserializer._deserialize(value, []) return typing.cast(typing.Callable[[typing.Any], typing.Any], deserializer)(value) diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py b/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py index 28693b8c286..7d88ecbbb5c 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +++ b/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +import datetime import pytest from payload.xml.aio import XmlClient from payload.xml.models import ( @@ -18,6 +19,8 @@ ModelWithText, ModelWithDictionary, ModelWithEncodedNames, + ModelWithEnum, + ModelWithDatetime, ) @@ -119,6 +122,24 @@ async def test_model_with_encoded_names(client: XmlClient): await client.model_with_encoded_names_value.put(model) +@pytest.mark.asyncio +async def test_model_with_enum(client: XmlClient): + model = ModelWithEnum(status="success") + assert await client.model_with_enum_value.get() == model + await client.model_with_enum_value.put(model) + + +@pytest.mark.asyncio +async def test_model_with_datetime(client: XmlClient): + model = ModelWithDatetime( + rfc3339=datetime.datetime(2022, 8, 26, 18, 38, 0, tzinfo=datetime.timezone.utc), + rfc7231=datetime.datetime(2022, 8, 26, 14, 38, 0, tzinfo=datetime.timezone.utc), + ) + result = await client.model_with_datetime_value.get() + assert result.rfc3339 == model.rfc3339 + assert result.rfc7231 == model.rfc7231 + + @pytest.mark.asyncio async def test_xml_error_value(client: XmlClient, core_library): with pytest.raises(core_library.exceptions.HttpResponseError) as ex: diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py b/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py index f5e7a2da671..a1918285168 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py +++ b/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +import datetime import pytest from payload.xml import XmlClient from payload.xml.models import ( @@ -18,6 +19,8 @@ ModelWithText, ModelWithDictionary, ModelWithEncodedNames, + ModelWithEnum, + ModelWithDatetime, ) @@ -107,6 +110,22 @@ def test_model_with_encoded_names(client: XmlClient): client.model_with_encoded_names_value.put(model) +def test_model_with_enum(client: XmlClient): + model = ModelWithEnum(status="success") + assert client.model_with_enum_value.get() == model + client.model_with_enum_value.put(model) + + +def test_model_with_datetime(client: XmlClient): + model = ModelWithDatetime( + rfc3339=datetime.datetime(2022, 8, 26, 18, 38, 0, tzinfo=datetime.timezone.utc), + rfc7231=datetime.datetime(2022, 8, 26, 14, 38, 0, tzinfo=datetime.timezone.utc), + ) + result = client.model_with_datetime_value.get() + assert result.rfc3339 == model.rfc3339 + assert result.rfc7231 == model.rfc7231 + + def test_xml_error_value(client: XmlClient, core_library): with pytest.raises(core_library.exceptions.HttpResponseError) as ex: client.xml_error_value.get() diff --git a/packages/http-client-python/package-lock.json b/packages/http-client-python/package-lock.json index ee93f122732..e9f04b8b6e5 100644 --- a/packages/http-client-python/package-lock.json +++ b/packages/http-client-python/package-lock.json @@ -29,7 +29,7 @@ "@typespec/compiler": "^1.9.0", "@typespec/events": "~0.79.0", "@typespec/http": "^1.9.0", - "@typespec/http-specs": "0.1.0-alpha.32", + "@typespec/http-specs": "0.1.0-alpha.33-dev.2", "@typespec/openapi": "^1.9.0", "@typespec/rest": "~0.79.0", "@typespec/spec-api": "0.1.0-alpha.12", @@ -2486,14 +2486,14 @@ } }, "node_modules/@typespec/http-specs": { - "version": "0.1.0-alpha.32", - "resolved": "https://registry.npmjs.org/@typespec/http-specs/-/http-specs-0.1.0-alpha.32.tgz", - "integrity": "sha512-a5kOR6M6H23+w4cmYyprh/2Oa5bmPmz6wOQKc9cKfXH8f2sFJ4ViIHBMovyAl5HsSaDAY4VvVz1vmEWA+OWj8g==", + "version": "0.1.0-alpha.33-dev.2", + "resolved": "https://registry.npmjs.org/@typespec/http-specs/-/http-specs-0.1.0-alpha.33-dev.2.tgz", + "integrity": "sha512-Ex7PVBJgJAmNLKMbp9jA6+fXalcau3Rf+J7N8XMwCICvz6yFcRJKF07/NsM3Doc87e43VovnrJb2I2tb7LSuDw==", "dev": true, "license": "MIT", "dependencies": { - "@typespec/spec-api": "^0.1.0-alpha.12", - "@typespec/spector": "^0.1.0-alpha.23", + "@typespec/spec-api": "^0.1.0-alpha.12 || >=0.1.0-alpha.13-dev <0.1.0-alpha.13", + "@typespec/spector": "^0.1.0-alpha.23 || >=0.1.0-alpha.24-dev <0.1.0-alpha.24", "deep-equal": "^2.2.0" }, "engines": { @@ -2502,9 +2502,9 @@ "peerDependencies": { "@typespec/compiler": "^1.9.0", "@typespec/http": "^1.9.0", - "@typespec/rest": "^0.79.0", - "@typespec/versioning": "^0.79.0", - "@typespec/xml": "^0.79.0" + "@typespec/rest": "^0.79.0 || >=0.80.0-dev <0.80.0", + "@typespec/versioning": "^0.79.0 || >=0.80.0-dev <0.80.0", + "@typespec/xml": "^0.79.0 || >=0.80.0-dev <0.80.0" } }, "node_modules/@typespec/openapi": { @@ -7265,6 +7265,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/packages/http-client-python/package.json b/packages/http-client-python/package.json index 249dc8c3fe5..ffeeb32836c 100644 --- a/packages/http-client-python/package.json +++ b/packages/http-client-python/package.json @@ -94,7 +94,7 @@ "@typespec/sse": "~0.79.0", "@typespec/streams": "~0.79.0", "@typespec/xml": "~0.79.0", - "@typespec/http-specs": "0.1.0-alpha.32", + "@typespec/http-specs": "0.1.0-alpha.33-dev.2", "@types/js-yaml": "~4.0.5", "@types/node": "~25.0.2", "@types/semver": "7.5.8",