From 850dc690915babdc7b4adb38e7e9164cb511261e Mon Sep 17 00:00:00 2001 From: Georg Krause Date: Sun, 9 Jan 2022 11:40:49 +0000 Subject: [PATCH] Update Black & run for whole repository --- .gitlab-ci.yml | 7 +- api/config/api_urls.py | 5 +- api/config/plugins.py | 4 +- api/funkwhale_api/audio/serializers.py | 9 +- api/funkwhale_api/audio/views.py | 18 +++- api/funkwhale_api/cli/library.py | 3 +- api/funkwhale_api/cli/users.py | 13 ++- api/funkwhale_api/common/filters.py | 3 +- api/funkwhale_api/common/middleware.py | 4 +- api/funkwhale_api/common/models.py | 3 +- api/funkwhale_api/common/search.py | 14 +-- api/funkwhale_api/common/serializers.py | 4 +- .../contrib/scrobbler/scrobbler.py | 8 +- api/funkwhale_api/federation/actors.py | 3 +- .../federation/authentication.py | 4 +- api/funkwhale_api/federation/factories.py | 4 +- api/funkwhale_api/federation/jsonld.py | 4 +- api/funkwhale_api/federation/library.py | 8 +- api/funkwhale_api/federation/routes.py | 3 +- api/funkwhale_api/federation/serializers.py | 12 ++- api/funkwhale_api/federation/tasks.py | 21 ++++- api/funkwhale_api/federation/views.py | 6 +- api/funkwhale_api/manage/views.py | 5 +- .../management/commands/mrf_check.py | 3 +- api/funkwhale_api/moderation/models.py | 4 +- api/funkwhale_api/music/filters.py | 12 ++- .../music/management/commands/import_files.py | 34 +++++-- api/funkwhale_api/music/models.py | 8 +- api/funkwhale_api/music/tasks.py | 24 +++-- api/funkwhale_api/music/views.py | 3 +- api/funkwhale_api/radios/radios.py | 4 +- api/funkwhale_api/users/authentication.py | 4 +- api/tests/audio/test_views.py | 8 +- api/tests/cli/test_main.py | 7 +- api/tests/common/test_middleware.py | 56 ++++++++--- api/tests/federation/test_models.py | 4 +- api/tests/federation/test_routes.py | 5 +- api/tests/federation/test_serializers.py | 4 +- api/tests/federation/test_tasks.py | 9 +- .../test_third_party_activitypub.py | 3 +- api/tests/federation/test_views.py | 29 ++++-- api/tests/moderation/test_tasks.py | 6 +- api/tests/music/test_mutations.py | 13 ++- api/tests/music/test_serializers.py | 21 +++-- api/tests/music/test_tasks.py | 10 +- api/tests/playlists/test_views.py | 3 +- api/tests/plugins/test_plugins.py | 13 ++- api/tests/tags/test_tasks.py | 3 +- api/tests/test_import_audio_file.py | 18 +++- api/tests/users/test_authentication.py | 4 +- docs/conf.py | 18 +++- front/scripts/fix-fomantic-css.py | 93 ++++++++++++++----- pyproject.toml | 2 +- 53 files changed, 441 insertions(+), 149 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e3eef6e61..e842908d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -102,12 +102,13 @@ black: variables: GIT_STRATEGY: fetch before_script: - - pip install black==19.10b0 + - pip install black script: - - black --check --diff api/ + - black --check --diff . only: changes: - - api/**/* + - "**/*.py" + - .gitlab-ci.yml flake8: interruptible: true diff --git a/api/config/api_urls.py b/api/config/api_urls.py index bbfadbd4e..74b8cdd0b 100644 --- a/api/config/api_urls.py +++ b/api/config/api_urls.py @@ -73,7 +73,10 @@ v1_patterns += [ r"^history/", include(("funkwhale_api.history.urls", "history"), namespace="history"), ), - url(r"^", include(("funkwhale_api.users.api_urls", "users"), namespace="users"),), + url( + r"^", + include(("funkwhale_api.users.api_urls", "users"), namespace="users"), + ), # XXX: remove if Funkwhale 1.1 url( r"^users/", diff --git a/api/config/plugins.py b/api/config/plugins.py index 480580d44..d943cbe76 100644 --- a/api/config/plugins.py +++ b/api/config/plugins.py @@ -180,7 +180,9 @@ def set_conf(name, conf, user=None, registry=_plugins): if not registry[name]["conf"] and not registry[name]["source"]: return conf_serializer = get_serializer_from_conf_template( - registry[name]["conf"], user=user, source=registry[name]["source"], + registry[name]["conf"], + user=user, + source=registry[name]["source"], )(data=conf) conf_serializer.is_valid(raise_exception=True) if "library" in conf_serializer.validated_data: diff --git a/api/funkwhale_api/audio/serializers.py b/api/funkwhale_api/audio/serializers.py index 0bd8e6c4a..926ba0ab9 100644 --- a/api/funkwhale_api/audio/serializers.py +++ b/api/funkwhale_api/audio/serializers.py @@ -135,7 +135,8 @@ class ChannelCreateSerializer(serializers.Serializer): metadata=validated_data["metadata"], ) channel.actor = models.generate_actor( - validated_data["username"], name=validated_data["name"], + validated_data["username"], + name=validated_data["name"], ) channel.library = music_models.Library.objects.create( @@ -571,7 +572,8 @@ class RssFeedSerializer(serializers.Serializer): # create/update the channel channel, created = models.Channel.objects.update_or_create( - pk=existing.pk if existing else None, defaults=channel_defaults, + pk=existing.pk if existing else None, + defaults=channel_defaults, ) return channel @@ -773,7 +775,8 @@ class RssFeedItemSerializer(serializers.Serializer): # create/update the track track, created = music_models.Track.objects.update_or_create( - **track_kwargs, defaults=track_defaults, + **track_kwargs, + defaults=track_defaults, ) # optimisation for reducing SQL queries, because we cannot use select_related with # update or create, so we restore the cache by hand diff --git a/api/funkwhale_api/audio/views.py b/api/funkwhale_api/audio/views.py index 40ae12735..66a71fd39 100644 --- a/api/funkwhale_api/audio/views.py +++ b/api/funkwhale_api/audio/views.py @@ -27,7 +27,10 @@ from funkwhale_api.users.oauth import permissions as oauth_permissions from . import categories, filters, models, renderers, serializers ARTIST_PREFETCH_QS = ( - music_models.Artist.objects.select_related("description", "attachment_cover",) + music_models.Artist.objects.select_related( + "description", + "attachment_cover", + ) .prefetch_related(music_views.TAG_PREFETCH) .annotate(_tracks_count=Count("tracks")) ) @@ -192,7 +195,9 @@ class ChannelViewSet( "track", queryset=music_models.Track.objects.select_related( "attachment_cover", "description" - ).prefetch_related(music_views.TAG_PREFETCH,), + ).prefetch_related( + music_views.TAG_PREFETCH, + ), ), ) .select_related("track__attachment_cover", "track__description") @@ -232,7 +237,9 @@ class ChannelViewSet( if not serializer.is_valid(): return response.Response(serializer.errors, status=400) channel = ( - models.Channel.objects.filter(rss_url=serializer.validated_data["url"],) + models.Channel.objects.filter( + rss_url=serializer.validated_data["url"], + ) .order_by("id") .first() ) @@ -243,7 +250,10 @@ class ChannelViewSet( serializer.validated_data["url"] ) except serializers.FeedFetchException as e: - return response.Response({"detail": str(e)}, status=400,) + return response.Response( + {"detail": str(e)}, + status=400, + ) subscription = federation_models.Follow(actor=request.user.actor) subscription.fid = subscription.get_federation_id() diff --git a/api/funkwhale_api/cli/library.py b/api/funkwhale_api/cli/library.py index da4dd67ad..ed48164c3 100644 --- a/api/funkwhale_api/cli/library.py +++ b/api/funkwhale_api/cli/library.py @@ -6,7 +6,8 @@ from . import base def handler_add_tags_from_tracks( - artists=False, albums=False, + artists=False, + albums=False, ): result = None if artists: diff --git a/api/funkwhale_api/cli/users.py b/api/funkwhale_api/cli/users.py index 92d57d3e6..77c6f4650 100644 --- a/api/funkwhale_api/cli/users.py +++ b/api/funkwhale_api/cli/users.py @@ -157,13 +157,16 @@ def users(): type=click.INT, ) @click.option( - "--superuser/--no-superuser", default=False, + "--superuser/--no-superuser", + default=False, ) @click.option( - "--staff/--no-staff", default=False, + "--staff/--no-staff", + default=False, ) @click.option( - "--permission", multiple=True, + "--permission", + multiple=True, ) def create(username, password, email, superuser, staff, permission, upload_quota): """Create a new user""" @@ -210,7 +213,9 @@ def delete(username, hard): @click.option("--permission-settings/--no-permission-settings", default=None) @click.option("--password", default=None, envvar="FUNKWHALE_CLI_USER_UPDATE_PASSWORD") @click.option( - "-q", "--upload-quota", type=click.INT, + "-q", + "--upload-quota", + type=click.INT, ) def update(username, **kwargs): """Update attributes for given users""" diff --git a/api/funkwhale_api/common/filters.py b/api/funkwhale_api/common/filters.py index 5807d369f..6bfa12f04 100644 --- a/api/funkwhale_api/common/filters.py +++ b/api/funkwhale_api/common/filters.py @@ -227,7 +227,8 @@ class ActorScopeFilter(filters.CharFilter): username, domain = full_username.split("@") try: actor = federation_models.Actor.objects.get( - preferred_username__iexact=username, domain_id=domain, + preferred_username__iexact=username, + domain_id=domain, ) except federation_models.Actor.DoesNotExist: raise EmptyQuerySet() diff --git a/api/funkwhale_api/common/middleware.py b/api/funkwhale_api/common/middleware.py index f7d2acda4..cc897bf77 100644 --- a/api/funkwhale_api/common/middleware.py +++ b/api/funkwhale_api/common/middleware.py @@ -126,7 +126,9 @@ def get_spa_file(spa_url, name): if cached: return cached - response = session.get_session().get(utils.join_url(spa_url, name),) + response = session.get_session().get( + utils.join_url(spa_url, name), + ) response.raise_for_status() content = response.text caches["local"].set(cache_key, content, settings.FUNKWHALE_SPA_HTML_CACHE_DURATION) diff --git a/api/funkwhale_api/common/models.py b/api/funkwhale_api/common/models.py index 688af5406..3107fd583 100644 --- a/api/funkwhale_api/common/models.py +++ b/api/funkwhale_api/common/models.py @@ -222,7 +222,8 @@ class Attachment(models.Model): validators=[ validators.ImageDimensionsValidator(min_width=50, min_height=50), validators.FileValidator( - allowed_extensions=["png", "jpg", "jpeg"], max_size=1024 * 1024 * 5, + allowed_extensions=["png", "jpg", "jpeg"], + max_size=1024 * 1024 * 5, ), ], ) diff --git a/api/funkwhale_api/common/search.py b/api/funkwhale_api/common/search.py index 5daa03abb..580f1604f 100644 --- a/api/funkwhale_api/common/search.py +++ b/api/funkwhale_api/common/search.py @@ -26,20 +26,20 @@ def normalize_query( findterms=re.compile(r'"([^"]+)"|(\S+)').findall, normspace=re.compile(r"\s{2,}").sub, ): - """ Splits the query string in invidual keywords, getting rid of unecessary spaces - and grouping quoted words together. - Example: + """Splits the query string in invidual keywords, getting rid of unecessary spaces + and grouping quoted words together. + Example: - >>> normalize_query(' some random words "with quotes " and spaces') - ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] + >>> normalize_query(' some random words "with quotes " and spaces') + ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] """ return [normspace(" ", (t[0] or t[1]).strip()) for t in findterms(query_string)] def get_query(query_string, search_fields): - """ Returns a query, that is a combination of Q objects. That combination - aims to search keywords within a model by testing the given search fields. + """Returns a query, that is a combination of Q objects. That combination + aims to search keywords within a model by testing the given search fields. """ query = None # Query to search for every search term diff --git a/api/funkwhale_api/common/serializers.py b/api/funkwhale_api/common/serializers.py index fa194ea8a..7735c0f72 100644 --- a/api/funkwhale_api/common/serializers.py +++ b/api/funkwhale_api/common/serializers.py @@ -310,7 +310,9 @@ class ContentSerializer(serializers.Serializer): text = serializers.CharField( max_length=models.CONTENT_TEXT_MAX_LENGTH, allow_null=True ) - content_type = serializers.ChoiceField(choices=models.CONTENT_TEXT_SUPPORTED_TYPES,) + content_type = serializers.ChoiceField( + choices=models.CONTENT_TEXT_SUPPORTED_TYPES, + ) html = serializers.SerializerMethodField() def get_html(self, o): diff --git a/api/funkwhale_api/contrib/scrobbler/scrobbler.py b/api/funkwhale_api/contrib/scrobbler/scrobbler.py index 2d18ee778..51656de1e 100644 --- a/api/funkwhale_api/contrib/scrobbler/scrobbler.py +++ b/api/funkwhale_api/contrib/scrobbler/scrobbler.py @@ -139,7 +139,13 @@ def handshake_v2(username, password, session, api_key, api_secret, scrobble_url) def submit_scrobble_v2( - session, track, scrobble_time, session_key, scrobble_url, api_key, api_secret, + session, + track, + scrobble_time, + session_key, + scrobble_url, + api_key, + api_secret, ): params = { "method": "track.scrobble", diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py index 5af1d4012..7163bd258 100644 --- a/api/funkwhale_api/federation/actors.py +++ b/api/funkwhale_api/federation/actors.py @@ -15,7 +15,8 @@ logger = logging.getLogger(__name__) def get_actor_data(actor_url): logger.debug("Fetching actor %s", actor_url) response = session.get_session().get( - actor_url, headers={"Accept": "application/activity+json"}, + actor_url, + headers={"Accept": "application/activity+json"}, ) response.raise_for_status() try: diff --git a/api/funkwhale_api/federation/authentication.py b/api/funkwhale_api/federation/authentication.py index 5f836087c..b46e615f0 100644 --- a/api/funkwhale_api/federation/authentication.py +++ b/api/funkwhale_api/federation/authentication.py @@ -53,7 +53,9 @@ class SignatureAuthentication(authentication.BaseAuthentication): actor = actors.get_actor(actor_url) except Exception as e: logger.info( - "Discarding HTTP request from actor/domain %s, %s", actor_url, str(e), + "Discarding HTTP request from actor/domain %s, %s", + actor_url, + str(e), ) raise rest_exceptions.AuthenticationFailed( "Cannot fetch remote actor to authenticate signature" diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py index 51aef3afd..200e17d4c 100644 --- a/api/funkwhale_api/federation/factories.py +++ b/api/funkwhale_api/federation/factories.py @@ -128,7 +128,9 @@ class ActorFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory): model = models.Actor class Params: - with_real_keys = factory.Trait(keys=factory.LazyFunction(keys.get_key_pair),) + with_real_keys = factory.Trait( + keys=factory.LazyFunction(keys.get_key_pair), + ) @factory.post_generation def local(self, create, extracted, **kwargs): diff --git a/api/funkwhale_api/federation/jsonld.py b/api/funkwhale_api/federation/jsonld.py index d91690d1c..0ff7e0e64 100644 --- a/api/funkwhale_api/federation/jsonld.py +++ b/api/funkwhale_api/federation/jsonld.py @@ -192,7 +192,9 @@ def prepare_for_serializer(payload, config, fallbacks={}): for a in aliases: try: value = get_value( - payload[a["property"]], keep=a.get("keep"), attr=a.get("attr"), + payload[a["property"]], + keep=a.get("keep"), + attr=a.get("attr"), ) except (IndexError, KeyError): continue diff --git a/api/funkwhale_api/federation/library.py b/api/funkwhale_api/federation/library.py index e2f383fc7..e084021fa 100644 --- a/api/funkwhale_api/federation/library.py +++ b/api/funkwhale_api/federation/library.py @@ -9,7 +9,9 @@ def get_library_data(library_url, actor): auth = signing.get_auth(actor.private_key, actor.private_key_id) try: response = session.get_session().get( - library_url, auth=auth, headers={"Accept": "application/activity+json"}, + library_url, + auth=auth, + headers={"Accept": "application/activity+json"}, ) except requests.ConnectionError: return {"errors": ["This library is not reachable"]} @@ -30,7 +32,9 @@ def get_library_data(library_url, actor): def get_library_page(library, page_url, actor): auth = signing.get_auth(actor.private_key, actor.private_key_id) response = session.get_session().get( - page_url, auth=auth, headers={"Accept": "application/activity+json"}, + page_url, + auth=auth, + headers={"Accept": "application/activity+json"}, ) serializer = serializers.CollectionPageSerializer( data=response.json(), diff --git a/api/funkwhale_api/federation/routes.py b/api/funkwhale_api/federation/routes.py index fa98f736f..0a45f1d64 100644 --- a/api/funkwhale_api/federation/routes.py +++ b/api/funkwhale_api/federation/routes.py @@ -196,7 +196,8 @@ def inbox_create_audio(payload, context): if is_channel: channel = context["actor"].get_channel() serializer = serializers.ChannelCreateUploadSerializer( - data=payload, context={"channel": channel}, + data=payload, + context={"channel": channel}, ) else: serializer = serializers.UploadSerializer( diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py index d27736624..d86dc6ff0 100644 --- a/api/funkwhale_api/federation/serializers.py +++ b/api/funkwhale_api/federation/serializers.py @@ -500,7 +500,10 @@ def create_or_update_channel(actor, rss_url, attributed_to_fid, **validated_data reverse("federation:music:libraries-detail", kwargs={"uuid": uid}) ) library = attributed_to.libraries.create( - privacy_level="everyone", name=artist_defaults["name"], fid=fid, uuid=uid, + privacy_level="everyone", + name=artist_defaults["name"], + fid=fid, + uuid=uid, ) else: library = artist.channel.library @@ -512,7 +515,9 @@ def create_or_update_channel(actor, rss_url, attributed_to_fid, **validated_data "library": library, } channel, created = audio_models.Channel.objects.update_or_create( - actor=actor, attributed_to=attributed_to, defaults=channel_defaults, + actor=actor, + attributed_to=attributed_to, + defaults=channel_defaults, ) return channel @@ -1734,7 +1739,8 @@ class FlagSerializer(jsonld.JsonLdSerializer): } report, created = moderation_models.Report.objects.update_or_create( - fid=validated_data["id"], defaults=kwargs, + fid=validated_data["id"], + defaults=kwargs, ) moderation_signals.report_created.send(sender=None, report=report) return report diff --git a/api/funkwhale_api/federation/tasks.py b/api/funkwhale_api/federation/tasks.py index cf7d08ebc..c040082aa 100644 --- a/api/funkwhale_api/federation/tasks.py +++ b/api/funkwhale_api/federation/tasks.py @@ -338,7 +338,9 @@ def fetch(fetch_obj): if not payload: return error("blocked", message="Blocked by MRF") response = session.get_session().get( - auth=auth, url=url, headers={"Accept": "application/activity+json"}, + auth=auth, + url=url, + headers={"Accept": "application/activity+json"}, ) logger.debug("Remote answered with %s: %s", response.status_code, response.text) response.raise_for_status() @@ -425,7 +427,9 @@ def fetch(fetch_obj): # first page fetch is synchronous, so that at least some data is available # in the UI after subscription result = fetch_collection( - obj.actor.outbox_url, channel_id=obj.pk, max_pages=1, + obj.actor.outbox_url, + channel_id=obj.pk, + max_pages=1, ) except Exception: logger.exception( @@ -473,7 +477,8 @@ class PreserveSomeDataCollector(Collector): @celery.app.task(name="federation.remove_actor") @transaction.atomic @celery.require_instance( - models.Actor.objects.all(), "actor", + models.Actor.objects.all(), + "actor", ) def remove_actor(actor): # Then we broadcast the info over federation. We do this *before* deleting objects @@ -531,7 +536,9 @@ def match_serializer(payload, conf): @celery.app.task(name="federation.fetch_collection") @celery.require_instance( - audio_models.Channel.objects.all(), "channel", allow_null=True, + audio_models.Channel.objects.all(), + "channel", + allow_null=True, ) def fetch_collection(url, max_pages, channel, is_page=False): actor = actors.get_service_actor() @@ -564,7 +571,11 @@ def fetch_collection(url, max_pages, channel, is_page=False): for i in range(max_pages): page_url = results["next_page"] logger.debug("Handling page %s on max %s, at %s", i + 1, max_pages, page_url) - page = utils.retrieve_ap_object(page_url, actor=actor, serializer_class=None,) + page = utils.retrieve_ap_object( + page_url, + actor=actor, + serializer_class=None, + ) try: items = page["orderedItems"] except KeyError: diff --git a/api/funkwhale_api/federation/views.py b/api/funkwhale_api/federation/views.py index dfb0b86f0..f22e1c3ff 100644 --- a/api/funkwhale_api/federation/views.py +++ b/api/funkwhale_api/federation/views.py @@ -470,7 +470,8 @@ class IndexViewSet(FederationMixin, viewsets.GenericViewSet): return super().dispatch(request, *args, **kwargs) @action( - methods=["get"], detail=False, + methods=["get"], + detail=False, ) def libraries(self, request, *args, **kwargs): libraries = ( @@ -497,7 +498,8 @@ class IndexViewSet(FederationMixin, viewsets.GenericViewSet): return response.Response({}, status=200) @action( - methods=["get"], detail=False, + methods=["get"], + detail=False, ) def channels(self, request, *args, **kwargs): actors = ( diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py index 52bdfaf24..dc90ffe79 100644 --- a/api/funkwhale_api/manage/views.py +++ b/api/funkwhale_api/manage/views.py @@ -686,7 +686,10 @@ class ManageChannelViewSet( queryset = ( audio_models.Channel.objects.all() .order_by("-id") - .select_related("attributed_to", "actor",) + .select_related( + "attributed_to", + "actor", + ) .prefetch_related( Prefetch( "artist", diff --git a/api/funkwhale_api/moderation/management/commands/mrf_check.py b/api/funkwhale_api/moderation/management/commands/mrf_check.py index 3a8289f8f..51112de21 100644 --- a/api/funkwhale_api/moderation/management/commands/mrf_check.py +++ b/api/funkwhale_api/moderation/management/commands/mrf_check.py @@ -82,7 +82,8 @@ class Command(BaseCommand): content = models.Activity.objects.get(uuid=input).payload elif is_url(input): response = session.get_session().get( - input, headers={"Accept": "application/activity+json"}, + input, + headers={"Accept": "application/activity+json"}, ) response.raise_for_status() content = response.json() diff --git a/api/funkwhale_api/moderation/models.py b/api/funkwhale_api/moderation/models.py index 0271877e4..7e59729e9 100644 --- a/api/funkwhale_api/moderation/models.py +++ b/api/funkwhale_api/moderation/models.py @@ -205,7 +205,9 @@ class UserRequest(models.Model): max_length=40, choices=USER_REQUEST_STATUSES, default="pending" ) submitter = models.ForeignKey( - "federation.Actor", related_name="requests", on_delete=models.CASCADE, + "federation.Actor", + related_name="requests", + on_delete=models.CASCADE, ) assigned_to = models.ForeignKey( "federation.Actor", diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py index 07e645c4c..22be0b7cc 100644 --- a/api/funkwhale_api/music/filters.py +++ b/api/funkwhale_api/music/filters.py @@ -211,7 +211,9 @@ class UploadFilter(audio_filters.IncludeChannelsFilterSet): library = filters.UUIDFilter("library__uuid") playable = filters.BooleanFilter(field_name="_", method="filter_playable") scope = common_filters.ActorScopeFilter( - actor_field="library__actor", distinct=True, library_field="library", + actor_field="library__actor", + distinct=True, + library_field="library", ) import_status = common_filters.MultipleQueryFilter(coerce=str) q = fields.SmartSearchFilter( @@ -291,9 +293,13 @@ class AlbumFilter( class LibraryFilter(filters.FilterSet): - q = fields.SearchFilter(search_fields=["name"],) + q = fields.SearchFilter( + search_fields=["name"], + ) scope = common_filters.ActorScopeFilter( - actor_field="actor", distinct=True, library_field="pk", + actor_field="actor", + distinct=True, + library_field="pk", ) class Meta: diff --git a/api/funkwhale_api/music/management/commands/import_files.py b/api/funkwhale_api/music/management/commands/import_files.py index bd2564580..1c1d0917c 100644 --- a/api/funkwhale_api/music/management/commands/import_files.py +++ b/api/funkwhale_api/music/management/commands/import_files.py @@ -364,12 +364,15 @@ class Command(BaseCommand): time_stats = "" if i > 0: time_stats = " - running for {}s, previous batch took {}s".format( - int(time.time() - start_time), int(batch_duration), + int(time.time() - start_time), + int(batch_duration), ) if entries: self.stdout.write( "Handling batch {} ({} items){}".format( - i + 1, len(entries), time_stats, + i + 1, + len(entries), + time_stats, ) ) batch_errors = self.handle_batch( @@ -536,7 +539,8 @@ class Command(BaseCommand): watchdog_queue = queue.Queue() # Set up a worker thread to process database load worker = threading.Thread( - target=process_load_queue(self.stdout, **kwargs), args=(watchdog_queue,), + target=process_load_queue(self.stdout, **kwargs), + args=(watchdog_queue,), ) worker.setDaemon(True) worker.start() @@ -544,7 +548,9 @@ class Command(BaseCommand): # setup watchdog to monitor directory for trigger files patterns = ["*.{}".format(e) for e in extensions] event_handler = Watcher( - stdout=self.stdout, queue=watchdog_queue, patterns=patterns, + stdout=self.stdout, + queue=watchdog_queue, + patterns=patterns, ) observer = watchdog.observers.Observer() observer.schedule(event_handler, path, recursive=recursive) @@ -581,7 +587,14 @@ def prune(): def create_upload( - path, reference, library, async_, replace, in_place, dispatch_outbox, broadcast, + path, + reference, + library, + async_, + replace, + in_place, + dispatch_outbox, + broadcast, ): import_handler = tasks.process_upload.delay if async_ else tasks.process_upload upload = models.Upload(library=library, import_reference=reference) @@ -692,7 +705,9 @@ def handle_modified(event, stdout, library, in_place, **kwargs): existing_candidates.in_place() .filter(source=source) .select_related( - "track__attributed_to", "track__artist", "track__album__artist", + "track__attributed_to", + "track__artist", + "track__album__artist", ) .first() ) @@ -792,7 +807,12 @@ def check_updates(stdout, library, extensions, paths, batch_size): stdout.write("Found {} files to check in database!".format(total)) uploads = existing.order_by("source") for i, rows in enumerate(batch(uploads.iterator(), batch_size)): - stdout.write("Handling batch {} ({} items)".format(i + 1, len(rows),)) + stdout.write( + "Handling batch {} ({} items)".format( + i + 1, + len(rows), + ) + ) for upload in rows: diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index a34c927d5..563f41792 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -331,7 +331,8 @@ class AlbumQuerySet(common_models.LocalFromFidQuerySet, models.QuerySet): ) return self.annotate( duration=models.Sum( - "tracks__uploads__duration", filter=Q(tracks__uploads=subquery), + "tracks__uploads__duration", + filter=Q(tracks__uploads=subquery), ) ) @@ -1177,7 +1178,10 @@ class LibraryQuerySet(models.QuerySet): ).values_list("target", flat=True) followed_channels_libraries = ( Follow.objects.exclude(target__channel=None) - .filter(actor=actor, approved=True,) + .filter( + actor=actor, + approved=True, + ) .values_list("target__channel__library", flat=True) ) return self.filter( diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py index b01f68e5f..d21c2be20 100644 --- a/api/funkwhale_api/music/tasks.py +++ b/api/funkwhale_api/music/tasks.py @@ -173,7 +173,8 @@ def fail_import(upload, error_code, detail=None, **fields): @celery.app.task(name="music.process_upload") @celery.require_instance( models.Upload.objects.filter(import_status="pending").select_related( - "library__actor__user", "library__channel__artist", + "library__actor__user", + "library__channel__artist", ), "upload", ) @@ -239,7 +240,9 @@ def process_upload(upload, update_denormalization=True): ) else: final_metadata = collections.ChainMap( - additional_data, forced_values, internal_config, + additional_data, + forced_values, + internal_config, ) try: track = get_track_from_import_metadata( @@ -310,7 +313,8 @@ def process_upload(upload, update_denormalization=True): # update album cover, if needed if track.album and not track.album.attachment_cover: populate_album_cover( - track.album, source=final_metadata.get("upload_source"), + track.album, + source=final_metadata.get("upload_source"), ) if broadcast: @@ -793,7 +797,9 @@ def albums_set_tags_from_tracks(ids=None, dry_run=False): if ids is not None: qs = qs.filter(pk__in=ids) data = tags_tasks.get_tags_from_foreign_key( - ids=qs, foreign_key_model=models.Track, foreign_key_attr="album", + ids=qs, + foreign_key_model=models.Track, + foreign_key_attr="album", ) logger.info("Found automatic tags for %s albums…", len(data)) if dry_run: @@ -801,7 +807,8 @@ def albums_set_tags_from_tracks(ids=None, dry_run=False): return tags_tasks.add_tags_batch( - data, model=models.Album, + data, + model=models.Album, ) return data @@ -815,7 +822,9 @@ def artists_set_tags_from_tracks(ids=None, dry_run=False): if ids is not None: qs = qs.filter(pk__in=ids) data = tags_tasks.get_tags_from_foreign_key( - ids=qs, foreign_key_model=models.Track, foreign_key_attr="artist", + ids=qs, + foreign_key_model=models.Track, + foreign_key_attr="artist", ) logger.info("Found automatic tags for %s artists…", len(data)) if dry_run: @@ -823,7 +832,8 @@ def artists_set_tags_from_tracks(ids=None, dry_run=False): return tags_tasks.add_tags_batch( - data, model=models.Artist, + data, + model=models.Artist, ) return data diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index df01f5902..d7eba93cf 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -54,7 +54,8 @@ def get_libraries(filter_uploads): uploads = filter_uploads(obj, uploads) uploads = uploads.playable_by(actor) qs = models.Library.objects.filter( - pk__in=uploads.values_list("library", flat=True), channel=None, + pk__in=uploads.values_list("library", flat=True), + channel=None, ).annotate(_uploads_count=Count("uploads")) qs = qs.prefetch_related("actor") page = self.paginate_queryset(qs) diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py index 4f23fb281..820251c2c 100644 --- a/api/funkwhale_api/radios/radios.py +++ b/api/funkwhale_api/radios/radios.py @@ -316,7 +316,9 @@ class LibraryRadio(RelatedObjectRadio): def get_queryset(self, **kwargs): qs = super().get_queryset(**kwargs) - actor_uploads = Upload.objects.filter(library=self.session.related_object,) + actor_uploads = Upload.objects.filter( + library=self.session.related_object, + ) return qs.filter(pk__in=actor_uploads.values("track")) def get_related_object_id_repr(self, obj): diff --git a/api/funkwhale_api/users/authentication.py b/api/funkwhale_api/users/authentication.py index cb9ec8a8e..5e94dd385 100644 --- a/api/funkwhale_api/users/authentication.py +++ b/api/funkwhale_api/users/authentication.py @@ -27,7 +27,9 @@ def generate_scoped_token(user_id, user_secret, scopes): def authenticate_scoped_token(token): try: payload = signing.loads( - token, salt="scoped_tokens", max_age=settings.SCOPED_TOKENS_MAX_AGE, + token, + salt="scoped_tokens", + max_age=settings.SCOPED_TOKENS_MAX_AGE, ) except signing.BadSignature: raise exceptions.AuthenticationFailed("Invalid token signature") diff --git a/api/tests/audio/test_views.py b/api/tests/audio/test_views.py index 83a211ee4..fc5809b77 100644 --- a/api/tests/audio/test_views.py +++ b/api/tests/audio/test_views.py @@ -52,7 +52,8 @@ def test_channel_create(logged_in_api_client): @pytest.mark.parametrize( - "field", ["uuid", "actor.preferred_username", "actor.full_username"], + "field", + ["uuid", "actor.preferred_username", "actor.full_username"], ) def test_channel_detail(field, factories, logged_in_api_client): channel = factories["audio.Channel"]( @@ -423,7 +424,10 @@ def test_subscribe_to_rss_creates_channel(factories, logged_in_api_client, mocke def test_refresh_channel_when_param_is_true( - factories, mocker, logged_in_api_client, queryset_equal_queries, + factories, + mocker, + logged_in_api_client, + queryset_equal_queries, ): obj = factories["audio.Channel"]() refetch_obj = mocker.patch( diff --git a/api/tests/cli/test_main.py b/api/tests/cli/test_main.py index 1e1a35e60..9bea72db7 100644 --- a/api/tests/cli/test_main.py +++ b/api/tests/cli/test_main.py @@ -57,7 +57,12 @@ from funkwhale_api.cli import users ), ( ("users", "rm"), - ("testuser1", "testuser2", "--no-input", "--hard",), + ( + "testuser1", + "testuser2", + "--no-input", + "--hard", + ), [ ( users, diff --git a/api/tests/common/test_middleware.py b/api/tests/common/test_middleware.py index b5d4d02f1..11642b43e 100644 --- a/api/tests/common/test_middleware.py +++ b/api/tests/common/test_middleware.py @@ -301,13 +301,17 @@ def test_rewrite_manifest_json_url(link, new_url, expected, mocker, settings): request = mocker.Mock(path="/", META={}) mocker.patch.object(middleware, "get_spa_html", return_value=spa_html) mocker.patch.object( - middleware, "get_default_head_tags", return_value=[], + middleware, + "get_default_head_tags", + return_value=[], ) response = middleware.serve_spa(request) assert response.status_code == 200 - expected_html = "{}\n\n".format( - expected + expected_html = ( + "{}\n\n".format( + expected + ) ) assert response.content == expected_html.encode() @@ -319,7 +323,9 @@ def test_rewrite_manifest_json_url_rewrite_disabled(mocker, settings): request = mocker.Mock(path="/", META={}) mocker.patch.object(middleware, "get_spa_html", return_value=spa_html) mocker.patch.object( - middleware, "get_default_head_tags", return_value=[], + middleware, + "get_default_head_tags", + return_value=[], ) response = middleware.serve_spa(request) @@ -338,13 +344,17 @@ def test_rewrite_manifest_json_url_rewrite_default_url(mocker, settings): request = mocker.Mock(path="/", META={}) mocker.patch.object(middleware, "get_spa_html", return_value=spa_html) mocker.patch.object( - middleware, "get_default_head_tags", return_value=[], + middleware, + "get_default_head_tags", + return_value=[], ) response = middleware.serve_spa(request) assert response.status_code == 200 - expected_html = '\n\n'.format( - expected_url + expected_html = ( + '\n\n'.format( + expected_url + ) ) assert response.content == expected_html.encode() @@ -410,10 +420,34 @@ def test_get_request_head_tags_calls_view_with_proper_arg_when_accept_header_set "username", "actor.preferred_username", ), - ("music.Artist", {}, "library_artist", "pk", "pk",), - ("music.Album", {}, "library_album", "pk", "pk",), - ("music.Track", {}, "library_track", "pk", "pk",), - ("music.Library", {}, "library_library", "uuid", "uuid",), + ( + "music.Artist", + {}, + "library_artist", + "pk", + "pk", + ), + ( + "music.Album", + {}, + "library_album", + "pk", + "pk", + ), + ( + "music.Track", + {}, + "library_track", + "pk", + "pk", + ), + ( + "music.Library", + {}, + "library_library", + "uuid", + "uuid", + ), # when a track as a public upload, we should redirect to the upload instead ("music.Upload", {"playable": True}, "library_track", "pk", "track.pk"), ], diff --git a/api/tests/federation/test_models.py b/api/tests/federation/test_models.py index b6c8dc0ad..6f722c6e8 100644 --- a/api/tests/federation/test_models.py +++ b/api/tests/federation/test_models.py @@ -257,7 +257,9 @@ def test_update_library_follow_approved_create_entries( assert list(music_models.Track.objects.playable_by(actor)) == expected_tracks -def test_update_library_follow_delete_delete_denormalization_entries(factories,): +def test_update_library_follow_delete_delete_denormalization_entries( + factories, +): updated_playable_tracks = {"owner": [0], "follower": []} actors = { "owner": factories["federation.Actor"](local=True), diff --git a/api/tests/federation/test_routes.py b/api/tests/federation/test_routes.py index 753f286b7..108ca41b8 100644 --- a/api/tests/federation/test_routes.py +++ b/api/tests/federation/test_routes.py @@ -354,7 +354,10 @@ def test_inbox_create_audio_channel(factories, mocker): activity = factories["federation.Activity"]() channel = factories["audio.Channel"]() album = factories["music.Album"](artist=channel.artist) - upload = factories["music.Upload"](track__album=album, library=channel.library,) + upload = factories["music.Upload"]( + track__album=album, + library=channel.library, + ) payload = { "@context": jsonld.get_default_context(), "type": "Create", diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py index af774ab03..17c2de773 100644 --- a/api/tests/federation/test_serializers.py +++ b/api/tests/federation/test_serializers.py @@ -805,7 +805,9 @@ def test_activity_pub_album_serializer_to_ap(factories): def test_activity_pub_album_serializer_to_ap_channel_artist(factories): channel = factories["audio.Channel"]() - album = factories["music.Album"](artist=channel.artist,) + album = factories["music.Album"]( + artist=channel.artist, + ) serializer = serializers.AlbumSerializer(album) diff --git a/api/tests/federation/test_tasks.py b/api/tests/federation/test_tasks.py index 6974cf11f..82192cef0 100644 --- a/api/tests/federation/test_tasks.py +++ b/api/tests/federation/test_tasks.py @@ -530,7 +530,9 @@ def test_fetch_channel_actor_returns_channel_and_fetch_outbox( assert fetch.status == "finished" assert fetch.object == obj fetch_collection.assert_called_once_with( - obj.actor.outbox_url, channel_id=obj.pk, max_pages=1, + obj.actor.outbox_url, + channel_id=obj.pk, + max_pages=1, ) fetch_collection_delayed.assert_called_once_with( "http://outbox.url/page2", @@ -655,7 +657,10 @@ def test_fetch_collection(mocker, r_mock): r_mock.get(payloads["outbox"]["id"], json=payloads["outbox"]) r_mock.get(payloads["outbox"]["first"], json=payloads["page1"]) r_mock.get(payloads["page1"]["next"], json=payloads["page2"]) - result = tasks.fetch_collection(payloads["outbox"]["id"], max_pages=2,) + result = tasks.fetch_collection( + payloads["outbox"]["id"], + max_pages=2, + ) assert result["items"] == [ payloads["page1"]["orderedItems"][2], payloads["page2"]["orderedItems"][1], diff --git a/api/tests/federation/test_third_party_activitypub.py b/api/tests/federation/test_third_party_activitypub.py index 1e18feda5..66d109943 100644 --- a/api/tests/federation/test_third_party_activitypub.py +++ b/api/tests/federation/test_third_party_activitypub.py @@ -296,7 +296,8 @@ def test_reel2bits_upload_delete(factories): } routes.inbox_delete( - payload, context={"actor": actor, "raise_exception": True, "activity": payload}, + payload, + context={"actor": actor, "raise_exception": True, "activity": payload}, ) with pytest.raises(upload.track.DoesNotExist): diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py index 0e098465a..01dc66326 100644 --- a/api/tests/federation/test_views.py +++ b/api/tests/federation/test_views.py @@ -31,7 +31,10 @@ def test_authenticate_skips_anonymous_fetch_when_allow_list_enabled( ): preferences["moderation__allow_list_enabled"] = True library = factories["music.Library"]() - url = reverse("federation:music:libraries-detail", kwargs={"uuid": library.uuid},) + url = reverse( + "federation:music:libraries-detail", + kwargs={"uuid": library.uuid}, + ) response = api_client.get(url) assert response.status_code == 403 @@ -470,7 +473,10 @@ def test_upload_retrieve_redirects_to_html_if_header_set( ): upload = factories["music.Upload"](library__local=True, playable=True) - url = reverse("federation:music:uploads-detail", kwargs={"uuid": upload.uuid},) + url = reverse( + "federation:music:uploads-detail", + kwargs={"uuid": upload.uuid}, + ) response = api_client.get(url, HTTP_ACCEPT="text/html") expected_url = utils.join_url( settings.FUNKWHALE_URL, @@ -485,7 +491,10 @@ def test_track_retrieve_redirects_to_html_if_header_set( ): track = factories["music.Track"](local=True) - url = reverse("federation:music:tracks-detail", kwargs={"uuid": track.uuid},) + url = reverse( + "federation:music:tracks-detail", + kwargs={"uuid": track.uuid}, + ) response = api_client.get(url, HTTP_ACCEPT="text/html") expected_url = utils.join_url( settings.FUNKWHALE_URL, @@ -500,7 +509,10 @@ def test_album_retrieve_redirects_to_html_if_header_set( ): album = factories["music.Album"](local=True) - url = reverse("federation:music:albums-detail", kwargs={"uuid": album.uuid},) + url = reverse( + "federation:music:albums-detail", + kwargs={"uuid": album.uuid}, + ) response = api_client.get(url, HTTP_ACCEPT="text/html") expected_url = utils.join_url( settings.FUNKWHALE_URL, @@ -515,7 +527,10 @@ def test_artist_retrieve_redirects_to_html_if_header_set( ): artist = factories["music.Artist"](local=True) - url = reverse("federation:music:artists-detail", kwargs={"uuid": artist.uuid},) + url = reverse( + "federation:music:artists-detail", + kwargs={"uuid": artist.uuid}, + ) response = api_client.get(url, HTTP_ACCEPT="text/html") expected_url = utils.join_url( settings.FUNKWHALE_URL, @@ -548,7 +563,9 @@ def test_index_channels_retrieve(factories, api_client): }, ).data - url = reverse("federation:index:index-channels",) + url = reverse( + "federation:index:index-channels", + ) response = api_client.get(url) assert response.status_code == 200 diff --git a/api/tests/moderation/test_tasks.py b/api/tests/moderation/test_tasks.py index 54f0438dc..884d3b2f8 100644 --- a/api/tests/moderation/test_tasks.py +++ b/api/tests/moderation/test_tasks.py @@ -66,7 +66,8 @@ def test_signup_request_pending_sends_email_to_mods(factories, mailoutbox, setti for i, mod in enumerate([mod1, mod2]): m = mailoutbox[i] assert m.subject == "[{} moderation] New sign-up request from {}".format( - settings.FUNKWHALE_HOSTNAME, signup_request.submitter.preferred_username, + settings.FUNKWHALE_HOSTNAME, + signup_request.submitter.preferred_username, ) assert detail_url in m.body assert unresolved_requests_url in m.body @@ -91,7 +92,8 @@ def test_approved_request_sends_email_to_submitter_and_set_active( m = mailoutbox[-1] login_url = federation_utils.full_url("/login") assert m.subject == "Welcome to {}, {}!".format( - settings.FUNKWHALE_HOSTNAME, signup_request.submitter.preferred_username, + settings.FUNKWHALE_HOSTNAME, + signup_request.submitter.preferred_username, ) assert login_url in m.body assert list(m.to) == [user.email] diff --git a/api/tests/music/test_mutations.py b/api/tests/music/test_mutations.py index 1516473be..11e199706 100644 --- a/api/tests/music/test_mutations.py +++ b/api/tests/music/test_mutations.py @@ -213,7 +213,8 @@ def test_mutation_set_attachment_cover(factory_name, factories, now, mocker): @pytest.mark.parametrize( - "factory_name", ["music.Track", "music.Album", "music.Artist"], + "factory_name", + ["music.Track", "music.Album", "music.Artist"], ) def test_album_mutation_description(factory_name, factories, mocker): mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") @@ -236,7 +237,8 @@ def test_album_mutation_description(factory_name, factories, mocker): @pytest.mark.parametrize( - "factory_name", ["music.Track", "music.Album", "music.Artist"], + "factory_name", + ["music.Track", "music.Album", "music.Artist"], ) def test_mutation_description_keep_tags(factory_name, factories, mocker): mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") @@ -256,14 +258,17 @@ def test_mutation_description_keep_tags(factory_name, factories, mocker): @pytest.mark.parametrize( - "factory_name", ["music.Track", "music.Album", "music.Artist"], + "factory_name", + ["music.Track", "music.Album", "music.Artist"], ) def test_mutation_tags_keep_descriptions(factory_name, factories, mocker): mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") content = factories["common.Content"]() obj = factories[factory_name](description=content) mutation = factories["common.Mutation"]( - type="update", target=obj, payload={"tags": ["punk", "rock"]}, + type="update", + target=obj, + payload={"tags": ["punk", "rock"]}, ) mutation.apply() obj.refresh_from_db() diff --git a/api/tests/music/test_serializers.py b/api/tests/music/test_serializers.py index 24dd99c26..beb30279d 100644 --- a/api/tests/music/test_serializers.py +++ b/api/tests/music/test_serializers.py @@ -427,7 +427,8 @@ def test_upload_with_channel(factories, uploaded_audio_file): "import_status": "draft", } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) assert serializer.is_valid(raise_exception=True) is True upload = serializer.save() @@ -443,7 +444,8 @@ def test_upload_with_not_owned_channel_fails(factories, uploaded_audio_file): "audio_file": uploaded_audio_file, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) assert serializer.is_valid() is False assert "channel" in serializer.errors @@ -457,7 +459,8 @@ def test_upload_with_not_owned_library_fails(factories, uploaded_audio_file): "audio_file": uploaded_audio_file, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) assert serializer.is_valid() is False assert "library" in serializer.errors @@ -469,7 +472,8 @@ def test_upload_requires_library_or_channel(factories, uploaded_audio_file): "audio_file": uploaded_audio_file, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) with pytest.raises( @@ -491,7 +495,8 @@ def test_upload_requires_library_or_channel_but_not_both( "channel": channel.uuid, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) with pytest.raises( serializers.serializers.ValidationError, @@ -547,7 +552,8 @@ def test_upload_with_channel_keeps_import_metadata(factories, uploaded_audio_fil "import_metadata": {"title": "hello"}, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) assert serializer.is_valid(raise_exception=True) is True upload = serializer.save() @@ -564,7 +570,8 @@ def test_upload_with_channel_validates_import_metadata(factories, uploaded_audio "import_metadata": {"title": None}, } serializer = serializers.UploadForOwnerSerializer( - data=data, context={"user": user}, + data=data, + context={"user": user}, ) with pytest.raises(serializers.serializers.ValidationError): assert serializer.is_valid(raise_exception=True) diff --git a/api/tests/music/test_tasks.py b/api/tests/music/test_tasks.py index 414bf95e7..13522e338 100644 --- a/api/tests/music/test_tasks.py +++ b/api/tests/music/test_tasks.py @@ -1082,7 +1082,9 @@ def test_process_channel_upload_forces_artist_and_attributed_to( upload.refresh_from_db() expected_final_metadata = tasks.collections.ChainMap( - {"upload_source": None}, expected_forced_values, {"funkwhale": {}}, + {"upload_source": None}, + expected_forced_values, + {"funkwhale": {}}, ) assert upload.import_status == "finished" get_track_from_import_metadata.assert_called_once_with( @@ -1175,7 +1177,8 @@ def test_tag_albums_from_tracks(queryset_equal_queries, factories, mocker): ) add_tags_batch.assert_called_once_with( - get_tags_from_foreign_key.return_value, model=models.Album, + get_tags_from_foreign_key.return_value, + model=models.Album, ) @@ -1200,7 +1203,8 @@ def test_tag_artists_from_tracks(queryset_equal_queries, factories, mocker): ) add_tags_batch.assert_called_once_with( - get_tags_from_foreign_key.return_value, model=models.Artist, + get_tags_from_foreign_key.return_value, + model=models.Artist, ) diff --git a/api/tests/playlists/test_views.py b/api/tests/playlists/test_views.py index b71b242e5..5b9cf4202 100644 --- a/api/tests/playlists/test_views.py +++ b/api/tests/playlists/test_views.py @@ -61,7 +61,8 @@ def test_playlist_inherits_user_privacy(logged_in_api_client): @pytest.mark.parametrize( - "name,method", [("api:v1:playlists-list", "post")], + "name,method", + [("api:v1:playlists-list", "post")], ) def test_url_requires_login(name, method, factories, api_client): url = reverse(name) diff --git a/api/tests/plugins/test_plugins.py b/api/tests/plugins/test_plugins.py index ac0e046b4..1b63442bb 100644 --- a/api/tests/plugins/test_plugins.py +++ b/api/tests/plugins/test_plugins.py @@ -137,8 +137,12 @@ def test_get_confs_user(factories): def test_filter_is_called_with_plugin_conf(mocker, factories): - plugins.get_plugin_config("test1",) - plugins.get_plugin_config("test2",) + plugins.get_plugin_config( + "test1", + ) + plugins.get_plugin_config( + "test2", + ) factories["common.PluginConfiguration"](code="test1", enabled=True) factories["common.PluginConfiguration"]( code="test2", conf={"foo": "baz"}, enabled=True @@ -411,7 +415,10 @@ def test_set_plugin_source_conf_valid(factories): def test_can_trigger_scan(logged_in_api_client, mocker, factories): library = factories["music.Library"](actor=logged_in_api_client.user.create_actor()) plugin = plugins.get_plugin_config( - name="test_plugin", description="Hello world", conf=[], source=True, + name="test_plugin", + description="Hello world", + conf=[], + source=True, ) handler = mocker.Mock() plugins.register_hook(plugins.SCAN, plugin)(handler) diff --git a/api/tests/tags/test_tasks.py b/api/tests/tags/test_tasks.py index 77f2724b4..2dab64544 100644 --- a/api/tests/tags/test_tasks.py +++ b/api/tests/tags/test_tasks.py @@ -29,7 +29,8 @@ def test_add_tags_batch(factories): data = {artist.pk: [rock_tag.pk, rap_tag.pk]} tasks.add_tags_batch( - data, model=artist.__class__, + data, + model=artist.__class__, ) assert artist.get_tags() == ["Rap", "Rock"] diff --git a/api/tests/test_import_audio_file.py b/api/tests/test_import_audio_file.py index 7ee1028c8..11b11fef5 100644 --- a/api/tests/test_import_audio_file.py +++ b/api/tests/test_import_audio_file.py @@ -297,7 +297,10 @@ def test_handle_modified_skips_existing_checksum(tmpfile, factories, mocker): import_status="finished", ) import_files.handle_modified( - event=event, stdout=stdout, library=library, in_place=True, + event=event, + stdout=stdout, + library=library, + in_place=True, ) assert library.uploads.count() == 1 @@ -322,10 +325,14 @@ def test_handle_modified_update_existing_path_if_found(tmpfile, factories, mocke audio_file=None, ) import_files.handle_modified( - event=event, stdout=stdout, library=library, in_place=True, + event=event, + stdout=stdout, + library=library, + in_place=True, ) update_track_metadata.assert_called_once_with( - get_metadata.return_value, upload.track, + get_metadata.return_value, + upload.track, ) @@ -349,7 +356,10 @@ def test_handle_modified_update_existing_path_if_found_and_attributed_to( audio_file=None, ) import_files.handle_modified( - event=event, stdout=stdout, library=library, in_place=True, + event=event, + stdout=stdout, + library=library, + in_place=True, ) update_track_metadata.assert_not_called() diff --git a/api/tests/users/test_authentication.py b/api/tests/users/test_authentication.py index 3de92bd18..a6fcbefd4 100644 --- a/api/tests/users/test_authentication.py +++ b/api/tests/users/test_authentication.py @@ -9,7 +9,9 @@ def test_generate_scoped_token(mocker): dumps = mocker.patch("django.core.signing.dumps") result = authentication.generate_scoped_token( - user_id=42, user_secret="hello", scopes=["read"], + user_id=42, + user_secret="hello", + scopes=["read"], ) assert result == dumps.return_value diff --git a/docs/conf.py b/docs/conf.py index 355eea6d5..b325ac0e1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,7 +47,13 @@ for key, value in FUNKWHALE_CONFIG.items(): # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ["sphinx.ext.graphviz", "sphinx.ext.autodoc"] -autodoc_mock_imports = ["celery", "django_auth_ldap", "ldap", "persisting_theory", "rest_framework"] +autodoc_mock_imports = [ + "celery", + "django_auth_ldap", + "ldap", + "persisting_theory", + "rest_framework", +] add_module_names = False # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -107,7 +113,7 @@ html_theme = "sphinx_rtd_theme" # further. For a list of options available for each theme, see the # documentation. # -#html_theme_options = {} +# html_theme_options = {} html_context = { "display_gitlab": True, "gitlab_host": "dev.funkwhale.audio", @@ -152,7 +158,13 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (root_doc, "funkwhale.tex", "funkwhale Documentation", "The Funkwhale Collective", "manual") + ( + root_doc, + "funkwhale.tex", + "funkwhale Documentation", + "The Funkwhale Collective", + "manual", + ) ] diff --git a/front/scripts/fix-fomantic-css.py b/front/scripts/fix-fomantic-css.py index e2a9b6b0a..4979e705a 100755 --- a/front/scripts/fix-fomantic-css.py +++ b/front/scripts/fix-fomantic-css.py @@ -174,7 +174,7 @@ def discard_unused_icons(rule): ".gitlab", ".chevron", ".right", - ".left" + ".left", ] if ":before" not in rule["lines"][0]: return False @@ -355,7 +355,9 @@ REPLACEMENTS = { ".ui.checkbox input:focus ~ label", ".ui.toggle.checkbox input:focus:checked ~ label", ".ui.checkbox input:active ~ label", - ): [("color", "var(--form-label-color)"),], + ): [ + ("color", "var(--form-label-color)"), + ], (".ui.toggle.checkbox label:before",): [ ("background", "var(--input-background)"), ], @@ -365,7 +367,9 @@ REPLACEMENTS = { ("border-top", "var(--divider)"), ("border-bottom", "var(--divider)"), ], - (".ui.divider",): [("color", "var(--text-color)"),], + (".ui.divider",): [ + ("color", "var(--text-color)"), + ], }, "dimmer": { (".ui.inverted.dimmer",): [ @@ -374,7 +378,12 @@ REPLACEMENTS = { ], }, "dropdown": { - "skip": [".error", ".info", ".success", ".warning",], + "skip": [ + ".error", + ".info", + ".success", + ".warning", + ], ( ".ui.selection.dropdown", ".ui.selection.visible.dropdown > .text:not(.default)", @@ -383,7 +392,9 @@ REPLACEMENTS = { ("background", "var(--dropdown-background)"), ("color", "var(--dropdown-color)"), ], - (".ui.dropdown .menu > .item",): [("color", "var(--dropdown-item-color)"),], + (".ui.dropdown .menu > .item",): [ + ("color", "var(--dropdown-item-color)"), + ], (".ui.dropdown .menu > .item:hover",): [ ("color", "var(--dropdown-item-hover-color)"), ("background", "var(--dropdown-item-hover-background)"), @@ -395,10 +406,18 @@ REPLACEMENTS = { (".ui.dropdown .menu > .header:not(.ui)",): [ ("color", "var(--dropdown-header-color)"), ], - (".ui.dropdown .menu > .divider",): [("border-top", "var(--divider)"),], + (".ui.dropdown .menu > .divider",): [ + ("border-top", "var(--divider)"), + ], }, "form": { - "skip": [".inverted", ".success", ".warning", ".error", ".info",], + "skip": [ + ".inverted", + ".success", + ".warning", + ".error", + ".info", + ], ('.ui.form input[type="text"]', ".ui.form select", ".ui.input textarea"): [ ("background", "var(--input-background)"), ("color", "var(--input-color)"), @@ -415,12 +434,16 @@ REPLACEMENTS = { ".ui.form ::-webkit-input-placeholder", ".ui.form :-ms-input-placeholder", ".ui.form ::-moz-placeholder", - ): [("color", "var(--input-placeholder-color)"),], + ): [ + ("color", "var(--input-placeholder-color)"), + ], ( ".ui.form :focus::-webkit-input-placeholder", ".ui.form :focus:-ms-input-placeholder", ".ui.form :focus::-moz-placeholder", - ): [("color", "var(--input-focus-placeholder-color)"),], + ): [ + ("color", "var(--input-focus-placeholder-color)"), + ], (".ui.form .field > label", ".ui.form .inline.fields .field > label",): [ ("color", "var(--form-label-color)"), ], @@ -475,16 +498,24 @@ REPLACEMENTS = { ".ui.input > input::-webkit-input-placeholder", ".ui.input > input::-moz-placeholder", ".ui.input > input:-ms-input-placeholder", - ): [("color", "var(--input-placeholder-color)"),], + ): [ + ("color", "var(--input-placeholder-color)"), + ], ( ".ui.input > input:focus::-webkit-input-placeholder", ".ui.input > input:focus::-moz-placeholder", ".ui.input > input:focus:-ms-input-placeholder", - ): [("color", "var(--input-focus-placeholder-color)"),], + ): [ + ("color", "var(--input-focus-placeholder-color)"), + ], }, "item": { - (".ui.divided.items > .item",): [("border-top", "var(--divider)"),], - (".ui.items > .item > .content",): [("color", "var(--text-color)"),], + (".ui.divided.items > .item",): [ + ("border-top", "var(--divider)"), + ], + (".ui.items > .item > .content",): [ + ("color", "var(--text-color)"), + ], (".ui.items > .item .extra",): [ ("color", "var(--really-discrete-text-color)"), ], @@ -503,8 +534,12 @@ REPLACEMENTS = { ".black", ".pink", ], - (".ui.header",): [("color", "var(--header-color)"),], - (".ui.header .sub.header",): [("color", "var(--header-color)"),], + (".ui.header",): [ + ("color", "var(--header-color)"), + ], + (".ui.header .sub.header",): [ + ("color", "var(--header-color)"), + ], }, "label": { "skip": [ @@ -580,7 +615,9 @@ REPLACEMENTS = { ".danger", ".elastic", ], - (".ui.inverted.dimmer > .ui.loader",): [("color", "var(--dimmer-color)"),], + (".ui.inverted.dimmer > .ui.loader",): [ + ("color", "var(--dimmer-color)"), + ], }, "message": { "skip": [ @@ -620,7 +657,9 @@ REPLACEMENTS = { ".fitted", "fixed", ], - (".ui.menu .item",): [("color", "var(--menu-item-color)"),], + (".ui.menu .item",): [ + ("color", "var(--menu-item-color)"), + ], (".ui.vertical.inverted.menu .menu .item", ".ui.inverted.menu .item"): [ ("color", "var(--inverted-menu-item-color)"), ], @@ -633,7 +672,9 @@ REPLACEMENTS = { ( ".ui.secondary.pointing.menu a.item:hover", ".ui.secondary.pointing.menu .active.item:hover", - ): [("color", "var(--secondary-menu-hover-item-color)"),], + ): [ + ("color", "var(--secondary-menu-hover-item-color)"), + ], (".ui.menu .ui.dropdown .menu > .item",): [ ("color", "var(--dropdown-item-color) !important"), ], @@ -656,7 +697,9 @@ REPLACEMENTS = { ("border-bottom", "var(--divider)"), ("border-top", "var(--divider)"), ], - (".ui.modal > .close.inside",): [("color", "var(--text-color)"),], + (".ui.modal > .close.inside",): [ + ("color", "var(--text-color)"), + ], (".ui.modal > .header",): [ ("color", "var(--header-color)"), ("background", "var(--modal-background)"), @@ -680,7 +723,9 @@ REPLACEMENTS = { ( ".ui.search > .results .result .title", ".ui.search > .results .result .description", - ): [("color", "var(--dropdown-item-color)"),], + ): [ + ("color", "var(--dropdown-item-color)"), + ], (".ui.search > .results .result:hover",): [ ("color", "var(--dropdown-item-hover-color)"), ("background", "var(--dropdown-item-hover-background)"), @@ -696,7 +741,9 @@ REPLACEMENTS = { ], }, "sidebar": { - (".ui.left.visible.sidebar",): [("box-shadow", "var(--sidebar-box-shadow)"),] + (".ui.left.visible.sidebar",): [ + ("box-shadow", "var(--sidebar-box-shadow)"), + ] }, "statistic": { (".ui.statistic > .value", ".ui.statistic > .label"): [ @@ -704,7 +751,9 @@ REPLACEMENTS = { ], }, "progress": { - (".ui.progress.success > .label",): [("color", "var(--text-color)"),], + (".ui.progress.success > .label",): [ + ("color", "var(--text-color)"), + ], }, "table": { "skip": [ diff --git a/pyproject.toml b/pyproject.toml index 21dd7c106..1d6c64b81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,4 +43,4 @@ showcontent = true [tool.black] - exclude = "(.git|.hg|.mypy_cache|.tox|.venv|_build|buck-out|build|dist|migrations)" + exclude = "(.git|.hg|.mypy_cache|.tox|.venv|_build|buck-out|build|dist|migrations|data)"