diff --git a/ChangeLog.md b/ChangeLog.md index 9f850b308ed..b9d1c87754d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,11 @@ generated library will use that auth policy unless they pass in a separate one t - Fix typing for discriminator values in models, so Python 3.5 can import py3 file for models #691 +**Bug Fixes** + +- Make enum names all upper case. This fixes issues that arise if the name of an enum is also a method that can be applied to, say, a string. +For example, if an enum's name is count. Made sure this fix will not break users currently accessing with lower case enum names #692 + ### 2020-06-08 - 5.1.0-preview.2 Modelerfour version: 4.13.351 diff --git a/README.md b/README.md index 980fbf8e990..982ea2510c6 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ modelerfour: operation: snakecase operationGroup: pascalcase choice: pascalcase - choiceValue: snakecase + choiceValue: uppercase constant: snakecase constantParameter: snakecase type: pascalcase diff --git a/autorest/codegen/templates/enum.py.jinja2 b/autorest/codegen/templates/enum.py.jinja2 index c4365ba766a..83273cbffdb 100644 --- a/autorest/codegen/templates/enum.py.jinja2 +++ b/autorest/codegen/templates/enum.py.jinja2 @@ -1,5 +1,5 @@ -class {{ enum.name }}({{ enum.enum_type.type_annotation }}, Enum): +class {{ enum.name }}(with_metaclass(_CaseInsensitiveEnumMeta, {{ enum.enum_type.type_annotation }}, Enum)): {% if enum.description %} """{{ enum.description | wordwrap(width=95, break_long_words=False, wrapstring='\n ') }} """ diff --git a/autorest/codegen/templates/enum_container.py.jinja2 b/autorest/codegen/templates/enum_container.py.jinja2 index c1de41512fa..5f35a581688 100644 --- a/autorest/codegen/templates/enum_container.py.jinja2 +++ b/autorest/codegen/templates/enum_container.py.jinja2 @@ -1,7 +1,25 @@ # coding=utf-8 {{ code_model.options['license_header'] }} -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass + +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + {% for enum in code_model.enums.values() | sort %} {% include "enum.py.jinja2" %} {% endfor %} \ No newline at end of file diff --git a/autorest/namer/name_converter.py b/autorest/namer/name_converter.py index 9668fca4542..376fb241775 100644 --- a/autorest/namer/name_converter.py +++ b/autorest/namer/name_converter.py @@ -82,7 +82,7 @@ def _convert_schemas(schemas: Dict[str, Any]) -> None: def _convert_enum_schema(schema: Dict[str, Any]) -> None: NameConverter._convert_language_default_pascal_case(schema) for choice in schema["choices"]: - NameConverter._convert_language_default_python_case(choice, pad_string=PadType.Enum) + NameConverter._convert_language_default_python_case(choice, pad_string=PadType.Enum, all_upper=True) @staticmethod def _convert_object_schema(schema: Dict[str, Any]) -> None: @@ -99,7 +99,11 @@ def _convert_object_schema(schema: Dict[str, Any]) -> None: @staticmethod def _convert_language_default_python_case( - schema: Dict[str, Any], *, pad_string: Optional[PadType] = None, convert_name: bool = False + schema: Dict[str, Any], + *, + pad_string: Optional[PadType] = None, + convert_name: bool = False, + all_upper: bool = False ) -> None: if not schema.get("language") or schema["language"].get("python"): return @@ -117,7 +121,12 @@ def _convert_language_default_python_case( schema_python_name = NameConverter._to_valid_python_name( name=schema_name, pad_string=pad_string, convert_name=convert_name ) - schema['language']['python']['name'] = schema_python_name.lower() + # need to add the lower in case certain words, like LRO, are overriden to + # always return LRO. Without .lower(), for example, begin_lro would be + # begin_LRO + schema['language']['python']['name'] = ( + schema_python_name.upper() if all_upper else schema_python_name.lower() + ) schema_description = schema["language"]["default"]["description"].strip() if pad_string == PadType.Method and not schema_description and not schema["language"]["default"].get("summary"): diff --git a/test/azure/Expected/AcceptanceTests/Lro/lro/models/_auto_rest_long_running_operation_test_service_enums.py b/test/azure/Expected/AcceptanceTests/Lro/lro/models/_auto_rest_long_running_operation_test_service_enums.py index 2d162975e60..05783dd69e8 100644 --- a/test/azure/Expected/AcceptanceTests/Lro/lro/models/_auto_rest_long_running_operation_test_service_enums.py +++ b/test/azure/Expected/AcceptanceTests/Lro/lro/models/_auto_rest_long_running_operation_test_service_enums.py @@ -6,48 +6,66 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class OperationResultStatus(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class OperationResultStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """The status of the request """ - succeeded = "Succeeded" - failed = "Failed" - canceled = "canceled" - accepted = "Accepted" - creating = "Creating" - created = "Created" - updating = "Updating" - updated = "Updated" - deleting = "Deleting" - deleted = "Deleted" - ok = "OK" - -class ProductPropertiesProvisioningStateValues(str, Enum): - - succeeded = "Succeeded" - failed = "Failed" - canceled = "canceled" - accepted = "Accepted" - creating = "Creating" - created = "Created" - updating = "Updating" - updated = "Updated" - deleting = "Deleting" - deleted = "Deleted" - ok = "OK" - -class SubProductPropertiesProvisioningStateValues(str, Enum): - - succeeded = "Succeeded" - failed = "Failed" - canceled = "canceled" - accepted = "Accepted" - creating = "Creating" - created = "Created" - updating = "Updating" - updated = "Updated" - deleting = "Deleting" - deleted = "Deleted" - ok = "OK" + SUCCEEDED = "Succeeded" + FAILED = "Failed" + CANCELED = "canceled" + ACCEPTED = "Accepted" + CREATING = "Creating" + CREATED = "Created" + UPDATING = "Updating" + UPDATED = "Updated" + DELETING = "Deleting" + DELETED = "Deleted" + OK = "OK" + +class ProductPropertiesProvisioningStateValues(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + SUCCEEDED = "Succeeded" + FAILED = "Failed" + CANCELED = "canceled" + ACCEPTED = "Accepted" + CREATING = "Creating" + CREATED = "Created" + UPDATING = "Updating" + UPDATED = "Updated" + DELETING = "Deleting" + DELETED = "Deleted" + OK = "OK" + +class SubProductPropertiesProvisioningStateValues(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + SUCCEEDED = "Succeeded" + FAILED = "Failed" + CANCELED = "canceled" + ACCEPTED = "Accepted" + CREATING = "Creating" + CREATED = "Created" + UPDATING = "Updating" + UPDATED = "Updated" + DELETING = "Deleting" + DELETED = "Deleted" + OK = "OK" diff --git a/test/azure/Expected/AcceptanceTests/Paging/paging/models/_auto_rest_paging_test_service_enums.py b/test/azure/Expected/AcceptanceTests/Paging/paging/models/_auto_rest_paging_test_service_enums.py index 3cf5fca696a..f11f0a2743b 100644 --- a/test/azure/Expected/AcceptanceTests/Paging/paging/models/_auto_rest_paging_test_service_enums.py +++ b/test/azure/Expected/AcceptanceTests/Paging/paging/models/_auto_rest_paging_test_service_enums.py @@ -6,20 +6,38 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class OperationResultStatus(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class OperationResultStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """The status of the request """ - succeeded = "Succeeded" - failed = "Failed" - canceled = "canceled" - accepted = "Accepted" - creating = "Creating" - created = "Created" - updating = "Updating" - updated = "Updated" - deleting = "Deleting" - deleted = "Deleted" - ok = "OK" + SUCCEEDED = "Succeeded" + FAILED = "Failed" + CANCELED = "canceled" + ACCEPTED = "Accepted" + CREATING = "Creating" + CREATED = "Created" + UPDATING = "Updating" + UPDATED = "Updated" + DELETING = "Deleting" + DELETED = "Deleted" + OK = "OK" diff --git a/test/azure/Expected/AcceptanceTests/StorageManagementClient/storage/models/_storage_management_client_enums.py b/test/azure/Expected/AcceptanceTests/StorageManagementClient/storage/models/_storage_management_client_enums.py index 2eb67ea74d4..46dd427d43b 100644 --- a/test/azure/Expected/AcceptanceTests/StorageManagementClient/storage/models/_storage_management_client_enums.py +++ b/test/azure/Expected/AcceptanceTests/StorageManagementClient/storage/models/_storage_management_client_enums.py @@ -6,54 +6,72 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class AccountStatus(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class AccountStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Gets the status indicating whether the primary location of the storage account is available or unavailable. """ - available = "Available" - unavailable = "Unavailable" + AVAILABLE = "Available" + UNAVAILABLE = "Unavailable" -class AccountType(str, Enum): +class AccountType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Gets or sets the account type. """ - standard_lrs = "Standard_LRS" - standard_zrs = "Standard_ZRS" - standard_grs = "Standard_GRS" - standard_ragrs = "Standard_RAGRS" - premium_lrs = "Premium_LRS" + STANDARD_LRS = "Standard_LRS" + STANDARD_ZRS = "Standard_ZRS" + STANDARD_GRS = "Standard_GRS" + STANDARD_RAGRS = "Standard_RAGRS" + PREMIUM_LRS = "Premium_LRS" -class KeyName(str, Enum): +class KeyName(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - key1 = "key1" - key2 = "key2" + KEY1 = "key1" + KEY2 = "key2" -class ProvisioningState(str, Enum): +class ProvisioningState(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Gets the status of the storage account at the time the operation was called. """ - creating = "Creating" - resolving_dns = "ResolvingDNS" - succeeded = "Succeeded" + CREATING = "Creating" + RESOLVING_DNS = "ResolvingDNS" + SUCCEEDED = "Succeeded" -class Reason(str, Enum): +class Reason(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Gets the reason that a storage account name could not be used. The Reason element is only returned if NameAvailable is false. """ - account_name_invalid = "AccountNameInvalid" - already_exists = "AlreadyExists" + ACCOUNT_NAME_INVALID = "AccountNameInvalid" + ALREADY_EXISTS = "AlreadyExists" -class UsageUnit(str, Enum): +class UsageUnit(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Gets the unit of measurement. """ - count = "Count" - bytes = "Bytes" - seconds = "Seconds" - percent = "Percent" - counts_per_second = "CountsPerSecond" - bytes_per_second = "BytesPerSecond" + COUNT = "Count" + BYTES = "Bytes" + SECONDS = "Seconds" + PERCENT = "Percent" + COUNTS_PER_SECOND = "CountsPerSecond" + BYTES_PER_SECOND = "BytesPerSecond" diff --git a/test/multiapi/Expected/AcceptanceTests/Multiapi/multiapi/v3/models/_multiapi_service_client_enums.py b/test/multiapi/Expected/AcceptanceTests/Multiapi/multiapi/v3/models/_multiapi_service_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/multiapi/Expected/AcceptanceTests/Multiapi/multiapi/v3/models/_multiapi_service_client_enums.py +++ b/test/multiapi/Expected/AcceptanceTests/Multiapi/multiapi/v3/models/_multiapi_service_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/multiapi/Expected/AcceptanceTests/MultiapiCredentialDefaultPolicy/multiapicredentialdefaultpolicy/v3/models/_multiapi_service_client_enums.py b/test/multiapi/Expected/AcceptanceTests/MultiapiCredentialDefaultPolicy/multiapicredentialdefaultpolicy/v3/models/_multiapi_service_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/multiapi/Expected/AcceptanceTests/MultiapiCredentialDefaultPolicy/multiapicredentialdefaultpolicy/v3/models/_multiapi_service_client_enums.py +++ b/test/multiapi/Expected/AcceptanceTests/MultiapiCredentialDefaultPolicy/multiapicredentialdefaultpolicy/v3/models/_multiapi_service_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/multiapi/Expected/AcceptanceTests/MultiapiDataPlane/multiapidataplane/v3/models/_multiapi_service_client_enums.py b/test/multiapi/Expected/AcceptanceTests/MultiapiDataPlane/multiapidataplane/v3/models/_multiapi_service_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/multiapi/Expected/AcceptanceTests/MultiapiDataPlane/multiapidataplane/v3/models/_multiapi_service_client_enums.py +++ b/test/multiapi/Expected/AcceptanceTests/MultiapiDataPlane/multiapidataplane/v3/models/_multiapi_service_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/multiapi/Expected/AcceptanceTests/MultiapiNoAsync/multiapinoasync/v3/models/_multiapi_service_client_enums.py b/test/multiapi/Expected/AcceptanceTests/MultiapiNoAsync/multiapinoasync/v3/models/_multiapi_service_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/multiapi/Expected/AcceptanceTests/MultiapiNoAsync/multiapinoasync/v3/models/_multiapi_service_client_enums.py +++ b/test/multiapi/Expected/AcceptanceTests/MultiapiNoAsync/multiapinoasync/v3/models/_multiapi_service_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/multiapi/Expected/AcceptanceTests/MultiapiWithSubmodule/multiapiwithsubmodule/submodule/v3/models/_multiapi_service_client_enums.py b/test/multiapi/Expected/AcceptanceTests/MultiapiWithSubmodule/multiapiwithsubmodule/submodule/v3/models/_multiapi_service_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/multiapi/Expected/AcceptanceTests/MultiapiWithSubmodule/multiapiwithsubmodule/submodule/v3/models/_multiapi_service_client_enums.py +++ b/test/multiapi/Expected/AcceptanceTests/MultiapiWithSubmodule/multiapiwithsubmodule/submodule/v3/models/_multiapi_service_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/unittests/test_enums.py b/test/unittests/test_enums.py new file mode 100644 index 00000000000..9da7228bd58 --- /dev/null +++ b/test/unittests/test_enums.py @@ -0,0 +1,48 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +from enum import Enum, EnumMeta +from six import with_metaclass + +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + +class EnumsWithCallableNames(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + """Gets the unit of measurement. + """ + + COUNT = "count" + ENCODE = "encode" + FIND = "find" + JOIN = "join" + +def test_count(): + assert EnumsWithCallableNames.COUNT == "count" + assert callable(EnumsWithCallableNames.count) + +def test_encode(): + assert EnumsWithCallableNames.ENCODE == "encode" + assert callable(EnumsWithCallableNames.encode) + +def test_find(): + assert EnumsWithCallableNames.FIND == "find" + assert callable(EnumsWithCallableNames.find) + +def test_join(): + assert EnumsWithCallableNames.JOIN == "join" + assert callable(EnumsWithCallableNames.join) \ No newline at end of file diff --git a/test/vanilla/AcceptanceTests/asynctests/test_non_string_enums.py b/test/vanilla/AcceptanceTests/asynctests/test_non_string_enums.py index cd9844031d4..8dfff6af69f 100644 --- a/test/vanilla/AcceptanceTests/asynctests/test_non_string_enums.py +++ b/test/vanilla/AcceptanceTests/asynctests/test_non_string_enums.py @@ -41,20 +41,20 @@ class TestNonStringEnums(object): @pytest.mark.asyncio async def test_put_int_enum(self, client): - result = await client.int.put(IntEnum.two_hundred) + result = await client.int.put(IntEnum.TWO_HUNDRED) assert result == "Nice job posting an int enum" @pytest.mark.asyncio async def test_get_int_enum(self, client): result = await client.int.get() - assert result == IntEnum.four_hundred_twenty_nine.value + assert result == IntEnum.FOUR_HUNDRED_TWENTY_NINE.value @pytest.mark.asyncio async def test_put_float_enum(self, client): - result = await client.float.put(FloatEnum.two_hundred4) + result = await client.float.put(FloatEnum.TWO_HUNDRED4) assert result == "Nice job posting a float enum" @pytest.mark.asyncio async def test_get_float_enum(self, client): result = await client.float.get() - assert result == FloatEnum.four_hundred_twenty_nine1.value + assert result == FloatEnum.FOUR_HUNDRED_TWENTY_NINE1.value diff --git a/test/vanilla/AcceptanceTests/asynctests/test_string_tests.py b/test/vanilla/AcceptanceTests/asynctests/test_string_tests.py index 2eacb5a9dd5..467b68377a9 100644 --- a/test/vanilla/AcceptanceTests/asynctests/test_string_tests.py +++ b/test/vanilla/AcceptanceTests/asynctests/test_string_tests.py @@ -114,9 +114,9 @@ async def test_get_not_provided(self, client): @pytest.mark.asyncio async def test_enum_not_expandable(self, client): - assert Colors.red_color == (await client.enum.get_not_expandable()) + assert Colors.RED_COLOR == (await client.enum.get_not_expandable()) await client.enum.put_not_expandable('red color') - await client.enum.put_not_expandable(Colors.red_color) + await client.enum.put_not_expandable(Colors.RED_COLOR) with pytest.raises(HttpResponseError): await client.enum.put_not_expandable('not a colour') @@ -135,15 +135,15 @@ async def test_get_null_base64_url_encoded(self, client): @pytest.mark.asyncio async def test_enum_referenced(self, client): - await client.enum.put_referenced(Colors.red_color) + await client.enum.put_referenced(Colors.RED_COLOR) await client.enum.put_referenced("red color") - assert (await client.enum.get_referenced()) == Colors.red_color + assert (await client.enum.get_referenced()) == Colors.RED_COLOR @pytest.mark.asyncio async def test_enum_referenced_constant(self, client): await client.enum.put_referenced_constant() - assert (await client.enum.get_referenced_constant()).color_constant == Colors.green_color.value + assert (await client.enum.get_referenced_constant()).color_constant == Colors.GREEN_COLOR.value def test_patch_file(self): from bodystring.models import PatchAddedModel diff --git a/test/vanilla/AcceptanceTests/test_non_string_enums.py b/test/vanilla/AcceptanceTests/test_non_string_enums.py index 5fc4a948801..6cebeaefef2 100644 --- a/test/vanilla/AcceptanceTests/test_non_string_enums.py +++ b/test/vanilla/AcceptanceTests/test_non_string_enums.py @@ -38,17 +38,21 @@ def client(): class TestNonStringEnums(object): def test_put_int_enum(self, client): - result = client.int.put(IntEnum.two_hundred) + result = client.int.put(IntEnum.TWO_HUNDRED) assert result == "Nice job posting an int enum" def test_get_int_enum(self, client): result = client.int.get() - assert result == IntEnum.four_hundred_twenty_nine.value + assert result == IntEnum.FOUR_HUNDRED_TWENTY_NINE.value def test_put_float_enum(self, client): - result = client.float.put(FloatEnum.two_hundred4) + result = client.float.put(FloatEnum.TWO_HUNDRED4) assert result == "Nice job posting a float enum" def test_get_float_enum(self, client): result = client.float.get() - assert result == FloatEnum.four_hundred_twenty_nine1.value + assert result == FloatEnum.FOUR_HUNDRED_TWENTY_NINE1.value + + def test_lowercase_enum_retrieval(self): + assert FloatEnum.four_hundred_twenty_nine1 == FloatEnum.FOUR_HUNDRED_TWENTY_NINE1 + assert 429.1 == FloatEnum.FOUR_HUNDRED_TWENTY_NINE1 \ No newline at end of file diff --git a/test/vanilla/AcceptanceTests/test_string_tests.py b/test/vanilla/AcceptanceTests/test_string_tests.py index f87d9253102..2ead162336d 100644 --- a/test/vanilla/AcceptanceTests/test_string_tests.py +++ b/test/vanilla/AcceptanceTests/test_string_tests.py @@ -105,9 +105,9 @@ def test_get_not_provided(self, client): assert client.string.get_not_provided() is None def test_enum_not_expandable(self, client): - assert Colors.red_color == client.enum.get_not_expandable() + assert Colors.RED_COLOR == client.enum.get_not_expandable() client.enum.put_not_expandable('red color') - client.enum.put_not_expandable(Colors.red_color) + client.enum.put_not_expandable(Colors.RED_COLOR) # Autorest v3 is switching behavior here. Old Autorest would have thrown a serialization error, # but now we allow the user to pass strings as enums, so the raised exception is different. with pytest.raises(HttpResponseError): @@ -124,18 +124,22 @@ def test_get_null_base64_url_encoded(self, client): assert client.string.get_null_base64_url_encoded() is None def test_enum_referenced(self, client): - client.enum.put_referenced(Colors.red_color) + client.enum.put_referenced(Colors.RED_COLOR) client.enum.put_referenced("red color") - assert client.enum.get_referenced() == Colors.red_color + assert client.enum.get_referenced() == Colors.RED_COLOR def test_enum_referenced_constant(self, client): client.enum.put_referenced_constant() - assert client.enum.get_referenced_constant().color_constant == Colors.green_color.value + assert client.enum.get_referenced_constant().color_constant == Colors.GREEN_COLOR.value def test_patch_file(self): from bodystring.models import PatchAddedModel + def test_lowercase_enum_retrieval(self): + assert Colors.green_color == Colors.GREEN_COLOR + assert "green-color" == Colors.GREEN_COLOR + def test_models(self): from bodystring.models import Error diff --git a/test/vanilla/Expected/AcceptanceTests/BodyArray/bodyarray/models/_auto_rest_swagger_bat_array_service_enums.py b/test/vanilla/Expected/AcceptanceTests/BodyArray/bodyarray/models/_auto_rest_swagger_bat_array_service_enums.py index 4b64c54e379..1ab22925d3f 100644 --- a/test/vanilla/Expected/AcceptanceTests/BodyArray/bodyarray/models/_auto_rest_swagger_bat_array_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/BodyArray/bodyarray/models/_auto_rest_swagger_bat_array_service_enums.py @@ -6,22 +6,40 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class Enum0(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) -class Enum1(str, Enum): - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" +class Enum0(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class FooEnum(str, Enum): + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" +class Enum1(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" + +class FooEnum(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" diff --git a/test/vanilla/Expected/AcceptanceTests/BodyArrayWithNamespaceFolders/vanilla/body/array/models/_auto_rest_swagger_bat_array_service_enums.py b/test/vanilla/Expected/AcceptanceTests/BodyArrayWithNamespaceFolders/vanilla/body/array/models/_auto_rest_swagger_bat_array_service_enums.py index 4b64c54e379..1ab22925d3f 100644 --- a/test/vanilla/Expected/AcceptanceTests/BodyArrayWithNamespaceFolders/vanilla/body/array/models/_auto_rest_swagger_bat_array_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/BodyArrayWithNamespaceFolders/vanilla/body/array/models/_auto_rest_swagger_bat_array_service_enums.py @@ -6,22 +6,40 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class Enum0(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) -class Enum1(str, Enum): - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" +class Enum0(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class FooEnum(str, Enum): + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" - foo1 = "foo1" - foo2 = "foo2" - foo3 = "foo3" +class Enum1(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" + +class FooEnum(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + FOO1 = "foo1" + FOO2 = "foo2" + FOO3 = "foo3" diff --git a/test/vanilla/Expected/AcceptanceTests/BodyComplex/bodycomplex/models/_auto_rest_complex_test_service_enums.py b/test/vanilla/Expected/AcceptanceTests/BodyComplex/bodycomplex/models/_auto_rest_complex_test_service_enums.py index b9d88c1ac49..a496099ab4d 100644 --- a/test/vanilla/Expected/AcceptanceTests/BodyComplex/bodycomplex/models/_auto_rest_complex_test_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/BodyComplex/bodycomplex/models/_auto_rest_complex_test_service_enums.py @@ -6,21 +6,39 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class CMYKColors(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - cyan = "cyan" - magenta = "Magenta" - yellow = "YELLOW" - blac_k = "blacK" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) -class GoblinSharkColor(str, Enum): + +class CMYKColors(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + CYAN = "cyan" + MAGENTA = "Magenta" + YELLOW = "YELLOW" + BLAC_K = "blacK" + +class GoblinSharkColor(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Colors possible """ - pink = "pink" - gray = "gray" - brown = "brown" - upper_red = "RED" #: Uppercase RED. - lower_red = "red" #: Lowercase RED. + PINK = "pink" + GRAY = "gray" + BROWN = "brown" + UPPER_RED = "RED" #: Uppercase RED. + LOWER_RED = "red" #: Lowercase RED. diff --git a/test/vanilla/Expected/AcceptanceTests/BodyString/bodystring/models/_auto_rest_swagger_bat_service_enums.py b/test/vanilla/Expected/AcceptanceTests/BodyString/bodystring/models/_auto_rest_swagger_bat_service_enums.py index 67fdfa68878..944bb647105 100644 --- a/test/vanilla/Expected/AcceptanceTests/BodyString/bodystring/models/_auto_rest_swagger_bat_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/BodyString/bodystring/models/_auto_rest_swagger_bat_service_enums.py @@ -6,10 +6,28 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class Colors(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - red_color = "red color" - green_color = "green-color" - blue_color = "blue_color" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class Colors(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + RED_COLOR = "red color" + GREEN_COLOR = "green-color" + BLUE_COLOR = "blue_color" diff --git a/test/vanilla/Expected/AcceptanceTests/ExtensibleEnums/extensibleenumsswagger/models/_pet_store_inc_enums.py b/test/vanilla/Expected/AcceptanceTests/ExtensibleEnums/extensibleenumsswagger/models/_pet_store_inc_enums.py index a2e79e51dcb..e419229b59c 100644 --- a/test/vanilla/Expected/AcceptanceTests/ExtensibleEnums/extensibleenumsswagger/models/_pet_store_inc_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/ExtensibleEnums/extensibleenumsswagger/models/_pet_store_inc_enums.py @@ -6,22 +6,40 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class DaysOfWeekExtensibleEnum(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class DaysOfWeekExtensibleEnum(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Type of Pet """ - monday = "Monday" - tuesday = "Tuesday" - wednesday = "Wednesday" - thursday = "Thursday" - friday = "Friday" - saturday = "Saturday" - sunday = "Sunday" + MONDAY = "Monday" + TUESDAY = "Tuesday" + WEDNESDAY = "Wednesday" + THURSDAY = "Thursday" + FRIDAY = "Friday" + SATURDAY = "Saturday" + SUNDAY = "Sunday" -class IntEnum(str, Enum): +class IntEnum(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - one = "1" #: one. - two = "2" #: two. - three = "3" #: three. + ONE = "1" #: one. + TWO = "2" #: two. + THREE = "3" #: three. diff --git a/test/vanilla/Expected/AcceptanceTests/Header/header/models/_auto_rest_swagger_bat_header_service_enums.py b/test/vanilla/Expected/AcceptanceTests/Header/header/models/_auto_rest_swagger_bat_header_service_enums.py index 6e32ff19be6..8ffb2b38a6d 100644 --- a/test/vanilla/Expected/AcceptanceTests/Header/header/models/_auto_rest_swagger_bat_header_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/Header/header/models/_auto_rest_swagger_bat_header_service_enums.py @@ -6,10 +6,28 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class GreyscaleColors(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - white = "White" - black = "black" - grey = "GREY" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class GreyscaleColors(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + WHITE = "White" + BLACK = "black" + GREY = "GREY" diff --git a/test/vanilla/Expected/AcceptanceTests/MediaTypes/mediatypes/models/_media_types_client_enums.py b/test/vanilla/Expected/AcceptanceTests/MediaTypes/mediatypes/models/_media_types_client_enums.py index bf4c202fc64..0666ddf8a0b 100644 --- a/test/vanilla/Expected/AcceptanceTests/MediaTypes/mediatypes/models/_media_types_client_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/MediaTypes/mediatypes/models/_media_types_client_enums.py @@ -6,13 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class ContentType(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class ContentType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): """Content type for upload """ - application_pdf = "application/pdf" #: Content Type 'application/pdf'. - image_jpeg = "image/jpeg" #: Content Type 'image/jpeg'. - image_png = "image/png" #: Content Type 'image/png'. - image_tiff = "image/tiff" #: Content Type 'image/tiff'. + APPLICATION_PDF = "application/pdf" #: Content Type 'application/pdf'. + IMAGE_JPEG = "image/jpeg" #: Content Type 'image/jpeg'. + IMAGE_PNG = "image/png" #: Content Type 'image/png'. + IMAGE_TIFF = "image/tiff" #: Content Type 'image/tiff'. diff --git a/test/vanilla/Expected/AcceptanceTests/ModelFlattening/modelflattening/models/_auto_rest_resource_flattening_test_service_enums.py b/test/vanilla/Expected/AcceptanceTests/ModelFlattening/modelflattening/models/_auto_rest_resource_flattening_test_service_enums.py index c5eeb5243c9..7578bb142cd 100644 --- a/test/vanilla/Expected/AcceptanceTests/ModelFlattening/modelflattening/models/_auto_rest_resource_flattening_test_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/ModelFlattening/modelflattening/models/_auto_rest_resource_flattening_test_service_enums.py @@ -6,18 +6,36 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class FlattenedProductPropertiesProvisioningStateValues(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - succeeded = "Succeeded" - failed = "Failed" - canceled = "canceled" - accepted = "Accepted" - creating = "Creating" - created = "Created" - updating = "Updating" - updated = "Updated" - deleting = "Deleting" - deleted = "Deleted" - ok = "OK" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class FlattenedProductPropertiesProvisioningStateValues(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + SUCCEEDED = "Succeeded" + FAILED = "Failed" + CANCELED = "canceled" + ACCEPTED = "Accepted" + CREATING = "Creating" + CREATED = "Created" + UPDATING = "Updating" + UPDATED = "Updated" + DELETING = "Deleting" + DELETED = "Deleted" + OK = "OK" diff --git a/test/vanilla/Expected/AcceptanceTests/NonStringEnums/nonstringenums/models/_non_string_enums_client_enums.py b/test/vanilla/Expected/AcceptanceTests/NonStringEnums/nonstringenums/models/_non_string_enums_client_enums.py index 00e7458ac8f..f72658a22e3 100644 --- a/test/vanilla/Expected/AcceptanceTests/NonStringEnums/nonstringenums/models/_non_string_enums_client_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/NonStringEnums/nonstringenums/models/_non_string_enums_client_enums.py @@ -6,24 +6,42 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class FloatEnum(float, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class FloatEnum(with_metaclass(_CaseInsensitiveEnumMeta, float, Enum)): """List of float enums """ - two_hundred4 = 200.4 - four_hundred_three4 = 403.4 - four_hundred_five3 = 405.3 - four_hundred_six2 = 406.2 - four_hundred_twenty_nine1 = 429.1 + TWO_HUNDRED4 = 200.4 + FOUR_HUNDRED_THREE4 = 403.4 + FOUR_HUNDRED_FIVE3 = 405.3 + FOUR_HUNDRED_SIX2 = 406.2 + FOUR_HUNDRED_TWENTY_NINE1 = 429.1 -class IntEnum(int, Enum): +class IntEnum(with_metaclass(_CaseInsensitiveEnumMeta, int, Enum)): """List of integer enums """ - two_hundred = 200 - four_hundred_three = 403 - four_hundred_five = 405 - four_hundred_six = 406 - four_hundred_twenty_nine = 429 + TWO_HUNDRED = 200 + FOUR_HUNDRED_THREE = 403 + FOUR_HUNDRED_FIVE = 405 + FOUR_HUNDRED_SIX = 406 + FOUR_HUNDRED_TWENTY_NINE = 429 diff --git a/test/vanilla/Expected/AcceptanceTests/Url/url/models/_auto_rest_url_test_service_enums.py b/test/vanilla/Expected/AcceptanceTests/Url/url/models/_auto_rest_url_test_service_enums.py index d5a760f9f0e..4f29e0e6732 100644 --- a/test/vanilla/Expected/AcceptanceTests/Url/url/models/_auto_rest_url_test_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/Url/url/models/_auto_rest_url_test_service_enums.py @@ -6,10 +6,28 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class UriColor(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - red_color = "red color" - green_color = "green color" - blue_color = "blue color" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class UriColor(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + RED_COLOR = "red color" + GREEN_COLOR = "green color" + BLUE_COLOR = "blue color" diff --git a/test/vanilla/Expected/AcceptanceTests/Xml/xmlservice/models/_auto_rest_swagger_batxml_service_enums.py b/test/vanilla/Expected/AcceptanceTests/Xml/xmlservice/models/_auto_rest_swagger_batxml_service_enums.py index 02609f5b44b..51ee11b0d10 100644 --- a/test/vanilla/Expected/AcceptanceTests/Xml/xmlservice/models/_auto_rest_swagger_batxml_service_enums.py +++ b/test/vanilla/Expected/AcceptanceTests/Xml/xmlservice/models/_auto_rest_swagger_batxml_service_enums.py @@ -6,58 +6,76 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from enum import Enum +from enum import Enum, EnumMeta +from six import with_metaclass -class AccessTier(str, Enum): +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) - p4 = "P4" - p6 = "P6" - p10 = "P10" - p20 = "P20" - p30 = "P30" - p40 = "P40" - p50 = "P50" - hot = "Hot" - cool = "Cool" - archive = "Archive" + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) -class ArchiveStatus(str, Enum): - rehydrate_pending_to_hot = "rehydrate-pending-to-hot" - rehydrate_pending_to_cool = "rehydrate-pending-to-cool" +class AccessTier(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class BlobType(str, Enum): + P4 = "P4" + P6 = "P6" + P10 = "P10" + P20 = "P20" + P30 = "P30" + P40 = "P40" + P50 = "P50" + HOT = "Hot" + COOL = "Cool" + ARCHIVE = "Archive" - block_blob = "BlockBlob" - page_blob = "PageBlob" - append_blob = "AppendBlob" +class ArchiveStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class CopyStatusType(str, Enum): + REHYDRATE_PENDING_TO_HOT = "rehydrate-pending-to-hot" + REHYDRATE_PENDING_TO_COOL = "rehydrate-pending-to-cool" - pending = "pending" - success = "success" - aborted = "aborted" - failed = "failed" +class BlobType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class LeaseDurationType(str, Enum): + BLOCK_BLOB = "BlockBlob" + PAGE_BLOB = "PageBlob" + APPEND_BLOB = "AppendBlob" - infinite = "infinite" - fixed = "fixed" +class CopyStatusType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class LeaseStateType(str, Enum): + PENDING = "pending" + SUCCESS = "success" + ABORTED = "aborted" + FAILED = "failed" - available = "available" - leased = "leased" - expired = "expired" - breaking = "breaking" - broken = "broken" +class LeaseDurationType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class LeaseStatusType(str, Enum): + INFINITE = "infinite" + FIXED = "fixed" - locked = "locked" - unlocked = "unlocked" +class LeaseStateType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): -class PublicAccessType(str, Enum): + AVAILABLE = "available" + LEASED = "leased" + EXPIRED = "expired" + BREAKING = "breaking" + BROKEN = "broken" - container = "container" - blob = "blob" +class LeaseStatusType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + LOCKED = "locked" + UNLOCKED = "unlocked" + +class PublicAccessType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + CONTAINER = "container" + BLOB = "blob"