Merge branch 'main' into query-time

This commit is contained in:
Mouse Reeve 2024-08-09 13:47:52 -07:00 committed by GitHub
commit d56a21e232
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
73 changed files with 122 additions and 136 deletions

View file

@ -1,10 +1,5 @@
<!--
Thanks for contributing!
Please ensure the name of your PR is written in imperative present tense. For example:
- "fix color contrast on submit buttons"
- "add 'favourite food' value to Author model"
Thanks for contributing! This template has some checkboxes that help keep track of what changes go into a release.
To check (tick) a list item, replace the space between square brackets with an x, like this:
@ -12,24 +7,23 @@ To check (tick) a list item, replace the space between square brackets with an x
You can find more information and tips for BookWyrm contributors at https://docs.joinbookwyrm.com/contributing.html
-->
## Are you finished?
### Linters
## Description
<!--
Please run linters on your code before submitting your PR.
If you miss this step it is likely that the GitHub task runners will fail.
Describe what your pull request does here
-->
- [ ] I have checked my code with `black`, `pylint`, and `mypy`, or `./bw-dev formatters`
### Tests
<!-- Check one -->
<!--
For pull requests that relate or close an issue, please include them
below. We like to follow [Github's guidance on linking issues to pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
- [ ] My changes do not need new tests
- [ ] All tests I have added are passing
- [ ] I have written tests but need help to make them pass
- [ ] I have not written tests and need help to write them
For example having the text: "closes #1234" would connect the current pull
request to issue 1234. And when we merge the pull request, Github will
automatically close the issue.
-->
- Related Issue #
- Closes #
## What type of Pull Request is this?
<!-- Check all that apply -->
@ -48,21 +42,6 @@ If you miss this step it is likely that the GitHub task runners will fail.
### Details of breaking or configuration changes (if any of above checked)
## Description
<!--
Describe what your pull request does here.
For pull requests that relate or close an issue, please include them
below. We like to follow [Github's guidance on linking issues to pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
For example having the text: "closes #1234" would connect the current pull
request to issue 1234. And when we merge the pull request, Github will
automatically close the issue.
-->
- Related Issue #
- Closes #
## Documentation
<!--
@ -76,3 +55,14 @@ Our documentation is maintained in a separate repository at https://github.com/b
- [ ] I have created a matching pull request in the Documentation repository
- [ ] I intend to create a matching pull request in the Documentation repository after this PR is merged
<!-- Amazing! Thanks for filling that out. Your PR will need to have passing tests and happy linters before we can merge
You will need to check your code with `black`, `pylint`, and `mypy`, or `./bw-dev formatters`
-->
### Tests
<!-- Check one -->
- [ ] My changes do not need new tests
- [ ] All tests I have added are passing
- [ ] I have written tests but need help to make them pass
- [ ] I have not written tests and need help to write them

View file

@ -3,7 +3,19 @@ ignore=migrations
load-plugins=pylint.extensions.no_self_use
[MESSAGES CONTROL]
disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406,R0401,R0801,C3001,import-error
disable =
cyclic-import,
duplicate-code,
fixme,
no-member,
raise-missing-from,
too-few-public-methods,
too-many-ancestors,
too-many-instance-attributes,
unnecessary-lambda-assignment,
unsubscriptable-object,
enable =
useless-suppression
[FORMAT]
max-line-length=88

View file

@ -67,7 +67,6 @@ class Edition(Book):
type: str = "Edition"
# pylint: disable=invalid-name
@dataclass(init=False)
class Work(Book):
"""work instance of a book object"""

View file

@ -18,7 +18,6 @@ class OrderedCollection(ActivityObject):
type: str = "OrderedCollection"
# pylint: disable=invalid-name
@dataclass(init=False)
class OrderedCollectionPrivate(OrderedCollection):
"""an ordered collection with privacy settings"""

View file

@ -22,7 +22,6 @@ class Verb(ActivityObject):
self.object.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@dataclass(init=False)
class Create(Verb):
"""Create activity"""
@ -33,7 +32,6 @@ class Create(Verb):
type: str = "Create"
# pylint: disable=invalid-name
@dataclass(init=False)
class Delete(Verb):
"""Create activity"""
@ -63,7 +61,6 @@ class Delete(Verb):
# if we can't find it, we don't need to delete it because we don't have it
# pylint: disable=invalid-name
@dataclass(init=False)
class Update(Verb):
"""Update activity"""
@ -227,7 +224,6 @@ class Like(Verb):
self.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@dataclass(init=False)
class Announce(Verb):
"""boosting a status"""

View file

@ -32,7 +32,7 @@ class ActivityStream(RedisStore):
stream_id = self.stream_id(user_id)
return f"{stream_id}-unread-by-type"
def get_rank(self, obj): # pylint: disable=no-self-use
def get_rank(self, obj):
"""statuses are sorted by date published"""
return obj.published_date.timestamp()

View file

@ -33,7 +33,6 @@ class BookwyrmConfig(AppConfig):
name = "bookwyrm"
verbose_name = "BookWyrm"
# pylint: disable=no-self-use
def ready(self):
"""set up OTLP and preview image files, if desired"""
if settings.OTEL_EXPORTER_OTLP_ENDPOINT or settings.OTEL_EXPORTER_CONSOLE:

View file

@ -36,7 +36,6 @@ def search(
...
# pylint: disable=arguments-differ
def search(
query: str,
*,

View file

@ -2,7 +2,7 @@
from bookwyrm import models, settings
def site_settings(request): # pylint: disable=unused-argument
def site_settings(request):
"""include the custom info about the site"""
request_protocol = "https://"
if not request.is_secure():

View file

@ -15,9 +15,9 @@ class StyledForm(ModelForm):
css_classes["number"] = "input"
css_classes["checkbox"] = "checkbox"
css_classes["textarea"] = "textarea"
# pylint: disable=super-with-arguments
super().__init__(*args, **kwargs)
for visible in self.visible_fields():
input_type = ""
if hasattr(visible.field.widget, "input_type"):
input_type = visible.field.widget.input_type
if isinstance(visible.field.widget, Textarea):

View file

@ -34,7 +34,6 @@ class LoginForm(CustomForm):
def add_invalid_password_error(self):
"""We don't want to be too specific about this"""
# pylint: disable=attribute-defined-outside-init
self.non_field_errors = _("Username or password are incorrect")

View file

@ -5,8 +5,6 @@ from django import forms
class ArrayWidget(forms.widgets.TextInput):
"""Inputs for postgres array fields"""
# pylint: disable=unused-argument
# pylint: disable=no-self-use
def value_from_datadict(self, data, files, name):
"""get all values for this name"""
return [i for i in data.getlist(name) if i]

View file

@ -36,7 +36,6 @@ class Importer:
"reading": ["currently-reading", "reading", "currently reading"],
}
# pylint: disable=too-many-locals
def create_job(
self, user: User, csv_file: Iterable[str], include_reviews: bool, privacy: str
) -> ImportJob:

View file

@ -20,7 +20,7 @@ class LibrarythingImporter(Importer):
def normalize_row(
self, entry: dict[str, str], mappings: dict[str, Optional[str]]
) -> dict[str, Optional[str]]: # pylint: disable=no-self-use
) -> dict[str, Optional[str]]:
"""use the dataclass to create the formatted row of data"""
normalized = {
k: _remove_brackets(entry.get(v) if v else None)

View file

@ -18,7 +18,7 @@ class ListsStream(RedisStore):
return f"{user}-lists"
return f"{user.id}-lists"
def get_rank(self, obj): # pylint: disable=no-self-use
def get_rank(self, obj):
"""lists are sorted by updated date"""
return obj.updated_date.timestamp()

View file

@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
PropertyField = namedtuple("PropertyField", ("set_activity_from_field"))
# pylint: disable=invalid-name
def set_activity_from_property_field(activity, obj, field):
"""assign a model property value to the activity json"""
activity[field[1]] = getattr(obj, field[0])

View file

@ -133,7 +133,6 @@ class BookDataModel(ObjectMixin, BookWyrmModel):
related_models = [
(r.remote_field.name, r.related_model) for r in self._meta.related_objects
]
# pylint: disable=protected-access
for related_field, related_model in related_models:
# Skip the ManyToMany fields that arent auto-created. These
# should have a corresponding OneToMany field in the model for

View file

@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
class BookwyrmAwsSession(BotoSession):
"""a boto session that always uses settings.AWS_S3_ENDPOINT_URL"""
def client(self, *args, **kwargs): # pylint: disable=arguments-differ
def client(self, *args, **kwargs):
kwargs["endpoint_url"] = settings.AWS_S3_ENDPOINT_URL
return super().client("s3", *args, **kwargs)

View file

@ -193,8 +193,7 @@ class UsernameField(ActivitypubFieldMixin, models.CharField):
def __init__(self, activitypub_field="preferredUsername", **kwargs):
self.activitypub_field = activitypub_field
# I don't totally know why pylint is mad at this, but it makes it work
super(ActivitypubFieldMixin, self).__init__( # pylint: disable=bad-super-call
super(ActivitypubFieldMixin, self).__init__(
_("username"),
max_length=150,
unique=True,
@ -234,7 +233,6 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField):
def __init__(self, *args, **kwargs):
super().__init__(*args, max_length=255, choices=PrivacyLevels, default="public")
# pylint: disable=invalid-name
def set_field_from_activity(
self, instance, data, overwrite=True, allow_external_connections=True
):
@ -276,7 +274,6 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField):
if hasattr(instance, "mention_users"):
mentions = [u.remote_id for u in instance.mention_users.all()]
# this is a link to the followers list
# pylint: disable=protected-access
followers = instance.user.followers_url
if instance.privacy == "public":
activity["to"] = [self.public]
@ -444,7 +441,7 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
self.alt_field = alt_field
super().__init__(*args, **kwargs)
# pylint: disable=arguments-differ,arguments-renamed,too-many-arguments
# pylint: disable=arguments-renamed,too-many-arguments
def set_field_from_activity(
self, instance, data, save=True, overwrite=True, allow_external_connections=True
):

View file

@ -352,7 +352,7 @@ def import_item_task(item_id):
try:
item.resolve()
except Exception as err: # pylint: disable=broad-except
except Exception as err:
item.fail_reason = _("Error loading book")
item.save()
item.update_job()

View file

@ -135,7 +135,7 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
status = "follow_request"
activity_serializer = activitypub.Follow
def save(self, *args, broadcast=True, **kwargs): # pylint: disable=arguments-differ
def save(self, *args, broadcast=True, **kwargs):
"""make sure the follow or block relationship doesn't already exist"""
# if there's a request for a follow that already exists, accept it
# without changing the local database state

View file

@ -98,7 +98,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
self.thread_id = self.id
super().save(broadcast=False, update_fields=["thread_id"])
def delete(self, *args, **kwargs): # pylint: disable=unused-argument
def delete(self, *args, **kwargs):
""" "delete" a status"""
if hasattr(self, "boosted_status"):
# okay but if it's a boost really delete it
@ -213,7 +213,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
**kwargs,
).serialize()
def to_activity_dataclass(self, pure=False): # pylint: disable=arguments-differ
def to_activity_dataclass(self, pure=False):
"""return tombstone if the status is deleted"""
if self.deleted:
return activitypub.Tombstone(

View file

@ -409,7 +409,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def delete(self, *args, **kwargs):
"""We don't actually delete the database entry"""
# pylint: disable=attribute-defined-outside-init
self.is_active = False
self.allow_reactivation = False
self.is_deleted = True
@ -452,7 +451,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def deactivate(self):
"""Disable the user but allow them to reactivate"""
# pylint: disable=attribute-defined-outside-init
self.is_active = False
self.deactivation_reason = "self_deactivation"
self.allow_reactivation = True
@ -460,7 +458,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def reactivate(self):
"""Now you want to come back, huh?"""
# pylint: disable=attribute-defined-outside-init
if not self.allow_reactivation:
return
self.is_active = True

View file

@ -420,7 +420,6 @@ def save_and_cleanup(image, instance=None):
return True
# pylint: disable=invalid-name
@app.task(queue=IMAGES)
def generate_site_preview_image_task():
"""generate preview_image for the website"""
@ -445,7 +444,6 @@ def generate_site_preview_image_task():
save_and_cleanup(image, instance=site)
# pylint: disable=invalid-name
@app.task(queue=IMAGES)
def generate_edition_preview_image_task(book_id):
"""generate preview_image for a book"""

View file

@ -6,7 +6,7 @@ from base64 import b64encode, b64decode
from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15 # pylint: disable=no-name-in-module
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
MAX_SIGNATURE_AGE = 300
@ -84,7 +84,6 @@ class Signature:
self.headers = headers
self.signature = signature
# pylint: disable=invalid-name
@classmethod
def parse(cls, request):
"""extract and parse a signature from an http request"""

View file

@ -34,7 +34,6 @@ class SuggestedUsers(RedisStore):
def get_counts_from_rank(self, rank): # pylint: disable=no-self-use
"""calculate mutuals count and shared books count from rank"""
# pylint: disable=c-extension-no-member
return {
"mutuals": math.floor(rank),
# "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1,
@ -128,7 +127,6 @@ def get_annotated_users(viewer, *args, **kwargs):
),
distinct=True,
),
# pylint: disable=line-too-long
# shared_books=Count(
# "shelfbook",
# filter=Q(
@ -202,7 +200,7 @@ def update_suggestions_on_unfollow(sender, instance, **kwargs):
@receiver(signals.post_save, sender=models.User)
# pylint: disable=unused-argument, too-many-arguments
# pylint: disable=unused-argument
def update_user(sender, instance, created, update_fields=None, **kwargs):
"""an updated user, neat"""
# a new user is found, create suggestions for them

View file

@ -3,8 +3,10 @@
{% load utilities %}
{% block heading %}
{% block title %}
{% blocktrans with username=user.localname sitename=site.name %}Follow {{ username }} on the fediverse{% endblocktrans %}
{% endblock %}
{% endblock %}
{% block content %}
<div class="block card">

View file

@ -2,6 +2,10 @@
{% load i18n %}
{% load utilities %}
{% block title %}
{% blocktrans with display_name=user.display_name %}You are now following {{ display_name }}!{% endblocktrans %}
{% endblock %}
{% block content %}
<div class="block card">
<div class="card-content">

View file

@ -115,7 +115,6 @@ class AbstractConnector(TestCase):
@responses.activate
def test_get_or_create_author(self):
"""load an author"""
# pylint: disable=attribute-defined-outside-init
self.connector.author_mappings = [
Mapping("id"),
Mapping("name"),
@ -141,7 +140,6 @@ class AbstractConnector(TestCase):
def test_update_author_from_remote(self):
"""trigger the function that looks up the remote data"""
author = models.Author.objects.create(name="Test", openlibrary_key="OL123A")
# pylint: disable=attribute-defined-outside-init
self.connector.author_mappings = [
Mapping("id"),
Mapping("name"),

View file

@ -20,7 +20,7 @@ from bookwyrm.models.activitypub_mixin import (
from bookwyrm.settings import PAGE_LENGTH
# pylint: disable=invalid-name,too-many-public-methods
# pylint: disable=too-many-public-methods
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class ActivitypubMixins(TestCase):

View file

@ -42,7 +42,7 @@ class BaseModel(TestCase):
def test_remote_id(self):
"""these should be generated"""
self.test_model.id = 1 # pylint: disable=invalid-name
self.test_model.id = 1
expected = self.test_model.get_remote_id()
self.assertEqual(expected, f"{BASE_URL}/bookwyrmtestmodel/1")

View file

@ -13,7 +13,7 @@ from bookwyrm.utils.tar import BookwyrmTarFile
from bookwyrm.models import bookwyrm_import_job
class BookwyrmImport(TestCase): # pylint: disable=too-many-public-methods
class BookwyrmImport(TestCase):
"""testing user import functions"""
def setUp(self):

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, settings
# pylint: disable=unused-argument
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.lists_stream.populate_lists_task.delay")

View file

@ -10,7 +10,7 @@ class MergeBookDataModel(TestCase):
"""test merging of subclasses of BookDataModel"""
@classmethod
def setUpTestData(cls): # pylint: disable=invalid-name
def setUpTestData(cls):
"""shared data"""
models.SiteSettings.objects.create()

View file

@ -42,7 +42,7 @@ def validate_html(html):
validator.feed(str(html.content))
class HtmlValidator(HTMLParser): # pylint: disable=abstract-method
class HtmlValidator(HTMLParser):
"""Checks for custom html validation requirements"""
def __init__(self):

View file

@ -14,7 +14,6 @@ from bookwyrm.tests.validate_html import validate_html
class ImportUserViews(TestCase):
"""user import views"""
# pylint: disable=invalid-name
def setUp(self):
"""we need basic test data and mocks"""
self.factory = RequestFactory()

View file

@ -11,7 +11,6 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class Inbox(TestCase):
"""readthrough tests"""

View file

@ -7,7 +7,6 @@ import responses
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxAdd(TestCase):
"""inbox tests"""

View file

@ -7,7 +7,6 @@ import responses
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxBlock(TestCase):
"""inbox tests"""

View file

@ -9,7 +9,6 @@ from bookwyrm import models, views
from bookwyrm.activitypub import ActivitySerializerError
# pylint: disable=too-many-public-methods
class TransactionInboxCreate(TransactionTestCase):
"""readthrough tests"""

View file

@ -7,7 +7,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -7,7 +7,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxRelationships(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxActivities(TestCase):
"""inbox tests"""

View file

@ -6,7 +6,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxRemove(TestCase):
"""inbox tests"""

View file

@ -8,7 +8,6 @@ from django.test import TestCase
from bookwyrm import models, views
# pylint: disable=too-many-public-methods
class InboxUpdate(TestCase):
"""inbox tests"""
@ -161,7 +160,6 @@ class InboxUpdate(TestCase):
datafile = pathlib.Path(__file__).parent.joinpath("../../data/bw_edition.json")
bookdata = json.loads(datafile.read_bytes())
del bookdata["authors"]
# pylint: disable=line-too-long
link_data = {
"href": "https://openlibrary.org/books/OL11645413M/Queen_Victoria/daisy",
"mediaType": "Daisy",

View file

@ -11,7 +11,6 @@ from bookwyrm import forms, models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class LoginViews(TestCase):

View file

@ -11,7 +11,6 @@ from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""list view"""

View file

@ -11,7 +11,6 @@ from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""list view"""

View file

@ -13,7 +13,6 @@ from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
# pylint: disable=too-many-public-methods
class ListViews(TestCase):
"""list view"""

View file

@ -7,8 +7,6 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
# pylint: disable=unused-argument
# pylint: disable=too-many-public-methods
class ListItemViews(TestCase):
"""list view"""

View file

@ -11,7 +11,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class ListViews(TestCase):
"""lists of lists"""

View file

@ -18,7 +18,7 @@ class ExportViews(TestCase):
"""viewing and creating statuses"""
@classmethod
def setUpTestData(cls): # pylint: disable=invalid-name
def setUpTestData(cls):
"""we need basic test data and mocks"""
with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
@ -41,7 +41,6 @@ class ExportViews(TestCase):
bnf_id="beep",
)
# pylint: disable=invalid-name
def setUp(self):
"""individual test setup"""
self.factory = RequestFactory()

View file

@ -11,7 +11,7 @@ from django.test.client import RequestFactory
from bookwyrm import forms, models, views
# pylint: disable=too-many-public-methods
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
class TwoFactorViews(TestCase):

View file

@ -9,7 +9,7 @@ from django.test.client import RequestFactory
from bookwyrm import models, views
from bookwyrm.tests.validate_html import validate_html
# pylint: disable=unused-argument
class DirectoryViews(TestCase):
"""tag views"""

View file

@ -10,7 +10,6 @@ from bookwyrm import models, views
from bookwyrm.settings import USER_AGENT
# pylint: disable=too-many-public-methods
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
class OutboxView(TestCase):
"""sends out activities"""

View file

@ -1,9 +1,11 @@
""" test for app action functionality """
import json
from unittest.mock import patch
import dateutil
from django.core.exceptions import PermissionDenied
from django.test import TestCase, TransactionTestCase
from django.test.client import RequestFactory
from django.utils import timezone
from bookwyrm import forms, models, views
from bookwyrm.views.status import find_mentions, find_or_create_hashtags
@ -167,6 +169,37 @@ class StatusViews(TestCase):
self.assertEqual(status.rating, 4.0)
self.assertIsNone(status.edited_date)
def test_create_status_progress(self, *_):
"""create a status that updates a readthrough"""
start_date = timezone.make_aware(dateutil.parser.parse("2024-07-27"))
readthrough = models.ReadThrough.objects.create(
book=self.book, user=self.local_user, start_date=start_date
)
self.assertEqual(start_date, readthrough.start_date)
self.assertIsNone(readthrough.progress)
view = views.CreateStatus.as_view()
form = forms.CommentForm(
{
"progress": 1,
"progress_mode": "PG",
"content": "I started the book",
"id": readthrough.id,
"book": self.book.id,
"user": self.local_user.id,
"privacy": "public",
}
)
request = self.factory.post("", form.data)
request.user = self.local_user
view(request, "comment")
readthrough.refresh_from_db()
self.assertEqual(1, readthrough.progress)
self.assertEqual(start_date, readthrough.start_date) # not overwritten
def test_create_status_wrong_user(self, *_):
"""You can't compose statuses for someone else"""
view = views.CreateStatus.as_view()

View file

@ -52,7 +52,6 @@ class PartialDate(datetime):
Use subclasses to specify precision. If `dt` is naive, `ValueError`
is raised.
"""
# pylint: disable=invalid-name
if timezone.is_naive(dt):
raise ValueError("naive datetime not accepted")
return cls.combine(dt.date(), dt.time(), tzinfo=dt.tzinfo)

View file

@ -88,6 +88,7 @@ class CeleryStatus(View):
def post(self, request):
"""Submit form to clear queues"""
form = ClearCeleryForm(request.POST)
results = []
if form.is_valid():
if len(celery.control.ping()) != 0:
return HttpResponse(

View file

@ -43,7 +43,6 @@ class Dashboard(View):
) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN)
data["email_config_error"] = email_config_error
# pylint: disable=line-too-long
data[
"email_sender"
] = f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}"

View file

@ -152,7 +152,7 @@ class FederatedServer(View):
}
return TemplateResponse(request, "settings/federation/instance.html", data)
def post(self, request, server): # pylint: disable=unused-argument
def post(self, request, server):
"""update note"""
server = get_object_or_404(models.FederatedServer, id=server)
server.notes = request.POST.get("notes")

View file

@ -63,7 +63,6 @@ class ImportList(View):
}
return TemplateResponse(request, "settings/imports/imports.html", data)
# pylint: disable=unused-argument
def post(self, request, import_id):
"""Mark an import as complete"""
import_job = get_object_or_404(models.ImportJob, id=import_id)
@ -95,7 +94,6 @@ def enable_imports(request):
@require_POST
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
# pylint: disable=unused-argument
def set_import_size_limit(request):
"""Limit the amount of books users can import at once"""
site = models.SiteSettings.objects.get()
@ -120,7 +118,6 @@ def set_user_import_completed(request, import_id):
@require_POST
@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
# pylint: disable=unused-argument
def set_user_import_limit(request):
"""Limit how ofter users can import and export their account"""
site = models.SiteSettings.objects.get()

View file

@ -204,7 +204,6 @@ def resolve_book(request):
@login_required
@require_POST
@permission_required("bookwyrm.edit_book", raise_exception=True)
# pylint: disable=unused-argument
def update_book_from_remote(request, book_id, connector_identifier):
"""load the remote data for this book"""
connector = connector_manager.load_connector(

View file

@ -88,7 +88,6 @@ class CreateBook(View):
data = {"form": forms.EditionForm()}
return TemplateResponse(request, "book/edit/edit_book.html", data)
# pylint: disable=too-many-locals
def post(self, request):
"""create a new book"""
# returns None if no match is found

View file

@ -240,7 +240,7 @@ def redirect_to_referer(request, *args, **kwargs):
return redirect(*args or "/", **kwargs)
# pylint: disable=redefined-builtin,invalid-name
# pylint: disable=redefined-builtin
def get_mergeable_object_or_404(klass, id):
"""variant of get_object_or_404 that also redirects if id has been merged
into another object"""

View file

@ -97,7 +97,7 @@ class Register(View):
class ConfirmEmailCode(View):
"""confirm email address"""
def get(self, request, code): # pylint: disable=unused-argument
def get(self, request, code):
"""you got the code! good work"""
settings = models.SiteSettings.get()
if request.user.is_authenticated:
@ -124,7 +124,7 @@ class ConfirmEmailCode(View):
class ConfirmEmail(View):
"""enter code to confirm email address"""
def get(self, request): # pylint: disable=unused-argument
def get(self, request):
"""you need a code! keep looking"""
settings = models.SiteSettings.get()
if request.user.is_authenticated or not settings.require_confirm_email:

View file

@ -22,7 +22,6 @@ logger = logging.getLogger(__name__)
# pylint: disable=no-self-use
# pylint: disable=too-many-return-statements
@method_decorator(login_required, name="dispatch")
class ReadingStatus(View):
"""consider reading a book"""

View file

@ -7,7 +7,7 @@ from ..models import Review, Quotation, Comment
from .helpers import get_user_from_username
# pylint: disable=no-self-use, unused-argument
# pylint: disable=no-self-use
class RssFeed(Feed):
"""serialize user's posts in rss feed"""

View file

@ -119,7 +119,6 @@ class Shelf(View):
return TemplateResponse(request, "shelf/shelf.html", data)
@method_decorator(login_required, name="dispatch")
# pylint: disable=unused-argument
def post(self, request, username, shelf_identifier):
"""edit a shelf"""
user = get_user_from_username(request.user, username)

View file

@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
class EditStatus(View):
"""the view for *posting*"""
def get(self, request, status_id): # pylint: disable=unused-argument
def get(self, request, status_id):
"""load the edit panel"""
status = get_object_or_404(
models.Status.objects.select_subclasses(), id=status_id
@ -201,12 +201,11 @@ def edit_readthrough(request):
# TODO: remove this, it duplicates the code in the ReadThrough view
readthrough = get_object_or_404(models.ReadThrough, id=request.POST.get("id"))
readthrough.start_date = load_date_in_user_tz_as_utc(
request.POST.get("start_date"), request.user
)
readthrough.finish_date = load_date_in_user_tz_as_utc(
request.POST.get("finish_date"), request.user
)
if start_date := request.POST.get("start_date"):
readthrough.start_date = load_date_in_user_tz_as_utc(start_date, request.user)
if finish_date := request.POST.get("finish_date"):
readthrough.finish_date = load_date_in_user_tz_as_utc(finish_date, request.user)
progress = request.POST.get("progress")
try:

View file

@ -15,8 +15,12 @@ REDIS_BROKER_URL = env(
f"redis://:{REDIS_BROKER_PASSWORD}@{REDIS_BROKER_HOST}:{REDIS_BROKER_PORT}/{REDIS_BROKER_DB_INDEX}",
)
CELERY_BROKER_URL = REDIS_BROKER_URL.replace("unix:", "redis+socket:")
CELERY_RESULT_BACKEND = REDIS_BROKER_URL.replace("unix:", "redis+socket:")
CELERY_BROKER_URL = env(
"CELERY_BROKER_URL", REDIS_BROKER_URL.replace("unix:", "redis+socket:")
)
CELERY_RESULT_BACKEND = env(
"CELERY_RESULT_BACKEND", REDIS_BROKER_URL.replace("unix:", "redis+socket:")
)
CELERY_DEFAULT_QUEUE = "low_priority"
CELERY_CREATE_MISSING_QUEUES = True

View file

@ -15,11 +15,8 @@ env =
ALLOWED_HOSTS = your.domain.here
BOOKWYRM_DATABASE_BACKEND = postgres
MEDIA_ROOT = images/
CELERY_BROKER =
REDIS_BROKER_PORT = 6379
REDIS_BROKER_PASSWORD = beep
REDIS_ACTIVITY_PORT = 6379
REDIS_ACTIVITY_PASSWORD = beep
CELERY_BROKER_URL = memory://
CELERY_RESULT_BACKEND = cache+memory://
USE_DUMMY_CACHE = true
FLOWER_PORT = 8888
EMAIL_HOST = smtp.mailgun.org

View file

@ -4,7 +4,7 @@ boto3==1.34.74
bw-file-resubmit==0.6.0rc2
celery==5.3.6
colorthief==0.2.1
Django==4.2.14
Django==4.2.15
django-celery-beat==2.6.0
django-compressor==4.4
django-csp==3.8
@ -49,7 +49,7 @@ black==22.*
celery-types==0.22.0
django-stubs[compatible-mypy]==4.2.7
mypy==1.7.1
pylint==2.17.7
pylint==3.2.6
pytest==8.1.1
pytest-cov==5.0.0
pytest-django==4.8.0