From 7caa60dba5988d0d3ebcdd6bd6b424d7b4b00c62 Mon Sep 17 00:00:00 2001 From: Rajat Dwivedi <113243168+rkmdCodes@users.noreply.github.com> Date: Mon, 27 Feb 2023 20:14:32 +0530 Subject: [PATCH 001/113] Improving Feed link UI colours --- bookwyrm/static/css/themes/bookwyrm-light.scss | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bookwyrm/static/css/themes/bookwyrm-light.scss b/bookwyrm/static/css/themes/bookwyrm-light.scss index efb13c23e..5ed74c629 100644 --- a/bookwyrm/static/css/themes/bookwyrm-light.scss +++ b/bookwyrm/static/css/themes/bookwyrm-light.scss @@ -65,6 +65,23 @@ $family-secondary: $family-sans-serif; color: $grey !important; } +.tabs li:not(.is-active) a { + color: #3273dc !important; +} + .tabs li:not(.is-active) a:hover { + border-bottom-color: #3273dc !important; +} + +.tabs li:not(.is-active) a { + color: #3273dc !important; +} +.tabs li.is-active a { + color: #4a4a4a !important; + border-bottom-color: #4a4a4a !important ; +} + + + @import "../bookwyrm.scss"; @import "../vendor/icons.css"; @import "../vendor/shepherd.scss"; From 349c61f69876f6e92cce12b9f0cb22b5fd7a16d5 Mon Sep 17 00:00:00 2001 From: Rajat Dwivedi Date: Mon, 20 Mar 2023 04:11:44 +0000 Subject: [PATCH 002/113] Updated the _tabs.scss file --- .../static/css/bookwyrm/components/_tabs.scss | 6 +++--- bookwyrm/static/css/themes/bookwyrm-light.scss | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm/components/_tabs.scss b/bookwyrm/static/css/bookwyrm/components/_tabs.scss index 8e00f6a88..3fed83898 100644 --- a/bookwyrm/static/css/bookwyrm/components/_tabs.scss +++ b/bookwyrm/static/css/bookwyrm/components/_tabs.scss @@ -34,7 +34,7 @@ border-bottom-color: $border; border-bottom-style: solid; border-bottom-width: 1px; - color: $text; + color: $link; display: flex; justify-content: center; margin-bottom: -1px; @@ -44,12 +44,12 @@ .bw-tabs a:hover { border-bottom-color: transparent; - color: $text; + color: $link } .bw-tabs a.is-active { border-bottom-color: transparent; - color: $link; + color: $text } .bw-tabs.is-left { diff --git a/bookwyrm/static/css/themes/bookwyrm-light.scss b/bookwyrm/static/css/themes/bookwyrm-light.scss index 5ed74c629..21d46ff28 100644 --- a/bookwyrm/static/css/themes/bookwyrm-light.scss +++ b/bookwyrm/static/css/themes/bookwyrm-light.scss @@ -65,21 +65,6 @@ $family-secondary: $family-sans-serif; color: $grey !important; } -.tabs li:not(.is-active) a { - color: #3273dc !important; -} - .tabs li:not(.is-active) a:hover { - border-bottom-color: #3273dc !important; -} - -.tabs li:not(.is-active) a { - color: #3273dc !important; -} -.tabs li.is-active a { - color: #4a4a4a !important; - border-bottom-color: #4a4a4a !important ; -} - @import "../bookwyrm.scss"; From 05e154f93ed3b6238f98c10bef0d886384af257a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 20 Mar 2023 13:58:20 -0700 Subject: [PATCH 003/113] Uses referer redirect for some admin views --- bookwyrm/views/admin/imports.py | 3 ++- bookwyrm/views/admin/reports.py | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bookwyrm/views/admin/imports.py b/bookwyrm/views/admin/imports.py index 066bc42e4..7ae190ce8 100644 --- a/bookwyrm/views/admin/imports.py +++ b/bookwyrm/views/admin/imports.py @@ -8,6 +8,7 @@ from django.views import View from django.views.decorators.http import require_POST from bookwyrm import models +from bookwyrm.views.helpers import redirect_to_referer from bookwyrm.settings import PAGE_LENGTH @@ -57,7 +58,7 @@ class ImportList(View): """Mark an import as complete""" import_job = get_object_or_404(models.ImportJob, id=import_id) import_job.stop_job() - return redirect("settings-imports") + return redirect_to_referer(request, "settings-imports") @require_POST diff --git a/bookwyrm/views/admin/reports.py b/bookwyrm/views/admin/reports.py index cf91299d9..480f926a4 100644 --- a/bookwyrm/views/admin/reports.py +++ b/bookwyrm/views/admin/reports.py @@ -8,6 +8,7 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import forms, models +from bookwyrm.views.helpers import redirect_to_referer from bookwyrm.settings import PAGE_LENGTH @@ -84,26 +85,26 @@ class ReportAdmin(View): @login_required @permission_required("bookwyrm.moderate_user") -def suspend_user(_, user_id): +def suspend_user(request, user_id): """mark an account as inactive""" user = get_object_or_404(models.User, id=user_id) user.is_active = False user.deactivation_reason = "moderator_suspension" # this isn't a full deletion, so we don't want to tell the world user.save(broadcast=False) - return redirect("settings-user", user.id) + return redirect_to_referer(request, "settings-user", user.id) @login_required @permission_required("bookwyrm.moderate_user") -def unsuspend_user(_, user_id): +def unsuspend_user(request, user_id): """mark an account as inactive""" user = get_object_or_404(models.User, id=user_id) user.is_active = True user.deactivation_reason = None # this isn't a full deletion, so we don't want to tell the world user.save(broadcast=False) - return redirect("settings-user", user.id) + return redirect_to_referer(request, "settings-user", user.id) @login_required @@ -123,7 +124,7 @@ def moderator_delete_user(request, user_id): if form.is_valid() and moderator.check_password(form.cleaned_data["password"]): user.deactivation_reason = "moderator_deletion" user.delete() - return redirect("settings-user", user.id) + return redirect_to_referer(request, "settings-user", user.id) form.errors["password"] = ["Invalid password"] From 33c13608a80172dafe3deee96a57f2e8cc0d1673 Mon Sep 17 00:00:00 2001 From: Rajat Dwivedi Date: Wed, 29 Mar 2023 10:56:08 +0000 Subject: [PATCH 004/113] Refixing light and dark themes --- .../static/css/bookwyrm/components/_tabs.scss | 6 +++--- bookwyrm/static/css/themes/bookwyrm-dark.scss | 16 ++++++++++++++++ bookwyrm/static/css/themes/bookwyrm-light.scss | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm/components/_tabs.scss b/bookwyrm/static/css/bookwyrm/components/_tabs.scss index 3fed83898..2d68a383b 100644 --- a/bookwyrm/static/css/bookwyrm/components/_tabs.scss +++ b/bookwyrm/static/css/bookwyrm/components/_tabs.scss @@ -34,7 +34,7 @@ border-bottom-color: $border; border-bottom-style: solid; border-bottom-width: 1px; - color: $link; + color: $text; display: flex; justify-content: center; margin-bottom: -1px; @@ -44,12 +44,12 @@ .bw-tabs a:hover { border-bottom-color: transparent; - color: $link + color: $text } .bw-tabs a.is-active { border-bottom-color: transparent; - color: $text + color: $link } .bw-tabs.is-left { diff --git a/bookwyrm/static/css/themes/bookwyrm-dark.scss b/bookwyrm/static/css/themes/bookwyrm-dark.scss index ae904b4a4..c3e8655e3 100644 --- a/bookwyrm/static/css/themes/bookwyrm-dark.scss +++ b/bookwyrm/static/css/themes/bookwyrm-dark.scss @@ -98,6 +98,22 @@ $family-secondary: $family-sans-serif; } +.tabs li:not(.is-active) a { + color: #2e7eb9 !important; +} + .tabs li:not(.is-active) a:hover { + border-bottom-color: #2e7eb9 !important; +} + +.tabs li:not(.is-active) a { + color: #2e7eb9 !important; +} +.tabs li.is-active a { + color: #e6e6e6 !important; + border-bottom-color: #e6e6e6 !important ; +} + + #qrcode svg { background-color: #a6a6a6; } diff --git a/bookwyrm/static/css/themes/bookwyrm-light.scss b/bookwyrm/static/css/themes/bookwyrm-light.scss index 21d46ff28..bb7d340a9 100644 --- a/bookwyrm/static/css/themes/bookwyrm-light.scss +++ b/bookwyrm/static/css/themes/bookwyrm-light.scss @@ -65,6 +65,20 @@ $family-secondary: $family-sans-serif; color: $grey !important; } +.tabs li:not(.is-active) a { + color: #3273dc !important; +} + .tabs li:not(.is-active) a:hover { + border-bottom-color: #3273dc !important; +} + +.tabs li:not(.is-active) a { + color: #3273dc !important; +} +.tabs li.is-active a { + color: #4a4a4a !important; + border-bottom-color: #4a4a4a !important ; +} @import "../bookwyrm.scss"; From 42dd19908460557c1f5c362e09ed86c1d026681c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 08:28:45 -0700 Subject: [PATCH 005/113] Unit test that identifies clashes between links and mentions --- bookwyrm/tests/views/test_status.py | 10 ++++++++++ bookwyrm/views/status.py | 23 ++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index d02c71374..6863c9625 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -456,6 +456,16 @@ http://www.fish.com/""" views.status.format_links(url), f'{url[8:]}' ) + def test_format_links_with_at_symbol(self, *_): + """A link with an @username shouldn't treat the username as a mention""" + content = "a link to https://www.example.com/user/@mouse" + mentions = views.status.find_mentions(self.local_user, content) + # pylint: disable=line-too-long + self.assertEqual( + views.status.format_mentions(content, mentions), + 'a link to www.example.com/user/@mouse' + ) + def test_to_markdown(self, *_): """this is mostly handled in other places, but nonetheless""" text = "_hi_ and http://fish.com is rad" diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 82d033d7c..866657a3b 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -96,18 +96,12 @@ class CreateStatus(View): # inspect the text for user tags content = status.content - for (mention_text, mention_user) in find_mentions( - request.user, content - ).items(): + mentions = find_mentions(request.user, content) + for (_, mention_user) in mentions: # add them to status mentions fk status.mention_users.add(mention_user) + content = format_mentions(content, mentions) - # turn the mention into a link - content = re.sub( - rf"{mention_text}\b(?!@)", - rf'{mention_text}', - content, - ) # add reply parent to mentions if status.reply_parent: status.mention_users.add(status.reply_parent.user) @@ -149,6 +143,17 @@ class CreateStatus(View): return HttpResponse() return redirect_to_referer(request) +def format_mentions(content, mentions): + """Detect @mentions and make them links""" + for (mention_text, mention_user) in mentions.items(): + # turn the mention into a link + content = re.sub( + rf"{mention_text}\b(?!@)", + rf'{mention_text}', + content, + ) + return content + @method_decorator(login_required, name="dispatch") class DeleteStatus(View): From 8a0e88db8343341e5161cf0437407134b5182bc3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 08:39:41 -0700 Subject: [PATCH 006/113] Adds test for links with # symbols --- bookwyrm/tests/views/test_status.py | 16 +++++++++++++--- bookwyrm/views/status.py | 26 +++++++++++++++++--------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 6863c9625..1ec148991 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -456,14 +456,24 @@ http://www.fish.com/""" views.status.format_links(url), f'{url[8:]}' ) - def test_format_links_with_at_symbol(self, *_): + def test_format_mentions_with_at_symbol_links(self, *_): """A link with an @username shouldn't treat the username as a mention""" - content = "a link to https://www.example.com/user/@mouse" + content = "a link to https://example.com/user/@mouse" mentions = views.status.find_mentions(self.local_user, content) # pylint: disable=line-too-long self.assertEqual( views.status.format_mentions(content, mentions), - 'a link to www.example.com/user/@mouse' + 'a link to www.example.com/user/@mouse', + ) + + def test_format_hashtag_with_pound_symbol_links(self, *_): + """A link with an @username shouldn't treat the username as a mention""" + content = "a link to https://example.com/page#anchor" + hashtags = views.status.find_or_create_hashtags(content) + # pylint: disable=line-too-long + self.assertEqual( + views.status.format_hashtags(content, hashtags), + 'a link to example.com/page#anchor', ) def test_to_markdown(self, *_): diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 866657a3b..0e4d4e396 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -107,17 +107,11 @@ class CreateStatus(View): status.mention_users.add(status.reply_parent.user) # inspect the text for hashtags - for (mention_text, mention_hashtag) in find_or_create_hashtags(content).items(): + hashtags = find_or_create_hashtags(content) + for (_, mention_hashtag) in hashtags.items(): # add them to status mentions fk status.mention_hashtags.add(mention_hashtag) - - # turn the mention into a link - content = re.sub( - rf"{mention_text}\b(?!@)", - rf'' - + rf"{mention_text}", - content, - ) + content = format_hashtags(content, hashtags) # deduplicate mentions status.mention_users.set(set(status.mention_users.all())) @@ -143,6 +137,7 @@ class CreateStatus(View): return HttpResponse() return redirect_to_referer(request) + def format_mentions(content, mentions): """Detect @mentions and make them links""" for (mention_text, mention_user) in mentions.items(): @@ -155,6 +150,19 @@ def format_mentions(content, mentions): return content +def format_hashtags(content, hashtags): + """Detect #hashtags and make them links""" + for (mention_text, mention_hashtag) in hashtags.items(): + # turn the mention into a link + content = re.sub( + rf"{mention_text}\b(?!@)", + rf'' + + rf"{mention_text}", + content, + ) + return content + + @method_decorator(login_required, name="dispatch") class DeleteStatus(View): """tombstone that bad boy""" From 4fcb01805ef18eb9f4290acbe44acef48c1059d8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 09:14:30 -0700 Subject: [PATCH 007/113] Fixes test comparison string --- bookwyrm/tests/views/test_status.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 1ec148991..71b3eaacc 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -460,20 +460,18 @@ http://www.fish.com/""" """A link with an @username shouldn't treat the username as a mention""" content = "a link to https://example.com/user/@mouse" mentions = views.status.find_mentions(self.local_user, content) - # pylint: disable=line-too-long self.assertEqual( views.status.format_mentions(content, mentions), - 'a link to www.example.com/user/@mouse', + 'a link to https://example.com/user/@mouse', ) def test_format_hashtag_with_pound_symbol_links(self, *_): """A link with an @username shouldn't treat the username as a mention""" content = "a link to https://example.com/page#anchor" hashtags = views.status.find_or_create_hashtags(content) - # pylint: disable=line-too-long self.assertEqual( views.status.format_hashtags(content, hashtags), - 'a link to example.com/page#anchor', + 'a link to https://example.com/page#anchor', ) def test_to_markdown(self, *_): From fe856bcf2c69d5c806bb78a26ac5c5f53fedb5d9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 09:20:58 -0700 Subject: [PATCH 008/113] Updates regex on mentions and hashtags --- bookwyrm/views/status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 0e4d4e396..3c5b7bcf3 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -143,7 +143,7 @@ def format_mentions(content, mentions): for (mention_text, mention_user) in mentions.items(): # turn the mention into a link content = re.sub( - rf"{mention_text}\b(?!@)", + rf"(?{mention_text}', content, ) @@ -155,7 +155,7 @@ def format_hashtags(content, hashtags): for (mention_text, mention_hashtag) in hashtags.items(): # turn the mention into a link content = re.sub( - rf"{mention_text}\b(?!@)", + rf"(?' + rf"{mention_text}", content, From f2ab8c2fe260a12e354060a1a46653fe2f09e711 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 10:04:23 -0700 Subject: [PATCH 009/113] Fixes effect/affect error --- bookwyrm/templates/settings/imports/imports.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/imports/imports.html b/bookwyrm/templates/settings/imports/imports.html index 108003d85..8819220fb 100644 --- a/bookwyrm/templates/settings/imports/imports.html +++ b/bookwyrm/templates/settings/imports/imports.html @@ -28,7 +28,7 @@ >
{% trans "This is only intended to be used when things have gone very wrong with imports and you need to pause the feature while addressing issues." %} - {% trans "While imports are disabled, users will not be allowed to start new imports, but existing imports will not be effected." %} + {% trans "While imports are disabled, users will not be allowed to start new imports, but existing imports will not be affected." %}
{% csrf_token %}
From f1640399e3c3f1a08eb5755dc1f8c6d21fad3949 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 10:12:25 -0700 Subject: [PATCH 010/113] Python formatting --- bookwyrm/tests/views/test_status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 71b3eaacc..7c64fdb0c 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -462,7 +462,7 @@ http://www.fish.com/""" mentions = views.status.find_mentions(self.local_user, content) self.assertEqual( views.status.format_mentions(content, mentions), - 'a link to https://example.com/user/@mouse', + "a link to https://example.com/user/@mouse", ) def test_format_hashtag_with_pound_symbol_links(self, *_): @@ -471,7 +471,7 @@ http://www.fish.com/""" hashtags = views.status.find_or_create_hashtags(content) self.assertEqual( views.status.format_hashtags(content, hashtags), - 'a link to https://example.com/page#anchor', + "a link to https://example.com/page#anchor", ) def test_to_markdown(self, *_): From b76da26c983f519033b610b3a2cc4b62e2db11c9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 29 Mar 2023 10:13:02 -0700 Subject: [PATCH 011/113] Fixes iteration over mentions dict --- bookwyrm/views/status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 3c5b7bcf3..a8c874c13 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -97,7 +97,7 @@ class CreateStatus(View): # inspect the text for user tags content = status.content mentions = find_mentions(request.user, content) - for (_, mention_user) in mentions: + for (_, mention_user) in mentions.items(): # add them to status mentions fk status.mention_users.add(mention_user) content = format_mentions(content, mentions) From 282f41bdb8cf1aa37468e0a998fc3025d30cb144 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:28:59 +0000 Subject: [PATCH 012/113] Bump redis from 4.5.3 to 4.5.4 Bumps [redis](https://github.com/redis/redis-py) from 4.5.3 to 4.5.4. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v4.5.3...v4.5.4) --- updated-dependencies: - dependency-name: redis dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 29ce0e5de..f8f1ab937 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ Pillow==9.4.0 psycopg2==2.9.5 pycryptodome==3.16.0 python-dateutil==2.8.2 -redis==4.5.3 +redis==4.5.4 requests==2.28.2 responses==0.22.0 pytz>=2022.7 From b1962ef75d71a1fdbf2fc9301499d2effad95a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Wall=C3=B8e?= Date: Sat, 1 Apr 2023 11:23:27 +0200 Subject: [PATCH 013/113] Added command 'down', to bring down containers Added the command 'down', which can be used to bring down the docker containers. Equivalent to running 'docker-compose down' --- bw-dev | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bw-dev b/bw-dev index 9fae5dcde..7e2ef0b0f 100755 --- a/bw-dev +++ b/bw-dev @@ -77,6 +77,9 @@ case "$CMD" in up) docker-compose up --build "$@" ;; + down) + docker-compose down + ;; service_ports_web) prod_error docker-compose run --rm --service-ports web From 6e427cf37220a781d46a571ac88c8a575226816b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 3 Apr 2023 21:31:41 -0700 Subject: [PATCH 014/113] Update version number --- bookwyrm/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 4483c07d9..419b76195 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -12,7 +12,7 @@ from django.core.exceptions import ImproperlyConfigured env = Env() env.read_env() DOMAIN = env("DOMAIN") -VERSION = "0.6.0" +VERSION = "0.6.1" RELEASE_API = env( "RELEASE_API", From 0495da07a4ceb8d3adfeb5a62b552405049b1de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Wall=C3=B8e?= Date: Tue, 4 Apr 2023 12:08:39 +0200 Subject: [PATCH 015/113] Update bw-dev Added 'down' to list of of commands --- bw-dev | 1 + 1 file changed, 1 insertion(+) diff --git a/bw-dev b/bw-dev index 7e2ef0b0f..b2a23d852 100755 --- a/bw-dev +++ b/bw-dev @@ -287,6 +287,7 @@ case "$CMD" in echo "Unrecognised command. Try:" echo " setup" echo " up [container]" + echo " down [container]" echo " service_ports_web" echo " initdb" echo " resetdb" From def58a3e18a29894ceea44e7a87235e74f7c04c2 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:12:58 -0400 Subject: [PATCH 016/113] spelling: activity Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/activitypub/test_quotation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/activitypub/test_quotation.py b/bookwyrm/tests/activitypub/test_quotation.py index c90348bc3..74728274b 100644 --- a/bookwyrm/tests/activitypub/test_quotation.py +++ b/bookwyrm/tests/activitypub/test_quotation.py @@ -1,4 +1,4 @@ -""" quotation activty object serializer class """ +""" quotation activity object serializer class """ import json import pathlib from unittest.mock import patch From 118b5bfda73812b9c32cec9b31c096cdcccd13e1 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Tue, 4 Apr 2023 14:21:08 -0400 Subject: [PATCH 017/113] Add more information to get_audience telemetry This will assist with debugging #2720, by letting us see which kinds of requests take the longest. --- bookwyrm/activitystreams.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 74471883e..4bac49957 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -102,8 +102,15 @@ class ActivityStream(RedisStore): """go from zero to a timeline""" self.populate_store(self.stream_id(user.id)) + @tracer.start_as_current_span("ActivityStream._get_audience") def _get_audience(self, status): # pylint: disable=no-self-use """given a status, what users should see it""" + trace.get_current_span().set_attribute("status_type", status.status_type) + trace.get_current_span().set_attribute("status_privacy", status.privacy) + trace.get_current_span().set_attribute( + "status_reply_parent_privacy", + status.reply_parent.privacy if status.reply_parent else None, + ) # direct messages don't appeard in feeds, direct comments/reviews/etc do if status.privacy == "direct" and status.status_type == "Note": return [] From 94c573b469c31d383090fca151450ab3b2e2bb36 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:02:47 -0400 Subject: [PATCH 018/113] spelling: appear Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/activitystreams.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 74471883e..7f6a8d105 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -104,7 +104,7 @@ class ActivityStream(RedisStore): def _get_audience(self, status): # pylint: disable=no-self-use """given a status, what users should see it""" - # direct messages don't appeard in feeds, direct comments/reviews/etc do + # direct messages don't appear in feeds, direct comments/reviews/etc do if status.privacy == "direct" and status.status_type == "Note": return [] From 06fa1adc27d55544daf7f9935f003e881c653082 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:12:59 -0400 Subject: [PATCH 019/113] spelling: arbitrary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/connectors/connector_manager.py | 2 +- bookwyrm/templatetags/utilities.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 4330d4ac2..d7e2aad4b 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -73,7 +73,7 @@ async def async_connector_search(query, items, min_confidence): def search(query, min_confidence=0.1, return_first=False): - """find books based on arbitary keywords""" + """find books based on arbitrary keywords""" if not query: return [] results = [] diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py index 834d39a14..4aaf6b8a7 100644 --- a/bookwyrm/templatetags/utilities.py +++ b/bookwyrm/templatetags/utilities.py @@ -19,7 +19,7 @@ def get_uuid(identifier): @register.simple_tag(takes_context=False) def join(*args): - """concatenate an arbitary set of values""" + """concatenate an arbitrary set of values""" return "_".join(str(a) for a in args) From 319be60c8041bc64bf48f30300f28090d603290a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:00 -0400 Subject: [PATCH 020/113] spelling: assigning Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 6cfe4c10c..cd967c393 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -71,7 +71,7 @@ class ActivitypubFieldMixin: def set_field_from_activity( self, instance, data, overwrite=True, allow_external_connections=True ): - """helper function for assinging a value to the field. Returns if changed""" + """helper function for assigning a value to the field. Returns if changed""" try: value = getattr(data, self.get_activitypub_field()) except AttributeError: @@ -431,7 +431,7 @@ class ImageField(ActivitypubFieldMixin, models.ImageField): def set_field_from_activity( self, instance, data, save=True, overwrite=True, allow_external_connections=True ): - """helper function for assinging a value to the field""" + """helper function for assigning a value to the field""" value = getattr(data, self.get_activitypub_field()) formatted = self.field_from_activity( value, allow_external_connections=allow_external_connections From b3edeca295e380f188eaaac8c6cf953f767f439b Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:00 -0400 Subject: [PATCH 021/113] spelling: associated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/link.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/link.py b/bookwyrm/models/link.py index 56b096bc2..d334a9d29 100644 --- a/bookwyrm/models/link.py +++ b/bookwyrm/models/link.py @@ -31,7 +31,7 @@ class Link(ActivitypubMixin, BookWyrmModel): @property def name(self): - """link name via the assocaited domain""" + """link name via the associated domain""" return self.domain.name def save(self, *args, **kwargs): From 54285e4bcde9a110f41a7a330a6809102de40ef7 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:01 -0400 Subject: [PATCH 022/113] spelling: auxiliary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 83ca90b0a..36685152e 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -235,7 +235,7 @@ class ObjectMixin(ActivitypubMixin): self.broadcast(activity, user, software=software, queue=priority) except AttributeError: # janky as heck, this catches the mutliple inheritence chain - # for boosts and ignores this auxilliary broadcast + # for boosts and ignores this auxiliary broadcast return return From fb74c1977ebb27727a673ce8fd51e95064c71414 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:02 -0400 Subject: [PATCH 023/113] spelling: because Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index a8c874c13..e3a7481f8 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -232,7 +232,7 @@ def find_mentions(user, content): if not content: return {} # The regex has nested match groups, so the 0th entry has the full (outer) match - # And beacuse the strict username starts with @, the username is 1st char onward + # And because the strict username starts with @, the username is 1st char onward usernames = [m[0][1:] for m in re.findall(regex.STRICT_USERNAME, content)] known_users = ( From 72c292d2c3a7eddfc55994828c6e3aae920654b2 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:02 -0400 Subject: [PATCH 024/113] spelling: breakpoints Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/static/css/bookwyrm/components/_book_cover.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm/components/_book_cover.scss b/bookwyrm/static/css/bookwyrm/components/_book_cover.scss index d1125197e..db9391cc1 100644 --- a/bookwyrm/static/css/bookwyrm/components/_book_cover.scss +++ b/bookwyrm/static/css/bookwyrm/components/_book_cover.scss @@ -5,7 +5,7 @@ * - .book-cover is positioned and sized based on its container. * * To have the cover within specific dimensions, specify a width or height for - * standard bulma’s named breapoints: + * standard bulma’s named breakpoints: * * `is-(w|h)-(auto|xs|s|m|l|xl|xxl)[-(mobile|tablet|desktop)]` * From be31a4b576b906a02128c183faba96876ea0882e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:20:55 -0400 Subject: [PATCH 025/113] spelling: creating Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/books/edit_book.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 167bd4b46..97b012db8 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -154,7 +154,7 @@ def add_authors(request, data): data["author_matches"] = [] data["isni_matches"] = [] - # creting a book or adding an author to a book needs another step + # creating a book or adding an author to a book needs another step data["confirm_mode"] = True # this isn't preserved because it isn't part of the form obj data["remove_authors"] = request.POST.getlist("remove_authors") From 6b0e51caf45b19abe527dc70c4e643a7c9c5697f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:03 -0400 Subject: [PATCH 026/113] spelling: currently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/templatetags/test_rating_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/templatetags/test_rating_tags.py b/bookwyrm/tests/templatetags/test_rating_tags.py index a06ee9402..5abfa471a 100644 --- a/bookwyrm/tests/templatetags/test_rating_tags.py +++ b/bookwyrm/tests/templatetags/test_rating_tags.py @@ -41,7 +41,7 @@ class RatingTags(TestCase): @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_get_rating(self, *_): """privacy filtered rating. Commented versions are how it ought to work with - subjective ratings, which are currenly not used for performance reasons.""" + subjective ratings, which are currently not used for performance reasons.""" # follows-only: not included models.ReviewRating.objects.create( user=self.remote_user, From cfe388896bb88fbe0fc36ee5d90cb7594e97c136 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:04 -0400 Subject: [PATCH 027/113] spelling: dashboard Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/admin/dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py index b49c5a238..9d256fc6c 100644 --- a/bookwyrm/views/admin/dashboard.py +++ b/bookwyrm/views/admin/dashboard.py @@ -76,7 +76,7 @@ class Dashboard(View): def get_charts_and_stats(request): - """Defines the dashbaord charts""" + """Defines the dashboard charts""" interval = int(request.GET.get("days", 1)) now = timezone.now() start = request.GET.get("start") From 9ea5a3b89c1202f18343a65cd55d9461e42880b8 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:03 -0400 Subject: [PATCH 028/113] spelling: data Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/connectors/inventaire.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index a330b2c4a..f3e24c0ec 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -97,7 +97,7 @@ class Connector(AbstractConnector): ) def parse_isbn_search_data(self, data): - """got some daaaata""" + """got some data""" results = data.get("entities") if not results: return From c2022acf67457caf377d01a48ceec05ceef9393a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:04 -0400 Subject: [PATCH 029/113] spelling: deduplicate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/management/commands/deduplicate_book_data.py | 2 +- bookwyrm/management/commands/remove_editions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/management/commands/deduplicate_book_data.py b/bookwyrm/management/commands/deduplicate_book_data.py index ed01a7843..5c5888d36 100644 --- a/bookwyrm/management/commands/deduplicate_book_data.py +++ b/bookwyrm/management/commands/deduplicate_book_data.py @@ -68,7 +68,7 @@ def dedupe_model(model): class Command(BaseCommand): - """dedplucate allllll the book data models""" + """deduplicate allllll the book data models""" help = "merges duplicate book data" # pylint: disable=no-self-use,unused-argument diff --git a/bookwyrm/management/commands/remove_editions.py b/bookwyrm/management/commands/remove_editions.py index 9eb9b7da8..ee7253543 100644 --- a/bookwyrm/management/commands/remove_editions.py +++ b/bookwyrm/management/commands/remove_editions.py @@ -33,7 +33,7 @@ def remove_editions(): class Command(BaseCommand): - """dedplucate allllll the book data models""" + """deduplicate allllll the book data models""" help = "merges duplicate book data" # pylint: disable=no-self-use,unused-argument From 9cad11b2b341d7fb8dc7f3ef1a025aef488337e7 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:05 -0400 Subject: [PATCH 030/113] spelling: deduplication Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 36685152e..7f444b673 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -91,7 +91,7 @@ class ActivitypubMixin: @classmethod def find_existing(cls, data): - """compare data to fields that can be used for deduplation. + """compare data to fields that can be used for deduplication. This always includes remote_id, but can also be unique identifiers like an isbn for an edition""" filters = [] From 45a1457a4f7ec034644f484954b820f02284a4d5 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:06 -0400 Subject: [PATCH 031/113] spelling: deduplications Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/management/commands/deduplicate_book_data.py | 2 +- bookwyrm/management/commands/remove_editions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/management/commands/deduplicate_book_data.py b/bookwyrm/management/commands/deduplicate_book_data.py index 5c5888d36..5ca8496b0 100644 --- a/bookwyrm/management/commands/deduplicate_book_data.py +++ b/bookwyrm/management/commands/deduplicate_book_data.py @@ -73,7 +73,7 @@ class Command(BaseCommand): help = "merges duplicate book data" # pylint: disable=no-self-use,unused-argument def handle(self, *args, **options): - """run deudplications""" + """run deduplications""" dedupe_model(models.Edition) dedupe_model(models.Work) dedupe_model(models.Author) diff --git a/bookwyrm/management/commands/remove_editions.py b/bookwyrm/management/commands/remove_editions.py index ee7253543..5cb430a93 100644 --- a/bookwyrm/management/commands/remove_editions.py +++ b/bookwyrm/management/commands/remove_editions.py @@ -38,5 +38,5 @@ class Command(BaseCommand): help = "merges duplicate book data" # pylint: disable=no-self-use,unused-argument def handle(self, *args, **options): - """run deudplications""" + """run deduplications""" remove_editions() From c92cdec36e58f2fc73d33ff7400b8968d45e1727 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:05 -0400 Subject: [PATCH 032/113] spelling: default Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 3b541eb7c..fb0f7308d 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,7 @@ USE_HTTPS=true DOMAIN=your.domain.here EMAIL=your@email.here -# Instance defualt language (see options at bookwyrm/settings.py "LANGUAGES" +# Instance default language (see options at bookwyrm/settings.py "LANGUAGES" LANGUAGE_CODE="en-us" # Used for deciding which editions to prefer DEFAULT_LANGUAGE="English" From f6a6cb281b3e0a6115c55ed5d045eb566a9ac79d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:21:10 -0400 Subject: [PATCH 033/113] spelling: different Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index cd967c393..6fd94d019 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -221,7 +221,7 @@ PrivacyLevels = [ class PrivacyField(ActivitypubFieldMixin, models.CharField): - """this maps to two differente activitypub fields""" + """this maps to two different activitypub fields""" public = "https://www.w3.org/ns/activitystreams#Public" From 8d4b69927bbd0bb956d74cd25ceadfb03bb8892d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:06 -0400 Subject: [PATCH 034/113] spelling: directly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/connectors/abstract_connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 0e04ffaf2..ccb987ee2 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -321,7 +321,7 @@ def infer_physical_format(format_text): def unique_physical_format(format_text): - """only store the format if it isn't diretly in the format mappings""" + """only store the format if it isn't directly in the format mappings""" format_text = format_text.lower() if format_text in format_mappings: # try a direct match, so saving this would be redundant From 3850183e953f25f5efec50716ce89f4938f7c7d4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:07 -0400 Subject: [PATCH 035/113] spelling: doesn't Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/views/inbox/test_inbox_delete.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_delete.py b/bookwyrm/tests/views/inbox/test_inbox_delete.py index b4863aad5..0fb108e22 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_delete.py +++ b/bookwyrm/tests/views/inbox/test_inbox_delete.py @@ -58,7 +58,7 @@ class InboxActivities(TestCase): with patch("bookwyrm.activitystreams.remove_status_task.delay") as redis_mock: views.inbox.activity_task(activity) self.assertTrue(redis_mock.called) - # deletion doens't remove the status, it turns it into a tombstone + # deletion doesn't remove the status, it turns it into a tombstone status = models.Status.objects.get() self.assertTrue(status.deleted) self.assertIsInstance(status.deleted_date, datetime) @@ -87,7 +87,7 @@ class InboxActivities(TestCase): with patch("bookwyrm.activitystreams.remove_status_task.delay") as redis_mock: views.inbox.activity_task(activity) self.assertTrue(redis_mock.called) - # deletion doens't remove the status, it turns it into a tombstone + # deletion doesn't remove the status, it turns it into a tombstone status = models.Status.objects.get() self.assertTrue(status.deleted) self.assertIsInstance(status.deleted_date, datetime) From b949259c5760b2cd6f607bd5128b3384e146a991 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:08 -0400 Subject: [PATCH 036/113] spelling: embedded Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/list/embed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/list/embed.py b/bookwyrm/views/list/embed.py index 9d0078b65..a62c9c1ba 100644 --- a/bookwyrm/views/list/embed.py +++ b/bookwyrm/views/list/embed.py @@ -14,7 +14,7 @@ from bookwyrm.settings import PAGE_LENGTH # pylint: disable=no-self-use class EmbedList(View): - """embeded book list page""" + """embedded book list page""" def get(self, request, list_id, list_key): """display a book list""" From 445cb60f2c7962806bdc6473d746cda30204b7d0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:08 -0400 Subject: [PATCH 037/113] spelling: example Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 961fbd522..e5ca56a37 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -125,7 +125,7 @@ class ModelFields(TestCase): instance.run_validators("@example.com") instance.run_validators("mouse@examplecom") instance.run_validators("one two@fish.aaaa") - instance.run_validators("a*&@exampke.com") + instance.run_validators("a*&@example.com") instance.run_validators("trailingwhite@example.com ") self.assertIsNone(instance.run_validators("mouse@example.com")) self.assertIsNone(instance.run_validators("mo-2use@ex3ample.com")) From 3b9828c0fc6618512e2e808a1ecdd286023eb332 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:09 -0400 Subject: [PATCH 038/113] spelling: existing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/views/test_status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 7c64fdb0c..7e749112c 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -356,12 +356,12 @@ class StatusViews(TestCase): self.assertEqual(len(hashtags), 2) self.assertEqual(list(status.mention_hashtags.all()), list(hashtags)) - hashtag_exising = models.Hashtag.objects.filter(name="#existing").first() + hashtag_existing = models.Hashtag.objects.filter(name="#existing").first() hashtag_new = models.Hashtag.objects.filter(name="#NewTag").first() self.assertEqual( status.content, "

this is an " - + f'' + + f'' + "#EXISTING hashtag but all uppercase, this one is " + f'' + "#NewTag.

", From 050cd583df24a0bd62116058b6d402bb6bfbeb1d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:09 -0400 Subject: [PATCH 039/113] spelling: expiration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/forms/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/forms/admin.py b/bookwyrm/forms/admin.py index 1ad158119..72f50ccb8 100644 --- a/bookwyrm/forms/admin.py +++ b/bookwyrm/forms/admin.py @@ -15,7 +15,7 @@ from .custom_form import CustomForm, StyledForm # pylint: disable=missing-class-docstring class ExpiryWidget(widgets.Select): def value_from_datadict(self, data, files, name): - """human-readable exiration time buckets""" + """human-readable expiration time buckets""" selected_string = super().value_from_datadict(data, files, name) if selected_string == "day": From 9c5d588630035ff1d790300b94b26fc369d5cca1 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:10 -0400 Subject: [PATCH 040/113] spelling: fields Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index e5ca56a37..d58cf97af 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -29,7 +29,7 @@ from bookwyrm.settings import DOMAIN @patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.lists_stream.populate_lists_task.delay") class ModelFields(TestCase): - """overwrites standard model feilds to work with activitypub""" + """overwrites standard model fields to work with activitypub""" def test_validate_remote_id(self, *_): """should look like a url""" From 802a150c7651cef541fcb823be9f0b5ea9c45dfa Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:10 -0400 Subject: [PATCH 041/113] spelling: flex Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/templates/settings/dashboard/dashboard.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html index 99c0e9621..ead0d275e 100644 --- a/bookwyrm/templates/settings/dashboard/dashboard.html +++ b/bookwyrm/templates/settings/dashboard/dashboard.html @@ -16,7 +16,7 @@

{{ users|intcomma }}

-
+

{% trans "Active this month" %}

{{ active_users|intcomma }}

From 7f8279fe543634920cdd6af9d4b38ca59d08ed26 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:11 -0400 Subject: [PATCH 042/113] spelling: format Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/connectors/abstract_connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index ccb987ee2..bbe40f928 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -52,7 +52,7 @@ class AbstractMinimalConnector(ABC): return f"{self.search_url}{quote_plus(query)}" def process_search_response(self, query, data, min_confidence): - """Format the search results based on the formt of the query""" + """Format the search results based on the format of the query""" if maybe_isbn(query): return list(self.parse_isbn_search_data(data))[:10] return list(self.parse_search_data(data, min_confidence))[:10] From cee2de41cab7c4ffeecba53bbdee3bdbdb2c589f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:11 -0400 Subject: [PATCH 043/113] spelling: handling Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/connectors/test_openlibrary_connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/connectors/test_openlibrary_connector.py b/bookwyrm/tests/connectors/test_openlibrary_connector.py index 05ba39ab9..01b9b9f6a 100644 --- a/bookwyrm/tests/connectors/test_openlibrary_connector.py +++ b/bookwyrm/tests/connectors/test_openlibrary_connector.py @@ -46,7 +46,7 @@ class Openlibrary(TestCase): data = {"key": "/work/OL1234W"} result = self.connector.get_remote_id_from_data(data) self.assertEqual(result, "https://openlibrary.org/work/OL1234W") - # error handlding + # error handling with self.assertRaises(ConnectorException): self.connector.get_remote_id_from_data({}) From 7ec56505ea7a0f7eed9088f1283497d76070f71c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:23:49 -0400 Subject: [PATCH 044/113] spelling: having a Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/book.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index a5be51a29..4e7ffcad3 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -321,7 +321,7 @@ class Edition(Book): def get_rank(self): """calculate how complete the data is on this edition""" rank = 0 - # big ups for havinga cover + # big ups for having a cover rank += int(bool(self.cover)) * 3 # is it in the instance's preferred language? rank += int(bool(DEFAULT_LANGUAGE in self.languages)) From d2d087dcb7d268036d115e9248ef4a9a92317a56 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:22:08 -0400 Subject: [PATCH 045/113] spelling: identifiername Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/templatetags/shelf_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templatetags/shelf_tags.py b/bookwyrm/templatetags/shelf_tags.py index 1fb799883..6166cd6f1 100644 --- a/bookwyrm/templatetags/shelf_tags.py +++ b/bookwyrm/templatetags/shelf_tags.py @@ -37,7 +37,7 @@ def get_next_shelf(current_shelf): @register.filter(name="translate_shelf_name") def get_translated_shelf_name(shelf): - """produced translated shelf nidentifierame""" + """produced translated shelf identifiername""" if not shelf: return "" # support obj or dict From 649c782782c2fdc8c6614b1682143fdf16092b5e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:12 -0400 Subject: [PATCH 046/113] spelling: inheritance Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 7f444b673..06f68068b 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -234,7 +234,7 @@ class ObjectMixin(ActivitypubMixin): activity = self.to_create_activity(user) self.broadcast(activity, user, software=software, queue=priority) except AttributeError: - # janky as heck, this catches the mutliple inheritence chain + # janky as heck, this catches the mutliple inheritance chain # for boosts and ignores this auxiliary broadcast return return From e8894b159fd4ad3520068de6e606e6c3503e620a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:13 -0400 Subject: [PATCH 047/113] spelling: irrelevant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/test_postgres.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/test_postgres.py b/bookwyrm/tests/test_postgres.py index 94a8090f4..95ed06b0c 100644 --- a/bookwyrm/tests/test_postgres.py +++ b/bookwyrm/tests/test_postgres.py @@ -30,7 +30,7 @@ class PostgresTriggers(TestCase): title="The Long Goodbye", subtitle="wow cool", series="series name", - languages=["irrelevent"], + languages=["irrelevant"], ) book.authors.add(author) book.refresh_from_db() From 132010870364c6f2c0784d194882b6c6a0372cfb Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:13 -0400 Subject: [PATCH 048/113] spelling: markdown Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/templatetags/test_markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/templatetags/test_markdown.py b/bookwyrm/tests/templatetags/test_markdown.py index ba283a4f2..5b5959ad3 100644 --- a/bookwyrm/tests/templatetags/test_markdown.py +++ b/bookwyrm/tests/templatetags/test_markdown.py @@ -7,7 +7,7 @@ class MarkdownTags(TestCase): """lotta different things here""" def test_get_markdown(self): - """mardown format data""" + """markdown format data""" result = markdown.get_markdown("_hi_") self.assertEqual(result, "

hi

") From c216937dc4649193fc9ad8866e72aa56c8c51904 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:14 -0400 Subject: [PATCH 049/113] spelling: massively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 6fd94d019..df4bb2e4a 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -75,7 +75,7 @@ class ActivitypubFieldMixin: try: value = getattr(data, self.get_activitypub_field()) except AttributeError: - # masssively hack-y workaround for boosts + # massively hack-y workaround for boosts if self.get_activitypub_field() != "attributedTo": raise value = getattr(data, "actor") From 0b30373bd3154c2b3d67790f455f554c2505cfe0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:15 -0400 Subject: [PATCH 050/113] spelling: mention'd Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/views/test_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index 7e749112c..5874d9f2f 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -234,7 +234,7 @@ class StatusViews(TestCase): ) def test_create_status_reply_with_mentions(self, *_): - """reply to a post with an @mention'ed user""" + """reply to a post with an @mention'd user""" view = views.CreateStatus.as_view() user = models.User.objects.create_user( "rat", "rat@rat.com", "password", local=True, localname="rat" From 40632b2486326316ee7b1d4a73248a31a29ea162 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:15 -0400 Subject: [PATCH 051/113] spelling: multiple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 06f68068b..f8268b22a 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -25,7 +25,7 @@ from bookwyrm.tasks import app, MEDIUM, BROADCAST from bookwyrm.models.fields import ImageField, ManyToManyField logger = logging.getLogger(__name__) -# I tried to separate these classes into mutliple files but I kept getting +# I tried to separate these classes into multiple files but I kept getting # circular import errors so I gave up. I'm sure it could be done though! PropertyField = namedtuple("PropertyField", ("set_activity_from_field")) @@ -234,7 +234,7 @@ class ObjectMixin(ActivitypubMixin): activity = self.to_create_activity(user) self.broadcast(activity, user, software=software, queue=priority) except AttributeError: - # janky as heck, this catches the mutliple inheritance chain + # janky as heck, this catches the multiple inheritance chain # for boosts and ignores this auxiliary broadcast return return From d640bc9b1c708832a43663389a00474497fa255b Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:16 -0400 Subject: [PATCH 052/113] spelling: nonexistent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/views/landing/test_password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/landing/test_password.py b/bookwyrm/tests/views/landing/test_password.py index c7c7e05d5..c1adf61e9 100644 --- a/bookwyrm/tests/views/landing/test_password.py +++ b/bookwyrm/tests/views/landing/test_password.py @@ -72,7 +72,7 @@ class PasswordViews(TestCase): validate_html(result.render()) self.assertEqual(result.status_code, 200) - def test_password_reset_nonexistant_code(self): + def test_password_reset_nonexistent_code(self): """there are so many views, this just makes sure it LOADS""" view = views.PasswordReset.as_view() request = self.factory.get("") From d9a305a0f2428a87dd768b59f027b375d5f97d92 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:29:51 -0400 Subject: [PATCH 053/113] spelling: optimizequality Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/static/css/bookwyrm/components/_book_cover.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm/components/_book_cover.scss b/bookwyrm/static/css/bookwyrm/components/_book_cover.scss index db9391cc1..48b564a0b 100644 --- a/bookwyrm/static/css/bookwyrm/components/_book_cover.scss +++ b/bookwyrm/static/css/bookwyrm/components/_book_cover.scss @@ -43,7 +43,7 @@ max-height: 100%; /* Useful when stretching under-sized images. */ - image-rendering: optimizequality; + image-rendering: optimizeQuality; image-rendering: smooth; } From 56f38c178c4f4c68e856ad42d9ebc7832f49ef28 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:16 -0400 Subject: [PATCH 054/113] spelling: ordered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index f8268b22a..295807e21 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -339,7 +339,7 @@ class OrderedCollectionPageMixin(ObjectMixin): activity["id"] = remote_id paginated = Paginator(queryset, PAGE_LENGTH) - # add computed fields specific to orderd collections + # add computed fields specific to ordered collections activity["totalItems"] = paginated.count activity["first"] = f"{remote_id}?page=1" activity["last"] = f"{remote_id}?page={paginated.num_pages}" From c009f6e4dfae0bdf1bddf91daf1f238382590c9d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:17 -0400 Subject: [PATCH 055/113] spelling: overridden Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 295807e21..96002d4e0 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -311,7 +311,7 @@ class OrderedCollectionPageMixin(ObjectMixin): @property def collection_remote_id(self): - """this can be overriden if there's a special remote id, ie outbox""" + """this can be overridden if there's a special remote id, ie outbox""" return self.remote_id def to_ordered_collection( From 7b59f38cc8ebe19f3795c1b34b032e4f77ab2a7b Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:32:13 -0400 Subject: [PATCH 056/113] spelling: owner Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/lists_stream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index 7426488ce..2881e4880 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -86,14 +86,14 @@ class ListsStream(RedisStore): if group: audience = audience.filter( Q(id=book_list.user.id) # if the user is the list's owner - | Q(following=book_list.user) # if the user is following the pwmer + | Q(following=book_list.user) # if the user is following the owner # if a user is in the group | Q(memberships__group__id=book_list.group.id) ) else: audience = audience.filter( Q(id=book_list.user.id) # if the user is the list's owner - | Q(following=book_list.user) # if the user is following the pwmer + | Q(following=book_list.user) # if the user is following the owner ) return audience.distinct() From 9cddea11c774882139357b4dd142e58b423f3907 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:17 -0400 Subject: [PATCH 057/113] spelling: paginate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 96002d4e0..44f2919dd 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -565,7 +565,7 @@ async def sign_and_send( def to_ordered_collection_page( queryset, remote_id, id_only=False, page=1, pure=False, **kwargs ): - """serialize and pagiante a queryset""" + """serialize and paginate a queryset""" paginated = Paginator(queryset, PAGE_LENGTH) activity_page = paginated.get_page(page) From 44b4b10eb88b2705bc14e912bdc7dfd2e1e1681d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:18 -0400 Subject: [PATCH 058/113] spelling: password Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- ...06_auto_20200221_1702_squashed_0064_merge_20201101_1913.py | 2 +- bookwyrm/models/site.py | 4 ++-- bookwyrm/tests/views/landing/test_login.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/migrations/0006_auto_20200221_1702_squashed_0064_merge_20201101_1913.py b/bookwyrm/migrations/0006_auto_20200221_1702_squashed_0064_merge_20201101_1913.py index c06fa40a0..f25bafe15 100644 --- a/bookwyrm/migrations/0006_auto_20200221_1702_squashed_0064_merge_20201101_1913.py +++ b/bookwyrm/migrations/0006_auto_20200221_1702_squashed_0064_merge_20201101_1913.py @@ -1467,7 +1467,7 @@ class Migration(migrations.Migration): ( "expiry", models.DateTimeField( - default=bookwyrm.models.site.get_passowrd_reset_expiry + default=bookwyrm.models.site.get_password_reset_expiry ), ), ( diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index 35f007be2..a27c4b70d 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -209,7 +209,7 @@ class InviteRequest(BookWyrmModel): super().save(*args, **kwargs) -def get_passowrd_reset_expiry(): +def get_password_reset_expiry(): """give people a limited time to use the link""" now = timezone.now() return now + datetime.timedelta(days=1) @@ -219,7 +219,7 @@ class PasswordReset(models.Model): """gives someone access to create an account on the instance""" code = models.CharField(max_length=32, default=new_access_code) - expiry = models.DateTimeField(default=get_passowrd_reset_expiry) + expiry = models.DateTimeField(default=get_password_reset_expiry) user = models.OneToOneField(User, on_delete=models.CASCADE) def valid(self): diff --git a/bookwyrm/tests/views/landing/test_login.py b/bookwyrm/tests/views/landing/test_login.py index d76e9a55f..eab082609 100644 --- a/bookwyrm/tests/views/landing/test_login.py +++ b/bookwyrm/tests/views/landing/test_login.py @@ -114,7 +114,7 @@ class LoginViews(TestCase): view = views.Login.as_view() form = forms.LoginForm() form.data["localname"] = "mouse" - form.data["password"] = "passsword1" + form.data["password"] = "password1" request = self.factory.post("", form.data) request.user = self.anonymous_user From 1fdf5a7a396f63872305b9cdb25698a3f26d18d5 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:19 -0400 Subject: [PATCH 059/113] spelling: physical Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/migrations/0101_auto_20210929_1847.py | 2 +- bookwyrm/migrations/0102_remove_connector_local.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/migrations/0101_auto_20210929_1847.py b/bookwyrm/migrations/0101_auto_20210929_1847.py index 3fca28eac..967b59819 100644 --- a/bookwyrm/migrations/0101_auto_20210929_1847.py +++ b/bookwyrm/migrations/0101_auto_20210929_1847.py @@ -6,7 +6,7 @@ from bookwyrm.connectors.abstract_connector import infer_physical_format def infer_format(app_registry, schema_editor): - """set the new phsyical format field based on existing format data""" + """set the new physical format field based on existing format data""" db_alias = schema_editor.connection.alias editions = ( diff --git a/bookwyrm/migrations/0102_remove_connector_local.py b/bookwyrm/migrations/0102_remove_connector_local.py index 857f0f589..9bfd8b1d0 100644 --- a/bookwyrm/migrations/0102_remove_connector_local.py +++ b/bookwyrm/migrations/0102_remove_connector_local.py @@ -5,7 +5,7 @@ from bookwyrm.settings import DOMAIN def remove_self_connector(app_registry, schema_editor): - """set the new phsyical format field based on existing format data""" + """set the new physical format field based on existing format data""" db_alias = schema_editor.connection.alias app_registry.get_model("bookwyrm", "Connector").objects.using(db_alias).filter( connector_file="self_connector" From 27f025bc39d19360f2283f38434f5fa69f5a81fe Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:19 -0400 Subject: [PATCH 060/113] spelling: presence Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/activitypub/test_author.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/activitypub/test_author.py b/bookwyrm/tests/activitypub/test_author.py index 61d525fc0..51beac49a 100644 --- a/bookwyrm/tests/activitypub/test_author.py +++ b/bookwyrm/tests/activitypub/test_author.py @@ -19,7 +19,7 @@ class Author(TestCase): ) def test_serialize_model(self): - """check presense of author fields""" + """check presence of author fields""" activity = self.author.to_activity() self.assertEqual(activity["id"], self.author.remote_id) self.assertIsInstance(activity["aliases"], list) From 764bc0c204b23cf3f8f50942ef6e52380b58e17f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:22:19 -0400 Subject: [PATCH 061/113] spelling: produce Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/templatetags/shelf_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templatetags/shelf_tags.py b/bookwyrm/templatetags/shelf_tags.py index 6166cd6f1..5e6850363 100644 --- a/bookwyrm/templatetags/shelf_tags.py +++ b/bookwyrm/templatetags/shelf_tags.py @@ -37,7 +37,7 @@ def get_next_shelf(current_shelf): @register.filter(name="translate_shelf_name") def get_translated_shelf_name(shelf): - """produced translated shelf identifiername""" + """produce translated shelf identifiername""" if not shelf: return "" # support obj or dict From 3526d9fd19268acd9fc0887a2718961aafbaf680 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:20 -0400 Subject: [PATCH 062/113] spelling: progress Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/readthrough.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/readthrough.py b/bookwyrm/models/readthrough.py index 239ec56be..4911c715b 100644 --- a/bookwyrm/models/readthrough.py +++ b/bookwyrm/models/readthrough.py @@ -8,7 +8,7 @@ from .base_model import BookWyrmModel class ProgressMode(models.TextChoices): - """types of prgress available""" + """types of progress available""" PAGE = "PG", "page" PERCENT = "PCT", "percent" From 55b6d6377491c999c22821fe3a5f087d9758620d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:20 -0400 Subject: [PATCH 063/113] spelling: quotation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/activitypub/test_quotation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/activitypub/test_quotation.py b/bookwyrm/tests/activitypub/test_quotation.py index 74728274b..678ee7aa3 100644 --- a/bookwyrm/tests/activitypub/test_quotation.py +++ b/bookwyrm/tests/activitypub/test_quotation.py @@ -30,7 +30,7 @@ class Quotation(TestCase): self.status_data = json.loads(datafile.read_bytes()) def test_quotation_activity(self): - """create a Quoteation ap object from json""" + """create a Quotation ap object from json""" quotation = activitypub.Quotation(**self.status_data) self.assertEqual(quotation.type, "Quotation") From 0b14d3fddf48ce28c03fd1121a6e237631199e0a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:21 -0400 Subject: [PATCH 064/113] spelling: receive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/relationship.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py index 422967855..4754bea36 100644 --- a/bookwyrm/models/relationship.py +++ b/bookwyrm/models/relationship.py @@ -34,7 +34,7 @@ class UserRelationship(BookWyrmModel): @property def recipients(self): - """the remote user needs to recieve direct broadcasts""" + """the remote user needs to receive direct broadcasts""" return [u for u in [self.user_subject, self.user_object] if not u.local] def save(self, *args, **kwargs): From e7d8692836c5d0b6ef2a1c56b357f5b7cd51d4e0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:22 -0400 Subject: [PATCH 065/113] spelling: receiving Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index d58cf97af..c6e395753 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -292,7 +292,7 @@ class ModelFields(TestCase): self.assertEqual(value.name, "MOUSE?? MOUSE!!") def test_foreign_key_from_activity_dict(self, *_): - """test recieving activity json""" + """test receiving activity json""" instance = fields.ForeignKey(User, on_delete=models.CASCADE) datafile = pathlib.Path(__file__).parent.joinpath("../data/ap_user.json") userdata = json.loads(datafile.read_bytes()) From 182a722a55c0ca666524019da50cf71194a17ace Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:21 -0400 Subject: [PATCH 066/113] spelling: recurring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/static/js/bookwyrm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 6a6c0217f..ceed12eba 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -5,7 +5,7 @@ let BookWyrm = new (class { constructor() { this.MAX_FILE_SIZE_BYTES = 10 * 1000000; this.initOnDOMLoaded(); - this.initReccuringTasks(); + this.initRecurringTasks(); this.initEventListeners(); } @@ -77,7 +77,7 @@ let BookWyrm = new (class { /** * Execute recurring tasks. */ - initReccuringTasks() { + initRecurringTasks() { // Polling document.querySelectorAll("[data-poll]").forEach((liveArea) => this.polling(liveArea)); } From e5663f97c56fa3da35cae359efda23a788e23117 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:22 -0400 Subject: [PATCH 067/113] spelling: remove Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/static/js/forms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/js/forms.js b/bookwyrm/static/js/forms.js index a48675b35..08066f137 100644 --- a/bookwyrm/static/js/forms.js +++ b/bookwyrm/static/js/forms.js @@ -2,7 +2,7 @@ "use strict"; /** - * Remoev input field + * Remove input field * * @param {event} the button click event */ From 4c9408d77267acb5a279c95d3a50921bd4d7df28 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:23 -0400 Subject: [PATCH 068/113] spelling: revoke Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/management/commands/revoke_preview_image_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/management/commands/revoke_preview_image_tasks.py b/bookwyrm/management/commands/revoke_preview_image_tasks.py index 6d6e59e8f..7b0947b12 100644 --- a/bookwyrm/management/commands/revoke_preview_image_tasks.py +++ b/bookwyrm/management/commands/revoke_preview_image_tasks.py @@ -9,7 +9,7 @@ class Command(BaseCommand): # pylint: disable=unused-argument def handle(self, *args, **options): - """reveoke nonessential low priority tasks""" + """revoke nonessential low priority tasks""" types = [ "bookwyrm.preview_images.generate_edition_preview_image_task", "bookwyrm.preview_images.generate_user_preview_image_task", From 2fb771f0de2cb81eb7a219dd5934b512ca1305eb Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:23 -0400 Subject: [PATCH 069/113] spelling: sanitize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/reading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py index 958917eaa..65870b8dc 100644 --- a/bookwyrm/views/reading.py +++ b/bookwyrm/views/reading.py @@ -186,7 +186,7 @@ def update_readthrough_on_shelve( active_readthrough = models.ReadThrough.objects.create( user=user, book=annotated_book ) - # santiize and set dates + # sanitize and set dates active_readthrough.start_date = load_date_in_user_tz_as_utc(start_date, user) # if the stop or finish date is set, the readthrough will be set as inactive active_readthrough.finish_date = load_date_in_user_tz_as_utc(finish_date, user) From 02bf01827112fc5c37a5008734c55af69d9df46e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:47:15 -0400 Subject: [PATCH 070/113] spelling: search Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/test_postgres.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/test_postgres.py b/bookwyrm/tests/test_postgres.py index 95ed06b0c..8fc3c9d59 100644 --- a/bookwyrm/tests/test_postgres.py +++ b/bookwyrm/tests/test_postgres.py @@ -40,7 +40,7 @@ class PostgresTriggers(TestCase): "'cool':5B 'goodby':3A 'long':2A 'name':9 'rays':7C 'seri':8 'the':6C 'wow':4B", ) - def test_seach_vector_on_author_update(self, _): + def test_search_vector_on_author_update(self, _): """update search when an author name changes""" author = models.Author.objects.create(name="The Rays") book = models.Edition.objects.create( @@ -53,7 +53,7 @@ class PostgresTriggers(TestCase): self.assertEqual(book.search_vector, "'goodby':3A 'jeremy':4C 'long':2A") - def test_seach_vector_on_author_delete(self, _): + def test_search_vector_on_author_delete(self, _): """update search when an author name changes""" author = models.Author.objects.create(name="Jeremy") book = models.Edition.objects.create( From 7a6e249614afcfc260d6921cacb08924788e0667 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:24 -0400 Subject: [PATCH 071/113] spelling: sensitivity Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/views/test_wellknown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_wellknown.py b/bookwyrm/tests/views/test_wellknown.py index 465f39b40..80f5a56ae 100644 --- a/bookwyrm/tests/views/test_wellknown.py +++ b/bookwyrm/tests/views/test_wellknown.py @@ -53,7 +53,7 @@ class WellknownViews(TestCase): data = json.loads(result.getvalue()) self.assertEqual(data["subject"], "acct:mouse@local.com") - def test_webfinger_case_sensitivty(self): + def test_webfinger_case_sensitivity(self): """ensure that webfinger queries are not case sensitive""" request = self.factory.get("", {"resource": "acct:MoUsE@local.com"}) request.user = self.anonymous_user From 35f1d043f40f57d99dfea461454c413e16ca1528 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:24 -0400 Subject: [PATCH 072/113] spelling: separate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/templates/preferences/edit_user.html | 2 +- locale/en_US/LC_MESSAGES/django.po | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/preferences/edit_user.html b/bookwyrm/templates/preferences/edit_user.html index 493b18d2f..f2b14babf 100644 --- a/bookwyrm/templates/preferences/edit_user.html +++ b/bookwyrm/templates/preferences/edit_user.html @@ -133,7 +133,7 @@
{% url 'user-shelves' request.user.localname as path %}

- {% blocktrans %}Looking for shelf privacy? You can set a sepearate visibility level for each of your shelves. Go to Your Books, pick a shelf from the tab bar, and click "Edit shelf."{% endblocktrans %} + {% blocktrans %}Looking for shelf privacy? You can set a separate visibility level for each of your shelves. Go to Your Books, pick a shelf from the tab bar, and click "Edit shelf."{% endblocktrans %}

diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index e55690723..b45a6c218 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -4045,7 +4045,7 @@ msgstr "" #: bookwyrm/templates/preferences/edit_user.html:136 #, python-format -msgid "Looking for shelf privacy? You can set a sepearate visibility level for each of your shelves. Go to Your Books, pick a shelf from the tab bar, and click \"Edit shelf.\"" +msgid "Looking for shelf privacy? You can set a separate visibility level for each of your shelves. Go to Your Books, pick a shelf from the tab bar, and click \"Edit shelf.\"" msgstr "" #: bookwyrm/templates/preferences/export.html:4 From 18fcea35daff1f76a1a8169cb7d0b60ee896afce Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:25 -0400 Subject: [PATCH 073/113] spelling: should Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/templatetags/book_display_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templatetags/book_display_tags.py b/bookwyrm/templatetags/book_display_tags.py index 56eb096ec..0a0f228d8 100644 --- a/bookwyrm/templatetags/book_display_tags.py +++ b/bookwyrm/templatetags/book_display_tags.py @@ -18,7 +18,7 @@ def get_book_description(book): if book.description: return book.description if book.parent_work: - # this shoud always be true + # this should always be true return book.parent_work.description return None From 4607d30cad813ec90ee027a84213fcbd09a1b74e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:25 -0400 Subject: [PATCH 074/113] spelling: signatures Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/test_signing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/test_signing.py b/bookwyrm/tests/test_signing.py index cde193f08..d15d6eecf 100644 --- a/bookwyrm/tests/test_signing.py +++ b/bookwyrm/tests/test_signing.py @@ -107,7 +107,7 @@ class Signature(TestCase): @responses.activate def test_remote_signer(self): - """signtures for remote users""" + """signatures for remote users""" datafile = pathlib.Path(__file__).parent.joinpath("data/ap_user.json") data = json.loads(datafile.read_bytes()) data["id"] = self.fake_remote.remote_id From e4677eb6fae9fc9fc8263c94eb4a47c6c3441e12 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:26 -0400 Subject: [PATCH 075/113] spelling: someone Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/notification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index 29f7b0c2d..522038f9a 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -284,7 +284,7 @@ def notify_user_on_list_item_add(sender, instance, created, *args, **kwargs): return list_owner = instance.book_list.user - # create a notification if somoene ELSE added to a local user's list + # create a notification if someone ELSE added to a local user's list if list_owner.local and list_owner != instance.user: # keep the related_user singular, group the items Notification.notify_list_item(list_owner, instance) From 9dc3cdca5df265e48492a7315eb03bf5fcf9e3fe Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:26 -0400 Subject: [PATCH 076/113] spelling: statuses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/activitystreams/test_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py index 2e89f6ccc..cddcf0dcc 100644 --- a/bookwyrm/tests/activitystreams/test_tasks.py +++ b/bookwyrm/tests/activitystreams/test_tasks.py @@ -50,7 +50,7 @@ class Activitystreams(TestCase): self.assertEqual(args[1], self.book) def test_remove_book_statuses_task(self): - """remove stauses related to a book""" + """remove statuses related to a book""" with patch("bookwyrm.activitystreams.BooksStream.remove_book_statuses") as mock: activitystreams.remove_book_statuses_task(self.local_user.id, self.book.id) self.assertTrue(mock.called) From ffd035f25afaf399dad1d20b1cb3c76e8d76a59e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:27 -0400 Subject: [PATCH 077/113] spelling: stores Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/redis_store.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index f25829f5c..f7c852456 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -34,7 +34,7 @@ class RedisStore(ABC): def remove_object_from_related_stores(self, obj, stores=None): """remove an object from all stores""" - # if the stoers are provided, the object can just be an id + # if the stores are provided, the object can just be an id if stores and isinstance(obj, int): obj_id = obj else: From 63dbb6a29176d46dc7455113e201516ce7d47e83 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:27 -0400 Subject: [PATCH 078/113] spelling: successfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/activitypub/test_base_activity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/activitypub/test_base_activity.py b/bookwyrm/tests/activitypub/test_base_activity.py index df243d0db..c9022d35c 100644 --- a/bookwyrm/tests/activitypub/test_base_activity.py +++ b/bookwyrm/tests/activitypub/test_base_activity.py @@ -59,7 +59,7 @@ class BaseActivity(TestCase): self.assertIsInstance(representative, models.User) def test_init(self, *_): - """simple successfuly init""" + """simple successfully init""" instance = ActivityObject(id="a", type="b") self.assertTrue(hasattr(instance, "id")) self.assertTrue(hasattr(instance, "type")) From 2d4a42ceba009418ed594a2614ab5a020af1aaac Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:28 -0400 Subject: [PATCH 079/113] spelling: suggestions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/list/curate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/list/curate.py b/bookwyrm/views/list/curate.py index 7155ffc43..cf41636ba 100644 --- a/bookwyrm/views/list/curate.py +++ b/bookwyrm/views/list/curate.py @@ -14,7 +14,7 @@ from bookwyrm.views.list.list import normalize_book_list_ordering # pylint: disable=no-self-use @method_decorator(login_required, name="dispatch") class Curate(View): - """approve or discard list suggestsions""" + """approve or discard list suggestions""" def get(self, request, list_id): """display a pending list""" From 42e78b14e93cd9a21d7ec2e93b85c5493c231da2 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:28 -0400 Subject: [PATCH 080/113] spelling: translation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- locale/en_US/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index b45a6c218..65000c1d4 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -1,4 +1,4 @@ -# Stub English-language trnaslation file +# Stub English-language translation file # Copyright (C) 2021 Mouse Reeve # This file is distributed under the same license as the BookWyrm package. # Mouse Reeve , 2021 From 7170e8972d599d633cc051c9b9fa41be9681069e Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:29 -0400 Subject: [PATCH 081/113] spelling: uneventfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_activitypub_mixin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py index fdd1883a8..a465c2c12 100644 --- a/bookwyrm/tests/models/test_activitypub_mixin.py +++ b/bookwyrm/tests/models/test_activitypub_mixin.py @@ -245,7 +245,7 @@ class ActivitypubMixins(TestCase): # ObjectMixin def test_object_save_create(self, *_): - """should save uneventufully when broadcast is disabled""" + """should save uneventfully when broadcast is disabled""" class Success(Exception): """this means we got to the right method""" @@ -276,7 +276,7 @@ class ActivitypubMixins(TestCase): ObjectModel(user=None).save() def test_object_save_update(self, *_): - """should save uneventufully when broadcast is disabled""" + """should save uneventfully when broadcast is disabled""" class Success(Exception): """this means we got to the right method""" From 459b74294d8ae9cd020d8cfacf99bb46140373d0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:29 -0400 Subject: [PATCH 082/113] spelling: uniqueness Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/annual_goal.py | 2 +- bookwyrm/models/shelf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/models/annual_goal.py b/bookwyrm/models/annual_goal.py index 0eefacb32..d36b822df 100644 --- a/bookwyrm/models/annual_goal.py +++ b/bookwyrm/models/annual_goal.py @@ -24,7 +24,7 @@ class AnnualGoal(BookWyrmModel): ) class Meta: - """unqiueness constraint""" + """uniqueness constraint""" unique_together = ("user", "year") diff --git a/bookwyrm/models/shelf.py b/bookwyrm/models/shelf.py index 8e754bc47..c52cb6ab8 100644 --- a/bookwyrm/models/shelf.py +++ b/bookwyrm/models/shelf.py @@ -80,7 +80,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel): raise PermissionDenied() class Meta: - """user/shelf unqiueness""" + """user/shelf uniqueness""" unique_together = ("user", "identifier") From dfae27ca324252769a04054f9eb1c5a4bc76360d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 18:56:09 -0400 Subject: [PATCH 083/113] spelling: updated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/models/activitypub_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 44f2919dd..3350a4f6b 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -405,7 +405,7 @@ class CollectionItemMixin(ActivitypubMixin): # first off, we want to save normally no matter what super().save(*args, **kwargs) - # list items can be updateda, normally you would only broadcast on created + # list items can be updated, normally you would only broadcast on created if not broadcast or not self.user.local: return From 2a914f98b779e726a5c2b71fb784e4b407cf1ad4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:30 -0400 Subject: [PATCH 084/113] spelling: versions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_status_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 177bedb24..1bbca1896 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -397,7 +397,7 @@ class Status(TestCase): # pylint: disable=unused-argument def test_create_broadcast(self, one, two, broadcast_mock, *_): - """should send out two verions of a status on create""" + """should send out two versions of a status on create""" models.Comment.objects.create( content="hi", user=self.local_user, book=self.book ) From ba7f0fce71183145a2245523442f4ad23494f3d5 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:30 -0400 Subject: [PATCH 085/113] spelling: whenever Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/views/inbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/inbox.py b/bookwyrm/views/inbox.py index 89e644db8..2fb36507f 100644 --- a/bookwyrm/views/inbox.py +++ b/bookwyrm/views/inbox.py @@ -104,7 +104,7 @@ def raise_is_blocked_activity(activity_json): def sometimes_async_activity_task(activity_json, queue=MEDIUM): """Sometimes we can effectively respond to a request without queuing a new task, - and whever that is possible, we should do it.""" + and whenever that is possible, we should do it.""" activity = activitypub.parse(activity_json) # try resolving this activity without making any http requests From 359228127dee5c5c3eea06b5a38a69e719738e51 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:13:31 -0400 Subject: [PATCH 086/113] spelling: wyrm Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- bookwyrm/tests/models/test_base_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_base_model.py b/bookwyrm/tests/models/test_base_model.py index 8a8be2148..b94592571 100644 --- a/bookwyrm/tests/models/test_base_model.py +++ b/bookwyrm/tests/models/test_base_model.py @@ -51,7 +51,7 @@ class BaseModel(TestCase): def test_set_remote_id(self): """this function sets remote ids after creation""" - # using Work because it BookWrymModel is abstract and this requires save + # using Work because it BookWyrmModel is abstract and this requires save # Work is a relatively not-fancy model. instance = models.Work.objects.create(title="work title") instance.remote_id = None From 011844b7acdeca0921188ac8218f569afc2700c4 Mon Sep 17 00:00:00 2001 From: Jacob Torrey Date: Wed, 5 Apr 2023 15:45:22 +0000 Subject: [PATCH 087/113] Small quality of life improvements to list handling Signed-off-by: Jacob Torrey --- bookwyrm/templates/lists/created_text.html | 2 +- bookwyrm/views/list/list.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/lists/created_text.html b/bookwyrm/templates/lists/created_text.html index f5405b64a..b9e188686 100644 --- a/bookwyrm/templates/lists/created_text.html +++ b/bookwyrm/templates/lists/created_text.html @@ -3,7 +3,7 @@ {% if list.curation == 'group' %} {% blocktrans with username=list.user.display_name userpath=list.user.local_path groupname=list.group.name grouppath=list.group.local_path %}Created by {{ username }} and managed by {{ groupname }}{% endblocktrans %} -{% elif list.curation != 'open' %} +{% elif list.curation == 'curated' %} {% blocktrans with username=list.user.display_name path=list.user.local_path %}Created and curated by {{ username }}{% endblocktrans %} {% else %} {% blocktrans with username=list.user.display_name path=list.user.local_path %}Created by {{ username }}{% endblocktrans %} diff --git a/bookwyrm/views/list/list.py b/bookwyrm/views/list/list.py index 24d44d183..30d6f970a 100644 --- a/bookwyrm/views/list/list.py +++ b/bookwyrm/views/list/list.py @@ -8,7 +8,7 @@ from django.db import transaction from django.db.models import Avg, DecimalField, Q, Max from django.db.models.functions import Coalesce from django.http import HttpResponseBadRequest, HttpResponse -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.urls import reverse from django.utils.decorators import method_decorator @@ -183,7 +183,7 @@ def delete_list(request, list_id): book_list.raise_not_deletable(request.user) book_list.delete() - return redirect_to_referer(request, "lists") + return redirect("/list") @require_POST From 9c54030b61e0bcde862fcf6180da5c1ec10182a7 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 20:18:45 -0400 Subject: [PATCH 088/113] Add add_object_to_stores function This should enable some useful refactoring to allow us to cache some results of expensive queries better. --- bookwyrm/redis_store.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index f25829f5c..cd75fc5de 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -16,12 +16,12 @@ class RedisStore(ABC): """the object and rank""" return {obj.id: self.get_rank(obj)} - def add_object_to_related_stores(self, obj, execute=True): - """add an object to all suitable stores""" + def add_object_to_stores(self, obj, stores, execute=True): + """add an object to a given set of stores""" value = self.get_value(obj) # we want to do this as a bulk operation, hence "pipeline" pipeline = r.pipeline() - for store in self.get_stores_for_object(obj): + for store in stores: # add the status to the feed pipeline.zadd(store, value) # trim the store @@ -32,6 +32,10 @@ class RedisStore(ABC): # and go! return pipeline.execute() + def add_object_to_related_stores(self, obj, execute=True): + """add an object to all suitable stores""" + return self.add_object_to_stores(obj, self.get_stores_for_object(obj), execute) + def remove_object_from_related_stores(self, obj, stores=None): """remove an object from all stores""" # if the stoers are provided, the object can just be an id From 93bd66ad3ea944283c6ae2f89ced056b4602e2b7 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 20:37:17 -0400 Subject: [PATCH 089/113] Refactor to delete add_object_to_related_stores This is working towards some optimizations. --- bookwyrm/activitystreams.py | 4 +++- bookwyrm/lists_stream.py | 3 +-- bookwyrm/redis_store.py | 4 ---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 74471883e..76872609d 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -39,7 +39,9 @@ class ActivityStream(RedisStore): def add_status(self, status, increment_unread=False): """add a status to users' feeds""" # the pipeline contains all the add-to-stream activities - pipeline = self.add_object_to_related_stores(status, execute=False) + pipeline = self.add_object_to_stores( + status, self.get_stores_for_object(status), execute=False + ) if increment_unread: for user_id in self.get_audience(status): diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index 7426488ce..20f045afd 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -24,8 +24,7 @@ class ListsStream(RedisStore): def add_list(self, book_list): """add a list to users' feeds""" - # the pipeline contains all the add-to-stream activities - self.add_object_to_related_stores(book_list) + self.add_object_to_stores(book_list, self.get_stores_for_object(book_list)) def add_user_lists(self, viewer, user): """add a user's lists to another user's feed""" diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index cd75fc5de..3e88c09ac 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -32,10 +32,6 @@ class RedisStore(ABC): # and go! return pipeline.execute() - def add_object_to_related_stores(self, obj, execute=True): - """add an object to all suitable stores""" - return self.add_object_to_stores(obj, self.get_stores_for_object(obj), execute) - def remove_object_from_related_stores(self, obj, stores=None): """remove an object from all stores""" # if the stoers are provided, the object can just be an id From 8053f49acc80acc0386e50c55ab1c0273f0ef02f Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 20:50:02 -0400 Subject: [PATCH 090/113] Always pass stores to remove_object_from_related_stores --- bookwyrm/activitystreams.py | 4 +++- bookwyrm/suggested_users.py | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 76872609d..78f6d9ee0 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -516,7 +516,9 @@ def remove_status_task(status_ids): for stream in streams.values(): for status in statuses: - stream.remove_object_from_related_stores(status) + stream.remove_object_from_related_stores( + status, stores=stream.get_stores_for_object(status) + ) @app.task(queue=HIGH, ignore_result=True) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index ea6b1c55d..4cef0c5f3 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -254,7 +254,9 @@ def rerank_user_task(user_id, update_only=False): def remove_user_task(user_id): """do the hard work in celery""" user = models.User.objects.get(id=user_id) - suggested_users.remove_object_from_related_stores(user) + suggested_users.remove_object_from_related_stores( + user, stores=suggested_users.get_stores_for_object(user) + ) @app.task(queue=MEDIUM, ignore_result=True) @@ -268,7 +270,9 @@ def remove_suggestion_task(user_id, suggested_user_id): def bulk_remove_instance_task(instance_id): """remove a bunch of users from recs""" for user in models.User.objects.filter(federated_server__id=instance_id): - suggested_users.remove_object_from_related_stores(user) + suggested_users.remove_object_from_related_stores( + user, stores=suggested_users.get_stores_for_object(user) + ) @app.task(queue=LOW, ignore_result=True) From 68c6a9e748772ecdcee8a6507bb20ff7dbc40620 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 20:54:58 -0400 Subject: [PATCH 091/113] Rename remove_object_from_related_stores This makes the stores argument required, making it simpler to change the code. --- bookwyrm/activitystreams.py | 8 ++--- bookwyrm/lists_stream.py | 2 +- bookwyrm/redis_store.py | 4 +-- bookwyrm/suggested_users.py | 8 ++--- bookwyrm/tests/activitystreams/test_tasks.py | 36 ++++++++++---------- bookwyrm/tests/lists_stream/test_tasks.py | 2 +- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 78f6d9ee0..cda634b4c 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -516,8 +516,8 @@ def remove_status_task(status_ids): for stream in streams.values(): for status in statuses: - stream.remove_object_from_related_stores( - status, stores=stream.get_stores_for_object(status) + stream.remove_object_from_stores( + status, stream.get_stores_for_object(status) ) @@ -568,9 +568,9 @@ def handle_boost_task(boost_id): for stream in streams.values(): # people who should see the boost (not people who see the original status) audience = stream.get_stores_for_object(instance) - stream.remove_object_from_related_stores(boosted, stores=audience) + stream.remove_object_from_stores(boosted, audience) for status in old_versions: - stream.remove_object_from_related_stores(status, stores=audience) + stream.remove_object_from_stores(status, audience) def get_status_type(status): diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index 20f045afd..e19e16566 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -232,7 +232,7 @@ def remove_list_task(list_id, re_add=False): # delete for every store stores = [ListsStream().stream_id(idx) for idx in stores] - ListsStream().remove_object_from_related_stores(list_id, stores=stores) + ListsStream().remove_object_from_stores(list_id, stores) if re_add: add_list_task.delay(list_id) diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index 3e88c09ac..8904d123a 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -32,14 +32,14 @@ class RedisStore(ABC): # and go! return pipeline.execute() - def remove_object_from_related_stores(self, obj, stores=None): + # pylint: disable=no-self-use + def remove_object_from_stores(self, obj, stores): """remove an object from all stores""" # if the stoers are provided, the object can just be an id if stores and isinstance(obj, int): obj_id = obj else: obj_id = obj.id - stores = self.get_stores_for_object(obj) if stores is None else stores pipeline = r.pipeline() for store in stores: pipeline.zrem(store, -1, obj_id) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 4cef0c5f3..990bec11d 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -254,8 +254,8 @@ def rerank_user_task(user_id, update_only=False): def remove_user_task(user_id): """do the hard work in celery""" user = models.User.objects.get(id=user_id) - suggested_users.remove_object_from_related_stores( - user, stores=suggested_users.get_stores_for_object(user) + suggested_users.remove_object_from_stores( + user, suggested_users.get_stores_for_object(user) ) @@ -270,8 +270,8 @@ def remove_suggestion_task(user_id, suggested_user_id): def bulk_remove_instance_task(instance_id): """remove a bunch of users from recs""" for user in models.User.objects.filter(federated_server__id=instance_id): - suggested_users.remove_object_from_related_stores( - user, stores=suggested_users.get_stores_for_object(user) + suggested_users.remove_object_from_stores( + user, suggested_users.get_stores_for_object(user) ) diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py index 2e89f6ccc..c37a80363 100644 --- a/bookwyrm/tests/activitystreams/test_tasks.py +++ b/bookwyrm/tests/activitystreams/test_tasks.py @@ -75,7 +75,7 @@ class Activitystreams(TestCase): def test_remove_status_task(self): """remove a status from all streams""" with patch( - "bookwyrm.activitystreams.ActivityStream.remove_object_from_related_stores" + "bookwyrm.activitystreams.ActivityStream.remove_object_from_stores" ) as mock: activitystreams.remove_status_task(self.status.id) self.assertEqual(mock.call_count, 3) @@ -132,8 +132,8 @@ class Activitystreams(TestCase): self.assertEqual(args[0], self.local_user) self.assertEqual(args[1], self.another_user) - @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") - @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_stores") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_boost_to_another_timeline(self, *_): """boost from a non-follower doesn't remove original status from feed""" @@ -144,7 +144,7 @@ class Activitystreams(TestCase): user=self.another_user, ) with patch( - "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + "bookwyrm.activitystreams.HomeStream.remove_object_from_stores" ) as mock: activitystreams.handle_boost_task(boost.id) @@ -152,10 +152,10 @@ class Activitystreams(TestCase): self.assertEqual(mock.call_count, 1) call_args = mock.call_args self.assertEqual(call_args[0][0], status) - self.assertEqual(call_args[1]["stores"], [f"{self.another_user.id}-home"]) + self.assertEqual(call_args[0][1], [f"{self.another_user.id}-home"]) - @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") - @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_stores") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_boost_to_another_timeline_remote(self, *_): """boost from a remote non-follower doesn't remove original status from feed""" @@ -166,7 +166,7 @@ class Activitystreams(TestCase): user=self.remote_user, ) with patch( - "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + "bookwyrm.activitystreams.HomeStream.remove_object_from_stores" ) as mock: activitystreams.handle_boost_task(boost.id) @@ -174,10 +174,10 @@ class Activitystreams(TestCase): self.assertEqual(mock.call_count, 1) call_args = mock.call_args self.assertEqual(call_args[0][0], status) - self.assertEqual(call_args[1]["stores"], []) + self.assertEqual(call_args[0][1], []) - @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") - @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_stores") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_boost_to_following_timeline(self, *_): """add a boost and deduplicate the boosted status on the timeline""" @@ -189,17 +189,17 @@ class Activitystreams(TestCase): user=self.another_user, ) with patch( - "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + "bookwyrm.activitystreams.HomeStream.remove_object_from_stores" ) as mock: activitystreams.handle_boost_task(boost.id) self.assertTrue(mock.called) call_args = mock.call_args self.assertEqual(call_args[0][0], status) - self.assertTrue(f"{self.another_user.id}-home" in call_args[1]["stores"]) - self.assertTrue(f"{self.local_user.id}-home" in call_args[1]["stores"]) + self.assertTrue(f"{self.another_user.id}-home" in call_args[0][1]) + self.assertTrue(f"{self.local_user.id}-home" in call_args[0][1]) - @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_related_stores") - @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_related_stores") + @patch("bookwyrm.activitystreams.LocalStream.remove_object_from_stores") + @patch("bookwyrm.activitystreams.BooksStream.remove_object_from_stores") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") def test_boost_to_same_timeline(self, *_): """add a boost and deduplicate the boosted status on the timeline""" @@ -210,10 +210,10 @@ class Activitystreams(TestCase): user=self.local_user, ) with patch( - "bookwyrm.activitystreams.HomeStream.remove_object_from_related_stores" + "bookwyrm.activitystreams.HomeStream.remove_object_from_stores" ) as mock: activitystreams.handle_boost_task(boost.id) self.assertTrue(mock.called) call_args = mock.call_args self.assertEqual(call_args[0][0], status) - self.assertEqual(call_args[1]["stores"], [f"{self.local_user.id}-home"]) + self.assertEqual(call_args[0][1], [f"{self.local_user.id}-home"]) diff --git a/bookwyrm/tests/lists_stream/test_tasks.py b/bookwyrm/tests/lists_stream/test_tasks.py index 55c5d98c8..2e01cecad 100644 --- a/bookwyrm/tests/lists_stream/test_tasks.py +++ b/bookwyrm/tests/lists_stream/test_tasks.py @@ -59,7 +59,7 @@ class Activitystreams(TestCase): def test_remove_list_task(self, *_): """remove a list from all streams""" with patch( - "bookwyrm.lists_stream.ListsStream.remove_object_from_related_stores" + "bookwyrm.lists_stream.ListsStream.remove_object_from_stores" ) as mock: lists_stream.remove_list_task(self.list.id) self.assertEqual(mock.call_count, 1) From 78607a0c3edb6b0726540b9148684fe79c41f1c7 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 20:57:39 -0400 Subject: [PATCH 092/113] Remove get_stores_for_object abstract method The implementations still have and use this, we've just removed this concept from the RedisStore abstraction, which simplifies things somewhat. --- bookwyrm/activitystreams.py | 1 + bookwyrm/lists_stream.py | 1 + bookwyrm/redis_store.py | 4 ---- bookwyrm/suggested_users.py | 1 + 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index cda634b4c..9586edcbc 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -150,6 +150,7 @@ class ActivityStream(RedisStore): return [user.id for user in self._get_audience(status)] def get_stores_for_object(self, obj): + """the stores that an object belongs in""" return [self.stream_id(user_id) for user_id in self.get_audience(obj)] def get_statuses_for_user(self, user): # pylint: disable=no-self-use diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py index e19e16566..e0618dc1b 100644 --- a/bookwyrm/lists_stream.py +++ b/bookwyrm/lists_stream.py @@ -97,6 +97,7 @@ class ListsStream(RedisStore): return audience.distinct() def get_stores_for_object(self, obj): + """the stores that an object belongs in""" return [self.stream_id(u) for u in self.get_audience(obj)] def get_lists_for_user(self, user): # pylint: disable=no-self-use diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index 8904d123a..80bce4df3 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -82,10 +82,6 @@ class RedisStore(ABC): def get_objects_for_store(self, store): """a queryset of what should go in a store, used for populating it""" - @abstractmethod - def get_stores_for_object(self, obj): - """the stores that an object belongs in""" - @abstractmethod def get_rank(self, obj): """how to rank an object""" diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 990bec11d..49edc83e9 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -49,6 +49,7 @@ class SuggestedUsers(RedisStore): ) def get_stores_for_object(self, obj): + """the stores that an object belongs in""" return [self.store_id(u) for u in self.get_users_for_object(obj)] def get_users_for_object(self, obj): # pylint: disable=no-self-use From 7a93b5c315c3f82e9a78a3ee5e474804d3661e0b Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 21:03:07 -0400 Subject: [PATCH 093/113] Only call get_audience once in add_status This is by far the most expensive part of this task, so this should double the speed in the increment_unread case. Related: #2720 --- bookwyrm/activitystreams.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 9586edcbc..847dd379e 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -38,13 +38,14 @@ class ActivityStream(RedisStore): def add_status(self, status, increment_unread=False): """add a status to users' feeds""" + audience = self.get_audience(status) # the pipeline contains all the add-to-stream activities pipeline = self.add_object_to_stores( - status, self.get_stores_for_object(status), execute=False + status, self.get_stores_for_users(audience), execute=False ) if increment_unread: - for user_id in self.get_audience(status): + for user_id in audience: # add to the unread status count pipeline.incr(self.unread_id(user_id)) # add to the unread status count for status type @@ -149,6 +150,10 @@ class ActivityStream(RedisStore): trace.get_current_span().set_attribute("stream_id", self.key) return [user.id for user in self._get_audience(status)] + def get_stores_for_users(self, user_ids): + """convert a list of user ids into redis store ids""" + return [self.stream_id(user_id) for user_id in user_ids] + def get_stores_for_object(self, obj): """the stores that an object belongs in""" return [self.stream_id(user_id) for user_id in self.get_audience(obj)] From 776c5526c8f4367f2a6ea1dfd052c7dfd64c0a17 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 23:18:36 -0400 Subject: [PATCH 094/113] Remove ActivityStream.get_stores_for_object I think this makes the code somewhat more understandable. --- bookwyrm/activitystreams.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 847dd379e..891aacc09 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -154,10 +154,6 @@ class ActivityStream(RedisStore): """convert a list of user ids into redis store ids""" return [self.stream_id(user_id) for user_id in user_ids] - def get_stores_for_object(self, obj): - """the stores that an object belongs in""" - return [self.stream_id(user_id) for user_id in self.get_audience(obj)] - def get_statuses_for_user(self, user): # pylint: disable=no-self-use """given a user, what statuses should they see on this stream""" return models.Status.privacy_filter( @@ -523,7 +519,7 @@ def remove_status_task(status_ids): for stream in streams.values(): for status in statuses: stream.remove_object_from_stores( - status, stream.get_stores_for_object(status) + status, stream.get_stores_for_users(stream.get_audience(status)) ) @@ -573,7 +569,7 @@ def handle_boost_task(boost_id): for stream in streams.values(): # people who should see the boost (not people who see the original status) - audience = stream.get_stores_for_object(instance) + audience = stream.get_stores_for_users(stream.get_audience(instance)) stream.remove_object_from_stores(boosted, audience) for status in old_versions: stream.remove_object_from_stores(status, audience) From f91fcd518a942801dc8fedbaa60b93287e4d8c50 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 01:18:35 -0400 Subject: [PATCH 095/113] Increase network timeout in Celery tasks Since Celery tasks don't affect interactive latency, we should have a more generous timeout. This also allows admins to set the timeout for Celery and the web frontend separately, without breaking backwards compatibility with the previous environment variable. --- bookwyrm/settings.py | 2 +- celerywyrm/settings.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 419b76195..8dcf90fcb 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -226,7 +226,7 @@ STREAMS = [ # total time in seconds that the instance will spend searching connectors SEARCH_TIMEOUT = env.int("SEARCH_TIMEOUT", 8) # timeout for a query to an individual connector -QUERY_TIMEOUT = env.int("QUERY_TIMEOUT", 5) +QUERY_TIMEOUT = env.int("INTERACTIVE_QUERY_TIMEOUT", env.int("QUERY_TIMEOUT", 5)) # Redis cache backend if env.bool("USE_DUMMY_CACHE", False): diff --git a/celerywyrm/settings.py b/celerywyrm/settings.py index c1e533ac3..aa08a2417 100644 --- a/celerywyrm/settings.py +++ b/celerywyrm/settings.py @@ -3,6 +3,8 @@ # pylint: disable=unused-wildcard-import from bookwyrm.settings import * +QUERY_TIMEOUT = env.int("CELERY_QUERY_TIMEOUT", env.int("QUERY_TIMEOUT", 30)) + # pylint: disable=line-too-long REDIS_BROKER_PASSWORD = requests.utils.quote(env("REDIS_BROKER_PASSWORD", "")) REDIS_BROKER_HOST = env("REDIS_BROKER_HOST", "redis_broker") From 29ac34cb922727616f1765a5a57be6c6a3698707 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 05:57:21 -0400 Subject: [PATCH 096/113] Fix help text for `bw-dev down` --- bw-dev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bw-dev b/bw-dev index b2a23d852..3e804943b 100755 --- a/bw-dev +++ b/bw-dev @@ -287,7 +287,7 @@ case "$CMD" in echo "Unrecognised command. Try:" echo " setup" echo " up [container]" - echo " down [container]" + echo " down" echo " service_ports_web" echo " initdb" echo " resetdb" From 36c14655ecfd5b414c5b41be161a3d1e05437a1e Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 6 Apr 2023 11:37:19 +0200 Subject: [PATCH 097/113] =?UTF-8?q?Use=20the=20translated=20shelf=20name?= =?UTF-8?q?=20in=20a=20book=E2=80=99s=20shelf=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously in the list of shelves on the page for a book it was always using the English name of the shelf for the shelf of the reading status. --- bookwyrm/templates/book/book.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index e9eff99ab..1ebb3159e 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -4,6 +4,7 @@ {% load humanize %} {% load utilities %} {% load static %} +{% load shelf_tags %} {% block title %}{{ book|book_title }}{% endblock %} @@ -239,7 +240,7 @@
    {% for shelf in user_shelfbooks %}
  • - {{ shelf.shelf.name }} + {{ shelf.shelf|translate_shelf_name }}
    {% include 'snippets/shelf_selector.html' with shelf=shelf.shelf class="is-small" readthrough=readthrough %}
    From b0f90d05f24c997d326ce625c69337e383eeb8c8 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 6 Apr 2023 15:55:11 +0200 Subject: [PATCH 098/113] Move the shelf names to a dict instead of a chain of if statements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main reason to do this is that if we try to add another name then pylint will complain that there are too many return statements. It might be slightly faster too. If I understand correctly it doesn’t matter that the _ function is being called at module load time because it is mapped to gettext_lazy so the actual translation will be done when the string is used. --- bookwyrm/templatetags/shelf_tags.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/bookwyrm/templatetags/shelf_tags.py b/bookwyrm/templatetags/shelf_tags.py index 1fb799883..ea093b8a5 100644 --- a/bookwyrm/templatetags/shelf_tags.py +++ b/bookwyrm/templatetags/shelf_tags.py @@ -9,6 +9,14 @@ from bookwyrm.utils import cache register = template.Library() +SHELF_NAMES = { + "all": _("All books"), + "to-read": _("To Read"), + "reading": _("Currently Reading"), + "read": _("Read"), +} + + @register.filter(name="is_book_on_shelf") def get_is_book_on_shelf(book, shelf): """is a book on a shelf""" @@ -42,15 +50,11 @@ def get_translated_shelf_name(shelf): return "" # support obj or dict identifier = shelf["identifier"] if isinstance(shelf, dict) else shelf.identifier - if identifier == "all": - return _("All books") - if identifier == "to-read": - return _("To Read") - if identifier == "reading": - return _("Currently Reading") - if identifier == "read": - return _("Read") - return shelf["name"] if isinstance(shelf, dict) else shelf.name + + try: + return SHELF_NAMES[identifier] + except KeyError: + return shelf["name"] if isinstance(shelf, dict) else shelf.name @register.simple_tag(takes_context=True) From 9092c9c80c06154f3bd2394b68ca6599ea4ee4e6 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 6 Apr 2023 11:53:17 +0200 Subject: [PATCH 099/113] Add a translatable name for the "stopped-reading" status shelf --- bookwyrm/templatetags/shelf_tags.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/templatetags/shelf_tags.py b/bookwyrm/templatetags/shelf_tags.py index ea093b8a5..6243fcae2 100644 --- a/bookwyrm/templatetags/shelf_tags.py +++ b/bookwyrm/templatetags/shelf_tags.py @@ -14,6 +14,7 @@ SHELF_NAMES = { "to-read": _("To Read"), "reading": _("Currently Reading"), "read": _("Read"), + "stopped-reading": _("Stopped Reading"), } From 4e09391b2e246fab893b4171ee54b59b4adccd2c Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 12:20:23 -0400 Subject: [PATCH 100/113] Add telemetry for SuggestedUsers rerank_user_task Related: #2727 --- bookwyrm/suggested_users.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index ea6b1c55d..8ec967cf5 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -4,13 +4,16 @@ import logging from django.dispatch import receiver from django.db import transaction from django.db.models import signals, Count, Q, Case, When, IntegerField +from opentelemetry import trace from bookwyrm import models from bookwyrm.redis_store import RedisStore, r from bookwyrm.tasks import app, LOW, MEDIUM +from bookwyrm.telemetry import open_telemetry logger = logging.getLogger(__name__) +tracer = open_telemetry.tracer() class SuggestedUsers(RedisStore): @@ -57,22 +60,25 @@ class SuggestedUsers(RedisStore): Q(id=obj.id) | Q(followers=obj) | Q(id__in=obj.blocks.all()) | Q(blocks=obj) ) + @tracer.start_as_current_span("SuggestedUsers.rerank_obj") def rerank_obj(self, obj, update_only=True): """update all the instances of this user with new ranks""" + trace.get_current_span().set_attribute("update_only", update_only) pipeline = r.pipeline() for store_user in self.get_users_for_object(obj): - annotated_user = get_annotated_users( - store_user, - id=obj.id, - ).first() - if not annotated_user: - continue + with tracer.start_as_current_span("SuggestedUsers.rerank_obj/user") as _: + annotated_user = get_annotated_users( + store_user, + id=obj.id, + ).first() + if not annotated_user: + continue - pipeline.zadd( - self.store_id(store_user), - self.get_value(annotated_user), - xx=update_only, - ) + pipeline.zadd( + self.store_id(store_user), + self.get_value(annotated_user), + xx=update_only, + ) pipeline.execute() def rerank_user_suggestions(self, user): From b574a12fff7e9c242fb5a29498c9d6070794bbcc Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 23:30:40 -0400 Subject: [PATCH 101/113] Pass allow_external_connections through ignore_activity Previously, ignore_activity could unexpectedly make a outgoing HTTP connection, leading to unwanted latency, particularly when called via ActivityObject.to_model, which had the allow_external_connections parameter already. Related: #2717 --- bookwyrm/activitypub/base_activity.py | 2 +- bookwyrm/models/favorite.py | 3 ++- bookwyrm/models/status.py | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index 840dab6a4..44361f0d0 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -127,7 +127,7 @@ class ActivityObject: if ( allow_create and hasattr(model, "ignore_activity") - and model.ignore_activity(self) + and model.ignore_activity(self, allow_external_connections) ): return None diff --git a/bookwyrm/models/favorite.py b/bookwyrm/models/favorite.py index 4c3675219..98fbce550 100644 --- a/bookwyrm/models/favorite.py +++ b/bookwyrm/models/favorite.py @@ -20,8 +20,9 @@ class Favorite(ActivityMixin, BookWyrmModel): activity_serializer = activitypub.Like + # pylint: disable=unused-argument @classmethod - def ignore_activity(cls, activity): + def ignore_activity(cls, activity, allow_external_connections=True): """don't bother with incoming favs of unknown statuses""" return not Status.objects.filter(remote_id=activity.object).exists() diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 1fcc9ee75..047d0aba6 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -116,10 +116,16 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): return list(set(mentions)) @classmethod - def ignore_activity(cls, activity): # pylint: disable=too-many-return-statements + def ignore_activity( + cls, activity, allow_external_connections=True + ): # pylint: disable=too-many-return-statements """keep notes if they are replies to existing statuses""" if activity.type == "Announce": - boosted = activitypub.resolve_remote_id(activity.object, get_activity=True) + boosted = activitypub.resolve_remote_id( + activity.object, + get_activity=True, + allow_external_connections=allow_external_connections, + ) if not boosted: # if we can't load the status, definitely ignore it return True From 61453d48e6ab4983b57d1e4eccae43aee2099f97 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Fri, 7 Apr 2023 01:58:49 -0400 Subject: [PATCH 102/113] Add automatic instrumentation to Postgres queries This enables automatic instrumentation of Postgres queries when OpenTelemetry instrumentation is enabled, which will help with debugging performance problems. --- bookwyrm/apps.py | 1 + bookwyrm/telemetry/open_telemetry.py | 6 ++++++ celerywyrm/apps.py | 1 + requirements.txt | 1 + 4 files changed, 9 insertions(+) diff --git a/bookwyrm/apps.py b/bookwyrm/apps.py index 7f684722d..b0c3e3fa4 100644 --- a/bookwyrm/apps.py +++ b/bookwyrm/apps.py @@ -40,6 +40,7 @@ class BookwyrmConfig(AppConfig): from bookwyrm.telemetry import open_telemetry open_telemetry.instrumentDjango() + open_telemetry.instrumentPostgres() if settings.ENABLE_PREVIEW_IMAGES and settings.FONTS: # Download any fonts that we don't have yet diff --git a/bookwyrm/telemetry/open_telemetry.py b/bookwyrm/telemetry/open_telemetry.py index 2798582d0..00b24d4b0 100644 --- a/bookwyrm/telemetry/open_telemetry.py +++ b/bookwyrm/telemetry/open_telemetry.py @@ -22,6 +22,12 @@ def instrumentDjango(): DjangoInstrumentor().instrument() +def instrumentPostgres(): + from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor + + Psycopg2Instrumentor().instrument() + + def instrumentCelery(): from opentelemetry.instrumentation.celery import CeleryInstrumentor from celery.signals import worker_process_init diff --git a/celerywyrm/apps.py b/celerywyrm/apps.py index bb2d27edd..bf443afdb 100644 --- a/celerywyrm/apps.py +++ b/celerywyrm/apps.py @@ -11,3 +11,4 @@ class CelerywyrmConfig(AppConfig): from bookwyrm.telemetry import open_telemetry open_telemetry.instrumentCelery() + open_telemetry.instrumentPostgres() diff --git a/requirements.txt b/requirements.txt index f8f1ab937..3da1d5082 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,6 +29,7 @@ opentelemetry-api==1.16.0 opentelemetry-exporter-otlp-proto-grpc==1.16.0 opentelemetry-instrumentation-celery==0.37b0 opentelemetry-instrumentation-django==0.37b0 +opentelemetry-instrumentation-psycopg2==0.37b0 opentelemetry-sdk==1.16.0 protobuf==3.20.* pyotp==2.8.0 From 6986fc90251c3cf2f991760568546cafc1cab335 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 05:48:24 -0400 Subject: [PATCH 103/113] Add form to remove tasks from Celery --- bookwyrm/templates/settings/celery.html | 29 ++++++++++++++ bookwyrm/views/admin/celery_status.py | 50 +++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/bookwyrm/templates/settings/celery.html b/bookwyrm/templates/settings/celery.html index 65315da01..5f79dfd9d 100644 --- a/bookwyrm/templates/settings/celery.html +++ b/bookwyrm/templates/settings/celery.html @@ -116,6 +116,35 @@
{% endif %} +
+

{% trans "Clear Queues" %}

+ +
+ + {% trans "Clearing queues can cause serious problems including data loss! Only play with this if you really know what you're doing. You must shut down the Celery worker before you do this." %} +
+ +
+ {% csrf_token %} + +
+
+

{{ form.queues.label_tag }}

+ {{ form.queues }} +
+ +
+

{{ form.tasks.label_tag }}

+ {{ form.tasks }} +
+
+ +
+ +
+
+
+ {% if errors %}

{% trans "Errors" %}

diff --git a/bookwyrm/views/admin/celery_status.py b/bookwyrm/views/admin/celery_status.py index e0b1fe18c..392d7c471 100644 --- a/bookwyrm/views/admin/celery_status.py +++ b/bookwyrm/views/admin/celery_status.py @@ -1,10 +1,13 @@ """ celery status """ +import json + from django.contrib.auth.decorators import login_required, permission_required from django.http import HttpResponse from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.http import require_GET +from django import forms import redis from celerywyrm import settings @@ -46,14 +49,61 @@ class CeleryStatus(View): queues = None errors.append(err) + form = ClearCeleryForm() + data = { "stats": stats, "active_tasks": active_tasks, "queues": queues, + "form": form, "errors": errors, } return TemplateResponse(request, "settings/celery.html", data) + def post(self, request): + """Submit form to clear queues""" + form = ClearCeleryForm(request.POST) + if form.is_valid(): + if len(celery.control.ping()) != 0: + return HttpResponse( + "Refusing to delete tasks while Celery worker is active" + ) + pipeline = r.pipeline() + for queue in form.cleaned_data["queues"]: + for task in r.lrange(queue, 0, -1): + task_json = json.loads(task) + if task_json["headers"]["task"] in form.cleaned_data["tasks"]: + pipeline.lrem(queue, 0, task) + results = pipeline.execute() + + return HttpResponse(f"Deleted {sum(results)} tasks") + + +class ClearCeleryForm(forms.Form): + """Form to clear queues""" + + queues = forms.MultipleChoiceField( + label="Queues", + choices=[ + (LOW, "Low prioirty"), + (MEDIUM, "Medium priority"), + (HIGH, "High priority"), + (IMPORTS, "Imports"), + (BROADCAST, "Broadcasts"), + ], + widget=forms.CheckboxSelectMultiple, + ) + tasks = forms.MultipleChoiceField( + label="Tasks", choices=[], widget=forms.CheckboxSelectMultiple + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + celery.loader.import_default_modules() + self.fields["tasks"].choices = sorted( + [(k, k) for k in celery.tasks.keys() if not k.startswith("celery.")] + ) + @require_GET # pylint: disable=unused-argument From 3709f5c7a965f18fbf6788e28c041ca613ffad78 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Fri, 7 Apr 2023 03:18:43 -0400 Subject: [PATCH 104/113] Increase Celery ping timeout for monitoring page This should prevent some transient alerts. --- bookwyrm/views/admin/celery_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/admin/celery_status.py b/bookwyrm/views/admin/celery_status.py index e0b1fe18c..8175ae405 100644 --- a/bookwyrm/views/admin/celery_status.py +++ b/bookwyrm/views/admin/celery_status.py @@ -60,7 +60,7 @@ class CeleryStatus(View): def celery_ping(request): """Just tells you if Celery is on or not""" try: - ping = celery.control.inspect().ping() + ping = celery.control.inspect().ping(timeout=5) if ping: return HttpResponse() # pylint: disable=broad-except From c89da1bd66d465db00c584a8fa5437408c0d57c0 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Fri, 7 Apr 2023 04:17:51 -0400 Subject: [PATCH 105/113] Don't include deleted users in suggested users query Related: #2727 --- bookwyrm/suggested_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index ea6b1c55d..9ebf7ccb1 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -53,7 +53,7 @@ class SuggestedUsers(RedisStore): def get_users_for_object(self, obj): # pylint: disable=no-self-use """given a user, who might want to follow them""" - return models.User.objects.filter(local=True,).exclude( + return models.User.objects.filter(local=True, is_active=True).exclude( Q(id=obj.id) | Q(followers=obj) | Q(id__in=obj.blocks.all()) | Q(blocks=obj) ) From 912d0a0149d0f3a16fe5c0d2e179ade1c51ef527 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Fri, 7 Apr 2023 05:51:00 -0400 Subject: [PATCH 106/113] Fix Accept header for requesting ActivityPub objects This is the header described in the ActivityPub spec, which should fix some federation problems with GoToSocial and potentially other picky services. Related: #2794, superseriousbusiness/gotosocial#1676 --- bookwyrm/activitypub/base_activity.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index 840dab6a4..ef7ecd0b2 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -384,7 +384,8 @@ def get_activitypub_data(url): resp = requests.get( url, headers={ - "Accept": "application/json; charset=utf-8", + # pylint: disable=line-too-long + "Accept": 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', "Date": now, "Signature": make_signature("get", sender, url, now), }, From a8235fc3a2d06e3330682c2fe70e0e6c4e76dfb3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 7 Apr 2023 06:04:47 -0700 Subject: [PATCH 107/113] Moves the stray "e" back to "mobile" --- bookwyrm/templates/settings/dashboard/dashboard.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html index ead0d275e..4c109c7e1 100644 --- a/bookwyrm/templates/settings/dashboard/dashboard.html +++ b/bookwyrm/templates/settings/dashboard/dashboard.html @@ -16,7 +16,7 @@

{{ users|intcomma }}

-
+

{% trans "Active this month" %}

{{ active_users|intcomma }}

From 77264493eb23bbc85d0fc923e37bca43f0ea4e86 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Wed, 5 Apr 2023 23:54:42 -0400 Subject: [PATCH 108/113] Override get_audience instead of _get_audience in LocalStream I suspect this will make some future work simpler. --- bookwyrm/activitystreams.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 1a863f48b..3da9abc4e 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -208,11 +208,11 @@ class LocalStream(ActivityStream): key = "local" - def _get_audience(self, status): + def get_audience(self, status): # this stream wants no part in non-public statuses if status.privacy != "public" or not status.user.local: return [] - return super()._get_audience(status) + return super().get_audience(status) def get_statuses_for_user(self, user): # all public statuses by a local user From 07b50a1453ea831a75f0eb92768559b184a9b47f Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Thu, 6 Apr 2023 00:35:15 -0400 Subject: [PATCH 109/113] Optimize get_audience This avoids filtering for the user that made the post in the same query as we use for other things, which should allow for better use of indices in all cases. Previously, #2723 did some work on this that only worked for some cases in HomeStream, but this code should work for all cases. Related: #2720 --- bookwyrm/activitystreams.py | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 3da9abc4e..92076e6b8 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -107,7 +107,7 @@ class ActivityStream(RedisStore): @tracer.start_as_current_span("ActivityStream._get_audience") def _get_audience(self, status): # pylint: disable=no-self-use - """given a status, what users should see it""" + """given a status, what users should see it, excluding the author""" trace.get_current_span().set_attribute("status_type", status.status_type) trace.get_current_span().set_attribute("status_privacy", status.privacy) trace.get_current_span().set_attribute( @@ -129,15 +129,13 @@ class ActivityStream(RedisStore): # only visible to the poster and mentioned users if status.privacy == "direct": audience = audience.filter( - Q(id=status.user.id) # if the user is the post's author - | Q(id__in=status.mention_users.all()) # if the user is mentioned + Q(id__in=status.mention_users.all()) # if the user is mentioned ) # don't show replies to statuses the user can't see elif status.reply_parent and status.reply_parent.privacy == "followers": audience = audience.filter( - Q(id=status.user.id) # if the user is the post's author - | Q(id=status.reply_parent.user.id) # if the user is the OG author + Q(id=status.reply_parent.user.id) # if the user is the OG author | ( Q(following=status.user) & Q(following=status.reply_parent.user) ) # if the user is following both authors @@ -146,8 +144,7 @@ class ActivityStream(RedisStore): # only visible to the poster's followers and tagged users elif status.privacy == "followers": audience = audience.filter( - Q(id=status.user.id) # if the user is the post's author - | Q(following=status.user) # if the user is following the author + Q(following=status.user) # if the user is following the author ) return audience.distinct() @@ -155,7 +152,11 @@ class ActivityStream(RedisStore): def get_audience(self, status): """given a status, what users should see it""" trace.get_current_span().set_attribute("stream_id", self.key) - return [user.id for user in self._get_audience(status)] + audience = self._get_audience(status) + status_author = models.User.objects.filter( + is_active=True, local=True, id=status.user.id + ) + return list({user.id for user in list(audience) + list(status_author)}) def get_stores_for_users(self, user_ids): """convert a list of user ids into redis store ids""" @@ -184,11 +185,13 @@ class HomeStream(ActivityStream): audience = super()._get_audience(status) if not audience: return [] - # if the user is the post's author - ids_self = [user.id for user in audience.filter(Q(id=status.user.id))] # if the user is following the author - ids_following = [user.id for user in audience.filter(Q(following=status.user))] - return ids_self + ids_following + audience = audience.filter(following=status.user) + # if the user is the post's author + status_author = models.User.objects.filter( + is_active=True, local=True, id=status.user.id + ) + return list({user.id for user in list(audience) + list(status_author)}) def get_statuses_for_user(self, user): return models.Status.privacy_filter( @@ -229,13 +232,6 @@ class BooksStream(ActivityStream): def _get_audience(self, status): """anyone with the mentioned book on their shelves""" - # only show public statuses on the books feed, - # and only statuses that mention books - if status.privacy != "public" or not ( - status.mention_books.exists() or hasattr(status, "book") - ): - return [] - work = ( status.book.parent_work if hasattr(status, "book") @@ -247,6 +243,16 @@ class BooksStream(ActivityStream): return [] return audience.filter(shelfbook__book__parent_work=work).distinct() + def get_audience(self, status): + # only show public statuses on the books feed, + # and only statuses that mention books + if status.privacy != "public" or not ( + status.mention_books.exists() or hasattr(status, "book") + ): + return [] + + return super().get_audience(status) + def get_statuses_for_user(self, user): """any public status that mentions the user's books""" books = user.shelfbook_set.values_list( From 41633090baaa16a5255170caab6792e5975af771 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Sat, 8 Apr 2023 17:02:04 +0200 Subject: [PATCH 110/113] Don't show the series as a link if the book has no author The series link needs an author so if it doesn't have one, instead of showing a server error let's just show the series details as plain text without a link. Fixes: #2797 --- bookwyrm/templates/book/book.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index e9eff99ab..1024255e6 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -46,7 +46,13 @@ - ({{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %}) + {% if book.authors.exists %} + + {% endif %} + {{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %} + {% if book.authors.exists %} + + {% endif %} {% endif %}

{% endif %} From 43b34610a6082857f87a0c8126be44552d89e4f0 Mon Sep 17 00:00:00 2001 From: Wesley Aptekar-Cassels Date: Tue, 11 Apr 2023 21:51:31 -0400 Subject: [PATCH 111/113] Choose installed docker compose command in bw-dev Docker is removing support for docker-compose, and it doesn't appear to be possible to install it anymore. Instead, it has been replaced with compose V2 which is a docker plugin called with 'docker compose' (no hyphen). See https://docs.docker.com/compose/compose-v2/ Thanks to @Neriderc for noticing this in #2781. --- bw-dev | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/bw-dev b/bw-dev index 3e804943b..df88b06c6 100755 --- a/bw-dev +++ b/bw-dev @@ -23,21 +23,27 @@ trap showerr EXIT source .env trap - EXIT +if docker compose &> /dev/null ; then + DOCKER_COMPOSE="docker compose" +else + DOCKER_COMPOSE="docker-compose" +fi + function clean { - docker-compose stop - docker-compose rm -f + $DOCKER_COMPOSE stop + $DOCKER_COMPOSE rm -f } function runweb { - docker-compose run --rm web "$@" + $DOCKER_COMPOSE run --rm web "$@" } function execdb { - docker-compose exec db $@ + $DOCKER_COMPOSE exec db $@ } function execweb { - docker-compose exec web "$@" + $DOCKER_COMPOSE exec web "$@" } function initdb { @@ -75,23 +81,23 @@ set -x case "$CMD" in up) - docker-compose up --build "$@" + $DOCKER_COMPOSE up --build "$@" ;; down) - docker-compose down + $DOCKER_COMPOSE down ;; service_ports_web) prod_error - docker-compose run --rm --service-ports web + $DOCKER_COMPOSE run --rm --service-ports web ;; initdb) initdb "@" ;; resetdb) prod_error - docker-compose rm -svf + $DOCKER_COMPOSE rm -svf docker volume rm -f bookwyrm_media_volume bookwyrm_pgdata bookwyrm_redis_activity_data bookwyrm_redis_broker_data bookwyrm_static_volume - docker-compose build + $DOCKER_COMPOSE build migrate migrate django_celery_beat initdb @@ -116,7 +122,7 @@ case "$CMD" in execdb psql -U ${POSTGRES_USER} ${POSTGRES_DB} ;; restart_celery) - docker-compose restart celery_worker + $DOCKER_COMPOSE restart celery_worker ;; pytest) prod_error @@ -164,7 +170,7 @@ case "$CMD" in runweb django-admin compilemessages --ignore venv ;; build) - docker-compose build + $DOCKER_COMPOSE build ;; clean) prod_error @@ -172,7 +178,7 @@ case "$CMD" in ;; black) prod_error - docker-compose run --rm dev-tools black celerywyrm bookwyrm + $DOCKER_COMPOSE run --rm dev-tools black celerywyrm bookwyrm ;; pylint) prod_error @@ -181,25 +187,25 @@ case "$CMD" in ;; prettier) prod_error - docker-compose run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js + $DOCKER_COMPOSE run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js ;; eslint) prod_error - docker-compose run --rm dev-tools npx eslint bookwyrm/static --ext .js + $DOCKER_COMPOSE run --rm dev-tools npx eslint bookwyrm/static --ext .js ;; stylelint) prod_error - docker-compose run --rm dev-tools npx stylelint \ + $DOCKER_COMPOSE run --rm dev-tools npx stylelint \ bookwyrm/static/css/bookwyrm.scss bookwyrm/static/css/bookwyrm/**/*.scss --fix \ --config dev-tools/.stylelintrc.js ;; formatters) prod_error runweb pylint bookwyrm/ - docker-compose run --rm dev-tools black celerywyrm bookwyrm - docker-compose run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js - docker-compose run --rm dev-tools npx eslint bookwyrm/static --ext .js - docker-compose run --rm dev-tools npx stylelint \ + $DOCKER_COMPOSE run --rm dev-tools black celerywyrm bookwyrm + $DOCKER_COMPOSE run --rm dev-tools npx prettier --write bookwyrm/static/js/*.js + $DOCKER_COMPOSE run --rm dev-tools npx eslint bookwyrm/static --ext .js + $DOCKER_COMPOSE run --rm dev-tools npx stylelint \ bookwyrm/static/css/bookwyrm.scss bookwyrm/static/css/bookwyrm/**/*.scss --fix \ --config dev-tools/.stylelintrc.js ;; @@ -209,14 +215,14 @@ case "$CMD" in ;; update) git pull - docker-compose build + $DOCKER_COMPOSE build # ./update.sh runweb python manage.py migrate runweb python manage.py compile_themes runweb python manage.py collectstatic --no-input - docker-compose up -d - docker-compose restart web - docker-compose restart celery_worker + $DOCKER_COMPOSE up -d + $DOCKER_COMPOSE restart web + $DOCKER_COMPOSE restart celery_worker ;; populate_streams) runweb python manage.py populate_streams "$@" From f520d1b7f8c2ebca690ac3e246c39b3a5e70045a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 14 Apr 2023 16:40:50 +0200 Subject: [PATCH 112/113] Make the text on the search button translatable --- bookwyrm/templates/search/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/search/layout.html b/bookwyrm/templates/search/layout.html index a2f64ad07..340911cb0 100644 --- a/bookwyrm/templates/search/layout.html +++ b/bookwyrm/templates/search/layout.html @@ -29,7 +29,7 @@
From 3619d8960bf951bbc69f8aa23ce7d0f27d3d117d Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 14 Apr 2023 16:49:00 +0200 Subject: [PATCH 113/113] Mark two strings as translatable in the getting started questionnaire --- bookwyrm/templates/get_started/books.html | 2 +- bookwyrm/templates/get_started/users.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/get_started/books.html b/bookwyrm/templates/get_started/books.html index 9613508b9..93196dbcf 100644 --- a/bookwyrm/templates/get_started/books.html +++ b/bookwyrm/templates/get_started/books.html @@ -30,7 +30,7 @@
{% if book_results %}
-

Search results

+

{% trans "Search results" %}

{% for book in book_results %} diff --git a/bookwyrm/templates/get_started/users.html b/bookwyrm/templates/get_started/users.html index 7ec7ed9d3..4f95882f5 100644 --- a/bookwyrm/templates/get_started/users.html +++ b/bookwyrm/templates/get_started/users.html @@ -5,7 +5,7 @@

{% trans "Who to follow" %}

-

You can follow users on other BookWyrm instances and federated services like Mastodon.

+

{% trans "You can follow users on other BookWyrm instances and federated services like Mastodon." %}