Updates code for linter

This commit is contained in:
Mouse Reeve 2021-06-18 14:12:56 -07:00
parent 20f74ba02b
commit 4479864008
21 changed files with 71 additions and 61 deletions

View file

@ -20,5 +20,5 @@ jobs:
pip install pylint pip install pylint
- name: Analysing the code with pylint - name: Analysing the code with pylint
run: | run: |
pylint bookwyrm/ --ignore=migrations --disable=E1101,E1136,R0903,R0901,W0707,W0511 pylint bookwyrm/ --ignore=migrations,__init__ --disable=E1101,E1135,E1136,R0903,R0901,R0902,W0707,W0511,W0406

View file

@ -37,6 +37,7 @@ class Mention(Link):
@dataclass @dataclass
# pylint: disable=invalid-name
class Signature: class Signature:
"""public key block""" """public key block"""
@ -56,11 +57,11 @@ def naive_parse(activity_objects, activity_json, serializer=None):
activity_type = activity_json.get("type") activity_type = activity_json.get("type")
try: try:
serializer = activity_objects[activity_type] serializer = activity_objects[activity_type]
except KeyError as e: except KeyError as err:
# we know this exists and that we can't handle it # we know this exists and that we can't handle it
if activity_type in ["Question"]: if activity_type in ["Question"]:
return None return None
raise ActivitySerializerError(e) raise ActivitySerializerError(err)
return serializer(activity_objects=activity_objects, **activity_json) return serializer(activity_objects=activity_objects, **activity_json)

View file

@ -6,6 +6,7 @@ from .base_activity import ActivityObject
from .image import Document from .image import Document
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class BookData(ActivityObject): class BookData(ActivityObject):
"""shared fields for all book data and authors""" """shared fields for all book data and authors"""
@ -18,6 +19,7 @@ class BookData(ActivityObject):
lastEditedBy: str = None lastEditedBy: str = None
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Book(BookData): class Book(BookData):
"""serializes an edition or work, abstract""" """serializes an edition or work, abstract"""
@ -40,6 +42,7 @@ class Book(BookData):
type: str = "Book" type: str = "Book"
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Edition(Book): class Edition(Book):
"""Edition instance of a book object""" """Edition instance of a book object"""
@ -57,6 +60,7 @@ class Edition(Book):
type: str = "Edition" type: str = "Edition"
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Work(Book): class Work(Book):
"""work instance of a book object""" """work instance of a book object"""
@ -66,6 +70,7 @@ class Work(Book):
type: str = "Work" type: str = "Work"
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Author(BookData): class Author(BookData):
"""author of a book""" """author of a book"""

View file

@ -22,6 +22,7 @@ class Verb(ActivityObject):
self.object.to_model() self.object.to_model()
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Create(Verb): class Create(Verb):
"""Create activity""" """Create activity"""
@ -32,6 +33,7 @@ class Create(Verb):
type: str = "Create" type: str = "Create"
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Delete(Verb): class Delete(Verb):
"""Create activity""" """Create activity"""
@ -57,6 +59,7 @@ class Delete(Verb):
# if we can't find it, we don't need to delete it because we don't have it # 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) @dataclass(init=False)
class Update(Verb): class Update(Verb):
"""Update activity""" """Update activity"""
@ -192,6 +195,7 @@ class Like(Verb):
self.to_model() self.to_model()
# pylint: disable=invalid-name
@dataclass(init=False) @dataclass(init=False)
class Announce(Verb): class Announce(Verb):
"""boosting a status""" """boosting a status"""

View file

@ -127,8 +127,8 @@ class AbstractConnector(AbstractMinimalConnector):
edition_data = data edition_data = data
try: try:
work_data = self.get_work_from_edition_data(data) work_data = self.get_work_from_edition_data(data)
except (KeyError, ConnectorException) as e: except (KeyError, ConnectorException) as err:
logger.exception(e) logger.exception(err)
work_data = data work_data = data
if not work_data or not edition_data: if not work_data or not edition_data:
@ -237,16 +237,16 @@ def get_data(url, params=None, timeout=10):
}, },
timeout=timeout, timeout=timeout,
) )
except (RequestError, SSLError, ConnectionError) as e: except (RequestError, SSLError, ConnectionError) as err:
logger.exception(e) logger.exception(err)
raise ConnectorException() raise ConnectorException()
if not resp.ok: if not resp.ok:
raise ConnectorException() raise ConnectorException()
try: try:
data = resp.json() data = resp.json()
except ValueError as e: except ValueError as err:
logger.exception(e) logger.exception(err)
raise ConnectorException() raise ConnectorException()
return data return data
@ -262,8 +262,8 @@ def get_image(url, timeout=10):
}, },
timeout=timeout, timeout=timeout,
) )
except (RequestError, SSLError) as e: except (RequestError, SSLError) as err:
logger.exception(e) logger.exception(err)
return None return None
if not resp.ok: if not resp.ok:
return None return None

