From 0698327ef521ffe489cd8164068640dc738e683d Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Thu, 25 Aug 2022 17:07:12 +0200 Subject: [PATCH] [core][deps] Use sqlalchemy_utils instead of copy-paste code for merging references This fixes issues when using SQLite Signed-off-by: Ferdinand Thiessen --- flaschengeist/controller/userController.py | 2 +- flaschengeist/utils/foreign_keys.py | 51 ---------------------- setup.cfg | 1 + 3 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 flaschengeist/utils/foreign_keys.py diff --git a/flaschengeist/controller/userController.py b/flaschengeist/controller/userController.py index 65567ed..87f67c3 100644 --- a/flaschengeist/controller/userController.py +++ b/flaschengeist/controller/userController.py @@ -3,6 +3,7 @@ import secrets from io import BytesIO from sqlalchemy import exc +from sqlalchemy_utils import merge_references from datetime import datetime, timedelta, timezone from flask.helpers import send_file from werkzeug.exceptions import NotFound, BadRequest, Forbidden @@ -14,7 +15,6 @@ from ..models import Notification, User, Role from ..models.user import _PasswordReset from ..utils.hook import Hook from ..utils.datetime import from_iso_format -from ..utils.foreign_keys import merge_references from ..controller import imageController, messageController, pluginController, sessionController from ..plugins import AuthPlugin diff --git a/flaschengeist/utils/foreign_keys.py b/flaschengeist/utils/foreign_keys.py deleted file mode 100644 index ac2bedc..0000000 --- a/flaschengeist/utils/foreign_keys.py +++ /dev/null @@ -1,51 +0,0 @@ -# Borrowed from https://github.com/kvesteri/sqlalchemy-utils -# Modifications see: https://github.com/kvesteri/sqlalchemy-utils/issues/561 -# LICENSED under the BSD license, see upstream https://github.com/kvesteri/sqlalchemy-utils/blob/master/LICENSE - -import sqlalchemy as sa -from sqlalchemy.orm import object_session - - -def get_foreign_key_values(fk, obj): - mapper = sa.inspect(obj.__class__) - return dict( - ( - fk.constraint.columns.values()[index], - getattr(obj, element.column.key) - if hasattr(obj, element.column.key) - else getattr(obj, mapper.get_property_by_column(element.column).key), - ) - for index, element in enumerate(fk.constraint.elements) - ) - - -def get_referencing_foreign_keys(mixed): - tables = [mixed] - referencing_foreign_keys = set() - - for table in mixed.metadata.tables.values(): - if table not in tables: - for constraint in table.constraints: - if isinstance(constraint, sa.sql.schema.ForeignKeyConstraint): - for fk in constraint.elements: - if any(fk.references(t) for t in tables): - referencing_foreign_keys.add(fk) - return referencing_foreign_keys - - -def merge_references(from_, to, foreign_keys=None): - """ - Merge the references of an entity into another entity. - """ - if from_.__tablename__ != to.__tablename__: - raise TypeError("The tables of given arguments do not match.") - - session = object_session(from_) - foreign_keys = get_referencing_foreign_keys(from_.__table__) - - for fk in foreign_keys: - old_values = get_foreign_key_values(fk, from_) - new_values = get_foreign_key_values(fk, to) - session.query(from_.__mapper__).filter(*[k == old_values[k] for k in old_values]).update( - new_values, synchronize_session=False - ) diff --git a/setup.cfg b/setup.cfg index dcd1766..130d59a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,6 +28,7 @@ install_requires = flask_migrate>=3.1.0 flask_sqlalchemy>=2.5.1 sqlalchemy>=1.4.40 + sqlalchemy_utils>=0.38.3 toml werkzeug>=2.2.2