bpython / bpython

bpython - A fancy curses interface to the Python interactive interpreter
https://bpython-interpreter.org/
Other
2.64k stars 240 forks source link

bpython issues with Flask-SQLAlchemy session #676

Open nberrios opened 7 years ago

nberrios commented 7 years ago

I have been trying to find out why I am having some flask-sqlalchemy session handling issues while using bpython. Here is the issue in action:

(sockets) test@test~/checkouts/test$ bpython
bpython version 0.16 on top of Python 3.5.2 /home/test/virtualenvs/sockets/bin/python3
>>> from app import db, models
>>> db
<SQLAlchemy engine=postgresql://test:***@localhost/testdb>
>>> user = models.User(nickname='joe', email='joe@localhost')
>>> user in db.session
False
>>> db.session.add(user)
>>> user in db.session
False
>>>

Upon further inspection, it seems that the db.session.add() call in bpython is creating a new session entirely and placing the user instance in that one:

>>> from app import db, models
>>> db
<SQLAlchemy engine=postgresql://test:***@localhost/testdb>
>>> user = models.User(nickname='Joe', email='joe@localhost')
>>> user._sa_instance_state.transient
True
>>> user._sa_instance_state.session is None
True
>>> db.session
<sqlalchemy.orm.scoping.scoped_session object at 0x7f3532200a58>
>>> db.session.add(user)
>>> user in db.session
False
>>> user._sa_instance_state.pending
True
>>> user._sa_instance_state.session
<sqlalchemy.orm.session.SignallingSession object at 0x7f35336b1940>
>>> user._sa_instance_state.session.hash_key
1

and attempting to again add the instance to the db.session results in a conflict:

>>> db.session.add(user)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    db.session.add(user)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/scoping.py
", line 157, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/session.py
", line 1679, in add
    self._save_or_update_state(state)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/session.py
", line 1691, in _save_or_update_state
    self._save_or_update_impl(state)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/session.py
", line 1995, in _save_or_update_impl
    self._save_impl(state)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/session.py
", line 1947, in _save_impl
    to_attach = self._before_attach(state, obj)
  File "/home/test/virtualenvs/sockets/lib/python3.5/site-packages/sqlalchemy/orm/session.py
", line 2064, in _before_attach
    state.session_id, self.hash_key))
sqlalchemy.exc.InvalidRequestError: Object '<User at 0x7f3532055400>' is already attached to
session '1' (this is '3')

Any idea why this seems to only happen in bpython and not python/ipython?

sebastinas commented 7 years ago

I suspect that greenlets cause this issue.

thomasballinger commented 7 years ago

I agree the issue is greenlets here, see https://github.com/bpython/bpython/issues/641 which would be the fix.

thomasballinger commented 7 years ago

Probably a dup of https://github.com/bpython/bpython/issues/640 at least in root cause, but good to have this separate symptom of this filed.

jeurymejia301 commented 3 years ago

any updates here?