From 2cbd9f5b6d7a6be65d0b039387944cdbfa282fef Mon Sep 17 00:00:00 2001 From: Hugo Rodger-Brown Date: Mon, 13 Nov 2023 09:48:32 +0000 Subject: [PATCH] Update classifiers and add support for Django 5.0 --- .flake8 | 48 ------------------- .github/workflows/tox.yml | 97 +++++++++++++++++++++++++++++++++++++++ .gitignore | 2 + .isort.cfg | 8 ---- .pre-commit-config.yaml | 36 +++------------ .python-version | 1 - .ruff.toml | 66 ++++++++++++++++++++++++++ pyproject.toml | 25 ++++------ requirements.txt | 62 ++++++++++++------------- tox.ini | 37 ++++++++------- 10 files changed, 231 insertions(+), 151 deletions(-) delete mode 100644 .flake8 create mode 100644 .github/workflows/tox.yml delete mode 100644 .isort.cfg delete mode 100644 .python-version create mode 100644 .ruff.toml 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 new file mode 100644 index 0000000..02ec59a --- /dev/null +++ b/.github/workflows/tox.yml @@ -0,0 +1,97 @@ +name: Python / Django + +on: + push: + branches: + - master + + pull_request: + types: [opened, synchronize, reopened] + +jobs: + format: + name: Check formatting + runs-on: ubuntu-latest + strategy: + matrix: + toxenv: [fmt, lint, mypy] + 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: | + 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: | + pip install tox + tox + + test: + name: Run tests + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.8", "3.9", "3.10", "3.11", "3.12"] + # build LTS version, next version, HEAD + django: ["41", "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.12" + django: "41" + - python: "3.12" + django: "42" + + env: + TOXENV: django${{ matrix.django }}-py${{ matrix.python }} + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Install and run tox + run: | + pip install tox + tox diff --git a/.gitignore b/.gitignore index b3317a6..62a2ffd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .coverage .env .tox +.python-version .venv *.bak *.crt @@ -9,4 +10,5 @@ *.key *.lock *.pyc +*.whl staticfiles 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 70af49f..ff35e6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,41 +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.3.0 + rev: 23.10.1 hooks: - id: black - - repo: https://github.com/rtts/djhtml - rev: 3.0.6 - hooks: - - id: djhtml - - - 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.4" hooks: - - id: flake8 - additional_dependencies: - - flake8-bandit - - flake8-blind-except - - flake8-docstrings - - flake8-logging-format - - flake8-print + - id: ruff + args: [--fix, --exit-non-zero-on-fix] # python static type checking - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.1.1 + rev: v1.6.1 hooks: - id: mypy args: @@ -45,4 +24,3 @@ repos: - --no-implicit-optional - --ignore-missing-imports - --follow-imports=silent - exclude: ^tests diff --git a/.python-version b/.python-version deleted file mode 100644 index 2c07333..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.11 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/pyproject.toml b/pyproject.toml index a6daff9..3a635ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-simple-saml" -version = "0.1.0" +version = "0.2.0" description = "Django app for managing multiple SAML Identity Providers." license = "MIT" authors = ["YunoJuno "] @@ -10,39 +10,34 @@ homepage = "https://github.com/yunojuno/django-simple-saml" repository = "https://github.com/yunojuno/django-simple-saml" documentation = "https://github.com/yunojuno/django-simple-saml" classifiers = [ - "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "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.11", + "Programming Language :: Python :: 3.12", ] packages = [{ include = "simple_saml" }] [tool.poetry.dependencies] python = "^3.8" -django = "^4.1" +django = "^4.1 | ^5.0" social-auth-app-django = "*" python3-saml = "*" dj_database_url = { version = "*", optional=true} +django-sslserver = { version = "*", optional=true} psycopg2-binary = { version = "*", optional=true} gunicorn = { version = "*", optional=true} -whitenoise = "*" +whitenoise = { version = "*", optional=true} -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] black = "*" coverage = "*" -django-sslserver = { version = "*", optional=true} -flake8 = "*" -flake8-bandit = "*" -flake8-blind-except = "*" -flake8-docstrings = "*" -# flake8-logging-format = "*" -flake8-print = "*" freezegun = "*" -isort = "*" mypy = "*" pre-commit = "*" pytest = "*" @@ -51,8 +46,8 @@ pytest-django = "*" tox = "*" [tool.poetry.extras] -heroku = ["dj-database-url", "psycopg2-binary", "gunicorn"] -localhost = ["django-sslserver"] +heroku = ["dj-database-url", "psycopg2-binary", "gunicorn", "whitenoise"] +localhost = ["django-sslserver", "whitenoise"] [build-system] requires = ["poetry>=0.12"] diff --git a/requirements.txt b/requirements.txt index 565e4c3..ae16b53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,31 +1,31 @@ -# This file is autogenerated using the following command: -# poetry export --extras heroku --without-hashes -f requirements.txt --output requirements.txt -asgiref==3.6.0 ; python_version >= "3.11" and python_version < "4.0" -certifi==2022.12.7 ; python_version >= "3.11" and python_version < "4" -cffi==1.15.1 ; python_version >= "3.11" and python_version < "4.0" -charset-normalizer==3.1.0 ; python_version >= "3.11" and python_version < "4" -cryptography==40.0.1 ; python_version >= "3.11" and python_version < "4.0" -defusedxml==0.7.1 ; python_version >= "3.11" and python_version < "4.0" -dj-database-url==1.2.0 ; python_version >= "3.11" and python_version < "4.0" -django==4.1.7 ; python_version >= "3.11" and python_version < "4.0" -gunicorn==20.1.0 ; python_version >= "3.11" and python_version < "4.0" -idna==3.4 ; python_version >= "3.11" and python_version < "4" -isodate==0.6.1 ; python_version >= "3.11" and python_version < "4.0" -lxml==4.9.2 ; python_version >= "3.11" and python_version < "4.0" -oauthlib==3.2.2 ; python_version >= "3.11" and python_version < "4.0" -psycopg2-binary==2.9.5 ; python_version >= "3.11" and python_version < "4.0" -pycparser==2.21 ; python_version >= "3.11" and python_version < "4.0" -pyjwt==2.6.0 ; python_version >= "3.11" and python_version < "4.0" -python3-openid==3.2.0 ; python_version >= "3.11" and python_version < "4.0" -python3-saml==1.15.0 ; python_version >= "3.11" and python_version < "4.0" -requests-oauthlib==1.3.1 ; python_version >= "3.11" and python_version < "4.0" -requests==2.28.2 ; python_version >= "3.11" and python_version < "4" -setuptools==67.6.0 ; python_version >= "3.11" and python_version < "4.0" -six==1.16.0 ; python_version >= "3.11" and python_version < "4.0" -social-auth-app-django==5.1.0 ; python_version >= "3.11" and python_version < "4.0" -social-auth-core==4.4.0 ; python_version >= "3.11" and python_version < "4.0" -sqlparse==0.4.3 ; python_version >= "3.11" and python_version < "4.0" -tzdata==2023.2 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "win32" -urllib3==1.26.15 ; python_version >= "3.11" and python_version < "4" -whitenoise==6.4.0 ; python_version >= "3.11" and python_version < "4.0" -xmlsec==1.3.13 ; python_version >= "3.11" and python_version < "4.0" +asgiref==3.7.2 ; python_version >= "3.8" and python_version < "4.0" +backports-zoneinfo==0.2.1 ; python_version >= "3.8" and python_version < "3.9" +certifi==2023.7.22 ; python_version >= "3.8" and python_version < "4.0" +cffi==1.16.0 ; python_version >= "3.8" and python_version < "4.0" +charset-normalizer==3.3.2 ; python_version >= "3.8" and python_version < "4.0" +cryptography==41.0.5 ; python_version >= "3.8" and python_version < "4.0" +defusedxml==0.7.1 ; python_version >= "3.8" and python_version < "4.0" +dj-database-url==2.1.0 ; python_version >= "3.8" and python_version < "4.0" +django==4.2.7 ; python_version >= "3.8" and python_version < "4.0" +gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" +idna==3.4 ; python_version >= "3.8" and python_version < "4.0" +isodate==0.6.1 ; python_version >= "3.8" and python_version < "4.0" +lxml==4.9.3 ; python_version >= "3.8" and python_version < "4.0" +oauthlib==3.2.2 ; python_version >= "3.8" and python_version < "4.0" +packaging==23.2 ; python_version >= "3.8" and python_version < "4.0" +psycopg2-binary==2.9.9 ; python_version >= "3.8" and python_version < "4.0" +pycparser==2.21 ; python_version >= "3.8" and python_version < "4.0" +pyjwt==2.8.0 ; python_version >= "3.8" and python_version < "4.0" +python3-openid==3.2.0 ; python_version >= "3.8" and python_version < "4.0" +python3-saml==1.16.0 ; python_version >= "3.8" and python_version < "4.0" +requests-oauthlib==1.3.1 ; python_version >= "3.8" and python_version < "4.0" +requests==2.31.0 ; python_version >= "3.8" and python_version < "4.0" +six==1.16.0 ; python_version >= "3.8" and python_version < "4.0" +social-auth-app-django==5.4.0 ; python_version >= "3.8" and python_version < "4.0" +social-auth-core==4.5.0 ; python_version >= "3.8" and python_version < "4.0" +sqlparse==0.4.4 ; python_version >= "3.8" and python_version < "4.0" +typing-extensions==4.8.0 ; python_version >= "3.8" and python_version < "4.0" +tzdata==2023.3 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32" +urllib3==2.0.7 ; python_version >= "3.8" and python_version < "4.0" +whitenoise==6.6.0 ; python_version >= "3.8" and python_version < "4.0" +xmlsec==1.3.13 ; python_version >= "3.8" and python_version < "4.0" diff --git a/tox.ini b/tox.ini index 290e09f..e70a4c4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,58 +1,57 @@ [tox] isolated_build = True -envlist = fmt, lint, mypy, checks, py{3.8,3.9,3.10.3.11}-django{41,main} +envlist = + fmt, lint, mypy, + django-checks, + ; https://docs.djangoproject.com/en/5.0/releases/ + django41-py{38,39,310,311} + django42-py{38,39,310,311} + django50-py{310,311,312} + djangomain-py{311,312} [testenv] -setenv = - DJANGO_SETTINGS_MODULE = demo.settings.base deps = coverage pytest pytest-cov pytest-django + 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=simple_saml --verbose tests/ -[testenv:checks] +[testenv:django-checks] description = Django system checks and missing migrations deps = Django commands = python manage.py check --fail-level WARNING - python manage.py makemigrations --dry-run --check --verbosity 3 simple_saml + 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 simple_saml black --check simple_saml [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 + ruff commands = - flake8 simple_saml + ruff simple_saml [testenv:mypy] description = Python source code type hints (mypy) deps = mypy - types-requests - types-python-dateutil - types-simplejson commands = mypy simple_saml