diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d41366d..0b7a1c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,7 @@ default_language_version: - python: python3 + python: python3.11 +exclude: ^.*\b(migrations)\b.*$ repos: - - repo: https://github.com/psf/black - rev: 22.12.0 - hooks: - - id: black - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: @@ -18,21 +15,19 @@ repos: - id: check-toml - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: 'v0.0.209' hooks: - - id: flake8 - additional_dependencies: - - flake8-bugbear - - flake8-comprehensions - - flake8-tidy-imports - args: [--max-line-length=88, --extend-exclude=src/project/settings/deployments/*] + - id: ruff + args: + - --force-exclude + - --fix - repo: https://github.com/asottile/reorder_python_imports rev: v3.9.0 hooks: - id: reorder-python-imports args: - - --py3-plus + - --py310-plus - --application-directories=.:src exclude: migrations/ - repo: https://github.com/asottile/pyupgrade @@ -40,7 +35,7 @@ repos: hooks: - id: pyupgrade args: - - --py310-plus + - --py311-plus exclude: migrations/ - repo: https://github.com/adamchainz/django-upgrade rev: 1.12.0 @@ -48,3 +43,21 @@ repos: - id: django-upgrade args: - --target-version=4.1 + - repo: https://github.com/asottile/yesqa + rev: v1.4.0 + hooks: + - id: yesqa + - repo: https://github.com/asottile/add-trailing-comma + rev: v2.4.0 + hooks: + - id: add-trailing-comma + args: + - --py36-plus + - repo: https://github.com/hadialqattan/pycln + rev: v2.1.2 + hooks: + - id: pycln + - repo: https://github.com/psf/black + rev: 22.12.0 + hooks: + - id: black diff --git a/Dockerfile b/Dockerfile index e05257e..ce8ee95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim-bullseye +FROM python:3.11-slim-bullseye ENV PYTHONFAULTHANDLER=1 \ PYTHONUNBUFFERED=1 \ diff --git a/Makefile b/Makefile index bfb0bab..9bb2fc1 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,9 @@ setup_venv: pre_commit_install: venv/bin/pre-commit install +pre_commit_run_all: + venv/bin/pre-commit run --all-files + makemigrations: ${MANAGE_COMMAND} makemigrations ${EXTRA_ARGS} diff --git a/src/accounting/models.py b/src/accounting/models.py index 08c15cb..75e380b 100644 --- a/src/accounting/models.py +++ b/src/accounting/models.py @@ -37,7 +37,9 @@ class Transaction(CreatedModifiedAbstract): """ account = models.ForeignKey( - Account, on_delete=models.PROTECT, related_name="transactions" + Account, + on_delete=models.PROTECT, + related_name="transactions", ) amount = MoneyField( verbose_name=_("amount"), @@ -61,7 +63,9 @@ class Order(CreatedModifiedAbstract): description = models.CharField(max_length=1024, verbose_name=_("description")) price = MoneyField( - verbose_name=_("price (excl. VAT)"), max_digits=16, decimal_places=2 + verbose_name=_("price (excl. VAT)"), + max_digits=16, + decimal_places=2, ) vat = MoneyField(verbose_name=_("VAT"), max_digits=16, decimal_places=2) diff --git a/src/manage.py b/src/manage.py index 548b6a5..6299152 100755 --- a/src/manage.py +++ b/src/manage.py @@ -10,6 +10,6 @@ if __name__ == "__main__": raise ImportError( "Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" + "forget to activate a virtual environment?", ) execute_from_command_line(sys.argv) diff --git a/src/membership/models.py b/src/membership/models.py index 212cd61..85b0bb6 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -19,8 +19,8 @@ class Member(User): Membership.objects.filter( user=models.OuterRef("pk"), period=get_current_subscription_period().id, - ) - ) + ), + ), ) objects = QuerySet.as_manager() @@ -92,7 +92,8 @@ class Membership(CreatedModifiedAbstract): ) period = models.ForeignKey( - "membership.SubscriptionPeriod", on_delete=models.PROTECT + "membership.SubscriptionPeriod", + on_delete=models.PROTECT, ) def __str__(self): diff --git a/src/membership/permissions.py b/src/membership/permissions.py index 02a5388..8ea5ed2 100644 --- a/src/membership/permissions.py +++ b/src/membership/permissions.py @@ -29,7 +29,8 @@ class Permission: def persist_permission(self): content_type, _ = ContentType.objects.get_or_create( - app_label=self.app_label, model=self.model + app_label=self.app_label, + model=self.model, ) DjangoPermission.objects.get_or_create( content_type=content_type, diff --git a/src/membership/selectors.py b/src/membership/selectors.py index c1caec2..77e493d 100644 --- a/src/membership/selectors.py +++ b/src/membership/selectors.py @@ -19,12 +19,15 @@ def get_subscription_periods() -> list[SubscriptionPeriod]: def get_current_subscription_period() -> SubscriptionPeriod | None: with contextlib.suppress(SubscriptionPeriod.DoesNotExist): return SubscriptionPeriod.objects.prefetch_related( - "membership_set", "membership_set__user" + "membership_set", + "membership_set__user", ).get(period__contains=timezone.now()) def get_memberships( - *, user: User | None = None, period: SubscriptionPeriod | None = None + *, + user: User | None = None, + period: SubscriptionPeriod | None = None, ) -> Membership.QuerySet: memberships = Membership.objects.select_related("membership_type").all() diff --git a/src/membership/views.py b/src/membership/views.py index 2af8d1f..165fd5a 100644 --- a/src/membership/views.py +++ b/src/membership/views.py @@ -53,7 +53,7 @@ def members_admin(request): label=_("View"), url_name="admin-members-detail", url_kwargs={"member_id": "id"}, - ) + ), ], ) diff --git a/src/project/settings.py b/src/project/settings.py index 3a203f3..6bcac24 100644 --- a/src/project/settings.py +++ b/src/project/settings.py @@ -17,7 +17,8 @@ DEBUG = env.bool("DEBUG", default=False) ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["*"]) CSRF_TRUSTED_ORIGINS = env.list( - "CSRF_TRUSTED_ORIGINS", default=["http://localhost:8000"] + "CSRF_TRUSTED_ORIGINS", + default=["http://localhost:8000"], ) ADMINS = [tuple(x.split(":")) for x in env.list("DJANGO_ADMINS", default=[])] @@ -26,7 +27,7 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField" # Application definition -INSTALLED_APPS = [ +DJANGO_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", @@ -34,13 +35,24 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.staticfiles", "django.contrib.sites", +] + +THIRD_PARTY_APPS = [ "allauth", "allauth.account", +] + +LOCAL_APPS = [ "utils", "accounting", "membership", ] +INSTALLED_APPS = [ + *DJANGO_APPS, + *THIRD_PARTY_APPS, + *LOCAL_APPS, +] DATABASES = {"default": env.dj_db_url("DATABASE_URL")} @@ -68,9 +80,9 @@ TEMPLATES = [ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", - ] + ], }, - } + }, ] AUTHENTICATION_BACKENDS = ( @@ -101,7 +113,8 @@ SITE_ID = 1 LOGIN_REDIRECT_URL = "/" EMAIL_BACKEND = env.str( - "EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend" + "EMAIL_BACKEND", + default="django.core.mail.backends.console.EmailBackend", ) DEFAULT_FROM_EMAIL = env.str("DEFAULT_FROM_EMAIL", default="") # Parse email URLs, e.g. "smtp://" @@ -137,8 +150,11 @@ ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False ACCOUNT_USERNAME_REQUIRED = False if DEBUG: - INSTALLED_APPS += ["debug_toolbar"] - MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] + INSTALLED_APPS += ["debug_toolbar", "django_browser_reload"] + MIDDLEWARE += [ + "debug_toolbar.middleware.DebugToolbarMiddleware", + "django_browser_reload.middleware.BrowserReloadMiddleware", + ] # Always show DDT in development for any IP, not just 127.0.0.1 or # settings.INTERNAL_IPS. This is useful in a docker setup where the # requesting IP isn't static. diff --git a/src/project/urls.py b/src/project/urls.py index 42f2114..f7d189b 100644 --- a/src/project/urls.py +++ b/src/project/urls.py @@ -26,6 +26,7 @@ urlpatterns = [ ] if settings.DEBUG: - urlpatterns += [ + urlpatterns = [ path("__debug__/", include("debug_toolbar.urls")), - ] + path("__reload__/", include("django_browser_reload.urls")), + ] + urlpatterns diff --git a/src/utils/templates/utils/list.html b/src/utils/templates/utils/list.html index 445c4cb..a534b64 100644 --- a/src/utils/templates/utils/list.html +++ b/src/utils/templates/utils/list.html @@ -9,6 +9,9 @@ {% for column in columns %} {{ column }} {% endfor %} + {% if row_actions %} + {% trans "Actions" %} + {% endif %} {% for row in rows %}