kvesteri / sqlalchemy-continuum

Versioning extension for SQLAlchemy.
BSD 3-Clause "New" or "Revised" License
568 stars 128 forks source link

Incompatibility with version 1.4 and SQLAlchemy<2 #351

Closed cc-a closed 4 months ago

cc-a commented 4 months ago

I recently an issue using sql-continuum==1.4.0 and sql-alchemy==1.4.52. To recreate:

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
import sqlalchemy as sa
from sqlalchemy_continuum import make_versioned

make_versioned(user_cls=None)
Base = declarative_base()

class Article(Base):
    __versioned__ = {}
    __tablename__ = 'article'

    id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)

sa.orm.configure_mappers()

engine = create_engine("sqlite:///tmp.sqlite")
connection = engine.connect()
connection.execute("BEGIN")

gives:

/home/ccaveayl/sqlalchemy_continuum_bug/main.py:21: RemovedIn20Warning: Deprecated API features detected! These feature(s) are not compatible with SQLAlchemy 2.0. To prevent incompatible upgrades prior to updating applications, ensure requirements files are pinned to "sqlalchemy<2.0". Set environment variable SQLALCHEMY_WARN_20=1 to show all deprecation warnings.  Set environment variable SQLALCHEMY_SILENCE_UBER_WARNING=1 to silence this message. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
  connection.execute("BEGIN")
Traceback (most recent call last):
  File "/home/ccaveayl/sqlalchemy_continuum_bug/main.py", line 21, in <module>
    connection.execute("BEGIN")
  File "/home/ccaveayl/sqlalchemy_continuum_bug/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1370, in execute
    return self._exec_driver_sql(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ccaveayl/sqlalchemy_continuum_bug/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1669, in _exec_driver_sql
    ) = self._invoke_before_exec_event(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ccaveayl/sqlalchemy_continuum_bug/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1506, in _invoke_before_exec_event
    elem, event_multiparams, event_params = fn(
                                            ^^^
  File "/home/ccaveayl/sqlalchemy_continuum_bug/.venv/lib/python3.11/site-packages/sqlalchemy/engine/events.py", line 112, in wrap_before_execute
    orig_fn(
  File "/home/ccaveayl/sqlalchemy_continuum_bug/.venv/lib/python3.11/site-packages/sqlalchemy_continuum/manager.py", line 436, in track_association_operations
    if clauseelement.is_insert:
       ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'is_insert'

As noted in the deprecation warning of the output the Connection.execute API was updated to remove use of plain strings. The new API seems to be assumed by VersioningManager.track_association_operations leading to a basic incompatibility with SQLAlchemy<2. At present the specified package dependencies for v1.4.0 does not reflect this and I have had to pin sqlalchemy-continuum to <1.4.0 in my environment as other constraints prevent upgrade to SQLAlchemy. I suggest the SQLAlchemy requirement for v1.4.0 be changed to 'SQLAlchemy>=2.0'.

marksteward commented 4 months ago

The aim is for Continuum 1.4 to be compatible with SQLAlchemy 1.4+, so this is a bug, not a version issue. I'll take a look...

marksteward commented 4 months ago

I've fixed that and released as 1.4.1. Unfortunately I've also had to pin to SQLAlchemy < 2.0.22 but I'll look to fix that too.

Note that your code is incompatible with 2.0. If you set future=True on your engine, you should get this exception:

sqlalchemy.exc.ObjectNotExecutableError: Not an executable object: 'BEGIN'

I assume that's the reason nobody else has hit this.