Skip to content

Instantly share code, notes, and snippets.

@danielknell
Last active February 2, 2018 16:13
Show Gist options
  • Save danielknell/e3c9c7b65b395a2e295ee8237a70286e to your computer and use it in GitHub Desktop.
Save danielknell/e3c9c7b65b395a2e295ee8237a70286e to your computer and use it in GitHub Desktop.
SQLAlchemy Enum Bug

There is a problem with how SQLAlchemy stores Python Enum types when native enums are disabled and said Enum contains aliases.

class Country(enum.Enum):
    GB = 'gb'
    FR = 'fr'
    UK = 'gb' # alias the GB item

foo = Table(
    'foo',
    metadata,
    Column('country', Enum(Country,native_enum=False,create_constraint=False))
)
>>> Country.GB
<Country.GB: 'gb'>
>>> Country.UK
<Country.GB: 'gb'>
>>> Country.GB.name
'GB'
>>> Country.UK.name
'GB'
>>>

If you store the value Country.GB in the table foo it will be stored as UK instead of GB.

I believe this is caused by flipping the dictionary keys/values in Enum._setup_for_values, instead of using the name param of the enum.

https://github.com/zzzeek/sqlalchemy/blob/699272e4dcb9aa71ebbc0d9487fb6de82d3abc2b/lib/sqlalchemy/sql/sqltypes.py#L1357

>>> import enum
>>>
>>> class Country(enum.Enum):
... GB = 'gb'
... FR = 'fr'
... UK = 'gb' # alias the GB item
...
>>> values = list(Country.__members__)
>>> objects = [Country.__members__[k] for k in values]
>>> dict(zip(values, objects))
{'GB': <Country.GB: 'gb'>, 'FR': <Country.FR: 'fr'>, 'UK': <Country.GB: 'gb'>}
>>> dict((value, key) for key, value in _.items())
{<Country.GB: 'gb'>: 'UK', <Country.FR: 'fr'>: 'FR'}
>>>
_valid_lookup = dict(zip(reversed(objects), reversed(values)))
_object_lookup = dict(zip(values, objects))
_valid_lookup.update([(value, _valid_lookup[_object_lookup[value]]) for value in values])
>>> _object_lookup
{'GB': <Country.GB: 'gb'>, 'FR': <Country.FR: 'fr'>, 'UK': <Country.GB: 'gb'>}
>>> _valid_lookup
{<Country.GB: 'gb'>: 'GB', <Country.FR: 'fr'>: 'FR', 'GB': 'GB', 'FR': 'FR', 'UK': 'GB'}
>>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment