diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d695066..46dfe5f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,13 +8,13 @@ repos: # Note: hooks that add content must run before ones which check formatting, lint, etc - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.4 + rev: v0.9.2 hooks: # Run the linter - id: ruff @@ -22,11 +22,11 @@ repos: # Run the formatter - id: ruff-format - repo: https://github.com/tox-dev/pyproject-fmt - rev: 2.2.3 + rev: v2.5.0 hooks: - id: pyproject-fmt - repo: https://github.com/adamchainz/blacken-docs - rev: 1.18.0 + rev: 1.19.1 hooks: - id: blacken-docs additional_dependencies: diff --git a/csp/constants.py b/csp/constants.py index 5504339..b278462 100644 --- a/csp/constants.py +++ b/csp/constants.py @@ -1,4 +1,4 @@ -from typing import Any, Type +from typing import Any HEADER = "Content-Security-Policy" HEADER_REPORT_ONLY = "Content-Security-Policy-Report-Only" @@ -17,7 +17,7 @@ class Nonce: _instance = None - def __new__(cls: Type["Nonce"], *args: Any, **kwargs: Any) -> "Nonce": + def __new__(cls: type["Nonce"], *args: Any, **kwargs: Any) -> "Nonce": if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance diff --git a/csp/utils.py b/csp/utils.py index e42bfbe..f224197 100644 --- a/csp/utils.py +++ b/csp/utils.py @@ -2,9 +2,8 @@ import copy import re -from collections import OrderedDict from itertools import chain -from typing import Any, Callable, Dict +from typing import Any, Callable from django.conf import settings from django.utils.encoding import force_str @@ -52,7 +51,7 @@ "block-all-mixed-content": None, # Deprecated. } -DIRECTIVES_T = Dict[str, Any] +DIRECTIVES_T = dict[str, Any] def default_config(csp: DIRECTIVES_T | None) -> DIRECTIVES_T | None: @@ -172,15 +171,16 @@ def _async_attr_mapper(attr_name: str, val: str | bool) -> str: # Allow per-attribute customization of returned string template -SCRIPT_ATTRS: dict[str, Callable[[str, Any], str]] = OrderedDict() -SCRIPT_ATTRS["nonce"] = _default_attr_mapper -SCRIPT_ATTRS["id"] = _default_attr_mapper -SCRIPT_ATTRS["src"] = _default_attr_mapper -SCRIPT_ATTRS["type"] = _default_attr_mapper -SCRIPT_ATTRS["async"] = _async_attr_mapper -SCRIPT_ATTRS["defer"] = _bool_attr_mapper -SCRIPT_ATTRS["integrity"] = _default_attr_mapper -SCRIPT_ATTRS["nomodule"] = _bool_attr_mapper +SCRIPT_ATTRS: dict[str, Callable[[str, Any], str]] = { + "nonce": _default_attr_mapper, + "id": _default_attr_mapper, + "src": _default_attr_mapper, + "type": _default_attr_mapper, + "async": _async_attr_mapper, + "defer": _bool_attr_mapper, + "integrity": _default_attr_mapper, + "nomodule": _bool_attr_mapper, +} # Generates an interpolatable string of valid attrs eg - '{nonce}{id}...' ATTR_FORMAT_STR = "".join([f"{{{a}}}" for a in SCRIPT_ATTRS]) diff --git a/pyproject.toml b/pyproject.toml index 1bff982..2d1a282 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", "Framework :: Django :: 5.1", + "Framework :: Django :: 5.2", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", @@ -87,7 +88,7 @@ include-package-data = true find = { namespaces = false } [tool.ruff] -target-version = "py38" +target-version = "py39" line-length = 150 indent-width = 4 extend-exclude = [ diff --git a/tox.ini b/tox.ini index 3270743..96536b4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,15 @@ [tox] isolated_build = True envlist = - {3.10,3.11,3.12,3.13,pypy310}-dj{4.2,5.0,5.1,main} + {3.12,3.13}-djmain + {3.10,3.11,3.12,3.13,pypy310}-dj{5.0,5.1} {3.9,3.10,3.11,3.12,3.13,pypy39,pypy310}-dj4.2 {3.9,3.10,3.11,3.12,3.13,pypy39,pypy310}-types # Don't run coverage when testing with pypy: # see https://github.com/nedbat/coveragepy/issues/1382 -[testenv:pypy{39,310}-dj4.2,pypy310-dj{5.0,5.1,main}] +[testenv:pypy{39,310}-dj4.2,pypy310-dj{5.0,5.1}] commands = pytest {toxinidir}/csp