diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 133c0a1..c30f84c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ default_language_version: - python: python3.11 + python: python3.12 exclude: ^.*\b(migrations)\b.*$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -16,45 +16,22 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: 'v0.1.11' + rev: 'v0.3.0' hooks: - id: ruff args: - --fix - - repo: https://github.com/asottile/reorder_python_imports - rev: v3.12.0 - hooks: - - id: reorder-python-imports - args: - - --py310-plus - - --application-directories=.:src - exclude: migrations/ + - id: ruff-format - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + rev: v3.15.1 hooks: - id: pyupgrade args: - --py311-plus exclude: migrations/ - repo: https://github.com/adamchainz/django-upgrade - rev: 1.15.0 + rev: 1.16.0 hooks: - id: django-upgrade args: - - --target-version=4.1 - - repo: https://github.com/asottile/yesqa - rev: v1.5.0 - hooks: - - id: yesqa - - repo: https://github.com/asottile/add-trailing-comma - rev: v3.1.0 - hooks: - - id: add-trailing-comma - - repo: https://github.com/hadialqattan/pycln - rev: v2.4.0 - hooks: - - id: pycln - - repo: https://github.com/psf/black - rev: 23.12.1 - hooks: - - id: black + - --target-version=5.0 diff --git a/Dockerfile b/Dockerfile index ce8ee95..3e3971a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim-bullseye +FROM python:3.12-slim-bullseye ENV PYTHONFAULTHANDLER=1 \ PYTHONUNBUFFERED=1 \ diff --git a/pyproject.toml b/pyproject.toml index 2ff5219..5d27e93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,3 +104,26 @@ follow_imports = "normal" [[tool.mypy.overrides]] module = "tests.*" allow_untyped_defs = true + +[tool.ruff] +target-version = "py312" +extend-exclude = [ + ".git", + "__pycache__", +] +line-length = 120 + +[tool.ruff.lint] +select = ["ALL"] +ignore = [ + "G004", # Logging statement uses f-string + "ANN101", # Missing type annotation for `self` in method + "ANN102", # Missing type annotation for `cls` in classmethod + "EM101", # Exception must not use a string literal, assign to variable first + "EM102", # Exception must not use a f-string literal, assign to variable first + "COM812", # missing-trailing-comma (https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules) + "ISC001", # single-line-implicit-string-concatenation (https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules) +] + +[tool.ruff.lint.isort] +force-single-line = true diff --git a/src/accounting/migrations/0001_initial.py b/src/accounting/migrations/0001_initial.py index 0ff15ba..9b87e45 100644 --- a/src/accounting/migrations/0001_initial.py +++ b/src/accounting/migrations/0001_initial.py @@ -7,7 +7,6 @@ from django.db import models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -99,9 +98,7 @@ class Migration(migrations.Migration): ), ( "vat", - djmoney.models.fields.MoneyField( - decimal_places=2, max_digits=16, verbose_name="VAT" - ), + djmoney.models.fields.MoneyField(decimal_places=2, max_digits=16, verbose_name="VAT"), ), ("is_paid", models.BooleanField(default=False, verbose_name="is paid")), ( diff --git a/src/accounting/models.py b/src/accounting/models.py index ded800e..c6d1362 100644 --- a/src/accounting/models.py +++ b/src/accounting/models.py @@ -17,8 +17,7 @@ class CreatedModifiedAbstract(models.Model): class Account(CreatedModifiedAbstract): - """ - This is the model where we can give access to several users, such that they + """This is the model where we can give access to several users, such that they can decide which account to use to pay for something. """ @@ -30,8 +29,7 @@ class Account(CreatedModifiedAbstract): class Transaction(CreatedModifiedAbstract): - """ - Tracks in and outgoing events of an account. When an order is received, an + """Tracks in and outgoing events of an account. When an order is received, an amount is subtracted, when a payment is received, an amount is added. """ @@ -50,8 +48,7 @@ class Transaction(CreatedModifiedAbstract): class Order(CreatedModifiedAbstract): - """ - Scoped out: Contents of invoices will have to be tracked either here or in + """Scoped out: Contents of invoices will have to be tracked either here or in a separate Invoice model. This is undecided because we are not generating invoices at the moment. """ diff --git a/src/accounting/tests.py b/src/accounting/tests.py index c847203..0aebd0c 100644 --- a/src/accounting/tests.py +++ b/src/accounting/tests.py @@ -8,7 +8,7 @@ from . import models # do stuff -@pytest.mark.django_db +@pytest.mark.django_db() def test_balance(): user = User.objects.create_user("test", "lala@adas.com", "1234") account = models.Account.objects.create(owner=user) diff --git a/src/membership/__init__.py b/src/membership/__init__.py index fc35f0b..f9e27aa 100644 --- a/src/membership/__init__.py +++ b/src/membership/__init__.py @@ -1,5 +1,4 @@ -""" -Membership application +"""Membership application ====================== This application's domain relate to organizational structures and diff --git a/src/membership/migrations/0001_initial.py b/src/membership/migrations/0001_initial.py index 6657809..e4a6e3a 100644 --- a/src/membership/migrations/0001_initial.py +++ b/src/membership/migrations/0001_initial.py @@ -7,7 +7,6 @@ from django.db import models class Migration(migrations.Migration): - initial = True dependencies = [ diff --git a/src/membership/migrations/0002_subscriptionperiod_remove_membership_period_and_more.py b/src/membership/migrations/0002_subscriptionperiod_remove_membership_period_and_more.py index 60e4cd3..03336c5 100644 --- a/src/membership/migrations/0002_subscriptionperiod_remove_membership_period_and_more.py +++ b/src/membership/migrations/0002_subscriptionperiod_remove_membership_period_and_more.py @@ -2,11 +2,11 @@ import django.contrib.postgres.constraints import django.contrib.postgres.fields.ranges -from django.db import migrations, models +from django.db import migrations +from django.db import models class Migration(migrations.Migration): - dependencies = [ ("membership", "0001_initial"), ] @@ -34,9 +34,7 @@ class Migration(migrations.Migration): ), ( "period", - django.contrib.postgres.fields.ranges.DateRangeField( - verbose_name="period" - ), + django.contrib.postgres.fields.ranges.DateRangeField(verbose_name="period"), ), ], ), diff --git a/src/membership/migrations/0003_membership_period.py b/src/membership/migrations/0003_membership_period.py index d0f2535..03bf995 100644 --- a/src/membership/migrations/0003_membership_period.py +++ b/src/membership/migrations/0003_membership_period.py @@ -1,11 +1,11 @@ # Generated by Django 4.1 on 2023-01-02 21:05 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations +from django.db import models class Migration(migrations.Migration): - dependencies = [ ("membership", "0002_subscriptionperiod_remove_membership_period_and_more"), ] diff --git a/src/membership/migrations/0004_alter_membership_period.py b/src/membership/migrations/0004_alter_membership_period.py index c70b67e..1d87650 100644 --- a/src/membership/migrations/0004_alter_membership_period.py +++ b/src/membership/migrations/0004_alter_membership_period.py @@ -1,11 +1,11 @@ # Generated by Django 4.1 on 2023-01-02 21:06 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations +from django.db import models class Migration(migrations.Migration): - dependencies = [ ("membership", "0003_membership_period"), ] diff --git a/src/membership/migrations/0005_member.py b/src/membership/migrations/0005_member.py index a806d8f..4d5c8d0 100644 --- a/src/membership/migrations/0005_member.py +++ b/src/membership/migrations/0005_member.py @@ -4,22 +4,20 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), - ('membership', '0004_alter_membership_period'), + ("auth", "0012_alter_user_first_name_max_length"), + ("membership", "0004_alter_membership_period"), ] operations = [ migrations.CreateModel( - name='Member', - fields=[ - ], + name="Member", + fields=[], options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], + "proxy": True, + "indexes": [], + "constraints": [], }, - bases=('auth.user',), + bases=("auth.user",), ), ] diff --git a/src/membership/models.py b/src/membership/models.py index 29adc35..d61e157 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -5,7 +5,6 @@ from django.contrib.postgres.fields import RangeOperators from django.db import models from django.utils import timezone from django.utils.translation import gettext as _ - from utils.mixins import CreatedModifiedAbstract @@ -35,9 +34,7 @@ class Member(User): class SubscriptionPeriod(CreatedModifiedAbstract): - """ - Denotes a period for which members should pay their membership fee for. - """ + """Denotes a period for which members should pay their membership fee for.""" period = DateRangeField(verbose_name=_("period")) @@ -52,15 +49,11 @@ class SubscriptionPeriod(CreatedModifiedAbstract): ] def __str__(self): - return ( - f"{self.period.lower} - {self.period.upper or _('next general assembly')}" - ) + return f"{self.period.lower} - {self.period.upper or _('next general assembly')}" class Membership(CreatedModifiedAbstract): - """ - Tracks that a user has membership of a given type for a given period. - """ + """Tracks that a user has membership of a given type for a given period.""" class QuerySet(models.QuerySet): def for_member(self, member: Member): @@ -106,8 +99,7 @@ class Membership(CreatedModifiedAbstract): class MembershipType(CreatedModifiedAbstract): - """ - Models membership types. Currently only a name, but will in the future + """Models membership types. Currently only a name, but will in the future possibly contain more information like fees. """ diff --git a/src/membership/views.py b/src/membership/views.py index 7655d12..15c5a68 100644 --- a/src/membership/views.py +++ b/src/membership/views.py @@ -1,15 +1,14 @@ from django.utils.translation import gettext_lazy as _ from django_view_decorator import namespaced_decorator_factory +from utils.view_utils import RowAction +from utils.view_utils import render +from utils.view_utils import render_list from .permissions import ADMINISTRATE_MEMBERS from .selectors import get_member from .selectors import get_members from .selectors import get_memberships from .selectors import get_subscription_periods -from utils.view_utils import render -from utils.view_utils import render_list -from utils.view_utils import RowAction - member_view = namespaced_decorator_factory(namespace="member", base_path="membership") diff --git a/src/project/views.py b/src/project/views.py index 7882b02..1416f8d 100644 --- a/src/project/views.py +++ b/src/project/views.py @@ -1,5 +1,4 @@ from django_view_decorator import view - from utils.view_utils import render diff --git a/src/project/wsgi.py b/src/project/wsgi.py index 2af7561..e4c5320 100644 --- a/src/project/wsgi.py +++ b/src/project/wsgi.py @@ -1,5 +1,4 @@ -""" -WSGI config for membersystem project. +"""WSGI config for membersystem project. It exposes the WSGI callable as a module-level variable named ``application``. diff --git a/src/utils/templatetags/utils.py b/src/utils/templatetags/utils.py index cd3097a..8050639 100644 --- a/src/utils/templatetags/utils.py +++ b/src/utils/templatetags/utils.py @@ -7,7 +7,6 @@ register = template.Library() @register.simple_tag(takes_context=True) def active_path(context, path_name, class_name) -> str | None: """Return the given class name if the current path matches the given path name.""" - path = reverse(path_name) request_path = context.get("request").path diff --git a/src/utils/view_utils.py b/src/utils/view_utils.py index 9b752a8..b48d126 100644 --- a/src/utils/view_utils.py +++ b/src/utils/view_utils.py @@ -15,9 +15,7 @@ from zen_queries import render as zen_queries_render @dataclass class Row: - """ - A row in a table. - """ + """A row in a table.""" data: dict[str, str] actions: list[dict[str, str]] @@ -25,18 +23,14 @@ class Row: @dataclass class RowAction: - """ - An action that can be performed on a row in a table. - """ + """An action that can be performed on a row in a table.""" label: str url_name: str url_kwargs: dict[str, str] def render(self, obj) -> dict[str, str]: - """ - Render the action as a dictionary for the given object. - """ + """Render the action as a dictionary for the given object.""" url = reverse( self.url_name, kwargs={key: getattr(obj, value) for key, value in self.url_kwargs.items()}, @@ -50,14 +44,11 @@ def render_list( entity_name_plural: str, objects: list["Model"], columns: list[tuple[str, str]], - row_actions: list[RowAction] = None, - list_actions: list[tuple[str, str]] = None, - paginate_by: int = None, + row_actions: list[RowAction] | None = None, + list_actions: list[tuple[str, str]] | None = None, + paginate_by: int | None = None, ) -> HttpResponse: - """ - Render a list of objects with a table. - """ - + """Render a list of objects with a table.""" # TODO: List actions total_count = len(objects) @@ -107,16 +98,12 @@ def render_list( def base_context(request: HttpRequest) -> dict[str, Any]: - """ - Return a base context for all views. - """ + """Return a base context for all views.""" return {"site": get_current_site(request)} def render(request, template_name, context=None): - """ - Render a template with a base context. - """ + """Render a template with a base context.""" if context is None: context = {} context = base_context(request) | context