diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53899a4f..f0cf1e69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: rev: 1.21.0 hooks: - id: django-upgrade - args: [--target-version, '3.2'] + args: [--target-version, '4.2'] - repo: https://github.com/psf/black-pre-commit-mirror rev: 24.8.0 hooks: diff --git a/docs/changelog.rst b/docs/changelog.rst index ed9322bd..b29ef4cf 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +Unreleased +---------- + +* Drop Django 3.2 to 4.1 support. + * Drop Python 3.8 support. * Support Python 3.13. diff --git a/docs/django.rst b/docs/django.rst index 3b6e6421..216b1b01 100644 --- a/docs/django.rst +++ b/docs/django.rst @@ -83,9 +83,7 @@ caching. WhiteNoise comes with a storage backend which compresses your files and hashes them to unique names, so they can safely be cached forever. To use it, set it -as your staticfiles storage backend in your settings file. - -On Django 4.2+: +as your staticfiles storage backend in your settings file: .. code-block:: python @@ -96,12 +94,6 @@ On Django 4.2+: }, } -On older Django versions: - -.. code-block:: python - - STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" - This combines automatic compression with the caching behaviour provided by Django's ManifestStaticFilesStorage_ backend. If you want to apply compression but don't want the caching behaviour then you can use the alternative backend: diff --git a/docs/index.rst b/docs/index.rst index 75122865..09582507 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,7 +31,7 @@ WhiteNoise works with any WSGI-compatible application. Python 3.8 to 3.13 supported. -Django 3.2 to 5.1 supported. +Django 4.2 to 5.1 supported. Installation ------------ diff --git a/pyproject.toml b/pyproject.toml index b9f5b8ee..17ced5cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,9 +23,6 @@ requires-python = ">=3.9" classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Django", - "Framework :: Django :: 3.2", - "Framework :: Django :: 4.0", - "Framework :: Django :: 4.1", "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", "Framework :: Django :: 5.1", diff --git a/tests/django_settings.py b/tests/django_settings.py index 23bcd14e..139b920b 100644 --- a/tests/django_settings.py +++ b/tests/django_settings.py @@ -2,8 +2,6 @@ import os.path -import django - from tests.utils import TEST_FILE_PATH from tests.utils import AppServer @@ -20,14 +18,11 @@ STATIC_ROOT = os.path.join(TEST_FILE_PATH, "root") -if django.VERSION >= (4, 2): - STORAGES = { - "staticfiles": { - "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", - }, - } -else: - STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STORAGES = { + "staticfiles": { + "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", + }, +} MIDDLEWARE = ["whitenoise.middleware.WhiteNoiseMiddleware"] diff --git a/tests/requirements/compile.py b/tests/requirements/compile.py index be811200..85245736 100755 --- a/tests/requirements/compile.py +++ b/tests/requirements/compile.py @@ -22,36 +22,6 @@ *sys.argv[1:], ] run = partial(subprocess.run, check=True) - run( - [ - *common_args, - "--python", - "3.9", - "--output-file", - "py39-django32.txt", - ], - input=b"Django>=3.2a1,<3.3", - ) - run( - [ - *common_args, - "--python", - "3.9", - "--output-file", - "py39-django40.txt", - ], - input=b"Django>=4.0a1,<4.1", - ) - run( - [ - *common_args, - "--python", - "3.9", - "--output-file", - "py39-django41.txt", - ], - input=b"Django>=4.1a1,<4.2", - ) run( [ *common_args, @@ -62,36 +32,6 @@ ], input=b"Django>=4.2a1,<5.0", ) - run( - [ - *common_args, - "--python", - "3.10", - "--output-file", - "py310-django32.txt", - ], - input=b"Django>=3.2a1,<3.3", - ) - run( - [ - *common_args, - "--python", - "3.10", - "--output-file", - "py310-django40.txt", - ], - input=b"Django>=4.0a1,<4.1", - ) - run( - [ - *common_args, - "--python", - "3.10", - "--output-file", - "py310-django41.txt", - ], - input=b"Django>=4.1a1,<4.2", - ) run( [ *common_args, @@ -122,16 +62,6 @@ ], input=b"Django>=5.1a1,<5.2", ) - run( - [ - *common_args, - "--python", - "3.11", - "--output-file", - "py311-django41.txt", - ], - input=b"Django>=4.1a1,<4.2", - ) run( [ *common_args, diff --git a/tests/requirements/py310-django32.txt b/tests/requirements/py310-django32.txt deleted file mode 100644 index 296ab7a3..00000000 --- a/tests/requirements/py310-django32.txt +++ /dev/null @@ -1,44 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.10 --output-file py310-django32.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==3.2.25 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -pytz==2024.1 - # via django -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests diff --git a/tests/requirements/py310-django40.txt b/tests/requirements/py310-django40.txt deleted file mode 100644 index 69c7fc25..00000000 --- a/tests/requirements/py310-django40.txt +++ /dev/null @@ -1,42 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.10 --output-file py310-django40.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==4.0.10 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests diff --git a/tests/requirements/py310-django41.txt b/tests/requirements/py310-django41.txt deleted file mode 100644 index 5f277d77..00000000 --- a/tests/requirements/py310-django41.txt +++ /dev/null @@ -1,42 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.10 --output-file py310-django41.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==4.1.13 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests diff --git a/tests/requirements/py311-django41.txt b/tests/requirements/py311-django41.txt deleted file mode 100644 index 07a4f7bc..00000000 --- a/tests/requirements/py311-django41.txt +++ /dev/null @@ -1,34 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.11 --output-file py311-django41.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==4.1.13 - # via -r requirements.in -idna==3.8 - # via requests -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -urllib3==2.2.2 - # via requests diff --git a/tests/requirements/py39-django32.txt b/tests/requirements/py39-django32.txt deleted file mode 100644 index a8a832e5..00000000 --- a/tests/requirements/py39-django32.txt +++ /dev/null @@ -1,48 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.9 --output-file py39-django32.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==3.2.25 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -importlib-metadata==8.4.0 - # via pytest-randomly -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -pytz==2024.1 - # via django -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests -zipp==3.20.1 - # via importlib-metadata diff --git a/tests/requirements/py39-django40.txt b/tests/requirements/py39-django40.txt deleted file mode 100644 index ec09f009..00000000 --- a/tests/requirements/py39-django40.txt +++ /dev/null @@ -1,46 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.9 --output-file py39-django40.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==4.0.10 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -importlib-metadata==8.4.0 - # via pytest-randomly -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests -zipp==3.20.1 - # via importlib-metadata diff --git a/tests/requirements/py39-django41.txt b/tests/requirements/py39-django41.txt deleted file mode 100644 index 143ba58d..00000000 --- a/tests/requirements/py39-django41.txt +++ /dev/null @@ -1,46 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --constraint - requirements.in --python 3.9 --output-file py39-django41.txt -asgiref==3.8.1 - # via django -brotli==1.1.0 - # via -r requirements.in -certifi==2024.8.30 - # via requests -charset-normalizer==3.3.2 - # via requests -coverage==7.6.1 - # via -r requirements.in -django==4.1.13 - # via -r requirements.in -exceptiongroup==1.2.2 - # via pytest -idna==3.8 - # via requests -importlib-metadata==8.4.0 - # via pytest-randomly -iniconfig==2.0.0 - # via pytest -packaging==24.1 - # via pytest -pluggy==1.5.0 - # via pytest -pytest==8.3.2 - # via - # -r requirements.in - # pytest-randomly -pytest-randomly==3.15.0 - # via -r requirements.in -requests==2.32.3 - # via -r requirements.in -sqlparse==0.5.1 - # via django -tomli==2.0.1 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.2 - # via requests -zipp==3.20.1 - # via importlib-metadata diff --git a/tests/test_storage.py b/tests/test_storage.py index e890d12d..ee401e49 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -6,7 +6,6 @@ import tempfile from posixpath import basename -import django import pytest from django.conf import settings from django.contrib.staticfiles.storage import HashedFilesMixin @@ -37,15 +36,12 @@ def setup(): @pytest.fixture() def _compressed_storage(setup): backend = "whitenoise.storage.CompressedStaticFilesStorage" - if django.VERSION >= (4, 2): - storages = { - "STORAGES": { - **settings.STORAGES, - "staticfiles": {"BACKEND": backend}, - } + storages = { + "STORAGES": { + **settings.STORAGES, + "staticfiles": {"BACKEND": backend}, } - else: - storages = {"STATICFILES_STORAGE": backend} + } with override_settings(**storages): yield @@ -54,15 +50,12 @@ def _compressed_storage(setup): @pytest.fixture() def _compressed_manifest_storage(setup): backend = "whitenoise.storage.CompressedManifestStaticFilesStorage" - if django.VERSION >= (4, 2): - storages = { - "STORAGES": { - **settings.STORAGES, - "staticfiles": {"BACKEND": backend}, - } + storages = { + "STORAGES": { + **settings.STORAGES, + "staticfiles": {"BACKEND": backend}, } - else: - storages = {"STATICFILES_STORAGE": backend} + } with override_settings(**storages, WHITENOISE_KEEP_ONLY_HASHED_FILES=True): call_command("collectstatic", verbosity=0, interactive=False) diff --git a/tox.ini b/tox.ini index b30c92d6..09ecb62b 100644 --- a/tox.ini +++ b/tox.ini @@ -4,10 +4,10 @@ requires = env_list = py313-django{51} py312-django{51, 50, 42} - py311-django{51, 50, 42, 41} + py311-django{51, 50, 42} py311-codegen - py310-django{51, 50, 42, 41, 40, 32} - py39-django{42, 41, 40, 32} + py310-django{51, 50, 42} + py39-django{42} [testenv] package = wheel