From 9635ddd444fb3828a9d4f43aa4557fe4a3e4ada1 Mon Sep 17 00:00:00 2001 From: Hugo Rodger-Brown Date: Tue, 7 Nov 2023 11:04:01 +0000 Subject: [PATCH] Update Django / Python support Drop Django 3.1, add Django 4, 5. --- .flake8 | 38 ---------- .github/workflows/tox.yml | 76 ++++++++++++------- .isort.cfg | 8 -- .pre-commit-config.yaml | 47 ++++-------- .ruff.toml | 66 ++++++++++++++++ CHANGELOG.md | 7 ++ LICENSE | 2 +- README.md | 2 +- demo/__init__.py | 0 demo/apps.py | 1 - pyproject.toml | 25 +++--- tox.ini | 31 +++++--- visitors/admin.py | 4 +- visitors/decorators.py | 4 - visitors/migrations/0001_initial.py | 1 - visitors/migrations/0002_visitorlog.py | 1 - visitors/migrations/0003_visitor_is_active.py | 1 - .../migrations/0004_visitor_expires_at.py | 1 - .../migrations/0005_visitorlog_status_code.py | 1 - .../migrations/0006_alter_visitor_uuid.py | 1 - .../migrations/0007_visitor_session_expiry.py | 1 - 21 files changed, 170 insertions(+), 148 deletions(-) delete mode 100644 .flake8 delete mode 100644 .isort.cfg create mode 100644 .ruff.toml create mode 100644 demo/__init__.py diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 6e88df2..0000000 --- a/.flake8 +++ /dev/null @@ -1,38 +0,0 @@ -[flake8] -max-line-length = 88 -max-complexity = 8 - -exclude = - .git, - .venv, - .tox, - tests, - migrations - -ignore = - # http://flake8.pycqa.org/en/2.5.5/warnings.html#warning-error-codes - # pydocstyle - docstring conventions (PEP257) - D1 # [pydocstyle] missing docstring - D203 # [pydocstyle] 1 blank line required before class docstring - D212 # [pydocstyle] Multi-line docstring summary should start at the first line - D406 # [pydocstyle] Section name should end with a newline - D407 # [pydocstyle] Missing dashed underline after section - D412 # [pydocstyle] No blank lines allowed between a section header and its content - # pycodestyle - style checker (PEP8) - W503 # [pycodestyle] line break before binary operator - W504 # [pycodestyle] line break after binary operator - # bandit - security warnings - S308 # [bandit] Use of mark_safe - S311 # [bandit] Use of random - S703 # [bandit] Use of django_mark_safe - -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 - visitors/migrations/*:E501 diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 85f1670..9497167 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.9 - uses: actions/setup-python@v1 + - name: Set up Python (3.11) + uses: actions/setup-python@v4 with: - python-version: 3.9 + 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: | @@ -37,35 +60,34 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [3.8,3.9,"3.10"] - django: [31,32,40,main] + python: ["3.8", "3.9", "3.10", "3.11", "3.12"] + # build LTS version, next version, HEAD + django: ["32", "42", "50", "main"] + exclude: + - python: "3.8" + django: "50" + - python: "3.8" + django: "main" + - python: "3.9" + django: "50" + - python: "3.9" + django: "main" + - python: "3.10" + django: "main" + - python: "3.11" + django: "32" + - python: "3.12" + django: "32" env: - TOXENV: py${{ matrix.python }}-django${{ matrix.django }} - - # services: - # postgres: - # image: postgres:12 - # env: - # POSTGRES_USER: postgres - # POSTGRES_PASSWORD: postgres - # POSTGRES_DB: onfido - # # Set health checks to wait until postgres has started - # options: >- - # --health-cmd pg_isready - # --health-interval 10s - # --health-timeout 5s - # --health-retries 5 - # ports: - # # Maps tcp port 5432 on service container to the host - # - 5432:5432 + 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/.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 2d6b74a..ff35e6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,47 +1,26 @@ 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: 22.6.0 + rev: 23.10.1 hooks: - id: black - # update syntax where appropriate - - repo: https://github.com/asottile/pyupgrade - rev: v2.37.2 - hooks: - - id: pyupgrade - - # formatting of django templates - - repo: https://github.com/rtts/djhtml - rev: v1.5.1 - hooks: - - id: djhtml - - # Flake8 includes pyflakes, pycodestyle, mccabe, pydocstyle, bandit - - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.2 + - repo: https://github.com/charliermarsh/ruff-pre-commit + # Ruff version. + rev: "v0.1.4" hooks: - - id: flake8 - additional_dependencies: - - flake8-docstrings - - flake8-bandit - - flake8-print + - id: ruff + args: [--fix, --exit-non-zero-on-fix] # python static type checking - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.971 + rev: v1.6.1 hooks: - id: mypy args: - - --disallow-untyped-defs - - --disallow-incomplete-defs - - --check-untyped-defs - - --no-implicit-optional - - --ignore-missing-imports - - --follow-imports=silent + - --disallow-untyped-defs + - --disallow-incomplete-defs + - --check-untyped-defs + - --no-implicit-optional + - --ignore-missing-imports + - --follow-imports=silent 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.md b/CHANGELOG.md index 2ac49d9..d356779 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## v1.0 + +* Add support for Django 5.0 +* Add support for Python 3.11, 3.12 +* Drop support for Django 3.1 +* Replace isort, flake8 with ruff + ## v0.7 * Add support for per-token session expiry (#9) diff --git a/LICENSE b/LICENSE index 4a41f90..4b2a997 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 yunojuno +Copyright (c) 2023 YunoJuno Limited 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.md index 084e2eb..9f3e591 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Django app for managing temporary session-based users. ### Support -This project currently supports Python 3.8+, Django 3.1+. +This project currently supports Python 3.8+, Django 3.2+. ### Background diff --git a/demo/__init__.py b/demo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/demo/apps.py b/demo/apps.py index a260e12..3cee1d7 100644 --- a/demo/apps.py +++ b/demo/apps.py @@ -2,7 +2,6 @@ class DemoConfig(AppConfig): - name = "demo" def ready(self) -> None: diff --git a/pyproject.toml b/pyproject.toml index bf5f854..a9b0de9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-visitor-pass" -version = "0.8" +version = "1.0" description = "Django app for managing temporary session-based users." license = "MIT" authors = ["YunoJuno "] @@ -13,36 +13,35 @@ classifiers = [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", - "Framework :: Django :: 3.1", "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.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] packages = [{ include = "visitors" }] [tool.poetry.dependencies] python = "^3.8" -django = "^3.1 || ^4.0" +django = "^3.2 || ^4.0 || ^5.0" [tool.poetry.dev-dependencies] -pytest = "*" -pytest-cov = "*" -pytest-django = "*" +black = "*" coverage = "*" -pylint = "*" -flake8 = "*" -flake8-bandit = "*" -flake8-docstrings = "*" -isort = "*" mypy = "*" pre-commit = "*" -black = {version = "*", allow-prereleases = true} -freezegun = "*" +pytest = "*" +pytest-cov = "*" +pytest-django = "*" +ruff = "*" tox = "*" [build-system] diff --git a/tox.ini b/tox.ini index 27dd94f..cb84fbf 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,15 @@ [tox] isolated_build = True -envlist = fmt, lint, mypy, checks, py{3.8,3.9,3.10}-django{31,32,40,main} +envlist = + fmt, lint, mypy, + django-checks, + ; https://docs.djangoproject.com/en/5.0/releases/ + django32-py{38,39,310} + django40-py{38,39,310} + django41-py{38,39,310,311} + django42-py{38,39,310,311} + django50-py{310,311,312} + djangomain-py{311,312} [testenv] deps = @@ -8,15 +17,17 @@ deps = pytest pytest-cov pytest-django - django31: Django>=3.1,<3.2 django32: Django>=3.2,<3.3 django40: Django>=4.0,<4.1 - djangomaster: https://github.com/django/django/archive/main.tar.gz + 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=visitors --verbose tests/ -[testenv:checks] +[testenv:django-checks] description = Django system checks and missing migrations deps = Django commands = @@ -24,24 +35,20 @@ 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 visitors black --check visitors [testenv:lint] -description = Python source code linting (flake8, bandit, pydocstyle) +description = Python source code linting (ruff) deps = - flake8 - flake8-bandit - flake8-docstrings + ruff commands = - flake8 visitors + ruff visitors [testenv:mypy] description = Python source code type hints (mypy) diff --git a/visitors/admin.py b/visitors/admin.py index d3388c3..5ca6b20 100644 --- a/visitors/admin.py +++ b/visitors/admin.py @@ -5,7 +5,7 @@ from django.contrib import admin, messages from django.db.models.query import QuerySet from django.http.request import HttpRequest -from django.utils.safestring import mark_safe +from django.utils.html import format_html from .models import Visitor, VisitorLog @@ -16,7 +16,7 @@ def pretty_print(data: dict | None) -> str: return "" pretty = json.dumps(data, sort_keys=True, indent=4, separators=(",", ": ")) html = pretty.replace(" ", " ").replace("\n", "
") - return mark_safe("
%s
" % html) + return format_html("
%s
", html) @admin.register(Visitor) diff --git a/visitors/decorators.py b/visitors/decorators.py index 1b5b011..be0cbab 100644 --- a/visitors/decorators.py +++ b/visitors/decorators.py @@ -94,10 +94,6 @@ def user_is_visitor( # noqa: C901 @functools.wraps(view_func) def inner(*args: Any, **kwargs: Any) -> HttpResponse: - # should never happen, but keeps mypy happy as it _could_ - if not view_func: - raise ValueError("Callable (view_func) missing.") - # HACK: if this is decorating a method, then the first arg will be # the object (self), and not the request. In order to make this work # with functions and methods we need to determine where the request diff --git a/visitors/migrations/0001_initial.py b/visitors/migrations/0001_initial.py index eddafe2..ea18dff 100644 --- a/visitors/migrations/0001_initial.py +++ b/visitors/migrations/0001_initial.py @@ -7,7 +7,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [] diff --git a/visitors/migrations/0002_visitorlog.py b/visitors/migrations/0002_visitorlog.py index d7b4e6e..de79207 100644 --- a/visitors/migrations/0002_visitorlog.py +++ b/visitors/migrations/0002_visitorlog.py @@ -6,7 +6,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0001_initial"), ] diff --git a/visitors/migrations/0003_visitor_is_active.py b/visitors/migrations/0003_visitor_is_active.py index 95e95b9..1c4d2aa 100644 --- a/visitors/migrations/0003_visitor_is_active.py +++ b/visitors/migrations/0003_visitor_is_active.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0002_visitorlog"), ] diff --git a/visitors/migrations/0004_visitor_expires_at.py b/visitors/migrations/0004_visitor_expires_at.py index 8084216..35646d8 100644 --- a/visitors/migrations/0004_visitor_expires_at.py +++ b/visitors/migrations/0004_visitor_expires_at.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0003_visitor_is_active"), ] diff --git a/visitors/migrations/0005_visitorlog_status_code.py b/visitors/migrations/0005_visitorlog_status_code.py index 8d8de1e..f5cc950 100644 --- a/visitors/migrations/0005_visitorlog_status_code.py +++ b/visitors/migrations/0005_visitorlog_status_code.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0004_visitor_expires_at"), ] diff --git a/visitors/migrations/0006_alter_visitor_uuid.py b/visitors/migrations/0006_alter_visitor_uuid.py index cf0cbfb..bd1e73c 100644 --- a/visitors/migrations/0006_alter_visitor_uuid.py +++ b/visitors/migrations/0006_alter_visitor_uuid.py @@ -6,7 +6,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0005_visitorlog_status_code"), ] diff --git a/visitors/migrations/0007_visitor_session_expiry.py b/visitors/migrations/0007_visitor_session_expiry.py index 018846d..352c913 100644 --- a/visitors/migrations/0007_visitor_session_expiry.py +++ b/visitors/migrations/0007_visitor_session_expiry.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("visitors", "0006_alter_visitor_uuid"), ]