Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add typechecking using mypy #2897

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/mypy.yml
@@ -0,0 +1,51 @@
name: Mypy

on:
push:
branches: [ main, mypy ]
pull_request:
branches: [ main ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Analysing the code with mypy
env:
SECRET_KEY: beepbeep
DEBUG: false
USE_HTTPS: true
DOMAIN: your.domain.here
BOOKWYRM_DATABASE_BACKEND: postgres
MEDIA_ROOT: images/
POSTGRES_PASSWORD: hunter2
POSTGRES_USER: postgres
POSTGRES_DB: github_actions
POSTGRES_HOST: 127.0.0.1
CELERY_BROKER: ""
REDIS_BROKER_PORT: 6379
REDIS_BROKER_PASSWORD: beep
USE_DUMMY_CACHE: true
FLOWER_PORT: 8888
EMAIL_HOST: "smtp.mailgun.org"
EMAIL_PORT: 587
EMAIL_HOST_USER: ""
EMAIL_HOST_PASSWORD: ""
EMAIL_USE_TLS: true
ENABLE_PREVIEW_IMAGES: false
ENABLE_THUMBNAIL_GENERATION: true
HTTP_X_FORWARDED_PROTO: false
run: |
mypy bookwyrm celerywyrm

22 changes: 15 additions & 7 deletions bookwyrm/activitypub/base_activity.py
Expand Up @@ -2,11 +2,15 @@
from dataclasses import dataclass, fields, MISSING
from json import JSONEncoder
import logging
from typing import Optional, Type

import requests

from django.apps import apps
from django.db import IntegrityError, transaction
from django.db.models import Model
from django.utils.http import http_date
from typing_extensions import TypeVar

from bookwyrm import models
from bookwyrm.connectors import ConnectorException, get_data
Expand Down Expand Up @@ -58,6 +62,10 @@ def naive_parse(activity_objects, activity_json, serializer=None):
return serializer(activity_objects=activity_objects, **activity_json)


# TODO This should be more specific, but what should it be?
TModel = TypeVar("TModel", bound=Model)


@dataclass(init=False)
class ActivityObject:
"""actor activitypub json"""
Expand Down Expand Up @@ -101,13 +109,13 @@ def __init__(self, activity_objects=None, **kwargs):
# pylint: disable=too-many-locals,too-many-branches,too-many-arguments
def to_model(
self,
model=None,
instance=None,
allow_create=True,
save=True,
overwrite=True,
allow_external_connections=True,
):
model: Optional[Type[TModel]] = None,
instance: Optional[TModel] = None,
allow_create: bool = True,
save: bool = True,
overwrite: bool = True,
allow_external_connections: bool = True,
) -> Optional[TModel]:
"""convert from an activity to a model instance. Args:
model: the django model that this object is being converted to
(will guess if not known)
Expand Down
42 changes: 21 additions & 21 deletions bookwyrm/activitypub/book.py
@@ -1,6 +1,6 @@
""" book and author data """
from dataclasses import dataclass, field
from typing import List
from typing import List, Optional

from .base_activity import ActivityObject
from .image import Document
Expand All @@ -11,17 +11,17 @@
class BookData(ActivityObject):
"""shared fields for all book data and authors"""

openlibraryKey: str = None
inventaireId: str = None
librarythingKey: str = None
goodreadsKey: str = None
bnfId: str = None
viaf: str = None
wikidata: str = None
asin: str = None
aasin: str = None
isfdb: str = None
lastEditedBy: str = None
openlibraryKey: Optional[str] = None
inventaireId: Optional[str] = None
librarythingKey: Optional[str] = None
goodreadsKey: Optional[str] = None
bnfId: Optional[str] = None
viaf: Optional[str] = None
wikidata: Optional[str] = None
asin: Optional[str] = None
aasin: Optional[str] = None
isfdb: Optional[str] = None
lastEditedBy: Optional[str] = None
links: List[str] = field(default_factory=lambda: [])
fileLinks: List[str] = field(default_factory=lambda: [])

Expand All @@ -32,8 +32,8 @@ class Book(BookData):
"""serializes an edition or work, abstract"""

title: str
sortTitle: str = None
subtitle: str = None
sortTitle: Optional[str] = None
subtitle: Optional[str] = None
description: str = ""
languages: List[str] = field(default_factory=lambda: [])
series: str = ""
Expand All @@ -45,7 +45,7 @@ class Book(BookData):
firstPublishedDate: str = ""
publishedDate: str = ""

cover: Document = None
cover: Optional[Document] = None
type: str = "Book"


Expand All @@ -58,7 +58,7 @@ class Edition(Book):
isbn10: str = ""
isbn13: str = ""
oclcNumber: str = ""
pages: int = None
pages: Optional[int] = None
physicalFormat: str = ""
physicalFormatDetail: str = ""
publishers: List[str] = field(default_factory=lambda: [])
Expand All @@ -83,11 +83,11 @@ class Author(BookData):
"""author of a book"""

name: str
isni: str = None
viafId: str = None
gutenbergId: str = None
born: str = None
died: str = None
isni: Optional[str] = None
viafId: Optional[str] = None
gutenbergId: Optional[str] = None
born: Optional[str] = None
died: Optional[str] = None
aliases: List[str] = field(default_factory=lambda: [])
bio: str = ""
wikipediaLink: str = ""
Expand Down
26 changes: 13 additions & 13 deletions bookwyrm/activitypub/note.py
@@ -1,6 +1,6 @@
""" note serializer and children thereof """
from dataclasses import dataclass, field
from typing import Dict, List
from typing import Dict, List, Optional
import re

from django.apps import apps
Expand Down Expand Up @@ -33,12 +33,12 @@ class Note(ActivityObject):
to: List[str] = field(default_factory=lambda: [])
cc: List[str] = field(default_factory=lambda: [])
replies: Dict = field(default_factory=lambda: {})
inReplyTo: str = None
summary: str = None
inReplyTo: Optional[str] = None
summary: Optional[str] = None
tag: List[Link] = field(default_factory=lambda: [])
attachment: List[Document] = field(default_factory=lambda: [])
sensitive: bool = False
updated: str = None
updated: Optional[str] = None
type: str = "Note"

# pylint: disable=too-many-arguments
Expand Down Expand Up @@ -104,9 +104,9 @@ class Comment(Note):
"""like a note but with a book"""

inReplyToBook: str
readingStatus: str = None
progress: int = None
progressMode: str = None
readingStatus: Optional[str] = None
progress: Optional[int] = None
progressMode: Optional[str] = None
type: str = "Comment"


Expand All @@ -115,17 +115,17 @@ class Quotation(Comment):
"""a quote and commentary on a book"""

quote: str
position: int = None
positionMode: str = None
position: Optional[int] = None
positionMode: Optional[str] = None
type: str = "Quotation"


@dataclass(init=False)
class Review(Comment):
"""a full book review"""

name: str = None
rating: int = None
name: Optional[str] = None
rating: Optional[int] = None
type: str = "Review"


Expand All @@ -134,6 +134,6 @@ class Rating(Comment):
"""just a star rating"""

rating: int
content: str = None
name: str = None # not used, but the model inherits from Review
content: Optional[str] = None
name: Optional[str] = None # not used, but the model inherits from Review
type: str = "Rating"
20 changes: 10 additions & 10 deletions bookwyrm/activitypub/person.py
@@ -1,6 +1,6 @@
""" actor serializer """
from dataclasses import dataclass, field
from typing import Dict
from typing import Dict, Optional

from .base_activity import ActivityObject
from .image import Image
Expand Down Expand Up @@ -29,15 +29,15 @@ class Person(ActivityObject):
preferredUsername: str
inbox: str
publicKey: PublicKey
followers: str = None
following: str = None
outbox: str = None
endpoints: Dict = None
name: str = None
summary: str = None
followers: Optional[str] = None
following: Optional[str] = None
outbox: Optional[str] = None
endpoints: Optional[Dict] = None
name: Optional[str] = None
summary: Optional[str] = None
icon: Image = field(default_factory=lambda: {})
bookwyrmUser: bool = False
manuallyApprovesFollowers: str = False
discoverable: str = False
hideFollows: str = False
manuallyApprovesFollowers: bool = False
discoverable: bool = False
hideFollows: bool = False
type: str = "Person"