I’m writing a business application layer around SQLAlchemy. I would like to use python’s enum.Flag
class to define a enumeration to pass as a function argument for declaring what columns are desired from a query.
from enum import Flag, auto
class RunsetColumns(Flag):
name = auto()
date = auto()
manual_label= auto()
submission_type = auto()
purpose = auto()
That works
RunsetColumns.name | RunsetColumns.date
will produce a member that I can iterate over for performing the query and it allows validating that the requested columns are spelled correctly.
I find how writing RunsetColumns.name | RunsetColumns.date
to be verbose and I’m extremely certain that the business people are going to be confused by |
and want to naturally use &
which will produce undesired results.
So I wanted to implement _missing_
as a less verbose solution.
from enum import Flag, auto
from functools import reduce
from operator import or_
class RunsetColumns(Flag):
name = auto()
date = auto()
manual_label= auto()
submission_type = auto()
purpose = auto()
@classmethod
def _missing_(cls, values):
if isinstance(values, tuple):
cols = (cls[val] for val in values)
col_bits = reduce(or_, cols)
return col_bits
RunsetColumns(("name", "date"))
breaks. Even if this solution did work I don’t like having to wrap it into a tuple. I seriously don’t understand the design intent around EnumMeta.__call__
and overwriting the classes __new__
but that’s a different discussion.
Is there no way around this? Without writing a custom class method?
With _missing_
defined the previously working RunsetColumns.name | RunsetColumns.date
fails for the same error message
ValueError: 3 is not a valid RunsetColumns
I’m not seeing anything in the enum docs indicating we aren’t supposed to be overriding _missing_
for Flag
.