View file

@ -74,7 +74,7 @@ class Connector(AbstractConnector):
**{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks"]}, **{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks"]},
} }
def search(self, query, min_confidence=None): def search(self, query, min_confidence=None): # pylint: disable=arguments-differ
"""overrides default search function with confidence ranking""" """overrides default search function with confidence ranking"""
results = super().search(query) results = super().search(query)
if min_confidence: if min_confidence:

View file

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

View file

@ -93,7 +93,8 @@ class ListItem(CollectionItemMixin, BookWyrmModel):
) )
class Meta: class Meta:
# A book may only be placed into a list once, and each order in the list may be used only """A book may only be placed into a list once,
# once and each order in the list may be used only once"""
unique_together = (("book", "book_list"), ("order", "book_list")) unique_together = (("book", "book_list"), ("order", "book_list"))
ordering = ("-created_date",) ordering = ("-created_date",)

View file

@ -232,7 +232,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""populate fields for new local users""" """populate fields for new local users"""
created = not bool(self.id) created = not bool(self.id)
if not self.local and not re.match(regex.full_username, self.username): if not self.local and not re.match(regex.FULL_USERNAME, self.username):
# generate a username that uses the domain (webfinger format) # generate a username that uses the domain (webfinger format)
actor_parts = urlparse(self.remote_id) actor_parts = urlparse(self.remote_id)
self.username = "%s@%s" % (self.username, actor_parts.netloc) self.username = "%s@%s" % (self.username, actor_parts.netloc)

View file

@ -73,6 +73,7 @@ class Signature:
self.headers = headers self.headers = headers
self.signature = signature self.signature = signature
# pylint: disable=invalid-name
@classmethod @classmethod
def parse(cls, request): def parse(cls, request):
"""extract and parse a signature from an http request""" """extract and parse a signature from an http request"""

View file

@ -1,9 +1,12 @@
""" Makes the app aware of the users timezone """
import pytz import pytz
from django.utils import timezone from django.utils import timezone
class TimezoneMiddleware: class TimezoneMiddleware:
"""Determine the timezone based on the request"""
def __init__(self, get_response): def __init__(self, get_response):
self.get_response = get_response self.get_response = get_response

View file

@ -7,8 +7,8 @@ from django.views.generic.base import TemplateView
from bookwyrm import settings, views from bookwyrm import settings, views
from bookwyrm.utils import regex from bookwyrm.utils import regex
user_path = r"^user/(?P<username>%s)" % regex.username USER_PATH = r"^user/(?P<username>%s)" % regex.username
local_user_path = r"^user/(?P<username>%s)" % regex.localname LOCAL_USER_PATH = r"^user/(?P<username>%s)" % regex.localname
status_types = [ status_types = [
"status", "status",
@ -19,9 +19,9 @@ status_types = [
"boost", "boost",
"generatednote", "generatednote",
] ]
status_path = r"%s/(%s)/(?P<status_id>\d+)" % (user_path, "|".join(status_types)) STATUS_PATH = r"%s/(%s)/(?P<status_id>\d+)" % (USER_PATH, "|".join(status_types))
book_path = r"^book/(?P<book_id>\d+)" BOOK_PATH = r"^book/(?P<book_id>\d+)"
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
@ -31,8 +31,8 @@ urlpatterns = [
), ),
# federation endpoints # federation endpoints
re_path(r"^inbox/?$", views.Inbox.as_view()), re_path(r"^inbox/?$", views.Inbox.as_view()),
re_path(r"%s/inbox/?$" % local_user_path, views.Inbox.as_view()), re_path(r"%s/inbox/?$" % LOCAL_USER_PATH, views.Inbox.as_view()),
re_path(r"%s/outbox/?$" % local_user_path, views.Outbox.as_view()), re_path(r"%s/outbox/?$" % LOCAL_USER_PATH, views.Outbox.as_view()),
re_path(r"^\.well-known/webfinger/?$", views.webfinger), re_path(r"^\.well-known/webfinger/?$", views.webfinger),
re_path(r"^\.well-known/nodeinfo/?$", views.nodeinfo_pointer), re_path(r"^\.well-known/nodeinfo/?$", views.nodeinfo_pointer),
re_path(r"^\.well-known/host-meta/?$", views.host_meta), re_path(r"^\.well-known/host-meta/?$", views.host_meta),
@ -192,21 +192,21 @@ urlpatterns = [
re_path(r"^import/?$", views.Import.as_view(), name="import"), re_path(r"^import/?$", views.Import.as_view(), name="import"),
re_path(r"^import/(\d+)/?$", views.ImportStatus.as_view(), name="import-status"), re_path(r"^import/(\d+)/?$", views.ImportStatus.as_view(), name="import-status"),
# users # users
re_path(r"%s/?$" % user_path, views.User.as_view(), name="user-feed"), re_path(r"%s/?$" % USER_PATH, views.User.as_view(), name="user-feed"),
re_path(r"%s\.json$" % user_path, views.User.as_view()), re_path(r"%s\.json$" % USER_PATH, views.User.as_view()),
re_path(r"%s/rss" % user_path, views.rss_feed.RssFeed(), name="user-rss"), re_path(r"%s/rss" % USER_PATH, views.rss_feed.RssFeed(), name="user-rss"),
re_path( re_path(
r"%s/followers(.json)?/?$" % user_path, r"%s/followers(.json)?/?$" % USER_PATH,
views.Followers.as_view(), views.Followers.as_view(),
name="user-followers", name="user-followers",
), ),
re_path( re_path(
r"%s/following(.json)?/?$" % user_path, r"%s/following(.json)?/?$" % USER_PATH,
views.Following.as_view(), views.Following.as_view(),
name="user-following", name="user-following",
), ),
# lists # lists
re_path(r"%s/lists/?$" % user_path, views.UserLists.as_view(), name="user-lists"), re_path(r"%s/lists/?$" % USER_PATH, views.UserLists.as_view(), name="user-lists"),
re_path(r"^list/?$", views.Lists.as_view(), name="lists"), re_path(r"^list/?$", views.Lists.as_view(), name="lists"),
re_path(r"^list/(?P<list_id>\d+)(.json)?/?$", views.List.as_view(), name="list"), re_path(r"^list/(?P<list_id>\d+)(.json)?/?$", views.List.as_view(), name="list"),
re_path(r"^list/add-book/?$", views.list.add_book, name="list-add-book"), re_path(r"^list/add-book/?$", views.list.add_book, name="list-add-book"),
@ -224,14 +224,14 @@ urlpatterns = [
r"^list/(?P<list_id>\d+)/curate/?$", views.Curate.as_view(), name="list-curate" r"^list/(?P<list_id>\d+)/curate/?$", views.Curate.as_view(), name="list-curate"
), ),
# User books # User books
re_path(r"%s/books/?$" % user_path, views.Shelf.as_view(), name="user-shelves"), re_path(r"%s/books/?$" % USER_PATH, views.Shelf.as_view(), name="user-shelves"),
re_path( re_path(
r"^%s/(helf|books)/(?P<shelf_identifier>[\w-]+)(.json)?/?$" % user_path, r"^%s/(helf|books)/(?P<shelf_identifier>[\w-]+)(.json)?/?$" % USER_PATH,
views.Shelf.as_view(), views.Shelf.as_view(),
name="shelf", name="shelf",
), ),
re_path( re_path(
r"^%s/(books|shelf)/(?P<shelf_identifier>[\w-]+)(.json)?/?$" % local_user_path, r"^%s/(books|shelf)/(?P<shelf_identifier>[\w-]+)(.json)?/?$" % LOCAL_USER_PATH,
views.Shelf.as_view(), views.Shelf.as_view(),
name="shelf", name="shelf",
), ),
@ -241,7 +241,7 @@ urlpatterns = [
re_path(r"^unshelve/?$", views.unshelve), re_path(r"^unshelve/?$", views.unshelve),
# goals # goals
re_path( re_path(
r"%s/goal/(?P<year>\d{4})/?$" % user_path, r"%s/goal/(?P<year>\d{4})/?$" % USER_PATH,
views.Goal.as_view(), views.Goal.as_view(),
name="user-goal", name="user-goal",
), ),
@ -258,10 +258,10 @@ urlpatterns = [
re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()), re_path(r"^block/(?P<user_id>\d+)/?$", views.Block.as_view()),
re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock), re_path(r"^unblock/(?P<user_id>\d+)/?$", views.unblock),
# statuses # statuses
re_path(r"%s(.json)?/?$" % status_path, views.Status.as_view(), name="status"), re_path(r"%s(.json)?/?$" % STATUS_PATH, views.Status.as_view(), name="status"),
re_path(r"%s/activity/?$" % status_path, views.Status.as_view(), name="status"), re_path(r"%s/activity/?$" % STATUS_PATH, views.Status.as_view(), name="status"),
re_path( re_path(
r"%s/replies(.json)?/?$" % status_path, views.Replies.as_view(), name="replies" r"%s/replies(.json)?/?$" % STATUS_PATH, views.Replies.as_view(), name="replies"
), ),
re_path( re_path(
r"^post/?$", r"^post/?$",
@ -289,17 +289,17 @@ urlpatterns = [
re_path(r"^boost/(?P<status_id>\d+)/?$", views.Boost.as_view()), re_path(r"^boost/(?P<status_id>\d+)/?$", views.Boost.as_view()),
re_path(r"^unboost/(?P<status_id>\d+)/?$", views.Unboost.as_view()), re_path(r"^unboost/(?P<status_id>\d+)/?$", views.Unboost.as_view()),
# books # books
re_path(r"%s(.json)?/?$" % book_path, views.Book.as_view(), name="book"), re_path(r"%s(.json)?/?$" % BOOK_PATH, views.Book.as_view(), name="book"),
re_path( re_path(
r"%s/(?P<user_statuses>review|comment|quote)/?$" % book_path, r"%s/(?P<user_statuses>review|comment|quote)/?$" % BOOK_PATH,
views.Book.as_view(), views.Book.as_view(),
name="book-user-statuses", name="book-user-statuses",
), ),
re_path(r"%s/edit/?$" % book_path, views.EditBook.as_view()), re_path(r"%s/edit/?$" % BOOK_PATH, views.EditBook.as_view()),
re_path(r"%s/confirm/?$" % book_path, views.ConfirmEditBook.as_view()), re_path(r"%s/confirm/?$" % BOOK_PATH, views.ConfirmEditBook.as_view()),
re_path(r"^create-book/?$", views.EditBook.as_view(), name="create-book"), re_path(r"^create-book/?$", views.EditBook.as_view(), name="create-book"),
re_path(r"^create-book/confirm?$", views.ConfirmEditBook.as_view()), re_path(r"^create-book/confirm?$", views.ConfirmEditBook.as_view()),
re_path(r"%s/editions(.json)?/?$" % book_path, views.Editions.as_view()), re_path(r"%s/editions(.json)?/?$" % BOOK_PATH, views.Editions.as_view()),
re_path( re_path(
r"^upload-cover/(?P<book_id>\d+)/?$", views.upload_cover, name="upload-cover" r"^upload-cover/(?P<book_id>\d+)/?$", views.upload_cover, name="upload-cover"
), ),

View file

@ -1,10 +1,10 @@
""" defining regexes for regularly used concepts """ """ defining regexes for regularly used concepts """
domain = r"[\w_\-\.]+\.[a-z]{2,}" DOMAIN = r"[\w_\-\.]+\.[a-z]{2,}"
localname = r"@?[a-zA-Z_\-\.0-9]+" LOCALNAME = r"@?[a-zA-Z_\-\.0-9]+"
strict_localname = r"@[a-zA-Z_\-\.0-9]+" STRICT_LOCALNAME = r"@[a-zA-Z_\-\.0-9]+"
username = r"%s(@%s)?" % (localname, domain) USERNAME = r"%s(@%s)?" % (LOCALNAME, DOMAIN)
strict_username = r"\B%s(@%s)?\b" % (strict_localname, domain) STRICT_USERNAME = r"\B%s(@%s)?\b" % (STRICT_LOCALNAME, DOMAIN)
full_username = r"%s@%s\b" % (localname, domain) FULL_USERNAME = r"%s@%s\b" % (LOCALNAME, DOMAIN)
# should match (BookWyrm/1.0.0; or (BookWyrm/99.1.2; # should match (BookWyrm/1.0.0; or (BookWyrm/99.1.2;
bookwyrm_user_agent = r"\(BookWyrm/[0-9]+\.[0-9]+\.[0-9]+;" BOOKWYRM_USER_AGENT = r"\(BookWyrm/[0-9]+\.[0-9]+\.[0-9]+;"

View file

@ -38,7 +38,7 @@ def is_api_request(request):
def is_bookwyrm_request(request): def is_bookwyrm_request(request):
"""check if the request is coming from another bookwyrm instance""" """check if the request is coming from another bookwyrm instance"""
user_agent = request.headers.get("User-Agent") user_agent = request.headers.get("User-Agent")
if user_agent is None or re.search(regex.bookwyrm_user_agent, user_agent) is None: if user_agent is None or re.search(regex.BOOKWYRM_USER_AGENT, user_agent) is None:
return False return False
return True return True

View file

@ -21,6 +21,7 @@ from bookwyrm.utils import regex
class Inbox(View): class Inbox(View):
"""requests sent by outside servers""" """requests sent by outside servers"""
# pylint: disable=too-many-return-statements
def post(self, request, username=None): def post(self, request, username=None):
"""only works as POST request""" """only works as POST request"""
# first check if this server is on our shitlist # first check if this server is on our shitlist
@ -70,7 +71,7 @@ def is_blocked_user_agent(request):
user_agent = request.headers.get("User-Agent") user_agent = request.headers.get("User-Agent")
if not user_agent: if not user_agent:
return False return False
url = re.search(r"https?://{:s}/?".format(regex.domain), user_agent) url = re.search(r"https?://{:s}/?".format(regex.DOMAIN), user_agent)
if not url: if not url:
return False return False
url = url.group() url = url.group()

View file

@ -1,13 +1,8 @@
""" isbn search view """ """ isbn search view """
from django.http import HttpResponseNotFound
from django.http import JsonResponse from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View from django.views import View
from django.views.decorators.http import require_POST
from bookwyrm import forms, models
from bookwyrm.connectors import connector_manager from bookwyrm.connectors import connector_manager
from .helpers import is_api_request from .helpers import is_api_request
@ -23,7 +18,6 @@ class Isbn(View):
return JsonResponse([r.json() for r in book_results], safe=False) return JsonResponse([r.json() for r in book_results], safe=False)
data = { data = {
"title": "ISBN Search Results",
"results": book_results, "results": book_results,
"query": isbn, "query": isbn,
} }

View file

@ -314,8 +314,7 @@ def set_book_position(request, list_item_id):
Max("order") Max("order")
)["order__max"] )["order__max"]
if int_position > order_max: int_position = min(int_position, order_max)
int_position = order_max
if request.user not in (book_list.user, list_item.user): if request.user not in (book_list.user, list_item.user):
return HttpResponseNotFound() return HttpResponseNotFound()

View file

@ -10,7 +10,7 @@ class RssFeed(Feed):
description_template = "rss/content.html" description_template = "rss/content.html"
title_template = "rss/title.html" title_template = "rss/title.html"
def get_object(self, request, username): def get_object(self, request, username): # pylint: disable=arguments-differ
"""the user who's posts get serialized""" """the user who's posts get serialized"""
return get_user_from_username(request.user, username) return get_user_from_username(request.user, username)

View file

@ -83,7 +83,7 @@ def user_search(query, viewer, *_):
# use webfinger for mastodon style account@domain.com username to load the user if # use webfinger for mastodon style account@domain.com username to load the user if
# they don't exist locally (handle_remote_webfinger will check the db) # they don't exist locally (handle_remote_webfinger will check the db)
if re.match(regex.full_username, query): if re.match(regex.FULL_USERNAME, query):
handle_remote_webfinger(query) handle_remote_webfinger(query)
return ( return (

View file

@ -17,7 +17,7 @@ from bookwyrm import forms, models
from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.settings import PAGE_LENGTH from bookwyrm.settings import PAGE_LENGTH
from .helpers import is_api_request, get_edition, get_user_from_username from .helpers import is_api_request, get_edition, get_user_from_username
from .helpers import handle_reading_status, privacy_filter from .helpers import privacy_filter
# pylint: disable=no-self-use # pylint: disable=no-self-use

View file

@ -133,7 +133,7 @@ def find_mentions(content):
"""detect @mentions in raw status content""" """detect @mentions in raw status content"""
if not content: if not content:
return return
for match in re.finditer(regex.strict_username, content): for match in re.finditer(rhandle_reading_status, egex.STRICT_USERNAME, content):
username = match.group().strip().split("@")[1:] username = match.group().strip().split("@")[1:]
if len(username) == 1: if len(username) == 1:
# this looks like a local user (@user), fill in the domain # this looks like a local user (@user), fill in the domain
@ -150,7 +150,7 @@ def find_mentions(content):
def format_links(content): def format_links(content):
"""detect and format links""" """detect and format links"""
return re.sub( return re.sub(
r'([^(href=")]|^|\()(https?:\/\/(%s([\w\.\-_\/+&\?=:;,])*))' % regex.domain, r'([^(href=")]|^|\()(https?:\/\/(%s([\w\.\-_\/+&\?=:;,])*))' % regex.DOMAIN,
r'\g<1><a href="\g<2>">\g<3></a>', r'\g<1><a href="\g<2>">\g<3></a>',
content, content,
) )