Reputation: 5565
I am wondering if I can use python enums to enforce specific string inputs from a user into my functions and classes, and avoid having to code the explicit checks against acceptable values.
So instead of this:
e.g.
utilities_supplied = {
'electricity': 'Yes',
'gas': 'No',
'water': 'Yes',
}
def find_utility(utility):
try:
print(utilities_supplied[utility])
except KeyError:
raise KeyError(f'Please choose one of {utilities_supplied.keys()}, \'{utility}\' provided')
I would like to do this:
from enum import Enum
class Utility(Enum):
electricity = 1
gas = 2
water = 3
Utility['electric']
# not a member, I want this to raise an error which lists the acceptable options.
Is it possible for enums to raise an error listing the possible enumeration members?
Upvotes: 1
Views: 5350
Reputation: 5565
EDIT: This doesn't really work when I subclass the ValidatedEnum
class. Any help gratefully received.
The solution using _missing_
was fairly straightforward it turns out! Thanks for the idea @EthanFurman.
from enum import Enum
class ValidatedEnum(Enum):
electricity = 1
gas = 2
water = 3
@classmethod
def _missing_(cls, value):
choices = list(cls.__members__.keys())
raise ValueError("%r is not a valid %s, please choose from %s" % (value, cls.__name__, choices))
<ipython-input-1-8b49d805ac2d> in _missing_(cls, value)
8 def _missing_(cls, value):
9 choices = list(cls.__members__.keys())
---> 10 raise ValueError("%r is not a valid %s, please choose from %s" % (value, cls.__name__, choices))
11
ValueError: 'electric' is not a valid ValidatedEnum, please choose from ['electricity', 'gas', 'water']
Upvotes: 1
Reputation: 18106
You can use EnumMeta to overwrite __getitem__
, which fetches the values from the enum:
import enum
class MyEnum(enum.EnumMeta):
def __getitem__(cls, name):
try:
return super().__getitem__(name)
except (KeyError) as error:
options = ', '.join(cls._member_map_.keys())
msg = f'Please choose one of {options}, \'{name}\' provided'
raise ValueError(msg) from None
class Utility(enum.Enum, metaclass=MyEnum):
electricity = 1
gas = 2
water = 3
fire = Utility['fire']
print(fire)
Output:
ValueError: Please choose one of electricity, gas, water, 'fire' provided
Upvotes: 2