sqlalchemy-enum34 icon indicating copy to clipboard operation
sqlalchemy-enum34 copied to clipboard

LookupError when using EnumType as primary key in SQLAlchemy 1.3

Open pbzweihander opened this issue 3 years ago • 0 comments

Weird LookupError raises when using EnumType as primary key.

I added following test case to test.py:

class EnumForPkey(enum.Enum):

    A = 'a'
    B = 'b'
    C = 'c'


class TableWithPkeyEnum(Base):
    pkey = Column(Enum(EnumForPkey, name='enum_for_pkey'), primary_key=True)

    __tablename__ = 'tb_with_pkey_enum'


def test_enum_pkey(fx_session):
    row = TableWithPkeyEnum(pkey=EnumForPkey.A)
    fx_session.add(row)
    fx_session.commit()
    row.pkey = EnumForPkey.B
    fx_session.commit()

..and ran tox:

self = Enum('a', 'b', 'c', name='enum_for_pkey'), elem = <EnumForPkey.A: 'a'>

    def _db_value_for_elem(self, elem):
        try:
>           return self._valid_lookup[elem]
E           KeyError: <EnumForPkey.A: 'a'>

.tox/py38/lib/python3.8/site-packages/sqlalchemy/sql/sqltypes.py:1499: KeyError

The above exception was the direct cause of the following exception:

fx_session = <sqlalchemy.orm.session.Session object at 0x7fcb79370cd0>

    def test_enum_pkey(fx_session):
        row = TableWithPkeyEnum(pkey=EnumForPkey.A)
        fx_session.add(row)
        fx_session.commit()
        row.pkey = EnumForPkey.B
>       fx_session.commit()

test.py:184:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/py38/lib/python3.8/site-packages/sqlalchemy/orm/session.py:1046: in commit
    self.transaction.commit()
...(stack trace)...
.tox/py38/lib/python3.8/site-packages/sqlalchemy/sql/sqltypes.py:1514: in _db_value_for_elem
    util.raise_(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    def raise_(
        exception, with_traceback=None, replace_context=None, from_=False
    ):
        r"""implement "raise" with cause support.

        :param exception: exception to raise
        :param with_traceback: will call exception.with_traceback()
        :param replace_context: an as-yet-unsupported feature.  This is
         an exception object which we are "replacing", e.g., it's our
         "cause" but we don't want it printed.    Basically just what
         ``__suppress_context__`` does but we don't want to suppress
         the enclosing context, if any.  So for now we make it the
         cause.
        :param from\_: the cause.  this actually sets the cause and doesn't
         hope to hide it someday.

        """
        if with_traceback is not None:
            exception = exception.with_traceback(with_traceback)

        if from_ is not False:
            exception.__cause__ = from_
        elif replace_context is not None:
            # no good solution here, we would like to have the exception
            # have only the context of replace_context.__context__ so that the
            # intermediary exception does not change, but we can't figure
            # that out.
            exception.__cause__ = replace_context

        try:
>           raise exception
E           LookupError: 'EnumForPkey.A' is not among the defined enum values. Enum name: enum_for_pkey. Possible values: a, b, c

.tox/py38/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182: LookupError

It seems I cannot bind a new value to TableWithPkeyEnum.pkey with EnumForPkey. repr(row.pkey) returns <EnumForPkey.A: 'a'>, but I can't assign EnumForPkey.A to row.pkey. Even row.pkey = row.pkey gives same error.

pbzweihander avatar Dec 29 '20 07:12 pbzweihander