diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f65e60da..5dfbf0642 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,13 +3,39 @@ variables: IMAGE: $IMAGE_NAME:$CI_COMMIT_REF_NAME IMAGE_LATEST: $IMAGE_NAME:latest PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache" + PYTHONDONTWRITEBYTECODE: "true" stages: + - lint - test - build - deploy +black: + image: python:3.6 + stage: lint + variables: + GIT_STRATEGY: fetch + before_script: + - pip install black + script: + - black --check --diff api/ + +flake8: + image: python:3.6 + stage: lint + variables: + GIT_STRATEGY: fetch + before_script: + - pip install flake8 + script: + - flake8 -v api + cache: + key: "$CI_PROJECT_ID__flake8_pip_cache" + paths: + - "$PIP_CACHE_DIR" + test_api: services: - postgres:9.4 @@ -108,7 +134,7 @@ pages: tags: - docker -docker_develop: +docker_release: stage: deploy before_script: - docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD @@ -119,8 +145,9 @@ docker_develop: - docker push $IMAGE only: - develop@funkwhale/funkwhale + - tags@funkwhale/funkwhale tags: - - dind + - docker-build build_api: # Simply publish a zip containing api/ directory @@ -135,19 +162,3 @@ build_api: - tags@funkwhale/funkwhale - master@funkwhale/funkwhale - develop@funkwhale/funkwhale - - -docker_release: - stage: deploy - before_script: - - docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD - - cp -r front/dist api/frontend - - cd api - script: - - docker build -t $IMAGE -t $IMAGE_LATEST . - - docker push $IMAGE - - docker push $IMAGE_LATEST - only: - - tags@funkwhale/funkwhale - tags: - - dind diff --git a/api/config/api_urls.py b/api/config/api_urls.py index f3f61313e..9f87a7af3 100644 --- a/api/config/api_urls.py +++ b/api/config/api_urls.py @@ -1,15 +1,13 @@ +from django.conf.urls import include, url +from dynamic_preferences.api.viewsets import GlobalPreferencesViewSet from rest_framework import routers from rest_framework.urlpatterns import format_suffix_patterns -from django.conf.urls import include, url +from rest_framework_jwt import views as jwt_views + from funkwhale_api.activity import views as activity_views -from funkwhale_api.instance import views as instance_views from funkwhale_api.music import views from funkwhale_api.playlists import views as playlists_views from funkwhale_api.subsonic.views import SubsonicViewSet -from rest_framework_jwt import views as jwt_views - -from dynamic_preferences.api.viewsets import GlobalPreferencesViewSet -from dynamic_preferences.users.viewsets import UserPreferencesViewSet router = routers.SimpleRouter() router.register(r"settings", GlobalPreferencesViewSet, base_name="settings") diff --git a/api/config/asgi.py b/api/config/asgi.py index b976a02eb..5ecc3ffa4 100644 --- a/api/config/asgi.py +++ b/api/config/asgi.py @@ -1,8 +1,9 @@ -import django import os +import django + +from .routing import application # noqa + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production") django.setup() - -from .routing import application diff --git a/api/config/routing.py b/api/config/routing.py index b1f163759..fa25aad07 100644 --- a/api/config/routing.py +++ b/api/config/routing.py @@ -1,12 +1,9 @@ -from django.conf.urls import url - -from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter +from django.conf.urls import url from funkwhale_api.common.auth import TokenAuthMiddleware from funkwhale_api.instance import consumers - application = ProtocolTypeRouter( { # Empty for now (http->django views is added by default) diff --git a/api/config/settings/common.py b/api/config/settings/common.py index f7688a4e4..cb5573ed5 100644 --- a/api/config/settings/common.py +++ b/api/config/settings/common.py @@ -10,8 +10,9 @@ https://docs.djangoproject.com/en/dev/ref/settings/ """ from __future__ import absolute_import, unicode_literals -from urllib.parse import urlsplit -import os +import datetime +from urllib.parse import urlparse, urlsplit + import environ from celery.schedules import crontab @@ -21,7 +22,6 @@ ROOT_DIR = environ.Path(__file__) - 3 # (/a/b/myfile.py - 3 = /) APPS_DIR = ROOT_DIR.path("funkwhale_api") env = environ.Env() - try: env.read_env(ROOT_DIR.file(".env")) except FileNotFoundError: @@ -315,7 +315,6 @@ CACHE_DEFAULT = "redis://127.0.0.1:6379/0" CACHES = {"default": env.cache_url("CACHE_URL", default=CACHE_DEFAULT)} CACHES["default"]["BACKEND"] = "django_redis.cache.RedisCache" -from urllib.parse import urlparse cache_url = urlparse(CACHES["default"]["LOCATION"]) CHANNEL_LAYERS = { @@ -332,12 +331,12 @@ CACHES["default"]["OPTIONS"] = { } -########## CELERY +# CELERY INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",) CELERY_BROKER_URL = env( "CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT) ) -########## END CELERY +# END CELERY # Location of root django.contrib.admin URL, use {% url 'admin:index' %} # Your common stuff: Below this line define 3rd party library settings @@ -351,8 +350,6 @@ CELERYBEAT_SCHEDULE = { } } -import datetime - JWT_AUTH = { "JWT_ALLOW_REFRESH": True, "JWT_EXPIRATION_DELTA": datetime.timedelta(days=7), diff --git a/api/config/settings/local.py b/api/config/settings/local.py index 51e793476..9f0119cee 100644 --- a/api/config/settings/local.py +++ b/api/config/settings/local.py @@ -10,6 +10,7 @@ Local settings from .common import * # noqa + # DEBUG # ------------------------------------------------------------------------------ DEBUG = env.bool("DJANGO_DEBUG", default=True) @@ -49,10 +50,10 @@ INSTALLED_APPS += ("debug_toolbar",) # ------------------------------------------------------------------------------ TEST_RUNNER = "django.test.runner.DiscoverRunner" -########## CELERY +# CELERY # In development, all tasks will be executed locally by blocking until the task returns CELERY_TASK_ALWAYS_EAGER = False -########## END CELERY +# END CELERY # Your local stuff: Below this line define 3rd party library settings diff --git a/api/config/settings/production.py b/api/config/settings/production.py index 0c79ee2ef..72b08aa3c 100644 --- a/api/config/settings/production.py +++ b/api/config/settings/production.py @@ -11,9 +11,6 @@ Production Configurations """ from __future__ import absolute_import, unicode_literals -from django.utils import six - - from .common import * # noqa # SECRET CONFIGURATION diff --git a/api/config/urls.py b/api/config/urls.py index 60753294c..5ffcf211b 100644 --- a/api/config/urls.py +++ b/api/config/urls.py @@ -5,7 +5,6 @@ from django.conf import settings from django.conf.urls import include, url from django.conf.urls.static import static from django.contrib import admin -from django.views.generic import TemplateView from django.views import defaults as default_views urlpatterns = [ diff --git a/api/config/wsgi.py b/api/config/wsgi.py index a53b580d7..8e843eb4d 100644 --- a/api/config/wsgi.py +++ b/api/config/wsgi.py @@ -15,11 +15,9 @@ framework. """ import os - from django.core.wsgi import get_wsgi_application from whitenoise.django import DjangoWhiteNoise - # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks # if running multiple sites in the same mod_wsgi process. To fix this, use # mod_wsgi daemon mode with each site in its own daemon process, or use diff --git a/api/funkwhale_api/activity/views.py b/api/funkwhale_api/activity/views.py index f2f747d4d..701dd04b8 100644 --- a/api/funkwhale_api/activity/views.py +++ b/api/funkwhale_api/activity/views.py @@ -4,8 +4,7 @@ from rest_framework.response import Response from funkwhale_api.common.permissions import ConditionalAuthentication from funkwhale_api.favorites.models import TrackFavorite -from . import serializers -from . import utils +from . import serializers, utils class ActivityViewSet(viewsets.GenericViewSet): diff --git a/api/funkwhale_api/common/auth.py b/api/funkwhale_api/common/auth.py index 88010e798..7717c836b 100644 --- a/api/funkwhale_api/common/auth.py +++ b/api/funkwhale_api/common/auth.py @@ -1,12 +1,7 @@ from urllib.parse import parse_qs -import jwt - from django.contrib.auth.models import AnonymousUser -from django.utils.encoding import smart_text - from rest_framework import exceptions -from rest_framework_jwt.settings import api_settings from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication from funkwhale_api.users.models import User diff --git a/api/funkwhale_api/common/authentication.py b/api/funkwhale_api/common/authentication.py index 9ddc06a3b..10bf36613 100644 --- a/api/funkwhale_api/common/authentication.py +++ b/api/funkwhale_api/common/authentication.py @@ -1,6 +1,5 @@ from django.utils.encoding import smart_text from django.utils.translation import ugettext as _ - from rest_framework import exceptions from rest_framework_jwt import authentication from rest_framework_jwt.settings import api_settings diff --git a/api/funkwhale_api/common/consumers.py b/api/funkwhale_api/common/consumers.py index 32a8876dc..47a666f05 100644 --- a/api/funkwhale_api/common/consumers.py +++ b/api/funkwhale_api/common/consumers.py @@ -1,4 +1,5 @@ from channels.generic.websocket import JsonWebsocketConsumer + from funkwhale_api.common import channels diff --git a/api/funkwhale_api/common/fields.py b/api/funkwhale_api/common/fields.py index de3ee37e5..190576efa 100644 --- a/api/funkwhale_api/common/fields.py +++ b/api/funkwhale_api/common/fields.py @@ -1,10 +1,8 @@ import django_filters - from django.db import models from funkwhale_api.music import utils - PRIVACY_LEVEL_CHOICES = [ ("me", "Only me"), ("followers", "Me and my followers"), diff --git a/api/funkwhale_api/common/management/commands/script.py b/api/funkwhale_api/common/management/commands/script.py index 03e32d5dd..b46a4327b 100644 --- a/api/funkwhale_api/common/management/commands/script.py +++ b/api/funkwhale_api/common/management/commands/script.py @@ -41,7 +41,6 @@ class Command(BaseCommand): script["entrypoint"](self, **options) def show_help(self): - indentation = 4 self.stdout.write("") self.stdout.write("Available scripts:") self.stdout.write("Launch with: python manage.py ") diff --git a/api/funkwhale_api/common/permissions.py b/api/funkwhale_api/common/permissions.py index 82da2c577..8f391a70c 100644 --- a/api/funkwhale_api/common/permissions.py +++ b/api/funkwhale_api/common/permissions.py @@ -1,8 +1,6 @@ import operator -from django.conf import settings from django.http import Http404 - from rest_framework.permissions import BasePermission from funkwhale_api.common import preferences diff --git a/api/funkwhale_api/common/preferences.py b/api/funkwhale_api/common/preferences.py index 9b8f12e85..acda9a90c 100644 --- a/api/funkwhale_api/common/preferences.py +++ b/api/funkwhale_api/common/preferences.py @@ -1,8 +1,6 @@ -from django.conf import settings from django import forms - -from dynamic_preferences import serializers -from dynamic_preferences import types +from django.conf import settings +from dynamic_preferences import serializers, types from dynamic_preferences.registries import global_preferences_registry diff --git a/api/funkwhale_api/common/scripts/__init__.py b/api/funkwhale_api/common/scripts/__init__.py index 4b2d52520..e69de29bb 100644 --- a/api/funkwhale_api/common/scripts/__init__.py +++ b/api/funkwhale_api/common/scripts/__init__.py @@ -1,2 +0,0 @@ -from . import django_permissions_to_user_permissions -from . import test diff --git a/api/funkwhale_api/common/scripts/django_permissions_to_user_permissions.py b/api/funkwhale_api/common/scripts/django_permissions_to_user_permissions.py index 1c2072385..48144f8ea 100644 --- a/api/funkwhale_api/common/scripts/django_permissions_to_user_permissions.py +++ b/api/funkwhale_api/common/scripts/django_permissions_to_user_permissions.py @@ -2,10 +2,10 @@ Convert django permissions to user permissions in the database, following the work done in #152. """ -from django.db.models import Q -from funkwhale_api.users import models - from django.contrib.auth.models import Permission +from django.db.models import Q + +from funkwhale_api.users import models mapping = { "dynamic_preferences.change_globalpreferencemodel": "settings", diff --git a/api/funkwhale_api/common/serializers.py b/api/funkwhale_api/common/serializers.py index 8cc85ec0c..029338ef9 100644 --- a/api/funkwhale_api/common/serializers.py +++ b/api/funkwhale_api/common/serializers.py @@ -40,7 +40,6 @@ class ActionSerializer(serializers.Serializer): return value def validate_objects(self, value): - qs = None if value == "all": return self.queryset.all().order_by("id") if type(value) in [list, tuple]: diff --git a/api/funkwhale_api/common/session.py b/api/funkwhale_api/common/session.py index 871fc4c21..4d5d0bb60 100644 --- a/api/funkwhale_api/common/session.py +++ b/api/funkwhale_api/common/session.py @@ -1,5 +1,4 @@ import requests - from django.conf import settings import funkwhale_api diff --git a/api/funkwhale_api/common/utils.py b/api/funkwhale_api/common/utils.py index f2ea52a8c..221d2336b 100644 --- a/api/funkwhale_api/common/utils.py +++ b/api/funkwhale_api/common/utils.py @@ -1,6 +1,6 @@ -from urllib.parse import urlencode, parse_qs, urlsplit, urlunsplit import os import shutil +from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit from django.db import transaction diff --git a/api/funkwhale_api/downloader/__init__.py b/api/funkwhale_api/downloader/__init__.py index 29ec89954..eca15e121 100644 --- a/api/funkwhale_api/downloader/__init__.py +++ b/api/funkwhale_api/downloader/__init__.py @@ -1,2 +1,3 @@ - from .downloader import download + +__all__ = ["download"] diff --git a/api/funkwhale_api/downloader/downloader.py b/api/funkwhale_api/downloader/downloader.py index 3599b86ef..f2b7568cc 100644 --- a/api/funkwhale_api/downloader/downloader.py +++ b/api/funkwhale_api/downloader/downloader.py @@ -1,9 +1,7 @@ import os -import json -from urllib.parse import quote_plus + import youtube_dl from django.conf import settings -import glob def download( diff --git a/api/funkwhale_api/favorites/activities.py b/api/funkwhale_api/favorites/activities.py index d9d546335..294194e06 100644 --- a/api/funkwhale_api/favorites/activities.py +++ b/api/funkwhale_api/favorites/activities.py @@ -1,5 +1,5 @@ -from funkwhale_api.common import channels from funkwhale_api.activity import record +from funkwhale_api.common import channels from . import serializers diff --git a/api/funkwhale_api/favorites/factories.py b/api/funkwhale_api/favorites/factories.py index 797c135ef..d96ef1c15 100644 --- a/api/funkwhale_api/favorites/factories.py +++ b/api/funkwhale_api/favorites/factories.py @@ -1,7 +1,6 @@ import factory from funkwhale_api.factories import registry - from funkwhale_api.music.factories import TrackFactory from funkwhale_api.users.factories import UserFactory diff --git a/api/funkwhale_api/favorites/models.py b/api/funkwhale_api/favorites/models.py index dd2b8f3ec..a6a80cebd 100644 --- a/api/funkwhale_api/favorites/models.py +++ b/api/funkwhale_api/favorites/models.py @@ -1,4 +1,3 @@ -from django.conf import settings from django.db import models from django.utils import timezone diff --git a/api/funkwhale_api/favorites/serializers.py b/api/funkwhale_api/favorites/serializers.py index 40260c2aa..3cafb80f0 100644 --- a/api/funkwhale_api/favorites/serializers.py +++ b/api/funkwhale_api/favorites/serializers.py @@ -1,4 +1,3 @@ -from django.conf import settings from rest_framework import serializers diff --git a/api/funkwhale_api/favorites/urls.py b/api/funkwhale_api/favorites/urls.py index b85023ade..28d0c8676 100644 --- a/api/funkwhale_api/favorites/urls.py +++ b/api/funkwhale_api/favorites/urls.py @@ -1,8 +1,7 @@ -from django.conf.urls import include, url -from . import views - from rest_framework import routers +from . import views + router = routers.SimpleRouter() router.register(r"tracks", views.TrackFavoriteViewSet, "tracks") diff --git a/api/funkwhale_api/favorites/views.py b/api/funkwhale_api/favorites/views.py index 7deae7a98..4d1c1e756 100644 --- a/api/funkwhale_api/favorites/views.py +++ b/api/funkwhale_api/favorites/views.py @@ -1,15 +1,12 @@ -from rest_framework import generics, mixins, viewsets -from rest_framework import status -from rest_framework.response import Response -from rest_framework import pagination +from rest_framework import mixins, status, viewsets from rest_framework.decorators import list_route +from rest_framework.response import Response from funkwhale_api.activity import record -from funkwhale_api.music.models import Track from funkwhale_api.common.permissions import ConditionalAuthentication +from funkwhale_api.music.models import Track -from . import models -from . import serializers +from . import models, serializers class TrackFavoriteViewSet( diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py index 6dd26a87d..73e83e334 100644 --- a/api/funkwhale_api/federation/activity.py +++ b/api/funkwhale_api/federation/activity.py @@ -1,6 +1,3 @@ -from . import serializers -from . import tasks - ACTIVITY_TYPES = [ "Accept", "Add", @@ -52,9 +49,13 @@ OBJECT_TYPES = [ def deliver(activity, on_behalf_of, to=[]): + from . import tasks + return tasks.send.delay(activity=activity, actor_id=on_behalf_of.pk, to=to) def accept_follow(follow): + from . import serializers + serializer = serializers.AcceptFollowSerializer(follow) return deliver(serializer.data, to=[follow.actor.url], on_behalf_of=follow.target) diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py index 32b545656..7fbf815dc 100644 --- a/api/funkwhale_api/federation/actors.py +++ b/api/funkwhale_api/federation/actors.py @@ -1,29 +1,19 @@ import datetime import logging -import uuid import xml from django.conf import settings from django.db import transaction from django.urls import reverse from django.utils import timezone - from rest_framework.exceptions import PermissionDenied -from dynamic_preferences.registries import global_preferences_registry - -from funkwhale_api.common import preferences -from funkwhale_api.common import session +from funkwhale_api.common import preferences, session from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.music import models as music_models from funkwhale_api.music import tasks as music_tasks -from . import activity -from . import keys -from . import models -from . import serializers -from . import signing -from . import utils +from . import activity, keys, models, serializers, signing, utils logger = logging.getLogger(__name__) @@ -45,7 +35,7 @@ def get_actor_data(actor_url): response.raise_for_status() try: return response.json() - except: + except Exception: raise ValueError("Invalid actor payload: {}".format(response.text)) @@ -155,7 +145,6 @@ class SystemActor(object): return handler(data, actor) def handle_follow(self, ac, sender): - system_actor = self.get_actor_instance() serializer = serializers.FollowSerializer( data=ac, context={"follow_actor": sender} ) @@ -325,7 +314,6 @@ class TestActor(SystemActor): reply_url = "https://{}/activities/note/{}".format( settings.FEDERATION_HOSTNAME, now.timestamp() ) - reply_content = "{} Pong!".format(sender.mention_username) reply_activity = { "@context": [ "https://www.w3.org/ns/activitystreams", diff --git a/api/funkwhale_api/federation/authentication.py b/api/funkwhale_api/federation/authentication.py index b669b4004..f32c78ff3 100644 --- a/api/funkwhale_api/federation/authentication.py +++ b/api/funkwhale_api/federation/authentication.py @@ -1,16 +1,8 @@ import cryptography - from django.contrib.auth.models import AnonymousUser +from rest_framework import authentication, exceptions -from rest_framework import authentication -from rest_framework import exceptions - -from . import actors -from . import keys -from . import models -from . import serializers -from . import signing -from . import utils +from . import actors, keys, signing, utils class SignatureAuthentication(authentication.BaseAuthentication): diff --git a/api/funkwhale_api/federation/dynamic_preferences_registry.py b/api/funkwhale_api/federation/dynamic_preferences_registry.py index 21f4076ea..5119d2596 100644 --- a/api/funkwhale_api/federation/dynamic_preferences_registry.py +++ b/api/funkwhale_api/federation/dynamic_preferences_registry.py @@ -1,4 +1,3 @@ -from django.forms import widgets from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py index 52a5e8b54..7370ebd77 100644 --- a/api/funkwhale_api/federation/factories.py +++ b/api/funkwhale_api/federation/factories.py @@ -1,16 +1,14 @@ +import uuid + import factory import requests import requests_http_signature -import uuid - -from django.utils import timezone from django.conf import settings +from django.utils import timezone from funkwhale_api.factories import registry -from . import keys -from . import models - +from . import keys, models registry.register(keys.get_key_pair, name="federation.KeyPair") diff --git a/api/funkwhale_api/federation/keys.py b/api/funkwhale_api/federation/keys.py index fb6f0748c..e7c30c50a 100644 --- a/api/funkwhale_api/federation/keys.py +++ b/api/funkwhale_api/federation/keys.py @@ -1,11 +1,9 @@ -from cryptography.hazmat.primitives import serialization as crypto_serialization -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.backends import default_backend as crypto_default_backend - import re import urllib.parse -from . import exceptions +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa KEY_ID_REGEX = re.compile(r"keyId=\"(?P.*)\"") diff --git a/api/funkwhale_api/federation/library.py b/api/funkwhale_api/federation/library.py index 28bb9a762..d2ccb1952 100644 --- a/api/funkwhale_api/federation/library.py +++ b/api/funkwhale_api/federation/library.py @@ -1,15 +1,11 @@ import json -import requests +import requests from django.conf import settings from funkwhale_api.common import session -from . import actors -from . import models -from . import serializers -from . import signing -from . import webfinger +from . import actors, models, serializers, signing, webfinger def scan_from_account_name(account_name): @@ -28,13 +24,6 @@ def scan_from_account_name(account_name): except serializers.ValidationError: return {"webfinger": {"errors": ["Invalid account string"]}} system_library = actors.SYSTEM_ACTORS["library"].get_actor_instance() - library = ( - models.Library.objects.filter( - actor__domain=domain, actor__preferred_username=username - ) - .select_related("actor") - .first() - ) data["local"] = {"following": False, "awaiting_approval": False} try: follow = models.Follow.objects.get( diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py index 398ab23c4..979b0674a 100644 --- a/api/funkwhale_api/federation/models.py +++ b/api/funkwhale_api/federation/models.py @@ -1,6 +1,6 @@ import os -import uuid import tempfile +import uuid from django.conf import settings from django.contrib.postgres.fields import JSONField diff --git a/api/funkwhale_api/federation/permissions.py b/api/funkwhale_api/federation/permissions.py index ccffb1014..a08d57e5f 100644 --- a/api/funkwhale_api/federation/permissions.py +++ b/api/funkwhale_api/federation/permissions.py @@ -1,8 +1,8 @@ -from django.conf import settings from rest_framework.permissions import BasePermission from funkwhale_api.common import preferences + from . import actors diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py index 367ca9929..062f74f47 100644 --- a/api/funkwhale_api/federation/serializers.py +++ b/api/funkwhale_api/federation/serializers.py @@ -1,23 +1,16 @@ import logging import urllib.parse -from django.urls import reverse -from django.conf import settings from django.core.paginator import Paginator from django.db import transaction - from rest_framework import serializers -from dynamic_preferences.registries import global_preferences_registry -from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.common import serializers as common_serializers +from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.music import models as music_models from funkwhale_api.music import tasks as music_tasks -from . import activity -from . import filters -from . import models -from . import utils +from . import activity, filters, models, utils AP_CONTEXT = [ "https://www.w3.org/ns/activitystreams", @@ -341,7 +334,7 @@ class FollowSerializer(serializers.Serializer): return models.Follow.objects.get_or_create( actor=self.validated_data["actor"], target=self.validated_data["object"], - **kwargs, + **kwargs, # noqa )[0] def to_representation(self, instance): @@ -352,7 +345,6 @@ class FollowSerializer(serializers.Serializer): "object": instance.target.url, "type": "Follow", } - return ret class APIFollowSerializer(serializers.ModelSerializer): @@ -687,7 +679,7 @@ class AudioSerializer(serializers.Serializer): def validate_url(self, v): try: - url = v["href"] + v["href"] except (KeyError, TypeError): raise serializers.ValidationError("Missing href") diff --git a/api/funkwhale_api/federation/signing.py b/api/funkwhale_api/federation/signing.py index 46e7ae55a..15525b3e5 100644 --- a/api/funkwhale_api/federation/signing.py +++ b/api/funkwhale_api/federation/signing.py @@ -1,9 +1,9 @@ import logging + import requests import requests_http_signature -from . import exceptions -from . import utils +from . import exceptions, utils logger = logging.getLogger(__name__) @@ -47,7 +47,7 @@ def verify_django(django_request, public_key): v = request.headers[h] if v: request.headers[h] = str(v) - prepared_request = request.prepare() + request.prepare() return verify(request, public_key) diff --git a/api/funkwhale_api/federation/tasks.py b/api/funkwhale_api/federation/tasks.py index 0e6ee1e60..d1b5b7bd2 100644 --- a/api/funkwhale_api/federation/tasks.py +++ b/api/funkwhale_api/federation/tasks.py @@ -6,19 +6,15 @@ import os from django.conf import settings from django.db.models import Q from django.utils import timezone - -from requests.exceptions import RequestException from dynamic_preferences.registries import global_preferences_registry +from requests.exceptions import RequestException from funkwhale_api.common import session -from funkwhale_api.history.models import Listening from funkwhale_api.taskapp import celery from . import actors from . import library as lb -from . import models -from . import signing - +from . import models, signing logger = logging.getLogger(__name__) diff --git a/api/funkwhale_api/federation/urls.py b/api/funkwhale_api/federation/urls.py index 3cd4cb732..2594f5549 100644 --- a/api/funkwhale_api/federation/urls.py +++ b/api/funkwhale_api/federation/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import include, url - from rest_framework import routers + from . import views router = routers.SimpleRouter(trailing_slash=False) diff --git a/api/funkwhale_api/federation/views.py b/api/funkwhale_api/federation/views.py index 36bf1a444..63a1d7b71 100644 --- a/api/funkwhale_api/federation/views.py +++ b/api/funkwhale_api/federation/views.py @@ -1,35 +1,28 @@ from django import forms -from django.conf import settings from django.core import paginator from django.db import transaction -from django.http import HttpResponse +from django.http import HttpResponse, Http404 from django.urls import reverse - -from rest_framework import mixins -from rest_framework import permissions as rest_permissions -from rest_framework import response -from rest_framework import views -from rest_framework import viewsets -from rest_framework.decorators import list_route, detail_route -from rest_framework.serializers import ValidationError +from rest_framework import mixins, response, viewsets +from rest_framework.decorators import detail_route, list_route from funkwhale_api.common import preferences -from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.music import models as music_models from funkwhale_api.users.permissions import HasUserPermission -from . import activity -from . import actors -from . import authentication -from . import filters -from . import library -from . import models -from . import permissions -from . import renderers -from . import serializers -from . import tasks -from . import utils -from . import webfinger +from . import ( + actors, + authentication, + filters, + library, + models, + permissions, + renderers, + serializers, + tasks, + utils, + webfinger, +) class FederationMixin(object): @@ -64,7 +57,7 @@ class InstanceActorViewSet(FederationMixin, viewsets.GenericViewSet): handler = getattr(system_actor, "{}_inbox".format(request.method.lower())) try: - data = handler(request.data, actor=request.actor) + handler(request.data, actor=request.actor) except NotImplementedError: return response.Response(status=405) return response.Response({}, status=200) @@ -74,7 +67,7 @@ class InstanceActorViewSet(FederationMixin, viewsets.GenericViewSet): system_actor = self.get_object() handler = getattr(system_actor, "{}_outbox".format(request.method.lower())) try: - data = handler(request.data, actor=request.actor) + handler(request.data, actor=request.actor) except NotImplementedError: return response.Response(status=405) return response.Response({}, status=200) @@ -151,7 +144,7 @@ class MusicFilesViewSet(FederationMixin, viewsets.GenericViewSet): else: try: page_number = int(page) - except: + except Exception: return response.Response({"page": ["Invalid page number"]}, status=400) p = paginator.Paginator( qs, preferences.get("federation__collection_page_size") @@ -249,7 +242,7 @@ class LibraryViewSet( def create(self, request, *args, **kwargs): serializer = serializers.APILibraryCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True) - library = serializer.save() + serializer.save() return response.Response(serializer.data, status=201) diff --git a/api/funkwhale_api/federation/webfinger.py b/api/funkwhale_api/federation/webfinger.py index b37f02e8a..b899fe207 100644 --- a/api/funkwhale_api/federation/webfinger.py +++ b/api/funkwhale_api/federation/webfinger.py @@ -1,12 +1,9 @@ from django import forms from django.conf import settings -from django.urls import reverse from funkwhale_api.common import session -from . import actors -from . import utils -from . import serializers +from . import actors, serializers VALID_RESOURCE_TYPES = ["acct"] diff --git a/api/funkwhale_api/history/activities.py b/api/funkwhale_api/history/activities.py index 3e8556ce5..b63de1f26 100644 --- a/api/funkwhale_api/history/activities.py +++ b/api/funkwhale_api/history/activities.py @@ -1,5 +1,5 @@ -from funkwhale_api.common import channels from funkwhale_api.activity import record +from funkwhale_api.common import channels from . import serializers diff --git a/api/funkwhale_api/history/models.py b/api/funkwhale_api/history/models.py index 2edc98fbf..8da4e67cd 100644 --- a/api/funkwhale_api/history/models.py +++ b/api/funkwhale_api/history/models.py @@ -1,6 +1,5 @@ -from django.utils import timezone from django.db import models -from django.core.exceptions import ValidationError +from django.utils import timezone from funkwhale_api.music.models import Track diff --git a/api/funkwhale_api/history/urls.py b/api/funkwhale_api/history/urls.py index 30e0105c0..707e95cd7 100644 --- a/api/funkwhale_api/history/urls.py +++ b/api/funkwhale_api/history/urls.py @@ -1,8 +1,7 @@ -from django.conf.urls import include, url -from . import views - from rest_framework import routers +from . import views + router = routers.SimpleRouter() router.register(r"listenings", views.ListeningViewSet, "listenings") diff --git a/api/funkwhale_api/history/views.py b/api/funkwhale_api/history/views.py index 057e6b323..e104a2aa3 100644 --- a/api/funkwhale_api/history/views.py +++ b/api/funkwhale_api/history/views.py @@ -1,14 +1,8 @@ -from rest_framework import generics, mixins, viewsets -from rest_framework import permissions -from rest_framework import status -from rest_framework.response import Response -from rest_framework.decorators import detail_route +from rest_framework import mixins, permissions, viewsets from funkwhale_api.activity import record -from funkwhale_api.common.permissions import ConditionalAuthentication -from . import models -from . import serializers +from . import models, serializers class ListeningViewSet( diff --git a/api/funkwhale_api/instance/dynamic_preferences_registry.py b/api/funkwhale_api/instance/dynamic_preferences_registry.py index 618bd8ea4..0edb94482 100644 --- a/api/funkwhale_api/instance/dynamic_preferences_registry.py +++ b/api/funkwhale_api/instance/dynamic_preferences_registry.py @@ -1,5 +1,4 @@ from django.forms import widgets - from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry diff --git a/api/funkwhale_api/instance/nodeinfo.py b/api/funkwhale_api/instance/nodeinfo.py index ea982a63f..0b8f4b3ce 100644 --- a/api/funkwhale_api/instance/nodeinfo.py +++ b/api/funkwhale_api/instance/nodeinfo.py @@ -5,14 +5,12 @@ from funkwhale_api.common import preferences from . import stats - store = memoize.djangocache.Cache("default") memo = memoize.Memoizer(store, namespace="instance:stats") def get(): share_stats = preferences.get("instance__nodeinfo_stats_enabled") - private = preferences.get("instance__nodeinfo_private") data = { "version": "2.0", "software": {"name": "funkwhale", "version": funkwhale_api.__version__}, diff --git a/api/funkwhale_api/instance/views.py b/api/funkwhale_api/instance/views.py index 69663c125..ea6311033 100644 --- a/api/funkwhale_api/instance/views.py +++ b/api/funkwhale_api/instance/views.py @@ -1,16 +1,13 @@ -from rest_framework import views -from rest_framework.response import Response - from dynamic_preferences.api import serializers from dynamic_preferences.api import viewsets as preferences_viewsets from dynamic_preferences.registries import global_preferences_registry +from rest_framework import views +from rest_framework.response import Response from funkwhale_api.common import preferences from funkwhale_api.users.permissions import HasUserPermission from . import nodeinfo -from . import stats - NODEINFO_2_CONTENT_TYPE = "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8" # noqa diff --git a/api/funkwhale_api/manage/filters.py b/api/funkwhale_api/manage/filters.py index 6bb8a1ccc..2f2bde838 100644 --- a/api/funkwhale_api/manage/filters.py +++ b/api/funkwhale_api/manage/filters.py @@ -1,4 +1,3 @@ -from django.db.models import Count from django_filters import rest_framework as filters diff --git a/api/funkwhale_api/manage/urls.py b/api/funkwhale_api/manage/urls.py index 38ed7d1c9..60853034f 100644 --- a/api/funkwhale_api/manage/urls.py +++ b/api/funkwhale_api/manage/urls.py @@ -1,8 +1,8 @@ from django.conf.urls import include, url -from . import views - from rest_framework import routers +from . import views + library_router = routers.SimpleRouter() library_router.register(r"track-files", views.ManageTrackFileViewSet, "track-files") diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py index 77581acf0..8511732c9 100644 --- a/api/funkwhale_api/manage/views.py +++ b/api/funkwhale_api/manage/views.py @@ -1,13 +1,10 @@ -from rest_framework import mixins -from rest_framework import response -from rest_framework import viewsets +from rest_framework import mixins, response, viewsets from rest_framework.decorators import list_route from funkwhale_api.music import models as music_models from funkwhale_api.users.permissions import HasUserPermission -from . import filters -from . import serializers +from . import filters, serializers class ManageTrackFileViewSet( diff --git a/api/funkwhale_api/music/factories.py b/api/funkwhale_api/music/factories.py index 6e2e6a115..2dd4ba303 100644 --- a/api/funkwhale_api/music/factories.py +++ b/api/funkwhale_api/music/factories.py @@ -1,7 +1,8 @@ -import factory import os -from funkwhale_api.factories import registry, ManyToManyFromList +import factory + +from funkwhale_api.factories import ManyToManyFromList, registry from funkwhale_api.federation.factories import LibraryTrackFactory from funkwhale_api.users.factories import UserFactory diff --git a/api/funkwhale_api/music/fake_data.py b/api/funkwhale_api/music/fake_data.py index de7b61ef5..e5fd65d8e 100644 --- a/api/funkwhale_api/music/fake_data.py +++ b/api/funkwhale_api/music/fake_data.py @@ -3,7 +3,6 @@ Populates the database with fake data """ import random -from funkwhale_api.music import models from funkwhale_api.music import factories diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py index 6e1e4df09..1f73fc9b0 100644 --- a/api/funkwhale_api/music/filters.py +++ b/api/funkwhale_api/music/filters.py @@ -1,8 +1,8 @@ from django.db.models import Count - from django_filters import rest_framework as filters from funkwhale_api.common import fields + from . import models diff --git a/api/funkwhale_api/music/lyrics.py b/api/funkwhale_api/music/lyrics.py index 4fd31d92c..6d5f20e44 100644 --- a/api/funkwhale_api/music/lyrics.py +++ b/api/funkwhale_api/music/lyrics.py @@ -1,5 +1,5 @@ import urllib.request -import html.parser + from bs4 import BeautifulSoup diff --git a/api/funkwhale_api/music/management/commands/fix_track_files.py b/api/funkwhale_api/music/management/commands/fix_track_files.py index 94dd4fb9f..988f9bed3 100644 --- a/api/funkwhale_api/music/management/commands/fix_track_files.py +++ b/api/funkwhale_api/music/management/commands/fix_track_files.py @@ -1,10 +1,7 @@ import cacheops -import os - +from django.core.management.base import BaseCommand from django.db import transaction from django.db.models import Q -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError from funkwhale_api.music import models, utils @@ -70,8 +67,7 @@ class Command(BaseCommand): try: audio_file = tf.get_audio_file() if audio_file: - with audio_file as f: - data = utils.get_audio_file_data(audio_file) + data = utils.get_audio_file_data(audio_file) tf.bitrate = data["bitrate"] tf.duration = data["length"] tf.save(update_fields=["duration", "bitrate"]) diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py index 3a43521c5..d2534f6b2 100644 --- a/api/funkwhale_api/music/metadata.py +++ b/api/funkwhale_api/music/metadata.py @@ -1,6 +1,6 @@ -from django import forms import arrow import mutagen +from django import forms NODEFAULT = object() diff --git a/api/funkwhale_api/music/migrations/0004_track_tags.py b/api/funkwhale_api/music/migrations/0004_track_tags.py index c00f5edfe..b999a7031 100644 --- a/api/funkwhale_api/music/migrations/0004_track_tags.py +++ b/api/funkwhale_api/music/migrations/0004_track_tags.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import migrations, models +from django.db import migrations import taggit.managers diff --git a/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py b/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py index 2999df60c..eff0f82a0 100644 --- a/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py +++ b/api/funkwhale_api/music/migrations/0009_auto_20160920_1614.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals from django.db import migrations, models import django.utils.timezone -import versatileimagefield.fields class Migration(migrations.Migration): diff --git a/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py b/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py index dcb4f7950..2b5ce935b 100644 --- a/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py +++ b/api/funkwhale_api/music/migrations/0010_auto_20160920_1742.py @@ -2,7 +2,6 @@ from __future__ import unicode_literals from django.db import migrations, models -import versatileimagefield.fields class Migration(migrations.Migration): diff --git a/api/funkwhale_api/music/migrations/0011_rename_files.py b/api/funkwhale_api/music/migrations/0011_rename_files.py index 7152cca3b..2aafb126c 100644 --- a/api/funkwhale_api/music/migrations/0011_rename_files.py +++ b/api/funkwhale_api/music/migrations/0011_rename_files.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import os from django.db import migrations, models -from funkwhale_api.common.utils import rename_file def rename_files(apps, schema_editor): diff --git a/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py b/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py index 016d1c110..0cf1e44f0 100644 --- a/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py +++ b/api/funkwhale_api/music/migrations/0012_auto_20161122_1905.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import migrations, models +from django.db import migrations import versatileimagefield.fields diff --git a/api/funkwhale_api/music/migrations/0015_bind_track_file_to_import_job.py b/api/funkwhale_api/music/migrations/0015_bind_track_file_to_import_job.py index 9762864f1..c8bd1c5e3 100644 --- a/api/funkwhale_api/music/migrations/0015_bind_track_file_to_import_job.py +++ b/api/funkwhale_api/music/migrations/0015_bind_track_file_to_import_job.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import os -from django.db import migrations, models -from funkwhale_api.common.utils import rename_file +from django.db import migrations def bind_jobs(apps, schema_editor): diff --git a/api/funkwhale_api/music/migrations/0019_populate_mimetypes.py b/api/funkwhale_api/music/migrations/0019_populate_mimetypes.py index 55f9a127a..11678efbc 100644 --- a/api/funkwhale_api/music/migrations/0019_populate_mimetypes.py +++ b/api/funkwhale_api/music/migrations/0019_populate_mimetypes.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import os -from django.db import migrations, models +from django.db import migrations from funkwhale_api.music.utils import guess_mimetype diff --git a/api/funkwhale_api/music/migrations/0021_populate_batch_status.py b/api/funkwhale_api/music/migrations/0021_populate_batch_status.py index 5bda0edfb..065384a97 100644 --- a/api/funkwhale_api/music/migrations/0021_populate_batch_status.py +++ b/api/funkwhale_api/music/migrations/0021_populate_batch_status.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import os -from django.db import migrations, models +from django.db import migrations def populate_status(apps, schema_editor): diff --git a/api/funkwhale_api/music/migrations/0024_populate_uuid.py b/api/funkwhale_api/music/migrations/0024_populate_uuid.py index 349a901fc..63ab63862 100644 --- a/api/funkwhale_api/music/migrations/0024_populate_uuid.py +++ b/api/funkwhale_api/music/migrations/0024_populate_uuid.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import os import uuid from django.db import migrations, models diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index d4625a435..8b638ce7d 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -1,30 +1,26 @@ -import os -import io -import arrow import datetime -import tempfile +import os import shutil -import markdown +import tempfile import uuid +import arrow +import markdown from django.conf import settings -from django.db import models -from django.core.files.base import ContentFile from django.core.files import File +from django.core.files.base import ContentFile +from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse from django.utils import timezone - from taggit.managers import TaggableManager from versatileimagefield.fields import VersatileImageField -from funkwhale_api import downloader -from funkwhale_api import musicbrainz +from funkwhale_api import downloader, musicbrainz from funkwhale_api.federation import utils as federation_utils -from . import importers -from . import metadata -from . import utils + +from . import importers, metadata, utils class APIModelMixin(models.Model): @@ -71,7 +67,7 @@ class APIModelMixin(models.Model): try: cleaned_key, cleaned_value = mapping.from_musicbrainz(key, value) cleaned_data[cleaned_key] = cleaned_value - except KeyError as e: + except KeyError: pass return cleaned_data @@ -138,9 +134,7 @@ def import_tracks(instance, cleaned_data, raw_data): track_cleaned_data = Track.clean_musicbrainz_data(track_data["recording"]) track_cleaned_data["album"] = instance track_cleaned_data["position"] = int(track_data["position"]) - track = importers.load( - Track, track_cleaned_data, track_data, Track.import_hooks - ) + importers.load(Track, track_cleaned_data, track_data, Track.import_hooks) class AlbumQuerySet(models.QuerySet): @@ -265,13 +259,13 @@ class Work(APIModelMixin): import_hooks = [import_lyrics, link_recordings] def fetch_lyrics(self): - l = self.lyrics.first() - if l: - return l + lyric = self.lyrics.first() + if lyric: + return lyric data = self.api.get(self.mbid, includes=["url-rels"])["work"] - l = import_lyrics(self, {}, data) + lyric = import_lyrics(self, {}, data) - return l + return lyric class Lyrics(models.Model): @@ -612,7 +606,7 @@ def update_request_status(sender, instance, created, **kwargs): if not instance.import_request: return - if not created and not "status" in update_fields: + if not created and "status" not in update_fields: return r_status = instance.import_request.status diff --git a/api/funkwhale_api/music/permissions.py b/api/funkwhale_api/music/permissions.py index a85e5a9a6..dc589b5dd 100644 --- a/api/funkwhale_api/music/permissions.py +++ b/api/funkwhale_api/music/permissions.py @@ -1,10 +1,8 @@ -from django.conf import settings from rest_framework.permissions import BasePermission from funkwhale_api.common import preferences -from funkwhale_api.federation import actors -from funkwhale_api.federation import models +from funkwhale_api.federation import actors, models class Listen(BasePermission): diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py index 7aa8603e2..c34970d0b 100644 --- a/api/funkwhale_api/music/serializers.py +++ b/api/funkwhale_api/music/serializers.py @@ -1,16 +1,11 @@ -from django.db import transaction from django.db.models import Q from rest_framework import serializers from taggit.models import Tag from funkwhale_api.activity import serializers as activity_serializers -from funkwhale_api.federation import utils as federation_utils -from funkwhale_api.federation.models import LibraryTrack -from funkwhale_api.federation.serializers import AP_CONTEXT from funkwhale_api.users.serializers import UserBasicSerializer -from . import models -from . import tasks +from . import models, tasks class ArtistAlbumSerializer(serializers.ModelSerializer): diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py index 9dcaceec4..355af7706 100644 --- a/api/funkwhale_api/music/tasks.py +++ b/api/funkwhale_api/music/tasks.py @@ -1,22 +1,19 @@ import logging import os +from django.conf import settings from django.core.files.base import ContentFile - from musicbrainzngs import ResponseError from funkwhale_api.common import preferences -from funkwhale_api.federation import activity -from funkwhale_api.federation import actors -from funkwhale_api.federation import models as federation_models +from funkwhale_api.federation import activity, actors from funkwhale_api.federation import serializers as federation_serializers -from funkwhale_api.taskapp import celery from funkwhale_api.providers.acoustid import get_acoustid_client from funkwhale_api.providers.audiofile import tasks as audiofile_tasks +from funkwhale_api.taskapp import celery -from django.conf import settings -from . import models from . import lyrics as lyrics_utils +from . import models from . import utils as music_utils logger = logging.getLogger(__name__) @@ -259,7 +256,7 @@ def import_job_run(self, import_job, replace=False, use_acoustid=False): if not settings.DEBUG: try: self.retry(exc=exc, countdown=30, max_retries=3) - except: + except Exception: mark_errored(exc) raise mark_errored(exc) diff --git a/api/funkwhale_api/music/utils.py b/api/funkwhale_api/music/utils.py index 9b300ac2a..3080c1c6c 100644 --- a/api/funkwhale_api/music/utils.py +++ b/api/funkwhale_api/music/utils.py @@ -1,8 +1,8 @@ -import magic import mimetypes -import mutagen import re +import magic +import mutagen from django.db.models import Q diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 15421fa38..77a82dd21 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -1,46 +1,32 @@ -import ffmpeg -import os import json import logging -import subprocess -import unicodedata import urllib -from django.contrib.auth.decorators import login_required -from django.core.exceptions import ObjectDoesNotExist from django.conf import settings -from django.db import models, transaction -from django.db.models.functions import Length +from django.core.exceptions import ObjectDoesNotExist +from django.db import transaction from django.db.models import Count -from django.http import StreamingHttpResponse -from django.urls import reverse +from django.db.models.functions import Length from django.utils import timezone -from django.utils.decorators import method_decorator - -from rest_framework import viewsets, views, mixins +from musicbrainzngs import ResponseError +from rest_framework import mixins +from rest_framework import settings as rest_settings +from rest_framework import views, viewsets from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response -from rest_framework import settings as rest_settings -from rest_framework import permissions -from musicbrainzngs import ResponseError +from taggit.models import Tag from funkwhale_api.common import utils as funkwhale_utils from funkwhale_api.common.permissions import ConditionalAuthentication -from funkwhale_api.users.permissions import HasUserPermission -from taggit.models import Tag -from funkwhale_api.federation import actors from funkwhale_api.federation.authentication import SignatureAuthentication from funkwhale_api.federation.models import LibraryTrack from funkwhale_api.musicbrainz import api from funkwhale_api.requests.models import ImportRequest +from funkwhale_api.users.permissions import HasUserPermission -from . import filters -from . import importers -from . import models +from . import filters, importers, models from . import permissions as music_permissions -from . import serializers -from . import tasks -from . import utils +from . import serializers, tasks, utils logger = logging.getLogger(__name__) @@ -471,9 +457,7 @@ class SubmitViewSet(viewsets.ViewSet): import_request = self.get_import_request(data) artist_data = api.artists.get(id=data["artistId"])["artist"] cleaned_data = models.Artist.clean_musicbrainz_data(artist_data) - artist = importers.load( - models.Artist, cleaned_data, artist_data, import_hooks=[] - ) + importers.load(models.Artist, cleaned_data, artist_data, import_hooks=[]) import_data = [] batch = None diff --git a/api/funkwhale_api/musicbrainz/__init__.py b/api/funkwhale_api/musicbrainz/__init__.py index 00aa85d5c..103da679f 100644 --- a/api/funkwhale_api/musicbrainz/__init__.py +++ b/api/funkwhale_api/musicbrainz/__init__.py @@ -1 +1,3 @@ from .client import api + +__all__ = ["api"] diff --git a/api/funkwhale_api/musicbrainz/client.py b/api/funkwhale_api/musicbrainz/client.py index b3749a93b..deae0672f 100644 --- a/api/funkwhale_api/musicbrainz/client.py +++ b/api/funkwhale_api/musicbrainz/client.py @@ -1,7 +1,7 @@ -import musicbrainzngs import memoize.djangocache - +import musicbrainzngs from django.conf import settings + from funkwhale_api import __version__ _api = musicbrainzngs diff --git a/api/funkwhale_api/musicbrainz/urls.py b/api/funkwhale_api/musicbrainz/urls.py index edb421202..d14447f14 100644 --- a/api/funkwhale_api/musicbrainz/urls.py +++ b/api/funkwhale_api/musicbrainz/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.conf.urls import url from rest_framework import routers from . import views diff --git a/api/funkwhale_api/musicbrainz/views.py b/api/funkwhale_api/musicbrainz/views.py index 64d4ee152..b6f009dca 100644 --- a/api/funkwhale_api/musicbrainz/views.py +++ b/api/funkwhale_api/musicbrainz/views.py @@ -1,12 +1,10 @@ from rest_framework import viewsets -from rest_framework.views import APIView -from rest_framework.response import Response from rest_framework.decorators import list_route -import musicbrainzngs +from rest_framework.response import Response +from rest_framework.views import APIView from funkwhale_api.common.permissions import ConditionalAuthentication - from .client import api diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py index ef787d276..e9df4624d 100644 --- a/api/funkwhale_api/playlists/models.py +++ b/api/funkwhale_api/playlists/models.py @@ -1,12 +1,8 @@ -from django.conf import settings -from django.db import models -from django.db import transaction +from django.db import models, transaction from django.utils import timezone - from rest_framework import exceptions -from funkwhale_api.common import fields -from funkwhale_api.common import preferences +from funkwhale_api.common import fields, preferences class PlaylistQuerySet(models.QuerySet): diff --git a/api/funkwhale_api/playlists/serializers.py b/api/funkwhale_api/playlists/serializers.py index 3fac68b0e..17cc06b10 100644 --- a/api/funkwhale_api/playlists/serializers.py +++ b/api/funkwhale_api/playlists/serializers.py @@ -1,12 +1,11 @@ -from django.conf import settings from django.db import transaction from rest_framework import serializers -from taggit.models import Tag from funkwhale_api.common import preferences from funkwhale_api.music.models import Track from funkwhale_api.music.serializers import TrackSerializer from funkwhale_api.users.serializers import UserBasicSerializer + from . import models diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py index f45d8b272..d5d19df74 100644 --- a/api/funkwhale_api/playlists/views.py +++ b/api/funkwhale_api/playlists/views.py @@ -1,20 +1,13 @@ -from django.db.models import Count from django.db import transaction - -from rest_framework import exceptions -from rest_framework import generics, mixins, viewsets -from rest_framework import status +from django.db.models import Count +from rest_framework import exceptions, mixins, viewsets from rest_framework.decorators import detail_route -from rest_framework.response import Response from rest_framework.permissions import IsAuthenticatedOrReadOnly +from rest_framework.response import Response -from funkwhale_api.common import permissions -from funkwhale_api.common import fields -from funkwhale_api.music.models import Track +from funkwhale_api.common import fields, permissions -from . import filters -from . import models -from . import serializers +from . import filters, models, serializers class PlaylistViewSet( diff --git a/api/funkwhale_api/providers/acoustid/dynamic_preferences_registry.py b/api/funkwhale_api/providers/acoustid/dynamic_preferences_registry.py index 2e5a35f0d..2411de86a 100644 --- a/api/funkwhale_api/providers/acoustid/dynamic_preferences_registry.py +++ b/api/funkwhale_api/providers/acoustid/dynamic_preferences_registry.py @@ -1,7 +1,6 @@ from django import forms - -from dynamic_preferences.types import StringPreference, Section from dynamic_preferences.registries import global_preferences_registry +from dynamic_preferences.types import Section, StringPreference acoustid = Section("providers_acoustid") diff --git a/api/funkwhale_api/providers/audiofile/management/commands/import_files.py b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py index 9114375e0..de2560d3c 100644 --- a/api/funkwhale_api/providers/audiofile/management/commands/import_files.py +++ b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py @@ -5,8 +5,7 @@ from django.conf import settings from django.core.files import File from django.core.management.base import BaseCommand, CommandError -from funkwhale_api.music import models -from funkwhale_api.music import tasks +from funkwhale_api.music import models, tasks from funkwhale_api.users.models import User @@ -178,7 +177,6 @@ class Command(BaseCommand): async = options["async"] import_handler = tasks.import_job_run.delay if async else tasks.import_job_run batch = user.imports.create(source="shell") - total = len(paths) errors = [] for i, path in list(enumerate(paths)): try: diff --git a/api/funkwhale_api/providers/audiofile/tasks.py b/api/funkwhale_api/providers/audiofile/tasks.py index afd54dc24..ee486345a 100644 --- a/api/funkwhale_api/providers/audiofile/tasks.py +++ b/api/funkwhale_api/providers/audiofile/tasks.py @@ -1,12 +1,6 @@ -import acoustid -import os -import datetime -from django.core.files import File from django.db import transaction -from funkwhale_api.taskapp import celery -from funkwhale_api.providers.acoustid import get_acoustid_client -from funkwhale_api.music import models, metadata +from funkwhale_api.music import metadata, models @transaction.atomic @@ -49,33 +43,3 @@ def import_track_data_from_path(path): defaults={"title": data.get("title"), "position": position}, )[0] return track - - -def import_metadata_with_musicbrainz(path): - pass - - -@celery.app.task(name="audiofile.from_path") -def from_path(path): - acoustid_track_id = None - try: - client = get_acoustid_client() - result = client.get_best_match(path) - acoustid_track_id = result["id"] - except acoustid.WebServiceError: - track = import_track_data_from_path(path) - except (TypeError, KeyError): - track = import_metadata_without_musicbrainz(path) - else: - track, created = models.Track.get_or_create_from_api( - mbid=result["recordings"][0]["id"] - ) - - if track.files.count() > 0: - raise ValueError("File already exists for track {}".format(track.pk)) - - track_file = models.TrackFile(track=track, acoustid_track_id=acoustid_track_id) - track_file.audio_file.save(os.path.basename(path), File(open(path, "rb"))) - track_file.save() - - return track_file diff --git a/api/funkwhale_api/providers/urls.py b/api/funkwhale_api/providers/urls.py index 6d001ed9d..55a1193f5 100644 --- a/api/funkwhale_api/providers/urls.py +++ b/api/funkwhale_api/providers/urls.py @@ -1,5 +1,4 @@ from django.conf.urls import include, url -from funkwhale_api.music import views urlpatterns = [ url( diff --git a/api/funkwhale_api/providers/youtube/client.py b/api/funkwhale_api/providers/youtube/client.py index fbc32efa4..2235fcdc8 100644 --- a/api/funkwhale_api/providers/youtube/client.py +++ b/api/funkwhale_api/providers/youtube/client.py @@ -1,9 +1,6 @@ import threading from apiclient.discovery import build -from apiclient.errors import HttpError -from oauth2client.tools import argparser - from dynamic_preferences.registries import global_preferences_registry as registry YOUTUBE_API_SERVICE_NAME = "youtube" diff --git a/api/funkwhale_api/providers/youtube/dynamic_preferences_registry.py b/api/funkwhale_api/providers/youtube/dynamic_preferences_registry.py index 42b54b535..2d950eb6b 100644 --- a/api/funkwhale_api/providers/youtube/dynamic_preferences_registry.py +++ b/api/funkwhale_api/providers/youtube/dynamic_preferences_registry.py @@ -1,7 +1,6 @@ from django import forms - -from dynamic_preferences.types import StringPreference, Section from dynamic_preferences.registries import global_preferences_registry +from dynamic_preferences.types import Section, StringPreference youtube = Section("providers_youtube") diff --git a/api/funkwhale_api/providers/youtube/urls.py b/api/funkwhale_api/providers/youtube/urls.py index c496a2c69..d9687ac9f 100644 --- a/api/funkwhale_api/providers/youtube/urls.py +++ b/api/funkwhale_api/providers/youtube/urls.py @@ -1,6 +1,6 @@ -from django.conf.urls import include, url -from .views import APISearch, APISearchs +from django.conf.urls import url +from .views import APISearch, APISearchs urlpatterns = [ url(r"^search/$", APISearch.as_view(), name="search"), diff --git a/api/funkwhale_api/providers/youtube/views.py b/api/funkwhale_api/providers/youtube/views.py index 012b1825d..5e1982f48 100644 --- a/api/funkwhale_api/providers/youtube/views.py +++ b/api/funkwhale_api/providers/youtube/views.py @@ -1,5 +1,6 @@ -from rest_framework.views import APIView from rest_framework.response import Response +from rest_framework.views import APIView + from funkwhale_api.common.permissions import ConditionalAuthentication from .client import client diff --git a/api/funkwhale_api/radios/__init__.py b/api/funkwhale_api/radios/__init__.py index 1258181b5..e69de29bb 100644 --- a/api/funkwhale_api/radios/__init__.py +++ b/api/funkwhale_api/radios/__init__.py @@ -1 +0,0 @@ -from .registries import registry diff --git a/api/funkwhale_api/radios/factories.py b/api/funkwhale_api/radios/factories.py index 69d6ab6e8..a83c53737 100644 --- a/api/funkwhale_api/radios/factories.py +++ b/api/funkwhale_api/radios/factories.py @@ -24,7 +24,7 @@ class RadioSessionFactory(factory.django.DjangoModelFactory): @registry.register(name="radios.CustomRadioSession") -class RadioSessionFactory(factory.django.DjangoModelFactory): +class CustomRadioSessionFactory(factory.django.DjangoModelFactory): user = factory.SubFactory(UserFactory) radio_type = "custom" custom_radio = factory.SubFactory( diff --git a/api/funkwhale_api/radios/filters.py b/api/funkwhale_api/radios/filters.py index cb08e46ed..810673bd6 100644 --- a/api/funkwhale_api/radios/filters.py +++ b/api/funkwhale_api/radios/filters.py @@ -1,13 +1,11 @@ import collections +import persisting_theory from django.core.exceptions import ValidationError from django.db.models import Q from django.urls import reverse_lazy -import persisting_theory - from funkwhale_api.music import models -from funkwhale_api.taskapp.celery import require_instance class RadioFilterRegistry(persisting_theory.Registry): @@ -177,7 +175,6 @@ class TagFilter(RadioFilter): "type": "list", "subtype": "string", "autocomplete": reverse_lazy("api:v1:tags-list"), - "autocomplete_qs": "", "autocomplete_fields": { "remoteValues": "results", "name": "name", diff --git a/api/funkwhale_api/radios/models.py b/api/funkwhale_api/radios/models.py index af0fa26da..d0c3d1716 100644 --- a/api/funkwhale_api/radios/models.py +++ b/api/funkwhale_api/radios/models.py @@ -1,10 +1,9 @@ -from django.db import models -from django.utils import timezone -from django.core.exceptions import ValidationError -from django.contrib.postgres.fields import JSONField from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +from django.contrib.postgres.fields import JSONField from django.core.serializers.json import DjangoJSONEncoder +from django.db import models +from django.utils import timezone from funkwhale_api.music.models import Track @@ -77,7 +76,6 @@ class RadioSession(models.Model): @property def radio(self): from .registries import registry - from . import radios return registry[self.radio_type](session=self) diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py index f876d03b2..c7c361de9 100644 --- a/api/funkwhale_api/radios/radios.py +++ b/api/funkwhale_api/radios/radios.py @@ -1,13 +1,14 @@ import random -from rest_framework import serializers -from django.db.models import Count -from django.core.exceptions import ValidationError -from taggit.models import Tag -from funkwhale_api.users.models import User -from funkwhale_api.music.models import Track, Artist -from . import filters -from . import models +from django.core.exceptions import ValidationError +from django.db.models import Count +from rest_framework import serializers +from taggit.models import Tag + +from funkwhale_api.music.models import Artist, Track +from funkwhale_api.users.models import User + +from . import filters, models from .registries import registry @@ -147,7 +148,7 @@ class TagRadio(RelatedObjectRadio): def get_queryset(self, **kwargs): qs = super().get_queryset(**kwargs) - return Track.objects.filter(tags__in=[self.session.related_object]) + return qs.filter(tags__in=[self.session.related_object]) @registry.register(name="artist") diff --git a/api/funkwhale_api/radios/serializers.py b/api/funkwhale_api/radios/serializers.py index be60bbc3e..9bffbf5b9 100644 --- a/api/funkwhale_api/radios/serializers.py +++ b/api/funkwhale_api/radios/serializers.py @@ -3,8 +3,7 @@ from rest_framework import serializers from funkwhale_api.music.serializers import TrackSerializer from funkwhale_api.users.serializers import UserBasicSerializer -from . import filters -from . import models +from . import filters, models from .radios import registry diff --git a/api/funkwhale_api/radios/urls.py b/api/funkwhale_api/radios/urls.py index 3f48455b0..8b9fd52c8 100644 --- a/api/funkwhale_api/radios/urls.py +++ b/api/funkwhale_api/radios/urls.py @@ -1,8 +1,7 @@ -from django.conf.urls import include, url -from . import views - from rest_framework import routers +from . import views + router = routers.SimpleRouter() router.register(r"sessions", views.RadioSessionViewSet, "sessions") router.register(r"radios", views.RadioViewSet, "radios") diff --git a/api/funkwhale_api/radios/views.py b/api/funkwhale_api/radios/views.py index 1d933a293..77df238e1 100644 --- a/api/funkwhale_api/radios/views.py +++ b/api/funkwhale_api/radios/views.py @@ -1,19 +1,12 @@ from django.db.models import Q from django.http import Http404 - -from rest_framework import generics, mixins, viewsets -from rest_framework import permissions -from rest_framework import status -from rest_framework.response import Response +from rest_framework import mixins, permissions, status, viewsets from rest_framework.decorators import detail_route, list_route +from rest_framework.response import Response from funkwhale_api.music.serializers import TrackSerializer -from funkwhale_api.common.permissions import ConditionalAuthentication -from . import models -from . import filters -from . import filtersets -from . import serializers +from . import filters, filtersets, models, serializers class RadioViewSet( @@ -108,7 +101,7 @@ class RadioSessionTrackViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet) assert request.user == session.user except AssertionError: return Response(status=status.HTTP_403_FORBIDDEN) - track = session.radio.pick() + session.radio.pick() session_track = session.session_tracks.all().latest("id") # self.perform_create(serializer) # dirty override here, since we use a different serializer for creation and detail diff --git a/api/funkwhale_api/requests/api_urls.py b/api/funkwhale_api/requests/api_urls.py index c7c1a103b..403a0953b 100644 --- a/api/funkwhale_api/requests/api_urls.py +++ b/api/funkwhale_api/requests/api_urls.py @@ -1,8 +1,7 @@ -from django.conf.urls import include, url -from . import views - from rest_framework import routers +from . import views + router = routers.SimpleRouter() router.register(r"import-requests", views.ImportRequestViewSet, "import-requests") diff --git a/api/funkwhale_api/requests/filters.py b/api/funkwhale_api/requests/filters.py index ad8b000d2..4a06dea1b 100644 --- a/api/funkwhale_api/requests/filters.py +++ b/api/funkwhale_api/requests/filters.py @@ -1,6 +1,7 @@ import django_filters from funkwhale_api.common import fields + from . import models diff --git a/api/funkwhale_api/requests/models.py b/api/funkwhale_api/requests/models.py index 650d50240..a24086d7a 100644 --- a/api/funkwhale_api/requests/models.py +++ b/api/funkwhale_api/requests/models.py @@ -1,5 +1,4 @@ from django.db import models - from django.utils import timezone NATURE_CHOICES = [("artist", "artist"), ("album", "album"), ("track", "track")] diff --git a/api/funkwhale_api/requests/views.py b/api/funkwhale_api/requests/views.py index 4b68555a8..96d8c8927 100644 --- a/api/funkwhale_api/requests/views.py +++ b/api/funkwhale_api/requests/views.py @@ -1,11 +1,6 @@ -from rest_framework import generics, mixins, viewsets -from rest_framework import status -from rest_framework.response import Response -from rest_framework.decorators import detail_route +from rest_framework import mixins, viewsets -from . import filters -from . import models -from . import serializers +from . import filters, models, serializers class ImportRequestViewSet( diff --git a/api/funkwhale_api/subsonic/authentication.py b/api/funkwhale_api/subsonic/authentication.py index 808e5e5ec..a573a1092 100644 --- a/api/funkwhale_api/subsonic/authentication.py +++ b/api/funkwhale_api/subsonic/authentication.py @@ -1,8 +1,7 @@ import binascii import hashlib -from rest_framework import authentication -from rest_framework import exceptions +from rest_framework import authentication, exceptions from funkwhale_api.users.models import User diff --git a/api/funkwhale_api/subsonic/dynamic_preferences_registry.py b/api/funkwhale_api/subsonic/dynamic_preferences_registry.py index 0916b0a3e..439d16de3 100644 --- a/api/funkwhale_api/subsonic/dynamic_preferences_registry.py +++ b/api/funkwhale_api/subsonic/dynamic_preferences_registry.py @@ -1,8 +1,6 @@ from dynamic_preferences import types from dynamic_preferences.registries import global_preferences_registry -from funkwhale_api.common import preferences - subsonic = types.Section("subsonic") diff --git a/api/funkwhale_api/subsonic/negotiation.py b/api/funkwhale_api/subsonic/negotiation.py index 2b46b1753..96b41589e 100644 --- a/api/funkwhale_api/subsonic/negotiation.py +++ b/api/funkwhale_api/subsonic/negotiation.py @@ -1,9 +1,7 @@ -from rest_framework import exceptions -from rest_framework import negotiation +from rest_framework import exceptions, negotiation from . import renderers - MAPPING = { "json": (renderers.SubsonicJSONRenderer(), "application/json"), "xml": (renderers.SubsonicXMLRenderer(), "text/xml"), @@ -12,7 +10,6 @@ MAPPING = { class SubsonicContentNegociation(negotiation.DefaultContentNegotiation): def select_renderer(self, request, renderers, format_suffix=None): - path = request.path data = request.GET or request.POST requested_format = data.get("f", "xml") try: diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py index 7735b1a78..fc21a99f2 100644 --- a/api/funkwhale_api/subsonic/serializers.py +++ b/api/funkwhale_api/subsonic/serializers.py @@ -1,7 +1,6 @@ import collections -from django.db.models import functions, Count - +from django.db.models import Count, functions from rest_framework import serializers from funkwhale_api.history import models as history_models diff --git a/api/funkwhale_api/subsonic/views.py b/api/funkwhale_api/subsonic/views.py index 85d120a08..7fb5db0ee 100644 --- a/api/funkwhale_api/subsonic/views.py +++ b/api/funkwhale_api/subsonic/views.py @@ -2,12 +2,9 @@ import datetime from django.conf import settings from django.utils import timezone - from rest_framework import exceptions from rest_framework import permissions as rest_permissions -from rest_framework import renderers -from rest_framework import response -from rest_framework import viewsets +from rest_framework import renderers, response, viewsets from rest_framework.decorators import list_route from rest_framework.serializers import ValidationError @@ -19,10 +16,7 @@ from funkwhale_api.music import utils from funkwhale_api.music import views as music_views from funkwhale_api.playlists import models as playlists_models -from . import authentication -from . import filters -from . import negotiation -from . import serializers +from . import authentication, filters, negotiation, serializers def find_object(queryset, model_field="pk", field="id", cast=int): @@ -158,7 +152,6 @@ class SubsonicViewSet(viewsets.GenericViewSet): ) @find_object(music_models.Artist.objects.all()) def get_artist_info2(self, request, *args, **kwargs): - artist = kwargs.pop("obj") payload = {"artist-info2": {}} return response.Response(payload, status=200) @@ -463,6 +456,6 @@ class SubsonicViewSet(viewsets.GenericViewSet): {"error": {"code": 0, "message": "Invalid payload"}} ) if serializer.validated_data["submission"]: - l = serializer.save() - record.send(l) + listening = serializer.save() + record.send(listening) return response.Response({}) diff --git a/api/funkwhale_api/taskapp/celery.py b/api/funkwhale_api/taskapp/celery.py index 80fb1a60e..98e980f07 100644 --- a/api/funkwhale_api/taskapp/celery.py +++ b/api/funkwhale_api/taskapp/celery.py @@ -1,13 +1,13 @@ from __future__ import absolute_import -import os + import functools +import os from celery import Celery from django.apps import AppConfig from django.conf import settings - if not settings.configured: # set the default Django settings module for the 'celery' program. os.environ.setdefault( diff --git a/api/funkwhale_api/users/adapters.py b/api/funkwhale_api/users/adapters.py index 691697570..6d8c365d5 100644 --- a/api/funkwhale_api/users/adapters.py +++ b/api/funkwhale_api/users/adapters.py @@ -1,6 +1,5 @@ -from django.conf import settings - from allauth.account.adapter import DefaultAccountAdapter +from django.conf import settings from dynamic_preferences.registries import global_preferences_registry diff --git a/api/funkwhale_api/users/api_urls.py b/api/funkwhale_api/users/api_urls.py index dacb091f1..267ee2d69 100644 --- a/api/funkwhale_api/users/api_urls.py +++ b/api/funkwhale_api/users/api_urls.py @@ -1,4 +1,5 @@ from rest_framework import routers + from . import views router = routers.SimpleRouter() diff --git a/api/funkwhale_api/users/factories.py b/api/funkwhale_api/users/factories.py index 949bfdfe4..eed8c7175 100644 --- a/api/funkwhale_api/users/factories.py +++ b/api/funkwhale_api/users/factories.py @@ -1,8 +1,8 @@ import factory - -from funkwhale_api.factories import registry, ManyToManyFromList from django.contrib.auth.models import Permission +from funkwhale_api.factories import ManyToManyFromList, registry + @registry.register class GroupFactory(factory.django.DjangoModelFactory): diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py index 281fc4fe8..caf1e452b 100644 --- a/api/funkwhale_api/users/models.py +++ b/api/funkwhale_api/users/models.py @@ -1,19 +1,18 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals, absolute_import +from __future__ import absolute_import, unicode_literals import binascii import os import uuid from django.conf import settings -from django.contrib.auth.models import AbstractUser, Permission -from django.urls import reverse +from django.contrib.auth.models import AbstractUser from django.db import models +from django.urls import reverse from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ -from funkwhale_api.common import fields -from funkwhale_api.common import preferences +from funkwhale_api.common import fields, preferences def get_token(): @@ -91,7 +90,8 @@ class User(AbstractUser): perms[p] = v return perms - def has_permissions(self, *perms, operator="and"): + def has_permissions(self, *perms, **kwargs): + operator = kwargs.pop("operator", "and") if operator not in ["and", "or"]: raise ValueError("Invalid operator {}".format(operator)) permissions = self.get_permissions() diff --git a/api/funkwhale_api/users/rest_auth_urls.py b/api/funkwhale_api/users/rest_auth_urls.py index f5015ecbd..732a3bbbc 100644 --- a/api/funkwhale_api/users/rest_auth_urls.py +++ b/api/funkwhale_api/users/rest_auth_urls.py @@ -1,12 +1,10 @@ -from django.views.generic import TemplateView from django.conf.urls import url - -from rest_auth.registration import views as registration_views +from django.views.generic import TemplateView from rest_auth import views as rest_auth_views +from rest_auth.registration import views as registration_views from . import views - urlpatterns = [ url(r"^$", views.RegisterView.as_view(), name="rest_register"), url( diff --git a/api/funkwhale_api/users/serializers.py b/api/funkwhale_api/users/serializers.py index ab289bc51..b3bd431c7 100644 --- a/api/funkwhale_api/users/serializers.py +++ b/api/funkwhale_api/users/serializers.py @@ -1,7 +1,7 @@ from django.conf import settings - -from rest_framework import serializers from rest_auth.serializers import PasswordResetSerializer as PRS +from rest_framework import serializers + from funkwhale_api.activity import serializers as activity_serializers from . import models diff --git a/api/funkwhale_api/users/views.py b/api/funkwhale_api/users/views.py index dfb71dd05..69e69d26e 100644 --- a/api/funkwhale_api/users/views.py +++ b/api/funkwhale_api/users/views.py @@ -1,15 +1,12 @@ -from rest_framework.response import Response -from rest_framework import mixins -from rest_framework import viewsets -from rest_framework.decorators import detail_route, list_route - -from rest_auth.registration.views import RegisterView as BaseRegisterView from allauth.account.adapter import get_adapter +from rest_auth.registration.views import RegisterView as BaseRegisterView +from rest_framework import mixins, viewsets +from rest_framework.decorators import detail_route, list_route +from rest_framework.response import Response from funkwhale_api.common import preferences -from . import models -from . import serializers +from . import models, serializers class RegisterView(BaseRegisterView): diff --git a/api/requirements/local.txt b/api/requirements/local.txt index c5f2ad0b7..f11f976b8 100644 --- a/api/requirements/local.txt +++ b/api/requirements/local.txt @@ -9,3 +9,4 @@ django-debug-toolbar>=1.9,<1.10 # improved REPL ipdb==0.8.1 +black diff --git a/api/setup.cfg b/api/setup.cfg index b1267c904..18e34bc35 100644 --- a/api/setup.cfg +++ b/api/setup.cfg @@ -1,6 +1,10 @@ [flake8] max-line-length = 120 -exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules +exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,tests/data,tests/music/conftest.py +ignore = F405,W503,E203 + +[isort] +skip_glob = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules [pep8] max-line-length = 120 diff --git a/api/tests/activity/test_record.py b/api/tests/activity/test_record.py index 98cefaba2..69d3a28cf 100644 --- a/api/tests/activity/test_record.py +++ b/api/tests/activity/test_record.py @@ -1,4 +1,3 @@ -import pytest from django.db import models from rest_framework import serializers diff --git a/api/tests/activity/test_utils.py b/api/tests/activity/test_utils.py index b12e3d0cb..0dabd3a28 100644 --- a/api/tests/activity/test_utils.py +++ b/api/tests/activity/test_utils.py @@ -11,9 +11,9 @@ def test_get_activity(factories): def test_get_activity_honors_privacy_level(factories, anonymous_user): - listening = factories["history.Listening"](user__privacy_level="me") + factories["history.Listening"](user__privacy_level="me") favorite1 = factories["favorites.TrackFavorite"](user__privacy_level="everyone") - favorite2 = factories["favorites.TrackFavorite"](user__privacy_level="instance") + factories["favorites.TrackFavorite"](user__privacy_level="instance") objects = list(utils.get_activity(anonymous_user)) assert objects == [favorite1] diff --git a/api/tests/activity/test_views.py b/api/tests/activity/test_views.py index 188039e66..1f5efae51 100644 --- a/api/tests/activity/test_views.py +++ b/api/tests/activity/test_views.py @@ -1,13 +1,12 @@ from django.urls import reverse -from funkwhale_api.activity import serializers -from funkwhale_api.activity import utils +from funkwhale_api.activity import serializers, utils def test_activity_view(factories, api_client, preferences, anonymous_user): preferences["common__api_authentication_required"] = False - favorite = factories["favorites.TrackFavorite"](user__privacy_level="everyone") - listening = factories["history.Listening"]() + factories["favorites.TrackFavorite"](user__privacy_level="everyone") + factories["history.Listening"]() url = reverse("api:v1:activity-list") objects = utils.get_activity(anonymous_user) serializer = serializers.AutoSerializer(objects, many=True) diff --git a/api/tests/channels/test_auth.py b/api/tests/channels/test_auth.py index 19bdebe68..505bef1c0 100644 --- a/api/tests/channels/test_auth.py +++ b/api/tests/channels/test_auth.py @@ -1,5 +1,4 @@ import pytest - from rest_framework_jwt.settings import api_settings from funkwhale_api.common.auth import TokenAuthMiddleware diff --git a/api/tests/common/test_fields.py b/api/tests/common/test_fields.py index bd836f840..d26923148 100644 --- a/api/tests/common/test_fields.py +++ b/api/tests/common/test_fields.py @@ -1,5 +1,4 @@ import pytest - from django.contrib.auth.models import AnonymousUser from django.db.models import Q diff --git a/api/tests/common/test_permissions.py b/api/tests/common/test_permissions.py index 952ec589e..bf4d8bde5 100644 --- a/api/tests/common/test_permissions.py +++ b/api/tests/common/test_permissions.py @@ -1,8 +1,6 @@ import pytest - -from rest_framework.views import APIView - from django.http import Http404 +from rest_framework.views import APIView from funkwhale_api.common import permissions diff --git a/api/tests/common/test_preferences.py b/api/tests/common/test_preferences.py index 5ea398c87..7f941a450 100644 --- a/api/tests/common/test_preferences.py +++ b/api/tests/common/test_preferences.py @@ -1,6 +1,6 @@ import pytest - from dynamic_preferences.registries import global_preferences_registry + from funkwhale_api.common import preferences as common_preferences @@ -26,14 +26,14 @@ def string_list_pref(preferences): ], ) def test_string_list_serializer_to_db(input, output): - s = common_preferences.StringListSerializer.to_db(input) == output + common_preferences.StringListSerializer.to_db(input) == output @pytest.mark.parametrize( "input,output", [("a,b,c", ["a", "b", "c"]), (None, []), ("", [])] ) def test_string_list_serializer_to_python(input, output): - s = common_preferences.StringListSerializer.to_python(input) == output + common_preferences.StringListSerializer.to_python(input) == output def test_string_list_pref_default(string_list_pref, preferences): diff --git a/api/tests/common/test_scripts.py b/api/tests/common/test_scripts.py index afedc3e3a..40d9ea0a7 100644 --- a/api/tests/common/test_scripts.py +++ b/api/tests/common/test_scripts.py @@ -1,7 +1,7 @@ import pytest -from funkwhale_api.common.management.commands import script from funkwhale_api.common import scripts +from funkwhale_api.common.management.commands import script @pytest.fixture diff --git a/api/tests/common/test_serializers.py b/api/tests/common/test_serializers.py index 1bf13b1e0..ca5e5ad8f 100644 --- a/api/tests/common/test_serializers.py +++ b/api/tests/common/test_serializers.py @@ -47,7 +47,7 @@ def test_action_serializer_validates_objects(): def test_action_serializers_objects_clean_ids(factories): user1 = factories["users.User"]() - user2 = factories["users.User"]() + factories["users.User"]() data = {"objects": [user1.pk], "action": "test"} serializer = TestSerializer(data, queryset=models.User.objects.all()) @@ -69,8 +69,8 @@ def test_action_serializers_objects_clean_all(factories): def test_action_serializers_save(factories, mocker): handler = mocker.spy(TestSerializer, "handle_test") - user1 = factories["users.User"]() - user2 = factories["users.User"]() + factories["users.User"]() + factories["users.User"]() data = {"objects": "all", "action": "test"} serializer = TestSerializer(data, queryset=models.User.objects.all()) @@ -82,7 +82,7 @@ def test_action_serializers_save(factories, mocker): def test_action_serializers_filterset(factories): - user1 = factories["users.User"](is_active=False) + factories["users.User"](is_active=False) user2 = factories["users.User"](is_active=True) data = {"objects": "all", "action": "test", "filters": {"is_active": True}} diff --git a/api/tests/common/test_session.py b/api/tests/common/test_session.py index eba26dae0..531543455 100644 --- a/api/tests/common/test_session.py +++ b/api/tests/common/test_session.py @@ -1,5 +1,4 @@ import funkwhale_api - from funkwhale_api.common import session diff --git a/api/tests/conftest.py b/api/tests/conftest.py index 080e1a927..40203ee3d 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -1,23 +1,19 @@ import datetime -import factory -import pytest -import requests_mock import shutil import tempfile +import factory +import pytest +import requests_mock from django.contrib.auth.models import AnonymousUser from django.core.cache import cache as django_cache from django.test import client - from dynamic_preferences.registries import global_preferences_registry - from rest_framework import fields as rest_fields -from rest_framework.test import APIClient -from rest_framework.test import APIRequestFactory +from rest_framework.test import APIClient, APIRequestFactory from funkwhale_api.activity import record from funkwhale_api.users.permissions import HasUserPermission -from funkwhale_api.taskapp import celery @pytest.fixture(scope="session", autouse=True) @@ -186,7 +182,6 @@ def fake_request(): @pytest.fixture def activity_registry(): - r = record.registry state = list(record.registry.items()) yield record.registry record.registry.clear() diff --git a/api/tests/data/youtube.py b/api/tests/data/youtube.py index d3303d2ad..9c8f9e68f 100644 --- a/api/tests/data/youtube.py +++ b/api/tests/data/youtube.py @@ -1,5 +1,3 @@ - - search = {} @@ -13,7 +11,7 @@ search["8 bit adventure"] = { "etag": '"gMxXHe-zinKdE9lTnzKu8vjcmDI/GxK-wHBWUYfrJsd1dijBPTufrVE"', "snippet": { "liveBroadcastContent": "none", - "description": "Make sure to apply adhesive evenly before use. GET IT HERE: http://adhesivewombat.bandcamp.com/album/marsupial-madness Facebook: ...", + "description": "Description", "channelId": "UCps63j3krzAG4OyXeEyuhFw", "title": "AdhesiveWombat - 8 Bit Adventure", "channelTitle": "AdhesiveWombat", diff --git a/api/tests/favorites/test_activity.py b/api/tests/favorites/test_activity.py index a6eff9991..e4c040b20 100644 --- a/api/tests/favorites/test_activity.py +++ b/api/tests/favorites/test_activity.py @@ -1,7 +1,6 @@ -from funkwhale_api.users.serializers import UserActivitySerializer +from funkwhale_api.favorites import activities, serializers from funkwhale_api.music.serializers import TrackActivitySerializer -from funkwhale_api.favorites import serializers -from funkwhale_api.favorites import activities +from funkwhale_api.users.serializers import UserActivitySerializer def test_get_favorite_activity_url(settings, factories): @@ -56,6 +55,5 @@ def test_broadcast_track_favorite_to_instance_activity_private(factories, mocker favorite = factories["favorites.TrackFavorite"](user__privacy_level="me") data = serializers.TrackFavoriteActivitySerializer(favorite).data consumer = activities.broadcast_track_favorite_to_instance_activity - message = {"type": "event.send", "text": "", "data": data} consumer(data=data, obj=favorite) p.assert_not_called() diff --git a/api/tests/favorites/test_favorites.py b/api/tests/favorites/test_favorites.py index 345c24bde..cd75b0d26 100644 --- a/api/tests/favorites/test_favorites.py +++ b/api/tests/favorites/test_favorites.py @@ -1,8 +1,8 @@ import json + import pytest from django.urls import reverse -from funkwhale_api.music.models import Track, Artist from funkwhale_api.favorites.models import TrackFavorite diff --git a/api/tests/federation/test_activity.py b/api/tests/federation/test_activity.py index 8e9000ce0..9c7bb70ec 100644 --- a/api/tests/federation/test_activity.py +++ b/api/tests/federation/test_activity.py @@ -1,7 +1,5 @@ -import uuid -from funkwhale_api.federation import activity -from funkwhale_api.federation import serializers +from funkwhale_api.federation import activity, serializers def test_deliver(factories, r_mock, mocker, settings): diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py index 99c71b348..736ec8bf2 100644 --- a/api/tests/federation/test_actors.py +++ b/api/tests/federation/test_actors.py @@ -1,17 +1,10 @@ import arrow import pytest -import uuid - from django.urls import reverse from django.utils import timezone - from rest_framework import exceptions -from funkwhale_api.federation import activity -from funkwhale_api.federation import actors -from funkwhale_api.federation import models -from funkwhale_api.federation import serializers -from funkwhale_api.federation import utils +from funkwhale_api.federation import actors, models, serializers, utils from funkwhale_api.music import models as music_models from funkwhale_api.music import tasks as music_tasks @@ -55,9 +48,7 @@ def test_get_actor_refresh(factories, preferences, mocker): payload = serializers.ActorSerializer(actor).data # actor changed their username in the meantime payload["preferredUsername"] = "New me" - get_data = mocker.patch( - "funkwhale_api.federation.actors.get_actor_data", return_value=payload - ) + mocker.patch("funkwhale_api.federation.actors.get_actor_data", return_value=payload) new_actor = actors.get_actor(actor.url) assert new_actor == actor @@ -66,7 +57,7 @@ def test_get_actor_refresh(factories, preferences, mocker): def test_get_library(db, settings, mocker): - get_key_pair = mocker.patch( + mocker.patch( "funkwhale_api.federation.keys.get_key_pair", return_value=(b"private", b"public"), ) @@ -99,7 +90,7 @@ def test_get_library(db, settings, mocker): def test_get_test(db, mocker, settings): - get_key_pair = mocker.patch( + mocker.patch( "funkwhale_api.federation.keys.get_key_pair", return_value=(b"private", b"public"), ) @@ -247,7 +238,7 @@ def test_actor_is_system(username, domain, expected, nodb_factories, settings): ("test", "", actors.SYSTEM_ACTORS["test"]), ], ) -def test_actor_is_system(username, domain, expected, nodb_factories, settings): +def test_actor_system_conf(username, domain, expected, nodb_factories, settings): if not domain: domain = settings.FEDERATION_HOSTNAME actor = nodb_factories["federation.Actor"]( @@ -350,7 +341,7 @@ def test_library_actor_handles_follow_manual_approval(preferences, mocker, facto def test_library_actor_handles_follow_auto_approval(preferences, mocker, factories): preferences["federation__music_needs_approval"] = False actor = factories["federation.Actor"]() - accept_follow = mocker.patch("funkwhale_api.federation.activity.accept_follow") + mocker.patch("funkwhale_api.federation.activity.accept_follow") library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() data = { "actor": actor.url, diff --git a/api/tests/federation/test_authentication.py b/api/tests/federation/test_authentication.py index 566a3368d..95cec5d2a 100644 --- a/api/tests/federation/test_authentication.py +++ b/api/tests/federation/test_authentication.py @@ -1,6 +1,4 @@ -from funkwhale_api.federation import authentication -from funkwhale_api.federation import keys -from funkwhale_api.federation import signing +from funkwhale_api.federation import authentication, keys def test_authenticate(factories, mocker, api_request): diff --git a/api/tests/federation/test_library.py b/api/tests/federation/test_library.py index 8b2b18500..4e187e479 100644 --- a/api/tests/federation/test_library.py +++ b/api/tests/federation/test_library.py @@ -1,5 +1,4 @@ -from funkwhale_api.federation import library -from funkwhale_api.federation import serializers +from funkwhale_api.federation import library, serializers def test_library_scan_from_account_name(mocker, factories): diff --git a/api/tests/federation/test_models.py b/api/tests/federation/test_models.py index be353cb67..61d0aea96 100644 --- a/api/tests/federation/test_models.py +++ b/api/tests/federation/test_models.py @@ -1,11 +1,6 @@ import pytest -import uuid - from django import db -from funkwhale_api.federation import models -from funkwhale_api.federation import serializers - def test_cannot_duplicate_actor(factories): actor = factories["federation.Actor"]() diff --git a/api/tests/federation/test_permissions.py b/api/tests/federation/test_permissions.py index 15990ca91..75f76077c 100644 --- a/api/tests/federation/test_permissions.py +++ b/api/tests/federation/test_permissions.py @@ -1,7 +1,6 @@ from rest_framework.views import APIView -from funkwhale_api.federation import actors -from funkwhale_api.federation import permissions +from funkwhale_api.federation import actors, permissions def test_library_follower(factories, api_request, anonymous_user, preferences): diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py index ffcbd441d..e966d1711 100644 --- a/api/tests/federation/test_serializers.py +++ b/api/tests/federation/test_serializers.py @@ -1,14 +1,8 @@ import arrow import pytest - -from django.urls import reverse from django.core.paginator import Paginator -from funkwhale_api.federation import actors -from funkwhale_api.federation import keys -from funkwhale_api.federation import models -from funkwhale_api.federation import serializers -from funkwhale_api.federation import utils +from funkwhale_api.federation import actors, models, serializers, utils def test_actor_serializer_from_ap(db): @@ -168,7 +162,7 @@ def test_follow_serializer_save(factories): actor = factories["federation.Actor"]() target = factories["federation.Actor"]() - data = expected = { + data = { "id": "https://test.follow", "type": "Follow", "actor": actor.url, @@ -191,7 +185,7 @@ def test_follow_serializer_save_validates_on_context(factories): target = factories["federation.Actor"]() impostor = factories["federation.Actor"]() - data = expected = { + data = { "id": "https://test.follow", "type": "Follow", "actor": actor.url, diff --git a/api/tests/federation/test_signing.py b/api/tests/federation/test_signing.py index e88425e8f..159f31cd9 100644 --- a/api/tests/federation/test_signing.py +++ b/api/tests/federation/test_signing.py @@ -1,10 +1,7 @@ import cryptography.exceptions -import io import pytest -import requests_http_signature -from funkwhale_api.federation import signing -from funkwhale_api.federation import keys +from funkwhale_api.federation import keys, signing def test_can_sign_and_verify_request(nodb_factories): diff --git a/api/tests/federation/test_tasks.py b/api/tests/federation/test_tasks.py index f6fafffd6..bc10eae95 100644 --- a/api/tests/federation/test_tasks.py +++ b/api/tests/federation/test_tasks.py @@ -1,13 +1,11 @@ import datetime import os import pathlib -import pytest from django.core.paginator import Paginator from django.utils import timezone -from funkwhale_api.federation import serializers -from funkwhale_api.federation import tasks +from funkwhale_api.federation import serializers, tasks def test_scan_library_does_nothing_if_federation_disabled(mocker, factories): @@ -111,11 +109,11 @@ def test_clean_federation_music_cache_if_no_listen(preferences, factories): lt1 = factories["federation.LibraryTrack"](with_audio_file=True) lt2 = factories["federation.LibraryTrack"](with_audio_file=True) lt3 = factories["federation.LibraryTrack"](with_audio_file=True) - tf1 = factories["music.TrackFile"](accessed_date=timezone.now(), library_track=lt1) - tf2 = factories["music.TrackFile"]( + factories["music.TrackFile"](accessed_date=timezone.now(), library_track=lt1) + factories["music.TrackFile"]( accessed_date=timezone.now() - datetime.timedelta(minutes=61), library_track=lt2 ) - tf3 = factories["music.TrackFile"](accessed_date=None, library_track=lt3) + factories["music.TrackFile"](accessed_date=None, library_track=lt3) path1 = lt1.audio_file.path path2 = lt2.audio_file.path path3 = lt3.audio_file.path @@ -146,7 +144,7 @@ def test_clean_federation_music_cache_orphaned(settings, preferences, factories) lt = factories["federation.LibraryTrack"]( with_audio_file=True, audio_file__path=keep_path ) - tf = factories["music.TrackFile"](library_track=lt, accessed_date=timezone.now()) + factories["music.TrackFile"](library_track=lt, accessed_date=timezone.now()) tasks.clean_music_cache() diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py index 2b0e47cdb..9e2d66a62 100644 --- a/api/tests/federation/test_views.py +++ b/api/tests/federation/test_views.py @@ -1,16 +1,17 @@ +import pytest from django.core.paginator import Paginator from django.urls import reverse from django.utils import timezone -import pytest - -from funkwhale_api.federation import actors -from funkwhale_api.federation import activity -from funkwhale_api.federation import models -from funkwhale_api.federation import serializers -from funkwhale_api.federation import utils -from funkwhale_api.federation import views -from funkwhale_api.federation import webfinger +from funkwhale_api.federation import ( + activity, + actors, + models, + serializers, + utils, + views, + webfinger, +) @pytest.mark.parametrize( @@ -159,8 +160,7 @@ def test_audio_file_list_actor_page_exclude_federated_files( db, preferences, api_client, factories ): preferences["federation__music_needs_approval"] = False - library = actors.SYSTEM_ACTORS["library"].get_actor_instance() - tfs = factories["music.TrackFile"].create_batch(size=5, federation=True) + factories["music.TrackFile"].create_batch(size=5, federation=True) url = reverse("federation:music:files-list") response = api_client.get(url) @@ -188,7 +188,6 @@ def test_audio_file_list_actor_page_error_too_far( def test_library_actor_includes_library_link(db, preferences, api_client): - actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() url = reverse("federation:instance-actors-detail", kwargs={"actor": "library"}) response = api_client.get(url) expected_links = [ @@ -263,7 +262,7 @@ def test_follow_library(superuser_api_client, mocker, factories, r_mock): def test_can_list_system_actor_following(factories, superuser_api_client): library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() follow1 = factories["federation.Follow"](actor=library_actor) - follow2 = factories["federation.Follow"]() + factories["federation.Follow"]() url = reverse("api:v1:federation:libraries-following") response = superuser_api_client.get(url) @@ -274,7 +273,7 @@ def test_can_list_system_actor_following(factories, superuser_api_client): def test_can_list_system_actor_followers(factories, superuser_api_client): library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() - follow1 = factories["federation.Follow"](actor=library_actor) + factories["federation.Follow"](actor=library_actor) follow2 = factories["federation.Follow"](target=library_actor) url = reverse("api:v1:federation:libraries-followers") @@ -384,7 +383,7 @@ def test_can_update_follow_status(factories, superuser_api_client, mocker): def test_can_filter_pending_follows(factories, superuser_api_client): library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() - follow = factories["federation.Follow"](target=library_actor, approved=True) + factories["federation.Follow"](target=library_actor, approved=True) params = {"pending": True} url = reverse("api:v1:federation:libraries-followers") @@ -398,7 +397,7 @@ def test_library_track_action_import(factories, superuser_api_client, mocker): lt1 = factories["federation.LibraryTrack"]() lt2 = factories["federation.LibraryTrack"](library=lt1.library) lt3 = factories["federation.LibraryTrack"]() - lt4 = factories["federation.LibraryTrack"](library=lt3.library) + factories["federation.LibraryTrack"](library=lt3.library) mocked_run = mocker.patch("funkwhale_api.music.tasks.import_batch_run.delay") payload = { diff --git a/api/tests/federation/test_webfinger.py b/api/tests/federation/test_webfinger.py index 1b7db9278..0608df3e2 100644 --- a/api/tests/federation/test_webfinger.py +++ b/api/tests/federation/test_webfinger.py @@ -1,7 +1,5 @@ import pytest - from django import forms -from django.urls import reverse from funkwhale_api.federation import webfinger diff --git a/api/tests/history/test_activity.py b/api/tests/history/test_activity.py index c3cca5925..f3ada5052 100644 --- a/api/tests/history/test_activity.py +++ b/api/tests/history/test_activity.py @@ -1,7 +1,6 @@ -from funkwhale_api.users.serializers import UserActivitySerializer +from funkwhale_api.history import activities, serializers from funkwhale_api.music.serializers import TrackActivitySerializer -from funkwhale_api.history import serializers -from funkwhale_api.history import activities +from funkwhale_api.users.serializers import UserActivitySerializer def test_get_listening_activity_url(settings, factories): @@ -56,6 +55,5 @@ def test_broadcast_listening_to_instance_activity_private(factories, mocker): listening = factories["history.Listening"](user__privacy_level="me") data = serializers.ListeningActivitySerializer(listening).data consumer = activities.broadcast_listening_to_instance_activity - message = {"type": "event.send", "text": "", "data": data} consumer(data=data, obj=listening) p.assert_not_called() diff --git a/api/tests/history/test_history.py b/api/tests/history/test_history.py index 016c2a987..9cc4e3d14 100644 --- a/api/tests/history/test_history.py +++ b/api/tests/history/test_history.py @@ -1,8 +1,4 @@ -import random -import json from django.urls import reverse -from django.core.exceptions import ValidationError -from django.utils import timezone from funkwhale_api.history import models @@ -10,8 +6,7 @@ from funkwhale_api.history import models def test_can_create_listening(factories): track = factories["music.Track"]() user = factories["users.User"]() - now = timezone.now() - l = models.Listening.objects.create(user=user, track=track) + models.Listening.objects.create(user=user, track=track) def test_logged_in_user_can_create_listening_via_api( @@ -20,7 +15,7 @@ def test_logged_in_user_can_create_listening_via_api( track = factories["music.Track"]() url = reverse("api:v1:history:listenings-list") - response = logged_in_client.post(url, {"track": track.pk}) + logged_in_client.post(url, {"track": track.pk}) listening = models.Listening.objects.latest("id") @@ -34,7 +29,7 @@ def test_adding_listening_calls_activity_record( track = factories["music.Track"]() url = reverse("api:v1:history:listenings-list") - response = logged_in_client.post(url, {"track": track.pk}) + logged_in_client.post(url, {"track": track.pk}) listening = models.Listening.objects.latest("id") diff --git a/api/tests/instance/test_nodeinfo.py b/api/tests/instance/test_nodeinfo.py index 3c2fa862e..181ddf277 100644 --- a/api/tests/instance/test_nodeinfo.py +++ b/api/tests/instance/test_nodeinfo.py @@ -1,7 +1,5 @@ -from django.urls import reverse import funkwhale_api - from funkwhale_api.instance import nodeinfo diff --git a/api/tests/instance/test_preferences.py b/api/tests/instance/test_preferences.py index 85932145b..b465be9d3 100644 --- a/api/tests/instance/test_preferences.py +++ b/api/tests/instance/test_preferences.py @@ -1,9 +1,6 @@ import pytest - from django.urls import reverse -from dynamic_preferences.api import serializers - def test_can_list_settings_via_api(preferences, api_client): url = reverse("api:v1:instance:settings") diff --git a/api/tests/instance/test_stats.py b/api/tests/instance/test_stats.py index 9e60d1cdd..1d8bcfc0a 100644 --- a/api/tests/instance/test_stats.py +++ b/api/tests/instance/test_stats.py @@ -1,5 +1,3 @@ -from django.urls import reverse - from funkwhale_api.instance import stats @@ -55,7 +53,7 @@ def test_get(mocker): "listenings", "music_duration", ] - mocks = [ + [ mocker.patch.object(stats, "get_{}".format(k), return_value=i) for i, k in enumerate(keys) ] diff --git a/api/tests/instance/test_views.py b/api/tests/instance/test_views.py index dc9de2a8c..6dd4f6345 100644 --- a/api/tests/instance/test_views.py +++ b/api/tests/instance/test_views.py @@ -1,5 +1,4 @@ import pytest - from django.urls import reverse from funkwhale_api.instance import views @@ -12,9 +11,7 @@ def test_permissions(assert_user_permission, view, permissions): def test_nodeinfo_endpoint(db, api_client, mocker): payload = {"test": "test"} - mocked_nodeinfo = mocker.patch( - "funkwhale_api.instance.nodeinfo.get", return_value=payload - ) + mocker.patch("funkwhale_api.instance.nodeinfo.get", return_value=payload) url = reverse("api:v1:instance:nodeinfo-2.0") response = api_client.get(url) ct = "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8" # noqa diff --git a/api/tests/manage/test_views.py b/api/tests/manage/test_views.py index aa8347f76..e2bfbf3a8 100644 --- a/api/tests/manage/test_views.py +++ b/api/tests/manage/test_views.py @@ -1,9 +1,7 @@ import pytest - from django.urls import reverse -from funkwhale_api.manage import serializers -from funkwhale_api.manage import views +from funkwhale_api.manage import serializers, views @pytest.mark.parametrize( diff --git a/api/tests/music/conftest.py b/api/tests/music/conftest.py index 8108b1a49..0cb6f4778 100644 --- a/api/tests/music/conftest.py +++ b/api/tests/music/conftest.py @@ -1,6 +1,5 @@ import pytest - _artists = {"search": {}, "get": {}} _artists["search"]["adhesive_wombat"] = { @@ -618,7 +617,7 @@ def lyricswiki_content(): - + diff --git a/api/tests/music/test_activity.py b/api/tests/music/test_activity.py index 0d9879300..8c119394d 100644 --- a/api/tests/music/test_activity.py +++ b/api/tests/music/test_activity.py @@ -1,7 +1,3 @@ -from funkwhale_api.users.serializers import UserActivitySerializer -from funkwhale_api.favorites import serializers - - def test_get_track_activity_url_mbid(factories): track = factories["music.Track"]() expected = "https://musicbrainz.org/recording/{}".format(track.mbid) diff --git a/api/tests/music/test_api.py b/api/tests/music/test_api.py index d7d37bd4b..29a712ce6 100644 --- a/api/tests/music/test_api.py +++ b/api/tests/music/test_api.py @@ -1,13 +1,10 @@ import json import os + import pytest from django.urls import reverse -from funkwhale_api.music import models -from funkwhale_api.musicbrainz import api -from funkwhale_api.music import serializers -from funkwhale_api.music import tasks - +from funkwhale_api.music import models, tasks DATA_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -50,7 +47,7 @@ def test_import_creates_an_import_with_correct_data(mocker, superuser_client): mbid = "9968a9d6-8d92-4051-8f76-674e157b6eed" video_id = "tPEE9ZwTmy0" url = reverse("api:v1:submit-single") - response = superuser_client.post( + superuser_client.post( url, { "import_url": "https://www.youtube.com/watch?v={0}".format(video_id), @@ -96,9 +93,7 @@ def test_can_import_whole_album(artists, albums, mocker, superuser_client): ], } url = reverse("api:v1:submit-album") - response = superuser_client.post( - url, json.dumps(payload), content_type="application/json" - ) + superuser_client.post(url, json.dumps(payload), content_type="application/json") batch = models.ImportBatch.objects.latest("id") assert batch.jobs.count() == 3 @@ -156,9 +151,7 @@ def test_can_import_whole_artist(artists, albums, mocker, superuser_client): ], } url = reverse("api:v1:submit-artist") - response = superuser_client.post( - url, json.dumps(payload), content_type="application/json" - ) + superuser_client.post(url, json.dumps(payload), content_type="application/json") batch = models.ImportBatch.objects.latest("id") assert batch.jobs.count() == 3 diff --git a/api/tests/music/test_commands.py b/api/tests/music/test_commands.py index 9f8bad6c2..03a9420dc 100644 --- a/api/tests/music/test_commands.py +++ b/api/tests/music/test_commands.py @@ -49,7 +49,6 @@ def test_fix_track_files_size(factories, mocker): def test_fix_track_files_mimetype(factories, mocker): - name = "test.mp3" mp3_path = os.path.join(DATA_DIR, "test.mp3") ogg_path = os.path.join(DATA_DIR, "test.ogg") tf1 = factories["music.TrackFile"]( diff --git a/api/tests/music/test_import.py b/api/tests/music/test_import.py index 9ea8c4ec8..2be267cff 100644 --- a/api/tests/music/test_import.py +++ b/api/tests/music/test_import.py @@ -1,6 +1,5 @@ import json import os -import pytest from django.urls import reverse @@ -36,9 +35,7 @@ def test_create_import_can_bind_to_request( ], } url = reverse("api:v1:submit-album") - response = superuser_api_client.post( - url, json.dumps(payload), content_type="application/json" - ) + superuser_api_client.post(url, json.dumps(payload), content_type="application/json") batch = request.import_batches.latest("id") assert batch.import_request == request @@ -161,7 +158,7 @@ def test_import_job_run_triggers_notifies_followers(factories, mocker, tmpfile): ) batch = factories["music.ImportBatch"]() job = factories["music.ImportJob"](finished=True, batch=batch) - track = factories["music.Track"](mbid=job.mbid) + factories["music.Track"](mbid=job.mbid) batch.update_status() batch.refresh_from_db() @@ -194,14 +191,14 @@ def test_import_batch_notifies_followers(factories, mocker): library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() f1 = factories["federation.Follow"](approved=True, target=library_actor) - f2 = factories["federation.Follow"](approved=False, target=library_actor) - f3 = factories["federation.Follow"]() + factories["federation.Follow"](approved=False, target=library_actor) + factories["federation.Follow"]() mocked_deliver = mocker.patch("funkwhale_api.federation.activity.deliver") batch = factories["music.ImportBatch"]() job1 = factories["music.ImportJob"](finished=True, batch=batch) - job2 = factories["music.ImportJob"](finished=True, federation=True, batch=batch) - job3 = factories["music.ImportJob"](status="pending", batch=batch) + factories["music.ImportJob"](finished=True, federation=True, batch=batch) + factories["music.ImportJob"](status="pending", batch=batch) batch.status = "finished" batch.save() @@ -234,7 +231,7 @@ def test__do_import_in_place_mbid(factories, tmpfile): path = os.path.join(DATA_DIR, "test.ogg") job = factories["music.ImportJob"](in_place=True, source="file://{}".format(path)) - track = factories["music.Track"](mbid=job.mbid) + factories["music.Track"](mbid=job.mbid) tf = tasks._do_import(job, use_acoustid=False) assert bool(tf.audio_file) is False diff --git a/api/tests/music/test_lyrics.py b/api/tests/music/test_lyrics.py index c15e30637..c8ce92b6a 100644 --- a/api/tests/music/test_lyrics.py +++ b/api/tests/music/test_lyrics.py @@ -1,14 +1,10 @@ -import json from django.urls import reverse -from funkwhale_api.music import models -from funkwhale_api.musicbrainz import api -from funkwhale_api.music import serializers -from funkwhale_api.music import tasks from funkwhale_api.music import lyrics as lyrics_utils +from funkwhale_api.music import models, tasks -def test_works_import_lyrics_if_any(lyricswiki_content, mocker, factories): +def test_lyrics_tasks(lyricswiki_content, mocker, factories): mocker.patch( "funkwhale_api.music.lyrics._get_html", return_value=lyricswiki_content ) @@ -18,7 +14,7 @@ def test_works_import_lyrics_if_any(lyricswiki_content, mocker, factories): tasks.fetch_content(lyrics_id=lyrics.pk) lyrics.refresh_from_db() - self.assertIn("Grab a brush and put on a little makeup", lyrics.content) + assert "Grab a brush and put on a little makeup" in lyrics.content def test_clean_content(): @@ -36,10 +32,10 @@ def test_markdown_rendering(factories): content = """Hello Is it me you're looking for?""" - l = factories["music.Lyrics"](content=content) + lyrics = factories["music.Lyrics"](content=content) expected = "

Hello
\nIs it me you're looking for?

" - assert expected == l.content_rendered + assert expected == lyrics.content_rendered def test_works_import_lyrics_if_any( diff --git a/api/tests/music/test_metadata.py b/api/tests/music/test_metadata.py index f1e03ad12..fbdf5b81f 100644 --- a/api/tests/music/test_metadata.py +++ b/api/tests/music/test_metadata.py @@ -1,8 +1,9 @@ import datetime import os -import pytest import uuid +import pytest + from funkwhale_api.music import metadata DATA_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/api/tests/music/test_models.py b/api/tests/music/test_models.py index f81dd433f..df18a0909 100644 --- a/api/tests/music/test_models.py +++ b/api/tests/music/test_models.py @@ -1,9 +1,8 @@ import os + import pytest -from funkwhale_api.music import models -from funkwhale_api.music import importers -from funkwhale_api.music import tasks +from funkwhale_api.music import importers, models, tasks DATA_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -105,7 +104,7 @@ def test_saving_job_updates_batch_status(status, factories, mocker): assert batch.status == "pending" - job = factories["music.ImportJob"](batch=batch, status=status) + factories["music.ImportJob"](batch=batch, status=status) batch.refresh_from_db() diff --git a/api/tests/music/test_music.py b/api/tests/music/test_music.py index 391af26cb..387cebb2c 100644 --- a/api/tests/music/test_music.py +++ b/api/tests/music/test_music.py @@ -1,7 +1,9 @@ -import pytest -from funkwhale_api.music import models import datetime +import pytest + +from funkwhale_api.music import models + def test_can_create_artist_from_api(artists, mocker, db): mocker.patch( @@ -118,7 +120,7 @@ def test_can_get_or_create_track_from_api(artists, albums, tracks, mocker, db): def test_album_tags_deduced_from_tracks_tags(factories, django_assert_num_queries): tag = factories["taggit.Tag"]() album = factories["music.Album"]() - tracks = factories["music.Track"].create_batch(5, album=album, tags=[tag]) + factories["music.Track"].create_batch(5, album=album, tags=[tag]) album = models.Album.objects.prefetch_related("tracks__tags").get(pk=album.pk) @@ -130,7 +132,7 @@ def test_artist_tags_deduced_from_album_tags(factories, django_assert_num_querie tag = factories["taggit.Tag"]() album = factories["music.Album"]() artist = album.artist - tracks = factories["music.Track"].create_batch(5, album=album, tags=[tag]) + factories["music.Track"].create_batch(5, album=album, tags=[tag]) artist = models.Artist.objects.prefetch_related("albums__tracks__tags").get( pk=artist.pk diff --git a/api/tests/music/test_serializers.py b/api/tests/music/test_serializers.py index 9402e1459..51ca96b5d 100644 --- a/api/tests/music/test_serializers.py +++ b/api/tests/music/test_serializers.py @@ -63,7 +63,6 @@ def test_track_file_serializer(factories, to_api_date): "path": tf.path, "source": tf.source, "filename": tf.filename, - "mimetype": tf.mimetype, "track": tf.track.pk, "duration": tf.duration, "mimetype": tf.mimetype, diff --git a/api/tests/music/test_tasks.py b/api/tests/music/test_tasks.py index 1d35e75e2..71d605b2b 100644 --- a/api/tests/music/test_tasks.py +++ b/api/tests/music/test_tasks.py @@ -1,7 +1,7 @@ import os + import pytest -from funkwhale_api.providers.acoustid import get_acoustid_client from funkwhale_api.music import tasks DATA_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -44,10 +44,9 @@ def test_set_acoustid_on_track_file(factories, mocker, preferences): def test_set_acoustid_on_track_file_required_high_score(factories, mocker): track_file = factories["music.TrackFile"](acoustid_track_id=None) - id = "e475bf79-c1ce-4441-bed7-1e33f226c0a2" payload = {"results": [{"score": 0.79}], "status": "ok"} - m = mocker.patch("acoustid.match", return_value=payload) - r = tasks.set_acoustid_on_track_file(track_file_id=track_file.pk) + mocker.patch("acoustid.match", return_value=payload) + tasks.set_acoustid_on_track_file(track_file_id=track_file.pk) track_file.refresh_from_db() assert track_file.acoustid_track_id is None @@ -159,7 +158,6 @@ def test_import_job_skip_if_already_exists(artists, albums, tracks, factories, m ) job = factories["music.FileImportJob"](audio_file__path=path) - f = job.audio_file tasks.import_job_run(import_job_id=job.pk) job.refresh_from_db() @@ -172,7 +170,7 @@ def test_import_job_skip_if_already_exists(artists, albums, tracks, factories, m def test_import_job_can_be_errored(factories, mocker, preferences): path = os.path.join(DATA_DIR, "test.ogg") mbid = "9968a9d6-8d92-4051-8f76-674e157b6eed" - track_file = factories["music.TrackFile"](track__mbid=mbid) + factories["music.TrackFile"](track__mbid=mbid) class MyException(Exception): pass @@ -219,7 +217,6 @@ def test_update_album_cover_mbid(factories, mocker): def test_update_album_cover_file_data(factories, mocker): - path = os.path.join(DATA_DIR, "test.mp3") album = factories["music.Album"](cover="", mbid=None) tf = factories["music.TrackFile"](track__album=album) @@ -229,14 +226,13 @@ def test_update_album_cover_file_data(factories, mocker): return_value={"hello": "world"}, ) tasks.update_album_cover(album=album, track_file=tf) - md = data = tf.get_metadata() + tf.get_metadata() mocked_get.assert_called_once_with(data={"hello": "world"}) @pytest.mark.parametrize("ext,mimetype", [("jpg", "image/jpeg"), ("png", "image/png")]) def test_update_album_cover_file_cover_separate_file(ext, mimetype, factories, mocker): mocker.patch("funkwhale_api.music.tasks.IMAGE_TYPES", [(ext, mimetype)]) - path = os.path.join(DATA_DIR, "test.mp3") image_path = os.path.join(DATA_DIR, "cover.{}".format(ext)) with open(image_path, "rb") as f: image_content = f.read() @@ -246,7 +242,7 @@ def test_update_album_cover_file_cover_separate_file(ext, mimetype, factories, m mocked_get = mocker.patch("funkwhale_api.music.models.Album.get_image") mocker.patch("funkwhale_api.music.metadata.Metadata.get_picture", return_value=None) tasks.update_album_cover(album=album, track_file=tf) - md = data = tf.get_metadata() + tf.get_metadata() mocked_get.assert_called_once_with( data={"mimetype": mimetype, "content": image_content} ) diff --git a/api/tests/music/test_utils.py b/api/tests/music/test_utils.py index 276a450d4..4019e47b4 100644 --- a/api/tests/music/test_utils.py +++ b/api/tests/music/test_utils.py @@ -1,4 +1,5 @@ import os + import pytest from funkwhale_api.music import utils diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 139a33cf5..aa04521cb 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -1,12 +1,11 @@ import io -import pytest +import pytest from django.urls import reverse from django.utils import timezone -from funkwhale_api.music import serializers -from funkwhale_api.music import views from funkwhale_api.federation import actors +from funkwhale_api.music import serializers, views @pytest.mark.parametrize( @@ -106,7 +105,7 @@ def test_can_serve_track_file_as_remote_library( ): preferences["common__api_authentication_required"] = True library_actor = actors.SYSTEM_ACTORS["library"].get_actor_instance() - follow = factories["federation.Follow"]( + factories["federation.Follow"]( approved=True, actor=authenticated_actor, target=library_actor ) @@ -246,8 +245,8 @@ def test_can_list_import_jobs(factories, superuser_api_client): def test_import_job_stats(factories, superuser_api_client): - job1 = factories["music.ImportJob"](status="pending") - job2 = factories["music.ImportJob"](status="errored") + factories["music.ImportJob"](status="pending") + factories["music.ImportJob"](status="errored") url = reverse("api:v1:import-jobs-stats") response = superuser_api_client.get(url) @@ -258,7 +257,7 @@ def test_import_job_stats(factories, superuser_api_client): def test_import_job_stats_filter(factories, superuser_api_client): job1 = factories["music.ImportJob"](status="pending") - job2 = factories["music.ImportJob"](status="errored") + factories["music.ImportJob"](status="errored") url = reverse("api:v1:import-jobs-stats") response = superuser_api_client.get(url, {"batch": job1.batch.pk}) @@ -334,7 +333,7 @@ def test_import_job_viewset_get_queryset_upload_filters_user( logged_in_api_client.user.permission_upload = True logged_in_api_client.user.save() - job = factories["music.ImportJob"]() + factories["music.ImportJob"]() url = reverse("api:v1:import-jobs-list") response = logged_in_api_client.get(url) @@ -347,7 +346,7 @@ def test_import_batch_viewset_get_queryset_upload_filters_user( logged_in_api_client.user.permission_upload = True logged_in_api_client.user.save() - job = factories["music.ImportBatch"]() + factories["music.ImportBatch"]() url = reverse("api:v1:import-batches-list") response = logged_in_api_client.get(url) diff --git a/api/tests/music/test_works.py b/api/tests/music/test_works.py index 6b2e57fdc..96b537ca2 100644 --- a/api/tests/music/test_works.py +++ b/api/tests/music/test_works.py @@ -1,9 +1,4 @@ -import json -from django.urls import reverse - from funkwhale_api.music import models -from funkwhale_api.musicbrainz import api -from funkwhale_api.music import serializers def test_can_import_work(factories, mocker, works): @@ -40,7 +35,7 @@ def test_can_get_work_from_recording(factories, mocker, works, tracks): ) mbid = "e2ecabc4-1b9d-30b2-8f30-3596ec423dc5" - assert recording.work == None + assert recording.work is None work = recording.get_work() diff --git a/api/tests/musicbrainz/test_api.py b/api/tests/musicbrainz/test_api.py index de84813f1..0fdaf7ab6 100644 --- a/api/tests/musicbrainz/test_api.py +++ b/api/tests/musicbrainz/test_api.py @@ -1,8 +1,5 @@ -import json from django.urls import reverse -from funkwhale_api.musicbrainz import api - def test_can_search_recording_in_musicbrainz_api( recordings, db, mocker, logged_in_api_client diff --git a/api/tests/playlists/test_models.py b/api/tests/playlists/test_models.py index 3258e6d10..25c40d557 100644 --- a/api/tests/playlists/test_models.py +++ b/api/tests/playlists/test_models.py @@ -1,5 +1,4 @@ import pytest - from rest_framework import exceptions @@ -107,7 +106,7 @@ def test_remove_update_indexes(factories): def test_can_insert_many(factories): playlist = factories["playlists.Playlist"]() - existing = factories["playlists.PlaylistTrack"](playlist=playlist, index=0) + factories["playlists.PlaylistTrack"](playlist=playlist, index=0) tracks = factories["music.Track"].create_batch(size=3) plts = playlist.insert_many(tracks) for i, plt in enumerate(plts): @@ -119,7 +118,7 @@ def test_can_insert_many(factories): def test_insert_many_honor_max_tracks(preferences, factories): preferences["playlists__max_tracks"] = 4 playlist = factories["playlists.Playlist"]() - plts = factories["playlists.PlaylistTrack"].create_batch(size=2, playlist=playlist) + factories["playlists.PlaylistTrack"].create_batch(size=2, playlist=playlist) track = factories["music.Track"]() with pytest.raises(exceptions.ValidationError): playlist.insert_many([track, track, track]) diff --git a/api/tests/playlists/test_serializers.py b/api/tests/playlists/test_serializers.py index 05e5bd7ca..677288070 100644 --- a/api/tests/playlists/test_serializers.py +++ b/api/tests/playlists/test_serializers.py @@ -1,11 +1,10 @@ -from funkwhale_api.playlists import models -from funkwhale_api.playlists import serializers +from funkwhale_api.playlists import models, serializers def test_cannot_max_500_tracks_per_playlist(factories, preferences): preferences["playlists__max_tracks"] = 2 playlist = factories["playlists.Playlist"]() - plts = factories["playlists.PlaylistTrack"].create_batch(size=2, playlist=playlist) + factories["playlists.PlaylistTrack"].create_batch(size=2, playlist=playlist) track = factories["music.Track"]() serializer = serializers.PlaylistTrackWriteSerializer( data={"playlist": playlist.pk, "track": track.pk} @@ -53,7 +52,7 @@ def test_update_insert_is_called_when_index_is_provided(factories, mocker): second = factories["playlists.PlaylistTrack"](playlist=playlist, index=1) insert = mocker.spy(models.Playlist, "insert") factories["playlists.Playlist"]() - track = factories["music.Track"]() + factories["music.Track"]() serializer = serializers.PlaylistTrackWriteSerializer( second, data={"playlist": playlist.pk, "track": second.track.pk, "index": 0} ) diff --git a/api/tests/playlists/test_views.py b/api/tests/playlists/test_views.py index 7835a7258..e7b47c7a2 100644 --- a/api/tests/playlists/test_views.py +++ b/api/tests/playlists/test_views.py @@ -1,19 +1,14 @@ -import json import pytest - from django.urls import reverse -from django.core.exceptions import ValidationError -from django.utils import timezone -from funkwhale_api.playlists import models -from funkwhale_api.playlists import serializers +from funkwhale_api.playlists import models, serializers def test_can_create_playlist_via_api(logged_in_api_client): url = reverse("api:v1:playlists-list") data = {"name": "test", "privacy_level": "everyone"} - response = logged_in_api_client.post(url, data) + logged_in_api_client.post(url, data) playlist = logged_in_api_client.user.playlists.latest("id") assert playlist.name == "test" @@ -22,7 +17,7 @@ def test_can_create_playlist_via_api(logged_in_api_client): def test_serializer_includes_tracks_count(factories, logged_in_api_client): playlist = factories["playlists.Playlist"]() - plt = factories["playlists.PlaylistTrack"](playlist=playlist) + factories["playlists.PlaylistTrack"](playlist=playlist) url = reverse("api:v1:playlists-detail", kwargs={"pk": playlist.pk}) response = logged_in_api_client.get(url) @@ -38,7 +33,7 @@ def test_playlist_inherits_user_privacy(logged_in_api_client): data = {"name": "test"} - response = logged_in_api_client.post(url, data) + logged_in_api_client.post(url, data) playlist = user.playlists.latest("id") assert playlist.privacy_level == user.privacy_level @@ -80,7 +75,7 @@ def test_only_can_add_track_on_own_playlist_via_api(factories, logged_in_api_cli def test_deleting_plt_updates_indexes(mocker, factories, logged_in_api_client): remove = mocker.spy(models.Playlist, "remove") - track = factories["music.Track"]() + factories["music.Track"]() plt = factories["playlists.PlaylistTrack"]( index=0, playlist__user=logged_in_api_client.user ) @@ -165,7 +160,7 @@ def test_can_add_multiple_tracks_at_once_via_api( def test_can_clear_playlist_from_api(factories, mocker, logged_in_api_client): playlist = factories["playlists.Playlist"](user=logged_in_api_client.user) - plts = factories["playlists.PlaylistTrack"].create_batch(size=5, playlist=playlist) + factories["playlists.PlaylistTrack"].create_batch(size=5, playlist=playlist) url = reverse("api:v1:playlists-clear", kwargs={"pk": playlist.pk}) response = logged_in_api_client.delete(url) @@ -175,7 +170,7 @@ def test_can_clear_playlist_from_api(factories, mocker, logged_in_api_client): def test_update_playlist_from_api(factories, mocker, logged_in_api_client): playlist = factories["playlists.Playlist"](user=logged_in_api_client.user) - plts = factories["playlists.PlaylistTrack"].create_batch(size=5, playlist=playlist) + factories["playlists.PlaylistTrack"].create_batch(size=5, playlist=playlist) url = reverse("api:v1:playlists-detail", kwargs={"pk": playlist.pk}) response = logged_in_api_client.patch(url, {"name": "test"}) playlist.refresh_from_db() diff --git a/api/tests/radios/test_api.py b/api/tests/radios/test_api.py index 4a72d81ba..5f542c880 100644 --- a/api/tests/radios/test_api.py +++ b/api/tests/radios/test_api.py @@ -1,11 +1,9 @@ import json -import pytest from django.urls import reverse from funkwhale_api.music.serializers import TrackSerializer -from funkwhale_api.radios import filters -from funkwhale_api.radios import serializers +from funkwhale_api.radios import filters, serializers def test_can_list_config_options(logged_in_client): diff --git a/api/tests/radios/test_filters.py b/api/tests/radios/test_filters.py index 025fc7a63..89bb726af 100644 --- a/api/tests/radios/test_filters.py +++ b/api/tests/radios/test_filters.py @@ -1,5 +1,4 @@ import pytest - from django.core.exceptions import ValidationError from funkwhale_api.music.models import Track @@ -15,7 +14,7 @@ class NoopFilter(filters.RadioFilter): def test_most_simple_radio_does_not_filter_anything(factories): - tracks = factories["music.Track"].create_batch(3) + factories["music.Track"].create_batch(3) radio = factories["radios.Radio"](config=[{"type": "noop"}]) assert radio.version == 0 diff --git a/api/tests/radios/test_radios.py b/api/tests/radios/test_radios.py index ebc45f1f9..e218ced90 100644 --- a/api/tests/radios/test_radios.py +++ b/api/tests/radios/test_radios.py @@ -1,15 +1,12 @@ import json import random + import pytest - -from django.urls import reverse from django.core.exceptions import ValidationError +from django.urls import reverse - -from funkwhale_api.radios import radios -from funkwhale_api.radios import models -from funkwhale_api.radios import serializers from funkwhale_api.favorites.models import TrackFavorite +from funkwhale_api.radios import models, radios, serializers def test_can_pick_track_from_choices(): @@ -74,8 +71,7 @@ def test_can_get_choices_for_custom_radio(factories): artist = factories["music.Artist"]() files = factories["music.TrackFile"].create_batch(5, track__artist=artist) tracks = [f.track for f in files] - wrong_files = factories["music.TrackFile"].create_batch(5) - wrong_tracks = [f.track for f in wrong_files] + factories["music.TrackFile"].create_batch(5) session = factories["radios.CustomRadioSession"]( custom_radio__config=[{"type": "artist", "ids": [artist.pk]}] @@ -114,14 +110,13 @@ def test_can_start_custom_radio_from_api(logged_in_client, factories): def test_can_use_radio_session_to_filter_choices(factories): - files = factories["music.TrackFile"].create_batch(30) - tracks = [f.track for f in files] + factories["music.TrackFile"].create_batch(30) user = factories["users.User"]() radio = radios.RandomRadio() session = radio.start_session(user) for i in range(30): - p = radio.pick() + radio.pick() # ensure 30 differents tracks have been suggested tracks_id = [ @@ -141,7 +136,7 @@ def test_can_restore_radio_from_previous_session(factories): def test_can_start_radio_for_logged_in_user(logged_in_client): url = reverse("api:v1:radios:sessions-list") - response = logged_in_client.post(url, {"radio_type": "random"}) + logged_in_client.post(url, {"radio_type": "random"}) session = models.RadioSession.objects.latest("id") assert session.radio_type == "random" assert session.user == logged_in_client.user @@ -185,8 +180,7 @@ def test_related_object_radio_validate_related_object(factories): def test_can_start_artist_radio(factories): user = factories["users.User"]() artist = factories["music.Artist"]() - wrong_files = factories["music.TrackFile"].create_batch(5) - wrong_tracks = [f.track for f in wrong_files] + factories["music.TrackFile"].create_batch(5) good_files = factories["music.TrackFile"].create_batch(5, track__artist=artist) good_tracks = [f.track for f in good_files] @@ -200,8 +194,7 @@ def test_can_start_artist_radio(factories): def test_can_start_tag_radio(factories): user = factories["users.User"]() tag = factories["taggit.Tag"]() - wrong_files = factories["music.TrackFile"].create_batch(5) - wrong_tracks = [f.track for f in wrong_files] + factories["music.TrackFile"].create_batch(5) good_files = factories["music.TrackFile"].create_batch(5, track__tags=[tag]) good_tracks = [f.track for f in good_files] @@ -236,7 +229,7 @@ def test_can_start_less_listened_radio(factories): good_files = factories["music.TrackFile"].create_batch(5) good_tracks = [f.track for f in good_files] radio = radios.LessListenedRadio() - session = radio.start_session(user) + radio.start_session(user) for i in range(5): assert radio.pick() in good_tracks diff --git a/api/tests/requests/test_models.py b/api/tests/requests/test_models.py index d6b71635a..3ac8a5342 100644 --- a/api/tests/requests/test_models.py +++ b/api/tests/requests/test_models.py @@ -1,8 +1,3 @@ -import pytest - -from django.forms import ValidationError - - def test_can_bind_import_batch_to_request(factories): request = factories["requests.ImportRequest"]() diff --git a/api/tests/subsonic/test_authentication.py b/api/tests/subsonic/test_authentication.py index f404c8b0a..b2d2c0400 100644 --- a/api/tests/subsonic/test_authentication.py +++ b/api/tests/subsonic/test_authentication.py @@ -1,6 +1,6 @@ import binascii -import pytest +import pytest from rest_framework import exceptions from funkwhale_api.subsonic import authentication @@ -21,11 +21,9 @@ def test_auth_with_salt(api_request, factories): def test_auth_with_password_hex(api_request, factories): - salt = "salt" user = factories["users.User"]() user.subsonic_api_token = "password" user.save() - token = authentication.get_token(salt, "password") request = api_request.get( "/", { @@ -45,11 +43,9 @@ def test_auth_with_password_hex(api_request, factories): def test_auth_with_password_cleartext(api_request, factories): - salt = "salt" user = factories["users.User"]() user.subsonic_api_token = "password" user.save() - token = authentication.get_token(salt, "password") request = api_request.get("/", {"u": user.username, "p": "password"}) authenticator = authentication.SubsonicAuthentication() @@ -59,11 +55,9 @@ def test_auth_with_password_cleartext(api_request, factories): def test_auth_with_inactive_users(api_request, factories): - salt = "salt" user = factories["users.User"](is_active=False) user.subsonic_api_token = "password" user.save() - token = authentication.get_token(salt, "password") request = api_request.get("/", {"u": user.username, "p": "password"}) authenticator = authentication.SubsonicAuthentication() diff --git a/api/tests/subsonic/test_renderers.py b/api/tests/subsonic/test_renderers.py index 65dae6f22..301fee8b5 100644 --- a/api/tests/subsonic/test_renderers.py +++ b/api/tests/subsonic/test_renderers.py @@ -24,7 +24,7 @@ def test_xml_renderer_dict_to_xml(): def test_xml_renderer(): payload = {"hello": "world"} - expected = b'\n' + expected = b'\n' # noqa renderer = renderers.SubsonicXMLRenderer() rendered = renderer.render(payload) diff --git a/api/tests/subsonic/test_views.py b/api/tests/subsonic/test_views.py index d06bf5525..1523a2f62 100644 --- a/api/tests/subsonic/test_views.py +++ b/api/tests/subsonic/test_views.py @@ -1,16 +1,13 @@ import datetime import json + import pytest - -from django.utils import timezone from django.urls import reverse - -from rest_framework.response import Response +from django.utils import timezone from funkwhale_api.music import models as music_models from funkwhale_api.music import views as music_views -from funkwhale_api.subsonic import renderers -from funkwhale_api.subsonic import serializers +from funkwhale_api.subsonic import renderers, serializers def render_json(data): @@ -80,7 +77,7 @@ def test_ping(f, db, api_client): def test_get_artists(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-get-artists") assert url.endswith("getArtists") is True - artists = factories["music.Artist"].create_batch(size=10) + factories["music.Artist"].create_batch(size=10) expected = { "artists": serializers.GetArtistsSerializer( music_models.Artist.objects.all() @@ -97,7 +94,7 @@ def test_get_artist(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-get-artist") assert url.endswith("getArtist") is True artist = factories["music.Artist"]() - albums = factories["music.Album"].create_batch(size=3, artist=artist) + factories["music.Album"].create_batch(size=3, artist=artist) expected = {"artist": serializers.GetArtistSerializer(artist).data} response = logged_in_api_client.get(url, {"id": artist.pk}) @@ -124,7 +121,7 @@ def test_get_album(f, db, logged_in_api_client, factories): assert url.endswith("getAlbum") is True artist = factories["music.Artist"]() album = factories["music.Album"](artist=artist) - tracks = factories["music.Track"].create_batch(size=3, album=album) + factories["music.Track"].create_batch(size=3, album=album) expected = {"album": serializers.GetAlbumSerializer(album).data} response = logged_in_api_client.get(url, {"f": f, "id": album.pk}) @@ -166,9 +163,7 @@ def test_unstar(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-unstar") assert url.endswith("unstar") is True track = factories["music.Track"]() - favorite = factories["favorites.TrackFavorite"]( - track=track, user=logged_in_api_client.user - ) + factories["favorites.TrackFavorite"](track=track, user=logged_in_api_client.user) response = logged_in_api_client.get(url, {"f": f, "id": track.pk}) assert response.status_code == 200 @@ -283,7 +278,7 @@ def test_update_playlist(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-update-playlist") assert url.endswith("updatePlaylist") is True playlist = factories["playlists.Playlist"](user=logged_in_api_client.user) - plt = factories["playlists.PlaylistTrack"](index=0, playlist=playlist) + factories["playlists.PlaylistTrack"](index=0, playlist=playlist) new_track = factories["music.Track"]() response = logged_in_api_client.get( url, @@ -350,7 +345,7 @@ def test_get_music_folders(f, db, logged_in_api_client, factories): def test_get_indexes(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-get-indexes") assert url.endswith("getIndexes") is True - artists = factories["music.Artist"].create_batch(size=10) + factories["music.Artist"].create_batch(size=10) expected = { "indexes": serializers.GetArtistsSerializer( music_models.Artist.objects.all() @@ -384,5 +379,5 @@ def test_scrobble(factories, logged_in_api_client): assert response.status_code == 200 - l = logged_in_api_client.user.listenings.latest("id") - assert l.track == track + listening = logged_in_api_client.user.listenings.latest("id") + assert listening.track == track diff --git a/api/tests/test_import_audio_file.py b/api/tests/test_import_audio_file.py index 4346a4777..67f6c489d 100644 --- a/api/tests/test_import_audio_file.py +++ b/api/tests/test_import_audio_file.py @@ -1,13 +1,11 @@ -import pytest import datetime import os -import uuid +import pytest from django.core.management import call_command from django.core.management.base import CommandError from funkwhale_api.providers.audiofile import tasks -from funkwhale_api.music import tasks as music_tasks DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files") @@ -20,8 +18,8 @@ def test_can_create_track_from_file_metadata_no_mbid(db, mocker): "TRACKNUMBER": ["4"], "date": ["2012-08-15"], } - m1 = mocker.patch("mutagen.File", return_value=metadata) - m2 = mocker.patch( + mocker.patch("mutagen.File", return_value=metadata) + mocker.patch( "funkwhale_api.music.metadata.Metadata.get_file_type", return_value="OggVorbis" ) track = tasks.import_track_data_from_path(os.path.join(DATA_DIR, "dummy_file.ogg")) @@ -70,8 +68,8 @@ def test_can_create_track_from_file_metadata_mbid(factories, mocker): "musicbrainz_albumid": [album.mbid], "musicbrainz_trackid": [track_data["recording"]["id"]], } - m1 = mocker.patch("mutagen.File", return_value=metadata) - m2 = mocker.patch( + mocker.patch("mutagen.File", return_value=metadata) + mocker.patch( "funkwhale_api.music.metadata.Metadata.get_file_type", return_value="OggVorbis" ) track = tasks.import_track_data_from_path(os.path.join(DATA_DIR, "dummy_file.ogg")) @@ -85,7 +83,7 @@ def test_can_create_track_from_file_metadata_mbid(factories, mocker): def test_management_command_requires_a_valid_username(factories, mocker): path = os.path.join(DATA_DIR, "dummy_file.ogg") - user = factories["users.User"](username="me") + factories["users.User"](username="me") mocker.patch( "funkwhale_api.providers.audiofile.management.commands.import_files.Command.do_import", # noqa return_value=(mocker.MagicMock(), []), @@ -96,7 +94,7 @@ def test_management_command_requires_a_valid_username(factories, mocker): def test_in_place_import_only_from_music_dir(factories, settings): - user = factories["users.User"](username="me") + factories["users.User"](username="me") settings.MUSIC_DIRECTORY_PATH = "/nope" path = os.path.join(DATA_DIR, "dummy_file.ogg") with pytest.raises(CommandError): @@ -128,7 +126,7 @@ def test_import_files_creates_a_batch_and_job(factories, mocker): def test_import_files_skip_if_path_already_imported(factories, mocker): user = factories["users.User"](username="me") path = os.path.join(DATA_DIR, "dummy_file.ogg") - existing = factories["music.TrackFile"](source="file://{}".format(path)) + factories["music.TrackFile"](source="file://{}".format(path)) call_command("import_files", path, username="me", async=False, interactive=False) assert user.imports.count() == 0 diff --git a/api/tests/test_youtube.py b/api/tests/test_youtube.py index 629558cc3..cb5559ce1 100644 --- a/api/tests/test_youtube.py +++ b/api/tests/test_youtube.py @@ -1,6 +1,7 @@ -import json from collections import OrderedDict + from django.urls import reverse + from funkwhale_api.providers.youtube.client import client from .data import youtube as api_data @@ -32,7 +33,7 @@ def test_can_get_search_results_from_funkwhale(preferences, mocker, api_client, "id": "0HxZn6CzOIo", "url": "https://www.youtube.com/watch?v=0HxZn6CzOIo", "type": "youtube#video", - "description": "Make sure to apply adhesive evenly before use. GET IT HERE: http://adhesivewombat.bandcamp.com/album/marsupial-madness Facebook: ...", + "description": "Description", "channelId": "UCps63j3krzAG4OyXeEyuhFw", "title": "AdhesiveWombat - 8 Bit Adventure", "channelTitle": "AdhesiveWombat", @@ -81,7 +82,7 @@ def test_can_send_multiple_queries_at_once_from_funwkhale( "id": "0HxZn6CzOIo", "url": "https://www.youtube.com/watch?v=0HxZn6CzOIo", "type": "youtube#video", - "description": "Make sure to apply adhesive evenly before use. GET IT HERE: http://adhesivewombat.bandcamp.com/album/marsupial-madness Facebook: ...", + "description": "Description", "channelId": "UCps63j3krzAG4OyXeEyuhFw", "title": "AdhesiveWombat - 8 Bit Adventure", "channelTitle": "AdhesiveWombat", diff --git a/api/tests/users/test_jwt.py b/api/tests/users/test_jwt.py index 28ff09d74..83de757c8 100644 --- a/api/tests/users/test_jwt.py +++ b/api/tests/users/test_jwt.py @@ -1,11 +1,7 @@ import pytest -import uuid - from jwt.exceptions import DecodeError from rest_framework_jwt.settings import api_settings -from funkwhale_api.users.models import User - def test_can_invalidate_token_when_changing_user_secret_key(factories): user = factories["users.User"]() diff --git a/api/tests/users/test_permissions.py b/api/tests/users/test_permissions.py index f4b501018..7f72138f4 100644 --- a/api/tests/users/test_permissions.py +++ b/api/tests/users/test_permissions.py @@ -87,8 +87,6 @@ def test_has_user_permission_logged_in_multiple_or( request = api_request.get("/") setattr(request, "user", user) result = permission.has_permission(request, view) - assert ( - result - == user.has_permissions("federation", "library", operator="or") - == expected - ) + has_permission_result = user.has_permissions("federation", "library", operator="or") + + assert result == has_permission_result == expected diff --git a/api/tests/users/test_views.py b/api/tests/users/test_views.py index f7a11367e..00272c2ae 100644 --- a/api/tests/users/test_views.py +++ b/api/tests/users/test_views.py @@ -1,7 +1,4 @@ -import json import pytest - -from django.test import RequestFactory from django.urls import reverse from funkwhale_api.users.models import User @@ -114,7 +111,7 @@ def test_changing_password_updates_secret_key(logged_in_api_client): payload = {"old_password": "test", "new_password1": "new", "new_password2": "new"} url = reverse("change_password") - response = logged_in_api_client.post(url, payload) + logged_in_api_client.post(url, payload) user.refresh_from_db() @@ -164,7 +161,7 @@ def test_user_can_request_new_subsonic_token(logged_in_api_client): assert response.data == {"subsonic_api_token": user.subsonic_api_token} -def test_user_can_get_new_subsonic_token(logged_in_api_client): +def test_user_can_get_subsonic_token(logged_in_api_client): user = logged_in_api_client.user user.subsonic_api_token = "test" user.save() @@ -179,24 +176,6 @@ def test_user_can_get_new_subsonic_token(logged_in_api_client): assert response.data == {"subsonic_api_token": "test"} -def test_user_can_request_new_subsonic_token(logged_in_api_client): - user = logged_in_api_client.user - user.subsonic_api_token = "test" - user.save() - - url = reverse( - "api:v1:users:users-subsonic-token", kwargs={"username": user.username} - ) - - response = logged_in_api_client.post(url) - - assert response.status_code == 200 - user.refresh_from_db() - assert user.subsonic_api_token != "test" - assert user.subsonic_api_token is not None - assert response.data == {"subsonic_api_token": user.subsonic_api_token} - - def test_user_can_delete_subsonic_token(logged_in_api_client): user = logged_in_api_client.user user.subsonic_api_token = "test" diff --git a/changes/changelog.d/297.misc b/changes/changelog.d/297.misc new file mode 100644 index 000000000..ac47458fd --- /dev/null +++ b/changes/changelog.d/297.misc @@ -0,0 +1,2 @@ +Added Black and flake8 checks in CI to ensure consistent code styling and +formatting (#297)