diff --git a/.chronus/changes/python-fix-enum-member-reserved-word-suffix-2026-03-06-12-00-00.md b/.chronus/changes/python-fix-enum-member-reserved-word-suffix-2026-03-06-12-00-00.md new file mode 100644 index 00000000000..c3ed9c2c4e2 --- /dev/null +++ b/.chronus/changes/python-fix-enum-member-reserved-word-suffix-2026-03-06-12-00-00.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-python" +--- + +Fix extensible enum member names incorrectly getting an `Enum` suffix when the member name matched a Python reserved word (e.g. `ANDEnum` → `AND`, `CLASSEnum` → `CLASS`). diff --git a/.chronus/changes/python-special-words-extensible-strings-2026-3-6-9-28-8.md b/.chronus/changes/python-special-words-extensible-strings-2026-3-6-9-28-8.md new file mode 100644 index 00000000000..094e09a7d14 --- /dev/null +++ b/.chronus/changes/python-special-words-extensible-strings-2026-3-6-9-28-8.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/http-client-python" +--- + +Add mock API test coverage for extensible enum with special word member names in special-words spec. diff --git a/packages/http-client-python/generator/pygen/preprocess/__init__.py b/packages/http-client-python/generator/pygen/preprocess/__init__.py index e2f8cf842b3..5a784c2a783 100644 --- a/packages/http-client-python/generator/pygen/preprocess/__init__.py +++ b/packages/http-client-python/generator/pygen/preprocess/__init__.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- """The preprocessing autorest plugin.""" + import copy from typing import Callable, Any, Optional @@ -264,7 +265,7 @@ def update_types(self, yaml_data: list[dict[str, Any]]) -> None: property["clientName"].lower(), PadType.PROPERTY, property ) add_redefined_builtin_info(property["clientName"], property) - if type.get("name"): + if type.get("name") and type["type"] != "enumvalue": pad_type = PadType.MODEL if type["type"] == "model" else PadType.ENUM_CLASS name = self.pad_reserved_words(type["name"], pad_type, type) type["name"] = name[0].upper() + name[1:] diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py b/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py index 9f22c8c5d15..39a150e4db9 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py +++ b/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py @@ -6,6 +6,7 @@ import pytest from specialwords.aio import SpecialWordsClient from specialwords import models +from specialwords.extensiblestrings import models as extensible_strings_models @pytest.fixture @@ -63,3 +64,9 @@ async def test_model_properties_dict_methods(client: SpecialWordsClient): @pytest.mark.asyncio async def test_model_properties_with_list(client: SpecialWordsClient): await client.model_properties.with_list(models.ModelWithList(list="ok")) + + +@pytest.mark.asyncio +async def test_extensible_strings(client: SpecialWordsClient): + for enum_value in extensible_strings_models.ExtensibleString: + assert enum_value == await client.extensible_strings.put_extensible_string_value(body=enum_value) diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py b/packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py index cc083c94c0e..2f591680bb2 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py +++ b/packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py @@ -5,6 +5,7 @@ # -------------------------------------------------------------------------- import pytest from specialwords import SpecialWordsClient, models +from specialwords.extensiblestrings import models as extensible_strings_models @pytest.fixture @@ -56,3 +57,8 @@ def test_model_properties_dict_methods(client: SpecialWordsClient): def test_model_properties_with_list(client: SpecialWordsClient): client.model_properties.with_list(models.ModelWithList(list="ok")) + + +def test_extensible_strings(client: SpecialWordsClient): + for enum_value in extensible_strings_models.ExtensibleString: + assert enum_value == client.extensible_strings.put_extensible_string_value(body=enum_value) diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py b/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py index eb11843ab32..112533fa2db 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py +++ b/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py @@ -7,6 +7,7 @@ from specialwords.aio import SpecialWordsClient from specialwords.models import models from specialwords.modelproperties import models as model_properties_models +from specialwords.extensiblestrings import models as extensible_strings_models @pytest.fixture @@ -64,3 +65,9 @@ async def test_model_properties_dict_methods(client: SpecialWordsClient): @pytest.mark.asyncio async def test_model_properties_with_list(client: SpecialWordsClient): await client.model_properties.with_list(model_properties_models.ModelWithList(list="ok")) + + +@pytest.mark.asyncio +async def test_extensible_strings(client: SpecialWordsClient): + for enum_value in extensible_strings_models.ExtensibleString: + assert enum_value == await client.extensible_strings.put_extensible_string_value(body=enum_value) diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py b/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py index 89679bfd788..83269cc1e47 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py +++ b/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py @@ -7,6 +7,7 @@ from specialwords import SpecialWordsClient from specialwords.models import models from specialwords.modelproperties import models as model_properties_models +from specialwords.extensiblestrings import models as extensible_strings_models @pytest.fixture @@ -58,3 +59,8 @@ def test_model_properties_dict_methods(client: SpecialWordsClient): def test_model_properties_with_list(client: SpecialWordsClient): client.model_properties.with_list(model_properties_models.ModelWithList(list="ok")) + + +def test_extensible_strings(client: SpecialWordsClient): + for enum_value in extensible_strings_models.ExtensibleString: + assert enum_value == client.extensible_strings.put_extensible_string_value(body=enum_value) diff --git a/packages/http-client-python/generator/test/unittests/test_enums.py b/packages/http-client-python/generator/test/unittests/test_enums.py index 02134609523..2b671c90996 100644 --- a/packages/http-client-python/generator/test/unittests/test_enums.py +++ b/packages/http-client-python/generator/test/unittests/test_enums.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- from enum import Enum, EnumMeta +from specialwords.extensiblestrings import models as extensible_strings_models class _CaseInsensitiveEnumMeta(EnumMeta): @@ -50,3 +51,39 @@ def test_find(): def test_join(): assert EnumsWithCallableNames.JOIN == "join" assert callable(EnumsWithCallableNames.join) + + +def test_extensible_strings_enum_with_special_words(): + assert extensible_strings_models.ExtensibleString.AND == "and" + assert extensible_strings_models.ExtensibleString.AS == "as" + assert extensible_strings_models.ExtensibleString.ASSERT == "assert" + assert extensible_strings_models.ExtensibleString.ASYNC == "async" + assert extensible_strings_models.ExtensibleString.AWAIT == "await" + assert extensible_strings_models.ExtensibleString.BREAK == "break" + assert extensible_strings_models.ExtensibleString.CLASS == "class" + assert extensible_strings_models.ExtensibleString.CONSTRUCTOR == "constructor" + assert extensible_strings_models.ExtensibleString.CONTINUE == "continue" + assert extensible_strings_models.ExtensibleString.DEF == "def" + assert extensible_strings_models.ExtensibleString.DEL == "del" + assert extensible_strings_models.ExtensibleString.ELIF == "elif" + assert extensible_strings_models.ExtensibleString.ELSE == "else" + assert extensible_strings_models.ExtensibleString.EXCEPT == "except" + assert extensible_strings_models.ExtensibleString.EXEC == "exec" + assert extensible_strings_models.ExtensibleString.FINALLY == "finally" + assert extensible_strings_models.ExtensibleString.FOR == "for" + assert extensible_strings_models.ExtensibleString.FROM == "from" + assert extensible_strings_models.ExtensibleString.GLOBAL == "global" + assert extensible_strings_models.ExtensibleString.IF == "if" + assert extensible_strings_models.ExtensibleString.IMPORT == "import" + assert extensible_strings_models.ExtensibleString.IN == "in" + assert extensible_strings_models.ExtensibleString.IS == "is" + assert extensible_strings_models.ExtensibleString.LAMBDA == "lambda" + assert extensible_strings_models.ExtensibleString.NOT == "not" + assert extensible_strings_models.ExtensibleString.OR == "or" + assert extensible_strings_models.ExtensibleString.PASS == "pass" + assert extensible_strings_models.ExtensibleString.RAISE == "raise" + assert extensible_strings_models.ExtensibleString.RETURN == "return" + assert extensible_strings_models.ExtensibleString.TRY == "try" + assert extensible_strings_models.ExtensibleString.WHILE == "while" + assert extensible_strings_models.ExtensibleString.WITH == "with" + assert extensible_strings_models.ExtensibleString.YIELD == "yield" diff --git a/packages/http-client-python/package-lock.json b/packages/http-client-python/package-lock.json index f4a84d1c7c6..c8713c0b887 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.33-dev.2", + "@typespec/http-specs": "0.1.0-alpha.33-dev.5", "@typespec/openapi": "^1.9.0", "@typespec/rest": "~0.79.0", "@typespec/spec-api": "0.1.0-alpha.12", @@ -2492,25 +2492,25 @@ } }, "node_modules/@typespec/http-specs": { - "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==", + "version": "0.1.0-alpha.33-dev.5", + "resolved": "https://registry.npmjs.org/@typespec/http-specs/-/http-specs-0.1.0-alpha.33-dev.5.tgz", + "integrity": "sha512-C5lg4ZF2BC5b4mebR32iID+zaETSJQyDEu+vVjSGOp7BjlpviFhgLYw3zMwI8u8Q0FVUAW1WvVVjRZ5X/X74GA==", "dev": true, "license": "MIT", "dependencies": { - "@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", + "@typespec/spec-api": "^0.1.0-alpha.12 || >= 0.1.0-alpha.13-dev.1", + "@typespec/spector": "^0.1.0-alpha.23 || >= 0.1.0-alpha.24-dev.4", "deep-equal": "^2.2.0" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@typespec/compiler": "^1.9.0", - "@typespec/http": "^1.9.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" + "@typespec/compiler": "^1.9.0 || >= 1.10.0-dev.15", + "@typespec/http": "^1.9.1 || >= 1.10.0-dev.5", + "@typespec/rest": "^0.79.0 || >= 0.80.0-dev.2", + "@typespec/versioning": "^0.79.0 || >= 0.80.0-dev.3", + "@typespec/xml": "^0.79.0 || >= 0.80.0-dev.2" } }, "node_modules/@typespec/openapi": { diff --git a/packages/http-client-python/package.json b/packages/http-client-python/package.json index 2752851f089..ba7646b2abc 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.33-dev.2", + "@typespec/http-specs": "0.1.0-alpha.33-dev.5", "@types/js-yaml": "~4.0.5", "@types/node": "~25.0.2", "@types/semver": "7.5.8",