diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 3bcba95aa..b83257ebf 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -23,13 +23,14 @@ jobs: fail-fast: false matrix: job: - - pylint - - black - - isort - bandit - - pyright - - pending-migrations + - black - codespell + - isort + - pending-migrations + - pylint + - pyright + - ruff runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/Makefile b/Makefile index 531619624..84ee1de90 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ PWD = $(shell pwd) UID = $(shell id -u) GID = $(shell id -g) NPM_VERSION = $(shell python -m scripts.npm_version) +PY_SOURCES = authentik tests scripts lifecycle CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \ -I .github/codespell-words.txt \ @@ -38,13 +39,14 @@ test: coverage report lint-fix: - isort authentik tests scripts lifecycle - black authentik tests scripts lifecycle + isort authentik $(PY_SOURCES) + black authentik $(PY_SOURCES) + ruff authentik $(PY_SOURCES) codespell -w $(CODESPELL_ARGS) lint: - pylint authentik tests lifecycle - bandit -r authentik tests lifecycle -x node_modules + pylint $(PY_SOURCES) + bandit -r $(PY_SOURCES) -x node_modules golangci-lint run -v migrate: @@ -171,7 +173,6 @@ website-watch: # These targets are use by GitHub actions to allow usage of matrix # which makes the YAML File a lot smaller -PY_SOURCES=authentik tests lifecycle ci--meta-debug: python -V node --version @@ -182,6 +183,9 @@ ci-pylint: ci--meta-debug ci-black: ci--meta-debug black --check $(PY_SOURCES) +ci-ruff: ci--meta-debug + ruff check $(PY_SOURCES) + ci-codespell: ci--meta-debug codespell $(CODESPELL_ARGS) -s diff --git a/authentik/blueprints/migrations/0001_initial.py b/authentik/blueprints/migrations/0001_initial.py index 7b246b0cd..d0f897e76 100644 --- a/authentik/blueprints/migrations/0001_initial.py +++ b/authentik/blueprints/migrations/0001_initial.py @@ -6,7 +6,6 @@ from pathlib import Path import django.contrib.postgres.fields from dacite.core import from_dict from django.apps.registry import Apps -from django.conf import settings from django.db import migrations, models from django.db.backends.base.schema import BaseDatabaseSchemaEditor from yaml import load @@ -15,7 +14,7 @@ from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_SYSTEM from authentik.lib.config import CONFIG -def check_blueprint_v1_file(BlueprintInstance: type["BlueprintInstance"], path: Path): +def check_blueprint_v1_file(BlueprintInstance: type, path: Path): """Check if blueprint should be imported""" from authentik.blueprints.models import BlueprintInstanceStatus from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata diff --git a/authentik/crypto/migrations/0002_create_self_signed_kp.py b/authentik/crypto/migrations/0002_create_self_signed_kp.py index 315b67a82..2295742b2 100644 --- a/authentik/crypto/migrations/0002_create_self_signed_kp.py +++ b/authentik/crypto/migrations/0002_create_self_signed_kp.py @@ -2,8 +2,6 @@ from django.db import migrations -from authentik.lib.generators import generate_id - class Migration(migrations.Migration): dependencies = [ diff --git a/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py b/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py index 39ccd59e8..94b849c2c 100644 --- a/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py +++ b/authentik/events/migrations/0001_squashed_0019_alter_notificationtransport_webhook_url.py @@ -11,7 +11,6 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor import authentik.events.models import authentik.lib.models -from authentik.events.models import EventAction, NotificationSeverity, TransportMode from authentik.lib.migrations import progress_bar diff --git a/authentik/outposts/controllers/docker.py b/authentik/outposts/controllers/docker.py index 28e2fdf42..48918e25e 100644 --- a/authentik/outposts/controllers/docker.py +++ b/authentik/outposts/controllers/docker.py @@ -13,7 +13,6 @@ from paramiko.ssh_exception import SSHException from structlog.stdlib import get_logger from yaml import safe_dump -from authentik import __version__ from authentik.outposts.apps import MANAGED_OUTPOST from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException from authentik.outposts.docker_ssh import DockerInlineSSH, SSHManagedExternallyException diff --git a/authentik/outposts/controllers/k8s/deployment.py b/authentik/outposts/controllers/k8s/deployment.py index 1eef5c732..96d8a227f 100644 --- a/authentik/outposts/controllers/k8s/deployment.py +++ b/authentik/outposts/controllers/k8s/deployment.py @@ -22,7 +22,7 @@ from kubernetes.client import ( V1SecurityContext, ) -from authentik import __version__, get_full_version +from authentik import get_full_version from authentik.outposts.controllers.base import FIELD_MANAGER from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler from authentik.outposts.controllers.k8s.triggers import NeedsUpdate diff --git a/authentik/providers/oauth2/migrations/0001_initial.py b/authentik/providers/oauth2/migrations/0001_initial.py index 24f8019fe..4b39d4b34 100644 --- a/authentik/providers/oauth2/migrations/0001_initial.py +++ b/authentik/providers/oauth2/migrations/0001_initial.py @@ -1,10 +1,8 @@ # Generated by Django 3.1 on 2020-08-18 15:59 import django.db.models.deletion -from django.apps.registry import Apps from django.conf import settings from django.db import migrations, models -from django.db.backends.base.schema import BaseDatabaseSchemaEditor import authentik.core.models import authentik.lib.generators diff --git a/authentik/sources/plex/migrations/0002_auto_20210505_1717.py b/authentik/sources/plex/migrations/0002_auto_20210505_1717.py index 6f3292bc6..504a058a3 100644 --- a/authentik/sources/plex/migrations/0002_auto_20210505_1717.py +++ b/authentik/sources/plex/migrations/0002_auto_20210505_1717.py @@ -3,8 +3,6 @@ import django.contrib.postgres.fields from django.db import migrations, models -import authentik.lib.generators - class Migration(migrations.Migration): dependencies = [ diff --git a/authentik/stages/authenticator_duo/models.py b/authentik/stages/authenticator_duo/models.py index 542dfc31c..ecd5a694e 100644 --- a/authentik/stages/authenticator_duo/models.py +++ b/authentik/stages/authenticator_duo/models.py @@ -10,7 +10,6 @@ from duo_client.admin import Admin from duo_client.auth import Auth from rest_framework.serializers import BaseSerializer, Serializer -from authentik import __version__ from authentik.core.types import UserSettingSerializer from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage from authentik.lib.models import SerializerModel diff --git a/authentik/stages/password/migrations/0007_app_password.py b/authentik/stages/password/migrations/0007_app_password.py index 7961c22a6..71f708a35 100644 --- a/authentik/stages/password/migrations/0007_app_password.py +++ b/authentik/stages/password/migrations/0007_app_password.py @@ -4,7 +4,7 @@ from django.apps.registry import Apps from django.db import migrations, models from django.db.backends.base.schema import BaseDatabaseSchemaEditor -from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT +from authentik.stages.password import BACKEND_APP_PASSWORD def update_default_backends(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): diff --git a/authentik/stages/password/migrations/0008_replace_inbuilt.py b/authentik/stages/password/migrations/0008_replace_inbuilt.py index 3c5d55737..9b0f8273e 100644 --- a/authentik/stages/password/migrations/0008_replace_inbuilt.py +++ b/authentik/stages/password/migrations/0008_replace_inbuilt.py @@ -1,7 +1,6 @@ # Generated by Django 3.2.6 on 2021-08-23 14:34 -import django.contrib.postgres.fields from django.apps.registry import Apps -from django.db import migrations, models +from django.db import migrations from django.db.backends.base.schema import BaseDatabaseSchemaEditor from authentik.stages.password import BACKEND_INBUILT diff --git a/authentik/tenants/migrations/0001_squashed_0005_tenant_web_certificate.py b/authentik/tenants/migrations/0001_squashed_0005_tenant_web_certificate.py index fb0aae3e5..65cfaf01e 100644 --- a/authentik/tenants/migrations/0001_squashed_0005_tenant_web_certificate.py +++ b/authentik/tenants/migrations/0001_squashed_0005_tenant_web_certificate.py @@ -3,9 +3,7 @@ import uuid import django.db.models.deletion -from django.apps.registry import Apps from django.db import migrations, models -from django.db.backends.base.schema import BaseDatabaseSchemaEditor import authentik.lib.utils.time diff --git a/lifecycle/gunicorn.conf.py b/lifecycle/gunicorn.conf.py index f692abcd1..d2969edfb 100644 --- a/lifecycle/gunicorn.conf.py +++ b/lifecycle/gunicorn.conf.py @@ -155,6 +155,6 @@ if not CONFIG.y_bool("disable_startup_analytics", False): }, timeout=5, ) - # pylint: disable=bare-except - except: # nosec + # pylint: disable=broad-exception-caught + except Exception: # nosec pass diff --git a/poetry.lock b/poetry.lock index 3defdb7f0..013acf5da 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -2780,6 +2780,21 @@ pytest = ">=5.4.0" docs = ["sphinx", "sphinx-rtd-theme"] testing = ["Django", "django-configurations (>=2.0)"] +[[package]] +name = "pytest-github-actions-annotate-failures" +version = "0.1.8" +description = "pytest plugin to annotate failed tests with a workflow command for GitHub Actions" +category = "dev" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +files = [ + {file = "pytest-github-actions-annotate-failures-0.1.8.tar.gz", hash = "sha256:2d6e6cb5f8d0aae4a27a20cc4e20fabd3199a121c57f44bc48fe28e372e0be23"}, + {file = "pytest_github_actions_annotate_failures-0.1.8-py2.py3-none-any.whl", hash = "sha256:6a882ff21672fa79deae8d917eb965a6bde2b25191e7632e1adfc23ffac008ab"}, +] + +[package.dependencies] +pytest = ">=4.0.0" + [[package]] name = "pytest-randomly" version = "3.12.0" @@ -3025,6 +3040,33 @@ files = [ [package.dependencies] pyasn1 = ">=0.1.3" +[[package]] +name = "ruff" +version = "0.0.261" +description = "An extremely fast Python linter, written in Rust." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.261-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:6624a966c4a21110cee6780333e2216522a831364896f3d98f13120936eff40a"}, + {file = "ruff-0.0.261-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:2dba68a9e558ab33e6dd5d280af798a2d9d3c80c913ad9c8b8e97d7b287f1cc9"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd0cee5a81b0785dc0feeb2640c1e31abe93f0d77c5233507ac59731a626f1"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:581e64fa1518df495ca890a605ee65065101a86db56b6858f848bade69fc6489"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc970f6ece0b4950e419f0252895ee42e9e8e5689c6494d18f5dc2c6ebb7f798"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8fa98e747e0fe185d65a40b0ea13f55c492f3b5f9a032a1097e82edaddb9e52e"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f268d52a71bf410aa45c232870c17049df322a7d20e871cfe622c9fc784aab7b"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1293acc64eba16a11109678dc4743df08c207ed2edbeaf38b3e10eb2597321b"}, + {file = "ruff-0.0.261-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d95596e2f4cafead19a6d1ec0b86f8fda45ba66fe934de3956d71146a87959b3"}, + {file = "ruff-0.0.261-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4bcec45abdf65c1328a269cf6cc193f7ff85b777fa2865c64cf2c96b80148a2c"}, + {file = "ruff-0.0.261-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6c5f397ec0af42a434ad4b6f86565027406c5d0d0ebeea0d5b3f90c4bf55bc82"}, + {file = "ruff-0.0.261-py3-none-musllinux_1_2_i686.whl", hash = "sha256:39abd02342cec0c131b2ddcaace08b2eae9700cab3ca7dba64ae5fd4f4881bd0"}, + {file = "ruff-0.0.261-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:aaa4f52a6e513f8daa450dac4859e80390d947052f592f0d8e796baab24df2fc"}, + {file = "ruff-0.0.261-py3-none-win32.whl", hash = "sha256:daff64b4e86e42ce69e6367d63aab9562fc213cd4db0e146859df8abc283dba0"}, + {file = "ruff-0.0.261-py3-none-win_amd64.whl", hash = "sha256:0fbc689c23609edda36169c8708bb91bab111d8f44cb4a88330541757770ab30"}, + {file = "ruff-0.0.261-py3-none-win_arm64.whl", hash = "sha256:d2eddc60ae75fc87f8bb8fd6e8d5339cf884cd6de81e82a50287424309c187ba"}, + {file = "ruff-0.0.261.tar.gz", hash = "sha256:c1c715b0d1e18f9c509d7c411ca61da3543a4aa459325b1b1e52b8301d65c6d2"}, +] + [[package]] name = "selenium" version = "4.8.3" @@ -4062,4 +4104,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "61d20a7f2b76b6554b4c2095db152395c41d6c650b2f7f16662d5ed2f8cc0983" +content-hash = "8712c3c416712e7577cf1b1e3685e7032e3a4bdbd797ad99508554b15e0a2fbf" diff --git a/pyproject.toml b/pyproject.toml index c539d2b07..4641584fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,11 @@ line-length = 100 target-version = ['py311'] exclude = 'node_modules' +[tool.ruff] +line-length = 100 +target-version = "py311" +exclude = ["**/migrations/**", "**/node_modules/**"] + [tool.isort] multi_line_output = 3 include_trailing_comma = true @@ -30,12 +35,12 @@ force_to_top = "*" source = ["authentik"] relative_files = true omit = [ - "*/asgi.py", - "manage.py", - "*/migrations/*", - "*/management/commands/*", - "*/apps.py", - "website/", + "*/asgi.py", + "manage.py", + "*/migrations/*", + "*/management/commands/*", + "*/apps.py", + "website/", ] [tool.coverage.report] @@ -43,19 +48,19 @@ sort = "Cover" skip_covered = true precision = 2 exclude_lines = [ - "pragma: no cover", - # Don't complain about missing debug-only code: - "def __unicode__", - "def __str__", - "def __repr__", - "if self.debug", - "if TYPE_CHECKING", - # Don't complain if tests don't hit defensive assertion code: - "raise AssertionError", - "raise NotImplementedError", - # Don't complain if non-runnable code isn't run: - "if 0:", - "if __name__ == .__main__.:", + "pragma: no cover", + # Don't complain about missing debug-only code: + "def __unicode__", + "def __str__", + "def __repr__", + "if self.debug", + "if TYPE_CHECKING", + # Don't complain if tests don't hit defensive assertion code: + "raise AssertionError", + "raise NotImplementedError", + # Don't complain if non-runnable code isn't run: + "if 0:", + "if __name__ == .__main__.:", ] show_missing = true @@ -64,20 +69,20 @@ good-names = ["pk", "id", "i", "j", "k", "_", "bar"] [tool.pylint.master] disable = [ - "arguments-differ", - "locally-disabled", - "too-many-ancestors", - "too-few-public-methods", - "import-outside-toplevel", - "signature-differs", - "similarities", - "cyclic-import", - "protected-access", - "unused-argument", - "raise-missing-from", - "fixme", - # To preserve django's translation function we need to use %-formatting - "consider-using-f-string", + "arguments-differ", + "locally-disabled", + "too-many-ancestors", + "too-few-public-methods", + "import-outside-toplevel", + "signature-differs", + "similarities", + "cyclic-import", + "protected-access", + "unused-argument", + "raise-missing-from", + "fixme", + # To preserve django's translation function we need to use %-formatting + "consider-using-f-string", ] load-plugins = ["pylint_django", "pylint.extensions.bad_builtin"] @@ -99,8 +104,8 @@ python_files = ["tests.py", "test_*.py", "*_tests.py"] junit_family = "xunit2" addopts = "-p no:celery --junitxml=unittest.xml" filterwarnings = [ - "ignore:defusedxml.lxml is no longer supported and will be removed in a future release.:DeprecationWarning", - "ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning", + "ignore:defusedxml.lxml is no longer supported and will be removed in a future release.:DeprecationWarning", + "ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning", ] [tool.poetry] @@ -176,8 +181,10 @@ pylint-django = "*" pyrad = "*" pytest = "*" pytest-django = "*" +pytest-github-actions-annotate-failures = "*" pytest-randomly = "*" requests-mock = "*" +ruff = "*" selenium = "*" [build-system] diff --git a/scripts/generate_config.py b/scripts/generate_config.py index da48d10c5..6b95ca8cf 100644 --- a/scripts/generate_config.py +++ b/scripts/generate_config.py @@ -3,7 +3,7 @@ from yaml import safe_dump from authentik.lib.generators import generate_id -with open("local.env.yml", "w") as _config: +with open("local.env.yml", "w", encoding="utf-8") as _config: safe_dump( { "log_level": "debug", diff --git a/tests/e2e/test_provider_proxy.py b/tests/e2e/test_provider_proxy.py index a63f91276..01f4e1f5e 100644 --- a/tests/e2e/test_provider_proxy.py +++ b/tests/e2e/test_provider_proxy.py @@ -11,7 +11,6 @@ from docker.client import DockerClient, from_env from docker.models.containers import Container from selenium.webdriver.common.by import By -from authentik import __version__ from authentik.blueprints.tests import apply_blueprint, reconcile_app from authentik.core.models import Application from authentik.flows.models import Flow diff --git a/tests/integration/test_outpost_docker.py b/tests/integration/test_outpost_docker.py index 6bb6dd98a..98e4ec48a 100644 --- a/tests/integration/test_outpost_docker.py +++ b/tests/integration/test_outpost_docker.py @@ -9,7 +9,6 @@ from docker import DockerClient, from_env from docker.models.containers import Container from docker.types.healthcheck import Healthcheck -from authentik import __version__ from authentik.core.tests.utils import create_test_flow from authentik.crypto.models import CertificateKeyPair from authentik.outposts.controllers.docker import DockerController diff --git a/tests/integration/test_proxy_docker.py b/tests/integration/test_proxy_docker.py index 86b12ae12..147088ee6 100644 --- a/tests/integration/test_proxy_docker.py +++ b/tests/integration/test_proxy_docker.py @@ -9,7 +9,6 @@ from docker import DockerClient, from_env from docker.models.containers import Container from docker.types.healthcheck import Healthcheck -from authentik import __version__ from authentik.core.tests.utils import create_test_flow from authentik.crypto.models import CertificateKeyPair from authentik.outposts.models import (