Skip to content

Commit

Permalink
[Core] Added enum meta class (#16316)
Browse files Browse the repository at this point in the history
  • Loading branch information
annatisch authored Feb 4, 2021
1 parent c17f3f3 commit decb645
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
1 change: 1 addition & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Added `CaseInsensitiveEnumMeta` class for case-insensitive enums. #16316
- Add `raise_for_status` method onto `HttpResponse`. Calling `response.raise_for_status()` on a response with an error code
will raise an `HttpResponseError`. Calling it on a good response will do nothing #16399

Expand Down
14 changes: 14 additions & 0 deletions sdk/core/azure-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ class MatchConditions(Enum):
IfMissing = 5
```

#### CaseInsensitiveEnumMeta

A metaclass to support case-insensitive enums.
```python
from enum import Enum
from six import with_metaclass

from azure.core import CaseInsensitiveEnumMeta

class MyCustomEnum(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)):
FOO = 'foo'
BAR = 'bar'
```

## Contributing
This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
Expand Down
4 changes: 3 additions & 1 deletion sdk/core/azure-core/azure/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@

from ._pipeline_client import PipelineClient
from ._match_conditions import MatchConditions
from ._enum_meta import CaseInsensitiveEnumMeta


__all__ = [
"PipelineClient",
"MatchConditions"
"MatchConditions",
"CaseInsensitiveEnumMeta"
]

try:
Expand Down
61 changes: 61 additions & 0 deletions sdk/core/azure-core/azure/core/_enum_meta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------

from enum import EnumMeta


class CaseInsensitiveEnumMeta(EnumMeta):
"""Enum metaclass to allow for interoperability with case-insensitive strings.
Consuming this metaclass in an SDK should be done in the following manner:
.. code-block:: python
from enum import Enum
from six import with_metaclass
from azure.core import CaseInsensitiveEnumMeta
class MyCustomEnum(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)):
FOO = 'foo'
BAR = 'bar'
"""

def __getitem__(cls, name):
# disabling pylint bc of pylint bug https://github.com/PyCQA/astroid/issues/713
return super(CaseInsensitiveEnumMeta, cls).__getitem__(name.upper()) # pylint: disable=no-value-for-parameter

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)
44 changes: 44 additions & 0 deletions sdk/core/azure-core/tests/test_enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# --------------------------------------------------------------------------
from enum import Enum
from six import with_metaclass

from azure.core import CaseInsensitiveEnumMeta

class MyCustomEnum(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)):
FOO = 'foo'
BAR = 'bar'


def test_case_insensitive_enums():
assert MyCustomEnum.foo.value == 'foo'
assert MyCustomEnum.FOO.value == 'foo'
assert MyCustomEnum('bar').value == 'bar'
assert 'bar' == MyCustomEnum.BAR
assert 'bar' == MyCustomEnum.bar
assert MyCustomEnum['foo'] == 'foo'
assert MyCustomEnum['FOO'] == 'foo'
assert isinstance(MyCustomEnum.BAR, str)

0 comments on commit decb645

Please sign in to comment.