From 5d8d7968079f07be78e4bdaa5716d1f327c01427 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Sat, 20 Mar 2021 10:09:08 +0100 Subject: [PATCH] Compatibility for sqlalchemy 2.0 --- cps/config_sql.py | 8 ++++++-- cps/db.py | 14 ++++++++++---- cps/gdriveutils.py | 6 +++++- cps/ub.py | 24 ++++++++++++++---------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/cps/config_sql.py b/cps/config_sql.py index 60e17eb3..17f1c613 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -23,7 +23,11 @@ import sys from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean, BLOB, JSON from sqlalchemy.exc import OperationalError -from sqlalchemy.ext.declarative import declarative_base +try: + # Compability with sqlalchemy 2.0 + from sqlalchemy.orm import declarative_base +except ImportError: + from sqlalchemy.ext.declarative import declarative_base from . import constants, cli, logger, ub @@ -66,7 +70,7 @@ class _Settings(_Base): config_random_books = Column(Integer, default=4) config_authors_max = Column(Integer, default=0) config_read_column = Column(Integer, default=0) - config_title_regex = Column(String, default=u'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') + config_title_regex = Column(String, default=r'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') config_mature_content_tags = Column(String, default='') config_theme = Column(Integer, default=0) diff --git a/cps/db.py b/cps/db.py index 7e908476..ac59ac2b 100644 --- a/cps/db.py +++ b/cps/db.py @@ -30,7 +30,12 @@ from sqlalchemy import Table, Column, ForeignKey, CheckConstraint from sqlalchemy import String, Integer, Boolean, TIMESTAMP, Float from sqlalchemy.orm import relationship, sessionmaker, scoped_session from sqlalchemy.orm.collections import InstrumentedList -from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta +from sqlalchemy.ext.declarative import DeclarativeMeta +try: + # Compability with sqlalchemy 2.0 + from sqlalchemy.orm import declarative_base +except ImportError: + from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.pool import StaticPool from sqlalchemy.sql.expression import and_, true, false, text, func, or_ from sqlalchemy.ext.associationproxy import association_proxy @@ -465,8 +470,9 @@ class CalibreDB(): isolation_level="SERIALIZABLE", connect_args={'check_same_thread': False}, poolclass=StaticPool) - cls.engine.execute("attach database '{}' as calibre;".format(dbpath)) - cls.engine.execute("attach database '{}' as app_settings;".format(app_db_path)) + with cls.engine.begin() as connection: + connection.execute(text("attach database '{}' as calibre;".format(dbpath))) + connection.execute(text("attach database '{}' as app_settings;".format(app_db_path))) conn = cls.engine.connect() # conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302 @@ -477,7 +483,7 @@ class CalibreDB(): config.db_configured = True if not cc_classes: - cc = conn.execute("SELECT id, datatype FROM custom_columns") + cc = conn.execute(text("SELECT id, datatype FROM custom_columns")) cc_ids = [] books_custom_column_links = {} diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index 79587b79..5f970554 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -28,7 +28,11 @@ from sqlalchemy import create_engine from sqlalchemy import Column, UniqueConstraint from sqlalchemy import String, Integer from sqlalchemy.orm import sessionmaker, scoped_session -from sqlalchemy.ext.declarative import declarative_base +try: + # Compability with sqlalchemy 2.0 + from sqlalchemy.orm import declarative_base +except ImportError: + from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.exc import OperationalError, InvalidRequestError try: diff --git a/cps/ub.py b/cps/ub.py index 967ac0c5..ecf98679 100644 --- a/cps/ub.py +++ b/cps/ub.py @@ -38,12 +38,16 @@ except ImportError: oauth_support = True except ImportError: oauth_support = False -from sqlalchemy import create_engine, exc, exists, event +from sqlalchemy import create_engine, exc, exists, event, text from sqlalchemy import Column, ForeignKey from sqlalchemy import String, Integer, SmallInteger, Boolean, DateTime, Float, JSON -from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm.attributes import flag_modified from sqlalchemy.sql.expression import func +try: + # Compability with sqlalchemy 2.0 + from sqlalchemy.orm import declarative_base +except ImportError: + from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import backref, relationship, sessionmaker, Session, scoped_session from werkzeug.security import generate_password_hash @@ -484,7 +488,7 @@ def migrate_registration_table(engine, session): def migrate_guest_password(engine, session): try: with engine.connect() as conn: - conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''") + conn.execute(text("UPDATE user SET password='' where nickname = 'Guest' and password !=''")) session.commit() except exc.OperationalError: print('Settings database is not writeable. Exiting...') @@ -597,11 +601,11 @@ def migrate_Database(session): try: # check if one table with autoincrement is existing (should be user table) with engine.connect() as conn: - conn.execute("SELECT COUNT(*) FROM sqlite_sequence WHERE name='user'") + conn.execute(text("SELECT COUNT(*) FROM sqlite_sequence WHERE name='user'")) except exc.OperationalError: # Create new table user_id and copy contents of table user into it with engine.connect() as conn: - conn.execute("CREATE TABLE user_id (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + conn.execute(text("CREATE TABLE user_id (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," "nickname VARCHAR(64)," "email VARCHAR(120)," "role SMALLINT," @@ -612,14 +616,14 @@ def migrate_Database(session): "default_language VARCHAR(3)," "view_settings VARCHAR," "UNIQUE (nickname)," - "UNIQUE (email))") - conn.execute("INSERT INTO user_id(id, nickname, email, role, password, kindle_mail,locale," + "UNIQUE (email))")) + conn.execute(text("INSERT INTO user_id(id, nickname, email, role, password, kindle_mail,locale," "sidebar_view, default_language, view_settings) " "SELECT id, nickname, email, role, password, kindle_mail, locale," - "sidebar_view, default_language FROM user") + "sidebar_view, default_language FROM user")) # delete old user table and rename new user_id table to user: - conn.execute("DROP TABLE user") - conn.execute("ALTER TABLE user_id RENAME TO user") + conn.execute(text("DROP TABLE user")) + conn.execute(text("ALTER TABLE user_id RENAME TO user")) session.commit() migrate_guest_password(engine, session)