diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6fd5edc1..9e1deb81 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,6 +86,14 @@ jobs: python: '3.13' allow_failure: false + - name: py314-djmain-postgres-xdist-coverage + python: '3.14' + allow_failure: true + + - name: py314-dj52-postgres-xdist-coverage + python: '3.14' + allow_failure: false + - name: py313-dj52-postgres-xdist-coverage python: '3.13' allow_failure: false @@ -126,17 +134,13 @@ jobs: python: '3.10' allow_failure: false - - name: py39-dj42-mysql-xdist-coverage - python: '3.9' - allow_failure: false - - name: py313-djmain-sqlite-coverage python: '3.13' allow_failure: true - name: py313-dj52-sqlite-coverage python: '3.13' - allow_failure: true + allow_failure: false - name: py312-dj51-sqlite-xdist-coverage python: '3.12' @@ -148,7 +152,7 @@ jobs: # pypy3: not included with coverage reports (much slower then). - name: pypy3-dj42-postgres - python: 'pypy3.9' + python: 'pypy3.10' allow_failure: false check: # This job does nothing and is only used for the branch protection diff --git a/README.rst b/README.rst index 87291333..6b31e079 100644 --- a/README.rst +++ b/README.rst @@ -34,7 +34,7 @@ pytest-django allows you to test your Django project/applications with the * Django: 4.2, 5.1, 5.2 and latest main branch (compatible at the time of each release) - * Python: CPython>=3.9 or PyPy 3 + * Python: CPython>=3.10 or PyPy 3 * pytest: >=7.0 For compatibility with older versions, use previous pytest-django releases. diff --git a/docs/changelog.rst b/docs/changelog.rst index d5cd706c..8c256e4e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,12 @@ Changelog v4.12.0 (Not released yet) -------------------------- +Compatibility +^^^^^^^^^^^^^ + +* Official Python 3.14 support. +* Dropped support for Python 3.9, minimum version is now Python 3.10. + Improvements ^^^^^^^^^^^^ diff --git a/pyproject.toml b/pyproject.toml index 75915cc8..34843643 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" name = "pytest-django" description = "A Django plugin for pytest." readme = "README.rst" -requires-python = ">=3.9" +requires-python = ">=3.10" dynamic = ["version"] authors = [ { name = "Andreas Pelme", email = "andreas@pelme.se" }, @@ -28,11 +28,11 @@ classifiers = [ "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", - "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", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Testing", diff --git a/pytest_django/asserts.py b/pytest_django/asserts.py index 76a45809..0dbc47bf 100644 --- a/pytest_django/asserts.py +++ b/pytest_django/asserts.py @@ -5,7 +5,7 @@ from __future__ import annotations from functools import wraps -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING from django import VERSION from django.test import LiveServerTestCase, SimpleTestCase, TestCase, TransactionTestCase @@ -24,6 +24,15 @@ class MessagesTestCase(MessagesTestMixin, TestCase): else: test_case = TestCase("run") +if TYPE_CHECKING: + from collections.abc import Callable, Collection, Iterator, Sequence + from contextlib import AbstractContextManager + from typing import Any, overload + + from django import forms + from django.db.models import Model, QuerySet, RawQuerySet + from django.http.response import HttpResponseBase + def _wrapper(name: str) -> Callable[..., Any]: func = getattr(test_case, name) @@ -55,13 +64,6 @@ def assertion_func(*args: Any, **kwargs: Any) -> Any: if TYPE_CHECKING: - from collections.abc import Collection, Iterator, Sequence - from contextlib import AbstractContextManager - from typing import overload - - from django import forms - from django.db.models import Model, QuerySet, RawQuerySet - from django.http.response import HttpResponseBase def assertRedirects( response: HttpResponseBase, diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index 6f7929be..209133ef 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from collections.abc import Generator, Iterable, Sequence +from collections.abc import Callable, Generator, Iterable, Sequence from contextlib import AbstractContextManager, contextmanager from functools import partial from typing import TYPE_CHECKING, Protocol @@ -16,7 +16,7 @@ if TYPE_CHECKING: - from typing import Any, Callable, Literal, Optional, Union + from typing import Any, Literal import django import django.test @@ -24,8 +24,8 @@ from . import DjangoDbBlocker from .django_compat import _User, _UserModel - _DjangoDbDatabases = Optional[Union[Literal["__all__"], Iterable[str]]] - _DjangoDbAvailableApps = Optional[list[str]] + _DjangoDbDatabases = Literal["__all__"] | Iterable[str] | None + _DjangoDbAvailableApps = list[str] | None # transaction, reset_sequences, databases, serialized_rollback, available_apps _DjangoDb = tuple[bool, bool, _DjangoDbDatabases, bool, _DjangoDbAvailableApps] diff --git a/tox.ini b/tox.ini index 5ffeeead..255f016e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] envlist = + py314-dj{main,52,51}-postgres py313-dj{main,52,51}-postgres py312-dj{main,52,51,42}-postgres py311-dj{main,52,51,42}-postgres py310-dj{main,52,51,42}-postgres - py39-dj42-postgres linting [testenv]