diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 300d8d8c..697e4df7 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -39,6 +39,8 @@ class IdnaDomain(db.TypeDecorator): """ impl = db.String(80) + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode unicode domain name to punycode """ @@ -48,13 +50,13 @@ class IdnaDomain(db.TypeDecorator): """ decode punycode domain name to unicode """ return idna.decode(value) - python_type = str - class IdnaEmail(db.TypeDecorator): """ Stores a Unicode string in it's IDNA representation (ASCII only) """ impl = db.String(255) + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode unicode domain part of email address to punycode """ @@ -70,13 +72,13 @@ class IdnaEmail(db.TypeDecorator): localpart, domain_name = value.rsplit('@', 1) return f'{localpart}@{idna.decode(domain_name)}' - python_type = str - class CommaSeparatedList(db.TypeDecorator): """ Stores a list as a comma-separated string, compatible with Postfix. """ impl = db.String + cache_ok = True + python_type = list def process_bind_param(self, value, dialect): """ join list of items to comma separated string """ @@ -91,13 +93,13 @@ class CommaSeparatedList(db.TypeDecorator): """ split comma separated string to list """ return list(filter(bool, (item.strip() for item in value.split(',')))) if value else [] - python_type = list - class JSONEncoded(db.TypeDecorator): """ Represents an immutable structure as a json-encoded string. """ impl = db.String + cache_ok = True + python_type = str def process_bind_param(self, value, dialect): """ encode data as json """ @@ -107,8 +109,6 @@ class JSONEncoded(db.TypeDecorator): """ decode json to data """ return json.loads(value) if value else None - python_type = str - class Base(db.Model): """ Base class for all models """ diff --git a/core/admin/mailu/schemas.py b/core/admin/mailu/schemas.py index 191d01ac..00cbf464 100644 --- a/core/admin/mailu/schemas.py +++ b/core/admin/mailu/schemas.py @@ -145,6 +145,11 @@ class Logger: if history.has_changes() and history.deleted: before = history.deleted[-1] after = getattr(target, attr.key) + # we don't have ordered lists + if isinstance(before, list): + before = set(before) + if isinstance(after, list): + after = set(after) # TODO: this can be removed when comment is not nullable in model if attr.key == 'comment' and not before and not after: pass diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index 331239ba..d6c7aca3 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -26,8 +26,9 @@ Flask-Login==0.5.0 flask-marshmallow==0.14.0 Flask-Migrate==3.1.0 Flask-Script==2.0.6 -Flask-SQLAlchemy==2.4.0 +Flask-SQLAlchemy==2.5.1 Flask-WTF==0.15.1 +greenlet==1.1.2 gunicorn==20.1.0 html5lib==1.1 idna==3.3 @@ -39,16 +40,16 @@ limits==1.5.1 lockfile==0.12.2 Mako==1.1.5 MarkupSafe==2.0.1 -marshmallow==3.10.0 -marshmallow-sqlalchemy==0.24.1 +marshmallow==3.14.0 +marshmallow-sqlalchemy==0.26.1 msgpack==1.0.2 -mysqlclient==1.4.2.post1 +mysqlclient==2.0.3 ordered-set==4.0.2 # packaging==20.9 passlib==1.7.4 # pep517==0.10.0 progress==1.6 -psycopg2==2.8.2 +psycopg2==2.9.1 pycparser==2.20 Pygments==2.10.0 pyOpenSSL==21.0.0 @@ -60,7 +61,7 @@ requests==2.26.0 retrying==1.3.3 # six==1.15.0 socrate==0.2.0 -SQLAlchemy==1.3.3 +SQLAlchemy==1.4.26 srslib==0.1.4 tabulate==0.8.9 tenacity==8.0.1