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

`_sa_skip_events` error when invoking statement and calling `SignallingSession`

Open softzer0 opened this issue 3 years ago • 1 comments

Hello, I've got instructed to post here from the very same issue I've created on this place: https://github.com/sqlalchemy/sqlalchemy/issues/8260

Here's the example code from here which I am using: https://github.com/sqlalchemy/sqlalchemy/blob/rel_1_4_39/test/ext/test_baked.py#L1023

When I try to execute a query with this event interceptor being in effect, I get the error about unexpected keyword argument _sa_skip_events, which I see is being appended to _bind_arguments in invoke_statement method, before calling execute: https://github.com/sqlalchemy/sqlalchemy/blob/rel_1_4_39/lib/sqlalchemy/orm/session.py#L221

Example code to reproduce:

from sqlalchemy.testing.fixtures import fixture_session
from sqlalchemy.orm.query import Query

class CachingQuery(Query):
    cache = {}

    def set_cache_key(self, key):
        return self.execution_options(_cache_key=key)

    def set_cache_key_for_path(self, path, key):
        return self.execution_options(**{"_cache_key_%s" % path: key})

def get_value(cache_key, cache, createfunc):
    if cache_key in cache:
        return cache[cache_key]()
    else:
        cache[cache_key] = retval = createfunc().freeze()
        return retval()

s1 = fixture_session(query_cls=CachingQuery)

@event.listens_for(s1, "do_orm_execute", retval=True)
def do_orm_execute(orm_context):
    ckey = None
    for opt in orm_context.user_defined_options:
        ckey = opt.get_cache_key(orm_context)
        if ckey:
            break
    else:
        if "_cache_key" in orm_context.execution_options:
            ckey = orm_context.execution_options["_cache_key"]

    if ckey is not None:
        return get_value(
            ckey,
            CachingQuery.cache,
            orm_context.invoke_statement,
        )

s1.query(User).filter(User.id == 7).set_cache_key("user7")

The error with the stack trace I'm getting:

File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/query.py", line 2896, in __iter__
  return self._iter().__iter__()
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/query.py", line 2903, in _iter
  result = self.session.execute(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1693, in execute
  result = fn(orm_exec_state)
File "/opt/project/app/project/__init__.py", line 63, in _do_orm_execute
  retval = orm_context.invoke_statement().freeze()
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 233, in invoke_statement
  return self.session.execute(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1700, in execute
  bind = self.get_bind(**bind_arguments)
TypeError: SignallingSession.get_bind() got an unexpected keyword argument '_sa_skip_events'

Environment:

  • Python version: 3.9
  • Flask-SQLAlchemy version: 2.5.1
  • SQLAlchemy version: 1.4.39

softzer0 avatar Jul 16 '22 13:07 softzer0

It appears that in the latest official version (2.5.1) it's a bug: https://github.com/pallets-eco/flask-sqlalchemy/blob/2.5.1/flask_sqlalchemy/init.py#L187 While with the latest changes in this repository (main branch), it is already fixed with this commit: https://github.com/pallets-eco/flask-sqlalchemy/commit/afd9af64e5670f5c9bcc729a2c79f85b8d8b950f

softzer0 avatar Jul 16 '22 13:07 softzer0

Fixed in the linked commit, and addressed further in #1087.

davidism avatar Sep 18 '22 17:09 davidism