diff --git a/.github/workflows/CI-tests.yml b/.github/workflows/CI-tests.yml index c55ddbc..26dbe96 100644 --- a/.github/workflows/CI-tests.yml +++ b/.github/workflows/CI-tests.yml @@ -2,87 +2,53 @@ name: CI tests on: [push] -env: - poetry-version: 1.8.2 - jobs: lint: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python "3.9" - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - uses: pre-commit/action@v3.0.0 - - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] - django-version: ["4.2.16", "5.0.9", "5.1.2"] - exclude: - # Django too new - - django-version: "5.0.9" - python-version: "3.9" - - django-version: "5.1.2" - python-version: "3.9" steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Run image - uses: abatilo/actions-poetry@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 with: - poetry-version: ${{ env.poetry-version }} - - name: Cache Poetry virtual env - uses: actions/cache@v2 - env: - cache-name: cache-poetry-virtualenv - with: - path: .venv - key: ${{ runner.os }}-python-${{ matrix.python-version }}-django-${{ matrix.django-version }}-${{ hashFiles('pyproject.toml') }} - - name: Install packages - run: | - poetry config virtualenvs.in-project true - poetry remove django - poetry add django==${{ matrix.django-version }} --python ${{ matrix.python-version }} - poetry install - poetry show django + python-version: "3.9" + - uses: pre-commit/action@v3.0.1 test: runs-on: ubuntu-latest - needs: [build, lint] + needs: lint strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] - django-version: ["4.2.16", "5.0.9", "5.1.2"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + django-version: ["4.2", "5.1", "5.2"] exclude: # Django too new - - django-version: "5.0.9" + - django-version: "5.1" python-version: "3.9" - - django-version: "5.1.2" + - django-version: "5.2" python-version: "3.9" + # Django too old + - django-version: "4.2" + python-version: "3.13" + env: + DJANGO: ${{ matrix.django-version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Run image - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: ${{ env.poetry-version }} - - name: Cache Poetry virtual env - uses: actions/cache@v2 - env: - cache-name: cache-poetry-virtualenv + - name: Cache tox environments + uses: actions/cache@v4 with: - path: .venv - key: ${{ runner.os }}-python-${{ matrix.python-version }}-django-${{ matrix.django-version }}-${{ hashFiles('pyproject.toml') }} - - name: Test + path: .tox + key: ${{ runner.os }}-tox-py${{ matrix.python-version }}-django${{ matrix.django-version }}-${{ hashFiles('pyproject.toml', 'tox.ini') }} + restore-keys: | + ${{ runner.os }}-tox-py${{ matrix.python-version }}-django${{ matrix.django-version }}- + ${{ runner.os }}-tox-py${{ matrix.python-version }}- + ${{ runner.os }}-tox- + - name: Install tox and tox-gh-actions run: | - poetry run python runtests.py + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox diff --git a/.gitignore b/.gitignore index 6131e3b..a286120 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ wheels/ *.egg builds/ poetry.lock +.tox diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65c07c6..d10d02b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,16 @@ repos: - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 6.0.1 hooks: - id: isort language_version: python3.9 - repo: https://github.com/pycqa/flake8 - rev: 5.0.4 + rev: 7.3.0 hooks: - id: flake8 language_version: python3.9 - repo: https://github.com/python/black - rev: 23.10.1 + rev: 25.1.0 hooks: - id: black language_version: python3.9 @@ -36,14 +36,14 @@ repos: hooks: - id: prettier - repo: https://github.com/awebdeveloper/pre-commit-stylelint - rev: c4c991cd38b0218735858716b09924f8b20e3812 + rev: 0.0.2 hooks: - id: stylelint additional_dependencies: - stylelint@10.1.0 - stylelint-config-torchbox@0.5.0 - repo: https://github.com/Yelp/detect-secrets - rev: v0.13.0 + rev: v1.5.0 hooks: - id: detect-secrets args: ["--baseline", ".secrets.baseline"] diff --git a/.secrets.baseline b/.secrets.baseline index 96634c6..b510ba7 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -1,8 +1,4 @@ { - "exclude": { - "files": null, - "lines": null - }, "generated_at": "2020-05-29T17:40:29Z", "plugins_used": [ { @@ -12,15 +8,15 @@ "name": "ArtifactoryDetector" }, { - "base64_limit": 4.5, - "name": "Base64HighEntropyString" + "name": "Base64HighEntropyString", + "limit": 4.5 }, { "name": "BasicAuthDetector" }, { - "hex_limit": 3, - "name": "HexHighEntropyString" + "name": "HexHighEntropyString", + "limit": 3 }, { "name": "JwtTokenDetector" @@ -48,16 +44,49 @@ "results": { "poetry.lock": [ { + "type": "Hex High Entropy String", + "filename": "poetry.lock", "hashed_secret": "ad21572f9e3b4576a754f88e9873b445e8bb0660", "is_verified": false, - "line_number": 494, - "type": "Hex High Entropy String" + "line_number": 494 } ] }, - "version": "0.13.0", - "word_list": { - "file": null, - "hash": null - } + "version": "1.5.0", + "filters_used": [ + { + "path": "detect_secrets.filters.allowlist.is_line_allowlisted" + }, + { + "path": "detect_secrets.filters.heuristic.is_sequential_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_potential_uuid" + }, + { + "path": "detect_secrets.filters.heuristic.is_likely_id_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_templated_secret" + }, + { + "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" + }, + { + "path": "detect_secrets.filters.heuristic.is_indirect_reference" + }, + { + "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", + "min_level": 2 + }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + } + ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index d881915..f16622d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## 0.6.0 (2024-10-25) +## Unreleased + +- Support Python 3.13 +- Support Django 5.2 +- Drop support for Django 5.0 +- Add tox configuration for testing + ### Features - Drop support for Python 3.8 diff --git a/README.md b/README.md index 044b10c..693f348 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ This is implemented as a custom Django email backend. It presents a similar inte django-gov-notify supports: -- Python 3.9, 3.10, 3.11 and 3.12 -- Django 4.2, 5.0 and 5.1 +- Python 3.9, 3.10, 3.11, 3.12 and 3.13 +- Django 4.2, 5.1 and 5.2 ## Installation diff --git a/pyproject.toml b/pyproject.toml index 22da1b9..17b94ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,30 +15,29 @@ classifiers = [ "Topic :: Communications :: Email", "Framework :: Django", "Framework :: Django :: 4.2", - "Framework :: Django :: 5.0", "Framework :: Django :: 5.1", + "Framework :: Django :: 5.2", "License :: OSI Approved :: BSD License", "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", ] license = "BSD-2-Clause" [tool.poetry.dependencies] -python = ">=3.9,<3.13" -django = [ - {version = ">=4.2", python = ">=3.9,<3.13"}, -] +python = ">=3.9" +django = ">=4.2" notifications-python-client = "^8.1.0" [tool.poetry.dev-dependencies] -black = "^23.10.1" -isort = "^5.12.0" -flake8 = "^5.0.4" -pre-commit = "^3.5.0" -detect-secrets = "1.4.0" -factory-boy = "^3.2.0" +black = "^25.1.0" +isort = "^6.0.1" +flake8 = "^7.3.0" +pre-commit = "^4.2.0" +detect-secrets = "1.5.0" +factory-boy = "^3.3.3" [build-system] requires = ["poetry-core"] diff --git a/tests/settings.py b/tests/settings.py index 050b6b0..1150dad 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -40,7 +40,7 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "test-media") MEDIA_URL = "http://media.example.com/media/" -SECRET_KEY = "not needed" +SECRET_KEY = "not needed" # pragma: allowlist secret -GOVUK_NOTIFY_API_KEY = "not a real API key" +GOVUK_NOTIFY_API_KEY = "not a real API key" # pragma: allowlist secret GOVUK_NOTIFY_PLAIN_EMAIL_TEMPLATE_ID = str(uuid.uuid4()) diff --git a/tests/test_backend.py b/tests/test_backend.py index a2983d6..094afe9 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -14,7 +14,9 @@ class EmailBackendTest(TestCase): def setUp(self): self.backend = NotifyEmailBackend(govuk_notify_api_key="not a real key") - @override_settings(GOVUK_NOTIFY_API_KEY="fake settings key") + @override_settings( + GOVUK_NOTIFY_API_KEY="fake settings key" # pragma: allowlist secret + ) def test_default_key(self, mock_client): backend = NotifyEmailBackend() self.assertEqual(backend.api_key, "fake settings key") diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..315d2e4 --- /dev/null +++ b/tox.ini @@ -0,0 +1,61 @@ +[tox] +envlist = + py39-django42 + py310-django{42,51,52} + py311-django{42,51,52} + py312-django{42,51,52} + py313-django{51,52} + lint +minversion = 4.0 +isolated_build = true + +[gh-actions] +python = + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 + 3.13: py313 + +[gh-actions:env] +DJANGO = + 4.2: django42 + 5.1: django51 + 5.2: django52 + +[testenv] +deps = + django42: django>=4.2,<5.0 + django51: django>=5.1,<5.2 + django52: django>=5.2,<5.3 + notifications-python-client>=8.1.0 + factory-boy>=3.3.3 +commands = python runtests.py {posargs} + +[testenv:lint] # run with `tox -e lint` +deps = + black>=25.1.0 + isort>=6.0.1 + flake8>=7.3.0 +commands = + black --check --diff --exclude=".tox" . + isort --check-only --diff --skip=.tox . + flake8 . + +[testenv:format] # run with `tox -e format` +deps = + black>=25.1.0 + isort>=6.0.1 +commands = + black --exclude=".tox" . + isort --skip=.tox . + +[flake8] +max-line-length = 88 +extend-ignore = E203, W503 +exclude = .git,__pycache__,build,dist,.tox,.venv,venv + +[tool:isort] +profile = black +multi_line_output = 3 +line_length = 88