From ab7662a874cd95d9a26e3c581db5ec6e7b7635b1 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Thu, 5 Sep 2024 06:39:39 -0500 Subject: [PATCH] Drop Python 3.7 and 3.8 support; add 3.12 support --- .github/workflows/test.yaml | 14 +++++++++----- .pre-commit-config.yaml | 2 +- CHANGES.rst | 6 ++++++ docs/installation.rst | 11 +++++------ setup.py | 7 ++----- sqlalchemy_utils/compat.py | 7 +------ sqlalchemy_utils/models.py | 16 ++++++++++++---- tests/test_models.py | 12 +++++++----- tox.ini | 9 +++------ 9 files changed, 46 insertions(+), 38 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 22579142..0323d42c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,16 +6,20 @@ jobs: fail-fast: false matrix: os: ['ubuntu-latest'] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' tox_env: ['sqlalchemy14', 'sqlalchemy2'] include: - # Test against Python 3.7 and sqlalchemy 1.3 + # Test against Python 3.9 and sqlalchemy 1.3 - os: 'ubuntu-20.04' - python-version: '3.7' + python-version: '3.9' tox_env: 'sqlalchemy13' - # Test against Python 3.7 and sqlalchemy 1.4 + # Test against Python 3.9 and sqlalchemy 1.4 - os: 'ubuntu-20.04' - python-version: '3.7' + python-version: '3.9' tox_env: 'sqlalchemy14' runs-on: ${{ matrix.os }} services: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2c41da3..bd895f92 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,4 +28,4 @@ repos: rev: v3.17.0 hooks: - id: pyupgrade - args: [--py36-plus] + args: [--py39-plus] diff --git a/CHANGES.rst b/CHANGES.rst index 5dcde0e6..59455a2c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,12 @@ Changelog Here you can see the full list of changes between each SQLAlchemy-Utils release. +Unreleased changes +^^^^^^^^^^^^^^^^^^ + +- Drop support for Python 3.7 and 3.8. +- Add support for Python 3.12. + 0.41.2 (2024-03-22) ^^^^^^^^^^^^^^^^^^^ diff --git a/docs/installation.rst b/docs/installation.rst index fd5f4fe4..a2b1cce6 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -6,13 +6,12 @@ This part of the documentation covers the installation of SQLAlchemy-Utils. Supported platforms ------------------- -SQLAlchemy-Utils is currently tested against the following Python platforms. +SQLAlchemy-Utils is currently tested against the following Python platforms: -- cPython 3.7 -- cPython 3.8 -- cPython 3.9 -- cPython 3.10 -- cPython 3.11 +- CPython 3.9 +- CPython 3.10 +- CPython 3.11 +- CPython 3.12 Installing an official release diff --git a/setup.py b/setup.py index 125863fc..a1d44ad2 100644 --- a/setup.py +++ b/setup.py @@ -76,22 +76,19 @@ def get_version(): platforms='any', install_requires=[ 'SQLAlchemy>=1.3', - "importlib_metadata ; python_version<'3.8'", ], extras_require=extras_require, - python_requires='>=3.7', + python_requires='>=3.9', classifiers=[ 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ] diff --git a/sqlalchemy_utils/compat.py b/sqlalchemy_utils/compat.py index 2a4871f7..16cded7e 100644 --- a/sqlalchemy_utils/compat.py +++ b/sqlalchemy_utils/compat.py @@ -1,10 +1,5 @@ import re -import sys - -if sys.version_info >= (3, 8): - from importlib.metadata import metadata -else: - from importlib_metadata import metadata +from importlib.metadata import metadata def get_sqlalchemy_version(version=metadata("sqlalchemy")["Version"]): diff --git a/sqlalchemy_utils/models.py b/sqlalchemy_utils/models.py index ca272d6a..6eb5a0bf 100644 --- a/sqlalchemy_utils/models.py +++ b/sqlalchemy_utils/models.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import sqlalchemy as sa @@ -22,15 +22,23 @@ class SomeModel(Base, Timestamp): id = sa.Column(sa.Integer, primary_key=True) """ - created = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) - updated = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) + created = sa.Column( + sa.DateTime, + default=lambda: datetime.now(tz=timezone.utc).replace(tzinfo=None), + nullable=False, + ) + updated = sa.Column( + sa.DateTime, + default=lambda: datetime.now(tz=timezone.utc).replace(tzinfo=None), + nullable=False, + ) @sa.event.listens_for(Timestamp, 'before_update', propagate=True) def timestamp_before_update(mapper, connection, target): # When a model with a timestamp is updated; force update the updated # timestamp. - target.updated = datetime.utcnow() + target.updated = datetime.now(tz=timezone.utc).replace(tzinfo=None) NOT_LOADED_REPR = '' diff --git a/tests/test_models.py b/tests/test_models.py index e7c1d66f..b8739361 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import pytest import sqlalchemy as sa @@ -17,13 +17,14 @@ class Article(Base, Timestamp): return Article def test_created(self, session, Article): - then = datetime.utcnow() + then = datetime.now(tz=timezone.utc).replace(tzinfo=None) article = Article() session.add(article) session.commit() - assert article.created >= then and article.created <= datetime.utcnow() + assert article.created >= then + assert article.created <= datetime.now(tz=timezone.utc).replace(tzinfo=None) def test_updated(self, session, Article): article = Article() @@ -31,12 +32,13 @@ def test_updated(self, session, Article): session.add(article) session.commit() - then = datetime.utcnow() + then = datetime.now(tz=timezone.utc).replace(tzinfo=None) article.name = "Something" session.commit() - assert article.updated >= then and article.updated <= datetime.utcnow() + assert article.updated >= then + assert article.updated <= datetime.now(tz=timezone.utc).replace(tzinfo=None) class TestGenericRepr: diff --git a/tox.ini b/tox.ini index 62b80468..b72ac941 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{37, 38, 39, 310, 311}-sqlalchemy{13, 14, 2} + py{3.9, 3.10, 3.11, 3.12}-sqlalchemy{13, 14, 2} flake8 isort @@ -46,15 +46,12 @@ commands = pre-commit run --hook-stage manual --all isort-check [pytest] filterwarnings = error - ; Ignore DeprecationWarnings caused by backports.zoneinfo (Python 3.6). - ignore:open_text is deprecated. Use files\(\) instead.:DeprecationWarning - ignore:open_binary is deprecated. Use files\(\) instead.:DeprecationWarning ; Ignore ResourceWarnings caused by unclosed sockets in pg8000. ; These are caught and re-raised as pytest.PytestUnraisableExceptionWarnings. ignore:Exception ignored:pytest.PytestUnraisableExceptionWarning ; Ignore DeprecationWarnings caused by pg8000. ignore:distutils Version classes are deprecated.:DeprecationWarning - ; Ignore cryptography deprecation warnings (Python 3.6). - ignore:Python 3.6 is no longer supported:UserWarning ; Ignore warnings about passlib's use of the crypt module (Python 3.11). ignore:'crypt' is deprecated and slated for removal:DeprecationWarning + ; Ignore Python 3.12 UTC deprecation warnings caused by pendulum. + ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning