flask-sqlalchemy: Listening for 'before_flush' throws sqlalchemy.exc.ArgumentError

Registering a listener for ‘before_commit’ (and ‘before_flush’) like so, where:

db = SQLAlchemy(app)
...
event.listen(db.session, 'before_commit', before_commit)

Throws the following exception:

    @event.listens_for(db.session, "before_flush")
  File "/home/environments/python3/lib/python3.3/site-packages/sqlalchemy/event/api.py", line 68, in decorate
    listen(target, identifier, fn, *args, **kw)
  File "/home/environments/python3/lib/python3.3/site-packages/sqlalchemy/event/api.py", line 49, in listen
    _event_key(target, identifier, fn).listen(*args, **kw)
  File "/home/environments/python3/lib/python3.3/site-packages/sqlalchemy/event/api.py", line 22, in _event_key
    tgt = evt_cls._accept_with(target)
  File "/home/environments/python3/lib/python3.3/site-packages/sqlalchemy/orm/events.py", line 1142, in _accept_with
    "Session event listen on a scoped_session "
sqlalchemy.exc.ArgumentError: Session event listen on a scoped_session requires that its creation callable is associated with the Session class.

Per the comment in this thread from Mike Bayer, it seems the issue is with the factory being passed to scoped_session not being a sessionmaker(): http://stackoverflow.com/questions/21322158/event-listener-on-scoped-session

Stepping through the code, it barfs in this method in line 1132 of sqlalchemy/orm/events.py:

    @classmethod
    def _accept_with(cls, target):
        if isinstance(target, scoped_session):

            target = target.session_factory
            if not isinstance(target, sessionmaker) and \
                (
                    not isinstance(target, type) or
                    not issubclass(target, Session)
                ):
                raise exc.ArgumentError(
                            "Session event listen on a scoped_session "
                            "requires that its creation callable "
                            "is associated with the Session class.")

db.session.session_factory is of type functools.partial, which angers SQLAlchemy.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 15 (5 by maintainers)

Most upvoted comments

You can work around this by registering the event handler on the underlying session class instead of on the created session object:

event.listen(SignallingSession, 'before_commit', before_commit)