From 3861c368f7ea016049f0a7621455609aff8c4303 Mon Sep 17 00:00:00 2001 From: Hugo Rodger-Brown Date: Wed, 15 Nov 2023 10:10:57 +0000 Subject: [PATCH] Add Django 5.0 to build matrix --- .flake8 | 48 -------------- .github/workflows/tox.yml | 46 +++++++++---- .gitignore | 1 + .isort.cfg | 8 --- .pre-commit-config.yaml | 31 ++------- .ruff.toml | 66 +++++++++++++++++++ CHANGELOG | 11 +++- LICENSE | 2 +- README.md => README | 0 .../commands/truncate_csp_reports.py | 2 +- csp/settings.py | 2 +- demo/settings.py | 2 + pyproject.toml | 33 ++++------ tests/test_models.py | 4 +- tests/test_utils.py | 2 +- tox.ini | 36 +++++----- 16 files changed, 156 insertions(+), 138 deletions(-) delete mode 100644 .flake8 delete mode 100644 .isort.cfg create mode 100644 .ruff.toml rename README.md => README (100%) diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 4afc9f0..0000000 --- a/.flake8 +++ /dev/null @@ -1,48 +0,0 @@ -[flake8] -max-line-length = 88 -max-complexity = 8 -# http://flake8.pycqa.org/en/2.5.5/warnings.html#warning-error-codes -ignore = - # pydocstyle - docstring conventions (PEP257) - # Missing docstring in public module - D100 - # Missing docstring in public class - D101 - # Missing docstring in public method - D102 - # Missing docstring in public function - D103 - # Missing docstring in public package - D104 - # Missing docstring in magic method - D105 - # Missing docstring in public nested class - D106 - # Missing docstring in __init__ - D107 - # No blank lines allowed between a section header and its content - D412 - # pycodestyle - style checker (PEP8) - # line break before binary operator - W503 - # the following are ignored in CI using --extend-ignore option: - ; D205 # [pydocstyle] 1 blank line required between summary line and description - ; D400 # [pydocstyle] First line should end with a period - ; D401 # [pydocstyle] First line should be in imperative mood - ; S308 # [bandit] Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed. - ; S703 # [bandit] Potential XSS on mark_safe function. - -per-file-ignores = - ; D205 - 1 blank line required between summary line and description - ; D400 - First line should end with a period - ; D401 - First line should be in imperative mood - ; S101 - use of assert - ; S106 - hard-coded password - ; E501 - line-length - ; E731 - assigning a lambda to a variable - *tests/*:D205,D400,D401,S101,S106,E501,E731 - */migrations/*:E501 - ; F403 - unable to detect undefined names - ; F405 - may be undefined, or defined from star imports - */settings.py:F403,F405 - */settings/*:F403,F405 diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index d722455..812dd0f 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -14,18 +14,41 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - toxenv: [fmt,lint,mypy] + toxenv: [fmt, lint, mypy] env: TOXENV: ${{ matrix.toxenv }} steps: - name: Check out the repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Set up Python 3.10 - uses: actions/setup-python@v1 + - name: Set up Python (3.11) + uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" + + - name: Install and run tox + run: | + pip install tox + tox + + checks: + name: Run Django checks + runs-on: ubuntu-latest + strategy: + matrix: + toxenv: ["django-checks"] + env: + TOXENV: ${{ matrix.toxenv }} + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Set up Python (3.11) + uses: actions/setup-python@v4 + with: + python-version: "3.11" - name: Install and run tox run: | @@ -38,24 +61,25 @@ jobs: strategy: matrix: python: ["3.10", "3.11", "3.12"] - django: [32,42,50,main] + # build LTS version, next version, HEAD + django: ["32", "42", "50", "main"] exclude: + - python: "3.10" + django: "main" - python: "3.11" django: "32" - python: "3.12" django: "32" - - python: "3.12" - django: "42" env: - TOXENV: py${{ matrix.python }}-django${{ matrix.django }} + TOXENV: django${{ matrix.django }}-py${{ matrix.python }} steps: - name: Check out the repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} diff --git a/.gitignore b/.gitignore index 1940bea..7e6ab18 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.db *.egg-info *.pyc +dist node_modules poetry.lock test.db diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index 629cb68..0000000 --- a/.isort.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -default_section=THIRDPARTY -indent=' ' -sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER -multi_line_output=3 -line_length=88 -include_trailing_comma=True -use_parentheses=True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a3586e0..def9258 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,37 +1,20 @@ repos: - # python import sorting - will amend files - - repo: https://github.com/pre-commit/mirrors-isort - rev: v5.10.1 - hooks: - - id: isort - # python code formatting - will amend files - repo: https://github.com/ambv/black - rev: 23.1.0 + rev: 23.10.1 hooks: - id: black - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 - hooks: - - id: pyupgrade - - # Flake8 includes pyflakes, pycodestyle, mccabe, pydocstyle, bandit - - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + - repo: https://github.com/charliermarsh/ruff-pre-commit + # Ruff version. + rev: "v0.1.5" hooks: - - id: flake8 - additional_dependencies: - - flake8-bandit - - flake8-blind-except - - flake8-docstrings - - flake8-logging-format - - flake8-print - - pyyaml + - id: ruff + args: [--fix, --exit-non-zero-on-fix] # python static type checking - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.0 + rev: v1.7.0 hooks: - id: mypy args: diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..ccc1947 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,66 @@ +line-length = 88 +ignore = [ + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in __init__ + "D203", # 1 blank line required before class docstring + "D212", # Multi-line docstring summary should start at the first line + "D213", # Multi-line docstring summary should start at the second line + "D404", # First word of the docstring should not be "This" + "D405", # Section name should be properly capitalized + "D406", # Section name should end with a newline + "D407", # Missing dashed underline after section + "D410", # Missing blank line after section + "D411", # Missing blank line before section + "D412", # No blank lines allowed between a section header and its content + "D416", # Section name should end with a colon + "D417", + "D417", # Missing argument description in the docstring +] +select = [ + "A", # flake8 builtins + "C9", # mcabe + "D", # pydocstyle + "E", # pycodestyle (errors) + "F", # Pyflakes + "I", # isort + "S", # flake8-bandit + "T2", # flake8-print + "W", # pycodestype (warnings) +] + +[isort] +combine-as-imports = true + +[mccabe] +max-complexity = 8 + +[per-file-ignores] +"*tests/*" = [ + "D205", # 1 blank line required between summary line and description + "D400", # First line should end with a period + "D401", # First line should be in imperative mood + "D415", # First line should end with a period, question mark, or exclamation point + "E501", # Line too long + "E731", # Do not assign a lambda expression, use a def + "S101", # Use of assert detected + "S105", # Possible hardcoded password + "S106", # Possible hardcoded password + "S113", # Probable use of requests call with timeout set to {value} +] +"*/migrations/*" = [ + "E501", # Line too long +] +"*/settings.py" = [ + "F403", # from {name} import * used; unable to detect undefined names + "F405", # {name} may be undefined, or defined from star imports: +] +"*/settings/*" = [ + "F403", # from {name} import * used; unable to detect undefined names + "F405", # {name} may be undefined, or defined from star imports: +] diff --git a/CHANGELOG b/CHANGELOG index 17b214b..bd281ca 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,12 +2,19 @@ All notable changes to this project will be documented in this file. -## [1.0.0] - 2023-02-17 +## 3.1 - 2023-11-15 + +- Add Django 5.0 to build matrix +- Add Python 3.12 to build matrix + +No code changes. + +## 3.0.0 - 2023-11-07 - Drop support for Python < 3.10 - Drop support for Pydantic < 2 -## [0.10.0] - 2023-02-17 +## 0.10.0 - 2023-02-17 - Improve admin list view to include date filters and value search [#8] - Implement directive downgrades [#6] diff --git a/LICENSE b/LICENSE index 4a41f90..67a0b8c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 yunojuno +Copyright (c) 2023 yunojuno Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README similarity index 100% rename from README.md rename to README diff --git a/csp/management/commands/truncate_csp_reports.py b/csp/management/commands/truncate_csp_reports.py index 9fd94e5..bf789f2 100644 --- a/csp/management/commands/truncate_csp_reports.py +++ b/csp/management/commands/truncate_csp_reports.py @@ -4,7 +4,7 @@ class Command(BaseCommand): - help = "Clears out CSP violation reports" + help = "Clears out CSP violation reports" # noqa: A003 def handle(self, *args: object, **options: object) -> None: count, _ = CspReport.objects.all().delete() diff --git a/csp/settings.py b/csp/settings.py index f088ced..a6965f8 100644 --- a/csp/settings.py +++ b/csp/settings.py @@ -142,4 +142,4 @@ def get_default_rules_expanded() -> list[tuple[str, str]]: """ # Ask ChatGPT: how can I expand a dictionary of lists in python to a # list of tuples? - return [(k, v) for k, l in get_default_rules().items() for v in l] + return [(k, v) for k, lst in get_default_rules().items() for v in lst] diff --git a/demo/settings.py b/demo/settings.py index c026d78..8626918 100644 --- a/demo/settings.py +++ b/demo/settings.py @@ -7,6 +7,8 @@ DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": "demo.db"}} +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + INSTALLED_APPS = ( "django.contrib.admin", "django.contrib.auth", diff --git a/pyproject.toml b/pyproject.toml index 4475e8b..c6892bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,54 +1,49 @@ [tool.poetry] name = "django-csp-plus" -version = "3.0.0" +version = "3.1" description = "CSP tracking and violation report endpoint." license = "MIT" authors = ["YunoJuno "] maintainers = ["YunoJuno "] -readme = "README.md" +readme = "README" homepage = "https://github.com/yunojuno/django-csp-plus" repository = "https://github.com/yunojuno/django-csp-plus" documentation = "https://github.com/yunojuno/django-csp-plus" classifiers = [ - "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 3.2", "Framework :: Django :: 4.0", "Framework :: Django :: 4.1", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] packages = [{ include = "csp" }] [tool.poetry.dependencies] -python = "^3.8" -django = "^3.2 || ^4.0" +python = "^3.10" +django = "^3.2 || ^4.0 || ^5.0" pydantic = "*" -[tool.poetry.dev-dependencies] -black = "*" +[tool.poetry.group.test.dependencies] coverage = "*" -flake8 = "*" -flake8-bandit = "*" -flake8-blind-except = "*" -flake8-docstrings = "*" -flake8-logging-format = "*" -flake8-print = "*" -freezegun = "*" -isort = "*" -mypy = "*" -pre-commit = "*" pytest = "*" pytest-cov = "*" pytest-django = "*" -# forced dependency from flake8-bandit -pyyaml = "*" tox = "*" +[tool.poetry.group.dev.dependencies] +black = "*" +mypy = "*" +pre-commit = "*" +ruff = "*" + [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api" diff --git a/tests/test_models.py b/tests/test_models.py index 2999612..fd73ac2 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -34,7 +34,7 @@ ("ws://example.com", "ws://example.com"), ], ) -def test_clean_value(input: str, output: str) -> None: +def test_clean_value(input: str, output: str) -> None: # noqa: A002 assert CspRule.clean_value(input) == output @@ -73,7 +73,7 @@ def test_mandatory_fields(self, report_data: dict) -> None: ("https://example.com:80/foo/?bar", "https://example.com:80/foo/"), ], ) - def test_blocked_uri(self, input: str, output: str) -> None: + def test_blocked_uri(self, input: str, output: str) -> None: # noqa: A002 data = ReportData(effective_directive="img-src", blocked_uri=input) assert data.blocked_uri == output diff --git a/tests/test_utils.py b/tests/test_utils.py index e3c3d9a..a6b5c43 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -27,5 +27,5 @@ ("blob:", "blob:"), ], ) -def test_strip_path(input: str, output: str) -> None: +def test_strip_path(input: str, output: str) -> None: # noqa: A002 assert strip_path(input) == output diff --git a/tox.ini b/tox.ini index d72a37d..b0ae158 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,15 @@ [tox] isolated_build = True envlist = - fmt, lint, mypy, checks, - py{3.10}-django{32,42,50,main} - py{3.11}-django{42,50,main} - py{3.12}-django{50,main} + fmt, lint, mypy, + django-checks, + ; https://docs.djangoproject.com/en/5.0/releases/ + django32-py{310} + django40-py{310} + django41-py{310,311} + django42-py{310,311} + django50-py{310,311,312} + djangomain-py{311,312} [testenv] deps = @@ -15,12 +20,14 @@ deps = django32: Django>=3.2,<3.3 django40: Django>=4.0,<4.1 django41: Django>=4.1,<4.2 + django42: Django>=4.2,<4.3 + django50: https://github.com/django/django/archive/stable/5.0.x.tar.gz djangomain: https://github.com/django/django/archive/main.tar.gz commands = pytest --cov=csp --verbose tests/ -[testenv:checks] +[testenv:django-checks] description = Django system checks and missing migrations deps = Django commands = @@ -28,36 +35,25 @@ commands = python manage.py makemigrations --dry-run --check --verbosity 3 [testenv:fmt] -description = Python source code formatting (isort, black) +description = Python source code formatting (black) deps = - isort black commands = - isort --check-only csp black --check csp [testenv:lint] -description = Python source code linting (flake8, bandit, pydocstyle) +description = Python source code linting (ruff) deps = - flake8 - flake8-bandit - flake8-blind-except - flake8-docstrings - flake8-logging-format - flake8-print - pyyaml + ruff commands = - flake8 csp + ruff csp [testenv:mypy] description = Python source code type hints (mypy) deps = mypy - types-requests - types-python-dateutil - types-simplejson commands = mypy csp