From cfd6d45189d516c19b5e7915cefb6dce86e7dcd6 Mon Sep 17 00:00:00 2001 From: Tris Forster Date: Tue, 12 May 2026 13:26:56 +1000 Subject: [PATCH] Added linting and got tests passing --- Makefile | 11 ++++--- app/interface/tests/__init__.py | 4 +-- app/interface/urls.py | 2 +- app/interface/utils.py | 13 ++++---- app/library/models.py | 3 +- app/library/music_tags.py | 9 +++--- app/library/{tests.py => tests/__init__.py} | 2 +- app/library/tests/test_modules.py | 8 +++++ app/library/views/__init__.py | 4 +-- app/library/views/api.py | 36 ++++++++++----------- app/polyphonic/settings.py | 6 ++-- app/polyphonic/urls.py | 2 +- pyproject.toml | 1 + 13 files changed, 53 insertions(+), 48 deletions(-) rename app/library/{tests.py => tests/__init__.py} (99%) create mode 100644 app/library/tests/test_modules.py diff --git a/Makefile b/Makefile index 8566283..8e600dc 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,13 @@ PYTHON=env/bin/python DROPZONE=5.7.0 -test: - coverage run --include "app/*" --omit "*/migrations/*" app/manage.py test app - coverage html - coverage report +test: check + poetry run coverage run --include "app/*" --omit "*/migrations/*" app/manage.py test app + poetry run coverage html + poetry run coverage report + +check: + poetry run ruff check app dev-setup: env/bin/pip install -r requirements.txt diff --git a/app/interface/tests/__init__.py b/app/interface/tests/__init__.py index 1f199a8..6f8d571 100644 --- a/app/interface/tests/__init__.py +++ b/app/interface/tests/__init__.py @@ -1,5 +1,5 @@ from django.test import TestCase -from interface import models, utils +from interface import models from django.contrib.auth.models import User from django.utils import timezone from datetime import timedelta @@ -16,7 +16,6 @@ class AccessTestCase(TestCase): @classmethod def setUpTestData(cls): - cls.users = {} for details in cls.USERS: cls.users[details["username"]] = User.objects.create_user(**details) @@ -42,7 +41,6 @@ class AccessTestCase(TestCase): return def test_protected_views(self): - self.assertAccess({x: False for x in self.PROTECTED_URLS}) if "admin" in self.users: diff --git a/app/interface/urls.py b/app/interface/urls.py index 6badf5e..b83427c 100644 --- a/app/interface/urls.py +++ b/app/interface/urls.py @@ -1,6 +1,7 @@ from django.urls import path from django.contrib.auth import views as auth_views from django.views.generic.base import RedirectView +from django.conf import settings from . import views @@ -69,7 +70,6 @@ urlpatterns = [ ), ] -from django.conf import settings if settings.DEBUG: from django.views.static import serve diff --git a/app/interface/utils.py b/app/interface/utils.py index 10a1a06..164c3d1 100644 --- a/app/interface/utils.py +++ b/app/interface/utils.py @@ -1,20 +1,19 @@ from django.shortcuts import resolve_url from django.core.signing import Signer from django.core.exceptions import SuspiciousOperation +import logging signer = Signer() -import logging - logger = logging.getLogger(__name__) -def sign_data(data, l=None): +def sign_data(data, length=None): sig = signer.sign(data) - p = len(data) + 1 - if l: - l += p - return sig[p:l] + pos = len(data) + 1 + if length: + length += pos + return sig[pos:length] def signed_url(name, **kwargs): diff --git a/app/library/models.py b/app/library/models.py index a757d81..03eecd0 100644 --- a/app/library/models.py +++ b/app/library/models.py @@ -345,12 +345,11 @@ class Work(models.Model): @property def identifier(self): - if self.code: return self.code composer = self.composer or "Anon" - composer = re.sub("[^\w]", "", composer) + composer = re.sub(r"[^\w]", "", composer) words = self.name.split() work = words[0][:3] diff --git a/app/library/music_tags.py b/app/library/music_tags.py index 3afded2..b78e4a9 100644 --- a/app/library/music_tags.py +++ b/app/library/music_tags.py @@ -1,4 +1,5 @@ from collections import namedtuple +import re GENERAL = """ mvmt Movement @@ -195,8 +196,8 @@ class MusicTag(namedtuple("MusicTag", ("name", "variant"), defaults=[None])): @property def tag(self): - l = self.name.lower() - return MUSIC_TAG_BY_NAME.get(l, l) + lc = self.name.lower() + return MUSIC_TAG_BY_NAME.get(lc, lc) @property def is_general(self): @@ -232,9 +233,7 @@ class MusicTag(namedtuple("MusicTag", ("name", "variant"), defaults=[None])): return self.name -import re - -PATTERNS = [re.compile("([A-Za-z]+)[_\- ]*(\d+)"), re.compile("([A-Za-z]+)()")] +PATTERNS = [re.compile(r"([A-Za-z]+)[_\- ]*(\d+)"), re.compile(r"([A-Za-z]+)()")] def auto_tag(filename): diff --git a/app/library/tests.py b/app/library/tests/__init__.py similarity index 99% rename from app/library/tests.py rename to app/library/tests/__init__.py index 065b4ac..123ac52 100644 --- a/app/library/tests.py +++ b/app/library/tests/__init__.py @@ -1,7 +1,7 @@ from interface.tests import AccessTestCase from byostorage.user import UserStorage -from . import models +from library import models import tempfile import json diff --git a/app/library/tests/test_modules.py b/app/library/tests/test_modules.py new file mode 100644 index 0000000..de5482b --- /dev/null +++ b/app/library/tests/test_modules.py @@ -0,0 +1,8 @@ +from doctest import DocTestSuite + +from library import music_tags + + +def load_tests(loader, tests, ignore): + tests.addTests(DocTestSuite(music_tags)) + return tests diff --git a/app/library/views/__init__.py b/app/library/views/__init__.py index 9b376a6..beaed35 100644 --- a/app/library/views/__init__.py +++ b/app/library/views/__init__.py @@ -477,7 +477,7 @@ class WorkAddDocumentView(CollectionMixin, CreateView): doc.sections.create(tag=inst.abbreviate()) if self.request.headers["Accept"] == "application/json": - filename = os.path.basename(doc.upload.name) + os.path.basename(doc.upload.name) return JsonResponse( { "message": "created", @@ -541,7 +541,7 @@ class DocumentAnnotateView(DocumentMixin, DetailView): for tag, start, end in data: # pages.sort() # end = pages[-1] if len(pages) > 1 else None - o = self.object.sections.create(tag=tag, start=start, end=end) + self.object.sections.create(tag=tag, start=start, end=end) return HttpResponse(status=204) diff --git a/app/library/views/api.py b/app/library/views/api.py index 475288d..283599d 100644 --- a/app/library/views/api.py +++ b/app/library/views/api.py @@ -1,3 +1,20 @@ +from interface.views import AuthorizedResourceMixin + +from rest_framework import serializers +from rest_framework.exceptions import APIException +from rest_framework import generics + +from library.models import Collection, Work, Document, Section, WorkMeta + + +import requests +import urllib +import shutil +import os.path + +from django.db import transaction +from django.core.files.uploadedfile import TemporaryUploadedFile + """ Views relating to importing and exporting collection items """ @@ -33,22 +50,6 @@ class WorkExportView(EnsembleMixin, WorkMixin, View): """ -from interface.views import AuthorizedResourceMixin - -from rest_framework import serializers -from rest_framework.exceptions import APIException - -from library.models import Collection, Work, Document, Section, WorkMeta - - -import requests -import urllib -import shutil -import os.path - -from django.db import transaction -from django.core.files.uploadedfile import TemporaryUploadedFile - class WorkMetaSerializer(serializers.ModelSerializer): class Meta: @@ -176,9 +177,6 @@ class CollectionSerializer(serializers.Serializer): return Collection.objects.get(pk=collection) -from rest_framework import generics - - class CollectionExportView(AuthorizedResourceMixin, generics.RetrieveAPIView): serializer_class = CollectionSerializer diff --git a/app/polyphonic/settings.py b/app/polyphonic/settings.py index 251427e..cf49f75 100644 --- a/app/polyphonic/settings.py +++ b/app/polyphonic/settings.py @@ -1,6 +1,6 @@ try: - from .local_settings import * + from .local_settings import * # noqa except ImportError: - from .default_settings import * + from .default_settings import * # noqa -INSTALLED_APPS += POLYPHONIC_MODULES +INSTALLED_APPS += POLYPHONIC_MODULES # type: ignore #noqa diff --git a/app/polyphonic/urls.py b/app/polyphonic/urls.py index 042aef9..09f1881 100644 --- a/app/polyphonic/urls.py +++ b/app/polyphonic/urls.py @@ -15,7 +15,7 @@ Including another URLconf """ from django.contrib import admin -from django.urls import path, re_path, include +from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), diff --git a/pyproject.toml b/pyproject.toml index 57d8b09..0963ae0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ packages = [{include = "*", from="app"}] [tool.poetry.group.dev.dependencies] django-debug-toolbar = "5.2" ruff = "^0.15.12" +coverage = "^7.14.0" [tool.poetry.scripts] manage = "manage:main"