From f8b049f014c6252c0d3350a7994bb945070450747f9f04a94d4c78cb627fed4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=C3=A9ta=20Machov=C3=A1?= Date: Fri, 15 Nov 2024 13:31:07 +0000 Subject: [PATCH] - temporarily disable tests that are broken with SLQAlchemy 2.0.36 * https://github.com/pallets-eco/flask-sqlalchemy/issues/1378 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:flask/python-Flask-SQLAlchemy?expand=0&rev=35 --- .gitattributes | 23 +++ .gitignore | 1 + flask_sqlalchemy-3.1.1.tar.gz | 3 + python-Flask-SQLAlchemy.changes | 348 ++++++++++++++++++++++++++++++++ python-Flask-SQLAlchemy.spec | 71 +++++++ stop-using-utcnow.patch | 137 +++++++++++++ 6 files changed, 583 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 flask_sqlalchemy-3.1.1.tar.gz create mode 100644 python-Flask-SQLAlchemy.changes create mode 100644 python-Flask-SQLAlchemy.spec create mode 100644 stop-using-utcnow.patch diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/flask_sqlalchemy-3.1.1.tar.gz b/flask_sqlalchemy-3.1.1.tar.gz new file mode 100644 index 0000000..61e72ba --- /dev/null +++ b/flask_sqlalchemy-3.1.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4b68bb881802dda1a7d878b2fc84c06d1ee57fb40b874d3dc97dabfa36b8312 +size 81899 diff --git a/python-Flask-SQLAlchemy.changes b/python-Flask-SQLAlchemy.changes new file mode 100644 index 0000000..3da236a --- /dev/null +++ b/python-Flask-SQLAlchemy.changes @@ -0,0 +1,348 @@ +------------------------------------------------------------------- +Fri Nov 15 13:23:23 UTC 2024 - Nico Krapp + +- temporarily disable tests that are broken with SLQAlchemy 2.0.36 + * https://github.com/pallets-eco/flask-sqlalchemy/issues/1378 + +------------------------------------------------------------------- +Wed Oct 30 02:33:57 UTC 2024 - Steve Kowalik + +- Ignore ResourceWarning during pytest to avoid a Python 3.13 failure. + +------------------------------------------------------------------- +Thu Feb 1 05:13:58 UTC 2024 - Steve Kowalik + +- Add patch stop-using-utcnow.patch: + * Use a callable wrapping datetime.now(utc) rather than utcnow(). + +------------------------------------------------------------------- +Thu Oct 19 21:37:17 UTC 2023 - Matej Cepl + +- Clean up the SPEC file + +------------------------------------------------------------------- +Fri Sep 29 13:25:24 UTC 2023 - Ondřej Súkup + +- update to 3.1.1 + * Deprecate the __version__ attribute. + * Drop support for Python 3.7. + * Add support for the SQLAlchemy 2.x API via model_class parameter. + * Bump minimum version of SQLAlchemy to 2.0.16. + * Remove previously deprecated code. + * Pass extra keyword arguments from get_or_404 to session.get. + * Fix bug with finding right bind key for clause statements. + +------------------------------------------------------------------- +Wed Aug 2 07:00:50 UTC 2023 - Steve Kowalik + +- Update to 3.0.5: + * ``Pagination.next()`` enforces ``max_per_page``. + * Improve type hint for ``get_or_404`` return value to be non-optional. + * Fix type hint for ``get_or_404`` return value. + * Fix type hints for pyright (used by VS Code Pylance extension). + * Show helpful errors when mistakenly using multiple ``SQLAlchemy`` + instances for the same app, or without calling ``init_app`` + * Fix issue with getting the engine associated with a model that uses + polymorphic table inheritance. +- Update URL. + +------------------------------------------------------------------- +Sun Jun 11 14:16:45 UTC 2023 - ecsos + +- Add %{?sle15_python_module_pythons} + +------------------------------------------------------------------- +Sat Dec 3 14:35:16 UTC 2022 - John Vandenberg + +- Remove python-Flask-SQLAlchemy-no-mock.patch merged upstream +- Update to v3.0.2 + * Update compatibility with SQLAlchemy 2. +- from v3.0.1 + * Export typing information instead of using external typeshed definitions. + * If default engine options are set, but SQLALCHEMY_DATABASE_URI is not set, + an invalid default bind will not be configured. +- from v3.0.0 + * Drop support for Python 2, 3.4, 3.5, and 3.6. + * Bump minimum version of Flask to 2.2. + * Bump minimum version of SQLAlchemy to 1.4.18. + * Remove previously deprecated code. + * The session is scoped to the current app context instead of the thread. + This requires that an app context is active. This ensures that the + session is cleaned up after every request. + * An active Flask application context is always required to access session + and engine, regardless of if an application was passed to the constructor. + * Different bind keys use different SQLAlchemy MetaData registries, + allowing tables in different databases to have the same name. + Bind keys are stored and looked up on the resulting metadata rather + than the model or table. + * SQLALCHEMY_DATABASE_URI does not default to sqlite:///:memory:. + An error is raised if neither it nor SQLALCHEMY_BINDS define any engines. + * Configuring SQLite with a relative path is relative to app.instance_path + instead of app.root_path. The instance folder is created if necessary. + * Added get_or_404, first_or_404, one_or_404, and paginate methods to the + extension object. These use SQLAlchemy's preferred session.execute(select()) + pattern instead of the legacy query interface. + * Setup methods that create the engines and session are renamed with a + leading underscore. They are considered internal interfaces which may + change at any time. + * All parameters to SQLAlchemy except app are keyword-only. + * Renamed the bind parameter to bind_key and removed the app parameter + from various SQLAlchemy methods. + * The extension object uses __getattr__ to alias names from the SQLAlchemy + package, rather than copying them as attributes. + * The extension object is stored directly as app.extensions["sqlalchemy"]. + * The session class can be customized by passing the class_ key in the session_options parameter. + * SignallingSession is renamed to Session. + * Session.get_bind more closely matches the base implementation. + * Model classes and the db instance are available without imports in flask shell. + * The CamelCase to snake_case table name converter handles more patterns correctly. + If model that was already created in the database changed, either use Alembic + to rename the table, or set __tablename__ to keep the old name. + * Model repr distinguishes between transient and pending instances. + * A custom model class can implement __init_subclass__ with class parameters. + * db.Table is a subclass instead of a function. + * The engine_options parameter is applied as defaults before per-engine configuration. + * SQLALCHEMY_BINDS values can either be an engine URL, or a dict of engine options + including URL, for each bind. SQLALCHEMY_DATABASE_URI and SQLALCHEMY_ENGINE_OPTIONS + correspond to the None key and take precedence. + * Engines are created when calling init_app rather than the first time they are accessed. + * db.engines exposes the map of bind keys to engines for the current app. + * get_engine, get_tables_for_bind, and get_binds are deprecated. + * SQLite driver-level URIs that look like sqlite:///file:name.db?uri=true are supported. + * SQLite engines do not use NullPool if pool_size is 0. + * MySQL engines use the "utf8mb4" charset by default. + * MySQL engines do not set pool_size to 10. + * MySQL engines don't set a default for pool_recycle if not using a queue pool. + * Query is renamed from BaseQuery. + * Added Query.one_or_404. + * The query class is applied to backref in relationship. + * Creating Pagination objects manually is no longer a public API. + They should be created with db.paginate or query.paginate. + * Pagination.iter_pages and Query.paginate parameters are keyword-only. + * Pagination is iterable, iterating over its items. + * Pagination count query is more efficient. + * Pagination.iter_pages is more efficient. + * Pagination.iter_pages right_current parameter is inclusive. + * Pagination per_page cannot be 0. + * Pagination max_per_page defaults to 100. + * Added Pagination.first and last properties, which give the + number of the first and last item on the page. + * SQLALCHEMY_RECORD_QUERIES is disabled by default, and is not + enabled automatically with app.debug or app.testing. + * get_debug_queries is renamed to get_recorded_queries + to better match the config and functionality. + * Recorded query info is a dataclass instead of a tuple. + The context attribute is renamed to location. + Finding the location uses a more inclusive check. + * SQLALCHEMY_TRACK_MODIFICATIONS is disabled by default. + * SQLALCHEMY_COMMIT_ON_TEARDOWN is deprecated. It can cause various + design issues that are difficult to debug. Call db.session.commit() directly instead. + +------------------------------------------------------------------- +Tue May 17 11:46:36 UTC 2022 - pgajdos@suse.com + +- do not require python-mock for build +- added patches + fix https://github.com/pallets-eco/flask-sqlalchemy/commit/20864ddfe4f9b70f20d38e5dc3f8d49c1ca99207 + + python-Flask-SQLAlchemy-no-mock.patch + +------------------------------------------------------------------- +Thu Mar 3 11:35:08 UTC 2022 - Dominique Leuenberger + +- Work around test suite failure inside OBS: BuildRequire krb5. + krb5 is a dependency to python (via tirpc), and inside OBS we get + a slightly limited version of it as krb5-mini. The test suite of + this package fails to pass with the mini flavor though. As -mini + is never offered to actual users, we can get away with this + workaround. + +------------------------------------------------------------------- +Sun Apr 4 23:23:50 UTC 2021 - Arun Persaud + +- specfile: + * update copyright year + +- update to version 2.5.1: + * Fix compatibility with Python 2.7. + +- changes from version 2.5.0: + * Update to support SQLAlchemy 1.4. + * SQLAlchemy URL objects are immutable. Some internal methods have + changed to return a new URL instead of None. :issue:`885` + +------------------------------------------------------------------- +Sat Jul 18 18:04:37 UTC 2020 - Arun Persaud + +- update to version 2.4.4: + * Change base class of meta mixins to type. This fixes an issue + caused by a regression in CPython 3.8.4. :issue:`852` + +------------------------------------------------------------------- +Sun May 31 00:08:47 UTC 2020 - Arun Persaud + +- specfile: + * update copyright year + +- update to version 2.4.3: + * Deprecate SQLALCHEMY_COMMIT_ON_TEARDOWN as it can cause various + design issues that are difficult to debug. Call + db.session.commit() directly instead. :issue:`216` + +- changes from version 2.4.2: + * Fix bad pagination when records are de-duped. :pr:`812` + +------------------------------------------------------------------- +Thu Sep 26 16:40:48 UTC 2019 - Arun Persaud + +- update to version 2.4.1: + * Fix AttributeError when using multiple binds with polymorphic + models. :pr:`651` + +------------------------------------------------------------------- +Sat May 4 22:49:10 UTC 2019 - Arun Persaud + +- specfile: + * update copyright year + * be more specific in %files section + * CHANGES, README changed to rst + +- update to version 2.4.0: + * Make engine configuration more flexible. (:pr:`684`) + * Address SQLAlchemy 1.3 deprecations. (:pr:`684`) + * get_or_404() and first_or_404() now accept a description parameter + to control the 404 message. (:issue:`636`) + * Use time.perf_counter for Python 3 on Windows. (:issue:`638`) + * Drop support for Python 2.6 and 3.3. (:pr:`687`) + * Add an example of Flask's tutorial project, Flaskr, adapted for + Flask-SQLAlchemy. (:pr:`720`) + +- changes from version 2.3.3: + * Fix "AttributeError: 'NoneType' object has no attribute 'info'", + when using polymorphic models. (#651) + +------------------------------------------------------------------- +Thu Oct 12 02:50:06 UTC 2017 - arun@gmx.de + +- update to version 2.3.2: + * Don't mask the parent table for single-table inheritance + models. (#561) + +------------------------------------------------------------------- +Tue Oct 10 01:54:46 UTC 2017 - arun@gmx.de + +- specfile: + * increased SQLAlchemy dependency to >= 0.8 + * changed from nose to pytest + * added fdupes to remove some rpmlint warnings + +- update to version 2.3.1: + * If a model has a table name that matches an existing table in the + metadata, use that table. Fixes a regression where reflected + tables were not picked up by models. (#551) + * Raise the correct error when a model has a table name but no + primary key. (#556) + * Fix repr on models that don't have an identity because they have + not been flushed yet. (#555) + * Allow specifying a max_per_page limit for pagination, to avoid + users specifying high values in the request args. (#542) + * For paginate with error_out=False, the minimum value for page is 1 + and per_page is 0. (#558) + +- changes from version 2.3.0: + * Multiple bugs with __tablename__ generation are fixed. Names will + be generated for models that define a primary key, but not for + single-table inheritance subclasses. Names will not override a + declared_attr. PrimaryKeyConstraint is detected. (#541) + * Passing an existing declarative_base() as model_class to + SQLAlchemy.__init__ will use this as the base class instead of + creating one. This allows customizing the metaclass used to + construct the base. (#546) + * The undocumented DeclarativeMeta internals that the extension uses + for binds and table name generation have been refactored to work + as mixins. Documentation is added about how to create a custom + metaclass that does not do table name generation. (#546) + * Model and metaclass code has been moved to a new models + module. _BoundDeclarativeMeta is renamed to DefaultMeta; the old + name will be removed in 3.0. (#546) + * Models have a default repr that shows the model name and primary + key. (#530) + * Fixed a bug where using init_app would cause connectors to always + use the current_app rather than the app they were created + for. This caused issues when multiple apps were registered with + the extension. (#547) + +- changes from version 2.2: + * Minimum SQLAlchemy version is 0.8 due to use of + sqlalchemy.inspect. + * Added support for custom query_class and model_class as args to + the SQLAlchemy constructor. (#328) + * Allow listening to SQLAlchemy events on db.session. (#364) + * Allow __bind_key__ on abstract models. (#373) + * Allow SQLALCHEMY_ECHO to be a string. (#409) + * Warn when SQLALCHEMY_DATABASE_URI is not set. (#443) + * Don't let pagination generate invalid page numbers. (#460) + * Drop support of Flask < 0.10. This means the db session is always + tied to the app context and its teardown event. (#461) + * Tablename generation logic no longer accesses class properties + unless they are declared_attr. (#467) + +------------------------------------------------------------------- +Sat Oct 7 03:54:00 UTC 2017 - arun@gmx.de + +- convert to single spec +- update copyright + +------------------------------------------------------------------- +Thu Sep 15 17:39:24 UTC 2016 - toddrme2178@gmail.com + +- Update to Version 2.1 + - Table names are automatically generated in more cases, including + subclassing mixins and abstract models. + - Allow using a custom MetaData object. + - Add support for binds parameter to session. +- Update to Version 2.0 + - Changed how the builtin signals are subscribed to skip non Flask-SQLAlchemy + sessions. This will also fix the attribute error about model changes + not existing. + - Added a way to control how signals for model modifications are tracked. + - Made the ``SignallingSession`` a public interface and added a hook + for customizing session creation. + - If the ``bind`` parameter is given to the signalling session it will no + longer cause an error that a parameter is given twice. + - Added working table reflection support. + - Enabled autoflush by default. + - Consider ``SQLALCHEMY_COMMIT_ON_TEARDOWN`` harmful and remove from docs. +- Update to Version 1.0 + - Added Python 3.3 support. + - Dropped 2.5 compatibility. + - Various bugfixes + - Changed versioning format to do major releases for each update now. + +------------------------------------------------------------------- +Thu Oct 24 11:05:50 UTC 2013 - speilicke@suse.com + +- Require python-setuptools instead of distribute (upstreams merged) + +------------------------------------------------------------------- +Fri Jun 22 12:33:38 UTC 2012 - saschpe@suse.de + +- Update to version 0.16: + + New distribution format (flask_sqlalchemy) + + Added support for Flask 0.9 specifics. + +------------------------------------------------------------------- +Thu Nov 24 10:36:02 UTC 2011 - saschpe@suse.de + +- Fix bnc#732325 + +------------------------------------------------------------------- +Fri Sep 23 13:27:29 UTC 2011 - saschpe@suse.de + +- Update to version 0.15: + + Added session support for multiple databases + +------------------------------------------------------------------- +Wed Jul 20 20:06:56 UTC 2011 - saschpe@gmx.de + +- Initial version + diff --git a/python-Flask-SQLAlchemy.spec b/python-Flask-SQLAlchemy.spec new file mode 100644 index 0000000..f352dba --- /dev/null +++ b/python-Flask-SQLAlchemy.spec @@ -0,0 +1,71 @@ +# +# spec file for package python-Flask-SQLAlchemy +# +# Copyright (c) 2024 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%{?sle15_python_module_pythons} +Name: python-Flask-SQLAlchemy +Version: 3.1.1 +Release: 0 +Summary: SQLAlchemy support for Flask +License: BSD-3-Clause +URL: https://github.com/mitsuhiko/flask-sqlalchemy +Source: https://files.pythonhosted.org/packages/source/f/flask_sqlalchemy/flask_sqlalchemy-%{version}.tar.gz +# PATCH-FIX-UPSTREAM gh#pallets-eco/flask-sqlalchemy#1308 +Patch0: stop-using-utcnow.patch +BuildRequires: %{python_module flit-core} +BuildRequires: %{python_module pip} +BuildRequires: %{python_module wheel} +BuildRequires: fdupes +# BR krb5 - the test suite fails with krb5-mini (and users in any case will only ever get krb5, never krb5-mini) +BuildRequires: krb5 +BuildRequires: python-rpm-macros +Requires: python-Flask >= 2.2 +Requires: python-SQLAlchemy >= 2.0.16 +BuildArch: noarch +# SECTION test requirements +BuildRequires: %{python_module Flask >= 2.2} +BuildRequires: %{python_module SQLAlchemy >= 2.0.16} +BuildRequires: %{python_module pytest} +# /SECTION +%python_subpackages + +%description +Adds SQLAlchemy support to your Flask application. + +%prep +%autosetup -p1 -n flask_sqlalchemy-%{version} + +%build +%pyproject_wheel + +%install +%pyproject_install +%python_expand %fdupes %{buildroot}%{$python_sitelib} + +%check +# skip tests that are broken with SQLAlchemy 2.0.36 +# https://github.com/pallets-eco/flask-sqlalchemy/issues/1378 +donttest=("-k" "not test_model_bind") +%pytest -W "ignore::ResourceWarning" "${donttest[@]}" + +%files %{python_files} +%license LICENSE.rst +%doc CHANGES.rst README.rst +%{python_sitelib}/flask_sqlalchemy +%{python_sitelib}/flask_sqlalchemy-%{version}.dist-info + +%changelog diff --git a/stop-using-utcnow.patch b/stop-using-utcnow.patch new file mode 100644 index 0000000..eed8bf1 --- /dev/null +++ b/stop-using-utcnow.patch @@ -0,0 +1,137 @@ +From 172e2391ab3de16ec7a001226985aec3ee2f8353 Mon Sep 17 00:00:00 2001 +From: Steve Kowalik +Date: Wed, 31 Jan 2024 16:39:57 +1100 +Subject: [PATCH] Stop using datetime.utcnow() in tests + +datetime.utcnow() is deprecated for Python 3.12+, and raises a warning. +Since warnings are treated as errors, this results in test failures. +Since utcnow calls are done by the SQLAlchemy mapping machinery, we need +to use a callable. + +Fixes #1303 +--- + CHANGES.rst | 5 +++++ + tests/test_model.py | 38 ++++++++++++++++++++------------------ + 2 files changed, 25 insertions(+), 18 deletions(-) + +diff --git a/CHANGES.rst b/CHANGES.rst +index 60c7f2b2..afb639d9 100644 +--- a/CHANGES.rst ++++ b/CHANGES.rst +@@ -1,3 +1,8 @@ ++Unreleased ++---------- ++ ++- No longer call ``datetime.utcnow()`` in the test suite. :issue:`1303` ++ + Version 3.1.1 + ------------- + +diff --git a/tests/test_model.py b/tests/test_model.py +index 0968a1e2..dda0a5fa 100644 +--- a/tests/test_model.py ++++ b/tests/test_model.py +@@ -2,6 +2,7 @@ + + import typing as t + from datetime import datetime ++from datetime import timezone + + import pytest + import sqlalchemy as sa +@@ -14,6 +15,11 @@ + from flask_sqlalchemy.model import Model + + ++class UTCNow(datetime): ++ def __new__(cls): # type: ignore[no-untyped-def] ++ return datetime.now(tz=timezone.utc) ++ ++ + def test_default_model_class_1x(app: Flask) -> None: + db = SQLAlchemy(app) + +@@ -147,12 +153,12 @@ def test_abstractmodel(app: Flask, model_class: t.Any) -> None: + class TimestampModel(db.Model): + __abstract__ = True + created: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, nullable=False, insert_default=datetime.utcnow, init=False ++ db.DateTime, nullable=False, insert_default=UTCNow, init=False + ) + updated: sa_orm.Mapped[datetime] = sa_orm.mapped_column( + db.DateTime, +- insert_default=datetime.utcnow, +- onupdate=datetime.utcnow, ++ insert_default=UTCNow, ++ onupdate=UTCNow, + init=False, + ) + +@@ -167,10 +173,10 @@ class Post(TimestampModel): + class TimestampModel(db.Model): # type: ignore[no-redef] + __abstract__ = True + created: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, nullable=False, default=datetime.utcnow ++ db.DateTime, nullable=False, default=UTCNow + ) + updated: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow ++ db.DateTime, default=UTCNow, onupdate=UTCNow + ) + + class Post(TimestampModel): # type: ignore[no-redef] +@@ -181,10 +187,8 @@ class Post(TimestampModel): # type: ignore[no-redef] + + class TimestampModel(db.Model): # type: ignore[no-redef] + __abstract__ = True +- created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) +- updated = db.Column( +- db.DateTime, onupdate=datetime.utcnow, default=datetime.utcnow +- ) ++ created = db.Column(db.DateTime, nullable=False, default=UTCNow) ++ updated = db.Column(db.DateTime, onupdate=UTCNow, default=UTCNow) + + class Post(TimestampModel): # type: ignore[no-redef] + id = db.Column(db.Integer, primary_key=True) +@@ -207,12 +211,12 @@ def test_mixinmodel(app: Flask, model_class: t.Any) -> None: + + class TimestampMixin(sa_orm.MappedAsDataclass): + created: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, nullable=False, insert_default=datetime.utcnow, init=False ++ db.DateTime, nullable=False, insert_default=UTCNow, init=False + ) + updated: sa_orm.Mapped[datetime] = sa_orm.mapped_column( + db.DateTime, +- insert_default=datetime.utcnow, +- onupdate=datetime.utcnow, ++ insert_default=UTCNow, ++ onupdate=UTCNow, + init=False, + ) + +@@ -226,10 +230,10 @@ class Post(TimestampMixin, db.Model): + + class TimestampMixin: # type: ignore[no-redef] + created: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, nullable=False, default=datetime.utcnow ++ db.DateTime, nullable=False, default=UTCNow + ) + updated: sa_orm.Mapped[datetime] = sa_orm.mapped_column( +- db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow ++ db.DateTime, default=UTCNow, onupdate=UTCNow + ) + + class Post(TimestampMixin, db.Model): # type: ignore[no-redef] +@@ -239,10 +243,8 @@ class Post(TimestampMixin, db.Model): # type: ignore[no-redef] + else: + + class TimestampMixin: # type: ignore[no-redef] +- created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) +- updated = db.Column( +- db.DateTime, onupdate=datetime.utcnow, default=datetime.utcnow +- ) ++ created = db.Column(db.DateTime, nullable=False, default=UTCNow) ++ updated = db.Column(db.DateTime, onupdate=UTCNow, default=UTCNow) + + class Post(TimestampMixin, db.Model): # type: ignore[no-redef] + id = db.Column(db.Integer, primary_key=True)