From 99fb008d231bdc798072bb320be02f6bc808635b Mon Sep 17 00:00:00 2001 From: Federico Busetti <729029+febus982@users.noreply.github.com> Date: Sun, 15 Dec 2024 15:30:00 +0000 Subject: [PATCH] Python 3.13 (#62) * Add support for python 3.13 *Drop support for python 3.8 * Bump up actions to python 3.13 --- .github/workflows/python-code-style.yml | 4 +- .github/workflows/python-lint.yml | 4 +- .github/workflows/python-quality.yml | 4 +- .github/workflows/python-tests.yml | 2 +- .github/workflows/python-typing.yml | 4 +- .github/workflows/release.yml | 4 +- .github/workflows/reusable-github-pages.yml | 4 +- Makefile | 2 +- README.md | 2 +- pyproject.toml | 13 ++++--- .../result_presenters/test_composite_pk.py | 11 ++++-- tests/repository/test_save.py | 17 +++++---- .../session_handler/test_session_lifecycle.py | 38 +++++++++++-------- tox.ini | 4 +- 14 files changed, 64 insertions(+), 49 deletions(-) diff --git a/.github/workflows/python-code-style.yml b/.github/workflows/python-code-style.yml index 536b2e5..c84b626 100644 --- a/.github/workflows/python-code-style.yml +++ b/.github/workflows/python-code-style.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/python-lint.yml b/.github/workflows/python-lint.yml index 4cc679c..a00e294 100644 --- a/.github/workflows/python-lint.yml +++ b/.github/workflows/python-lint.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/python-quality.yml b/.github/workflows/python-quality.yml index 5fae30a..fcc57e4 100644 --- a/.github/workflows/python-quality.yml +++ b/.github/workflows/python-quality.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index b222f17..8335564 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + version: ["3.9", "3.10", "3.11", "3.12", "3.13"] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/python-typing.yml b/.github/workflows/python-typing.yml index adc79b9..d92e04e 100644 --- a/.github/workflows/python-typing.yml +++ b/.github/workflows/python-typing.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6630263..92d9656 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,10 +17,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | diff --git a/.github/workflows/reusable-github-pages.yml b/.github/workflows/reusable-github-pages.yml index 17231d4..5909f7d 100644 --- a/.github/workflows/reusable-github-pages.yml +++ b/.github/workflows/reusable-github-pages.yml @@ -39,10 +39,10 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install dependencies run: | diff --git a/Makefile b/Makefile index 1473d7d..9ee8046 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ docs: poetry run mkdocs serve fix: - poetry run ruff . --fix + poetry run ruff check . --fix poetry run ruff format . check: poetry-export diff --git a/README.md b/README.md index 820dde8..e97e93d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # SQLAlchemy bind manager -![Static Badge](https://img.shields.io/badge/Python-3.8_%7C_3.9_%7C_3.10_%7C_3.11_%7C_3.12-blue?logo=python&logoColor=white) +![Static Badge](https://img.shields.io/badge/Python-3.9_%7C_3.10_%7C_3.11_%7C_3.12_%7C_3.13-blue?logo=python&logoColor=white) [![Stable Version](https://img.shields.io/pypi/v/sqlalchemy-bind-manager?color=blue)](https://pypi.org/project/sqlalchemy-bind-manager/) [![stability-beta](https://img.shields.io/badge/stability-beta-33bbff.svg)](https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#beta) diff --git a/pyproject.toml b/pyproject.toml index 49933b8..18abe51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,10 +20,11 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "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", + "Programming Language :: Python :: 3.13", "Topic :: Database", "Topic :: Database :: Front-Ends", "Topic :: Software Development :: Libraries :: Python Modules", @@ -38,7 +39,7 @@ requires = ["poetry-core", "poetry-dynamic-versioning"] build-backend = "poetry_dynamic_versioning.backend" [tool.poetry.dependencies] -python = ">=3.8,<3.13" +python = ">=3.9,<3.14" pydantic = "^2.1.1" SQLAlchemy = { version = "~2.0.0", extras = ["asyncio", "mypy"] } @@ -51,9 +52,11 @@ coverage = ">=6.5.0" mike = ">=2.0.0" mkdocs = ">=1.4.3" mkdocstrings = { version = ">=0.24.0", extras = ["python"] } +mkdocs-awesome-pages-plugin = "^2.9.2" mkdocs-gen-files = ">=0.5.0" mkdocs-material = ">=9.1.16" mypy = ">=0.990" +poetry-plugin-export = "*" pymdown-extensions = ">=10.0.1" pytest = "^8.0.0" pytest-asyncio = ">=0.20.3" @@ -62,7 +65,6 @@ pytest-factoryboy = ">=2.5.0" pytest-xdist = ">=3.0.2" ruff = ">=0.0.263" tox = "^4.14.1" -mkdocs-awesome-pages-plugin = "^2.9.2" ############################ ### Tools configuration ### @@ -83,11 +85,12 @@ exclude_also = [ [tool.mypy] files = "sqlalchemy_bind_manager" -python_version = "3.8" +python_version = "3.9" plugins = "pydantic.mypy" [tool.pytest.ini_options] asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" minversion = "6.0" addopts = "-n auto --cov-report=term-missing" testpaths = [ @@ -96,7 +99,7 @@ testpaths = [ [tool.ruff] extend-exclude = ["docs", ".tox"] -target-version = "py38" +target-version = "py39" [tool.ruff.lint] select = [ diff --git a/tests/repository/result_presenters/test_composite_pk.py b/tests/repository/result_presenters/test_composite_pk.py index a65b321..20232f4 100644 --- a/tests/repository/result_presenters/test_composite_pk.py +++ b/tests/repository/result_presenters/test_composite_pk.py @@ -6,8 +6,11 @@ def test_exception_raised_if_multiple_primary_keys(): - with patch( - "sqlalchemy_bind_manager._repository.result_presenters.inspect", - return_value=Mock(primary_key=["1", "2"]), - ), pytest.raises(NotImplementedError): + with ( + patch( + "sqlalchemy_bind_manager._repository.result_presenters.inspect", + return_value=Mock(primary_key=["1", "2"]), + ), + pytest.raises(NotImplementedError), + ): _pk_from_result_object("irrelevant") diff --git a/tests/repository/test_save.py b/tests/repository/test_save.py index f523062..0918c85 100644 --- a/tests/repository/test_save.py +++ b/tests/repository/test_save.py @@ -49,13 +49,16 @@ class SomeTestError(Exception): ) session_mock = AsyncMock if isinstance(sa_bind, SQLAlchemyAsyncBind) else MagicMock - with patch.object( - session_class, "rollback", new_callable=session_mock, return_value=None - ) as mocked_rollback, patch.object( - session_class, - "commit", - new_callable=session_mock, - side_effect=SomeTestError, + with ( + patch.object( + session_class, "rollback", new_callable=session_mock, return_value=None + ) as mocked_rollback, + patch.object( + session_class, + "commit", + new_callable=session_mock, + side_effect=SomeTestError, + ), ): repo = repository_class(bind=sa_bind, model_class=model_class) diff --git a/tests/session_handler/test_session_lifecycle.py b/tests/session_handler/test_session_lifecycle.py index 300c66d..7c3a79d 100644 --- a/tests/session_handler/test_session_lifecycle.py +++ b/tests/session_handler/test_session_lifecycle.py @@ -32,14 +32,17 @@ def test_session_is_removed_on_cleanup_even_if_loop_is_not_running(sa_manager): original_session_remove = sh.scoped_session.remove original_get_event_loop = asyncio.get_event_loop - with patch.object( - sh.scoped_session, - "remove", - wraps=original_session_remove, - ) as mocked_close, patch( - "asyncio.get_event_loop", - wraps=original_get_event_loop, - ) as mocked_get_event_loop: + with ( + patch.object( + sh.scoped_session, + "remove", + wraps=original_session_remove, + ) as mocked_close, + patch( + "asyncio.get_event_loop", + wraps=original_get_event_loop, + ) as mocked_get_event_loop, + ): # This should trigger the garbage collector and close the session sh = None @@ -52,14 +55,17 @@ def test_session_is_removed_on_cleanup_even_if_loop_search_errors_out(sa_manager sh = AsyncSessionHandler(sa_manager.get_bind("async")) original_session_remove = sh.scoped_session.remove - with patch.object( - sh.scoped_session, - "remove", - wraps=original_session_remove, - ) as mocked_close, patch( - "asyncio.get_event_loop", - side_effect=RuntimeError(), - ) as mocked_get_event_loop: + with ( + patch.object( + sh.scoped_session, + "remove", + wraps=original_session_remove, + ) as mocked_close, + patch( + "asyncio.get_event_loop", + side_effect=RuntimeError(), + ) as mocked_get_event_loop, + ): # This should trigger the garbage collector and close the session sh = None diff --git a/tox.ini b/tox.ini index fda9829..ff1c841 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,11 @@ [tox] min_version = 4.0 env_list = + py313 py312 py311 py310 py39 - py38 typing lint format @@ -22,7 +22,7 @@ deps = commands = pytest -[testenv:py312] +[testenv:py313] ; Run with coverage in one python version to check coverage percentage commands = pytest --cov