Merge branch 'main' into main

This commit is contained in:
Mouse Reeve
2022-02-03 10:40:27 -08:00
committed by GitHub
32 changed files with 388 additions and 246 deletions

View File

@ -1,7 +1,9 @@
""" functionality outline for a book data connector """
from abc import ABC, abstractmethod
import imghdr
import logging
from django.core.files.base import ContentFile
from django.db import transaction
import requests
from requests.exceptions import RequestException
@ -290,10 +292,18 @@ def get_image(url, timeout=10):
)
except RequestException as err:
logger.exception(err)
return None
return None, None
if not resp.ok:
return None
return resp
return None, None
image_content = ContentFile(resp.content)
extension = imghdr.what(None, image_content.read())
if not extension:
logger.exception("File requested was not an image: %s", url)
return None, None
return image_content, extension
class Mapping:

View File

@ -0,0 +1,37 @@
# Generated by Django 3.2.10 on 2022-02-02 20:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0131_merge_20220125_1644"),
]
operations = [
migrations.AlterField(
model_name="user",
name="preferred_language",
field=models.CharField(
blank=True,
choices=[
("en-us", "English"),
("de-de", "Deutsch (German)"),
("es-es", "Español (Spanish)"),
("gl-es", "Galego (Galician)"),
("it-it", "Italiano (Italian)"),
("fr-fr", "Français (French)"),
("lt-lt", "Lietuvių (Lithuanian)"),
("no-no", "Norsk (Norwegian)"),
("pt-br", "Português do Brasil (Brazilian Portuguese)"),
("pt-pt", "Português Europeu (European Portuguese)"),
("sv-se", "Svenska (Swedish)"),
("zh-hans", "简体中文 (Simplified Chinese)"),
("zh-hant", "繁體中文 (Traditional Chinese)"),
],
max_length=255,
null=True,
),
),
]

View File

@ -1,6 +1,5 @@
""" activitypub-aware django model fields """
from dataclasses import MISSING
import imghdr
import re
from uuid import uuid4
from urllib.parse import urljoin
@ -9,7 +8,6 @@ import dateutil.parser
from dateutil.parser import ParserError
from django.contrib.postgres.fields import ArrayField as DjangoArrayField
from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from django.db import models
from django.forms import ClearableFileInput, ImageField as DjangoImageField
from django.utils import timezone
@ -443,12 +441,10 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
except ValidationError:
return None
response = get_image(url)
if not response:
image_content, extension = get_image(url)
if not image_content:
return None
image_content = ContentFile(response.content)
extension = imghdr.what(None, image_content.read()) or ""
image_name = f"{uuid4()}.{extension}"
return [image_name, image_content]

View File

@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _
env = Env()
env.read_env()
DOMAIN = env("DOMAIN")
VERSION = "0.2.0"
VERSION = "0.2.1"
PAGE_LENGTH = env("PAGE_LENGTH", 15)
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")
@ -255,7 +255,7 @@ LANGUAGES = [
("no-no", _("Norsk (Norwegian)")),
("pt-br", _("Português do Brasil (Brazilian Portuguese)")),
("pt-pt", _("Português Europeu (European Portuguese)")),
("sv-se", _("Swedish (Svenska)")),
("sv-se", _("Svenska (Swedish)")),
("zh-hans", _("简体中文 (Simplified Chinese)")),
("zh-hant", _("繁體中文 (Traditional Chinese)")),
]

View File

@ -356,10 +356,11 @@
<form name="list-add" method="post" action="{% url 'list-add-book' %}">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="user" value="{{ request.user.id }}">
<label class="label" for="id_list">{% trans "Add to list" %}</label>
<div class="field has-addons">
<div class="select control is-clipped">
<select name="list" id="id_list">
<select name="book_list" id="id_list">
{% for list in user.list_set.all %}
<option value="{{ list.id }}">{{ list.name }}</option>
{% endfor %}

View File

@ -97,7 +97,7 @@
<span class="details-close icon icon-pencil" aria-hidden></span>
</span>
</summary>
{% include "lists/edit_item_form.html" %}
{% include "lists/edit_item_form.html" with book=item.book %}
</details>
</div>
{% endif %}
@ -112,7 +112,7 @@
<span class="details-close icon icon-plus" aria-hidden></span>
</span>
</summary>
{% include "lists/edit_item_form.html" %}
{% include "lists/edit_item_form.html" with book=item.book %}
</details>
</div>
{% endif %}

View File

@ -45,7 +45,7 @@
href="{{ shelf_tab.local_path }}"
{% if shelf_tab.identifier == shelf.identifier %} aria-current="page"{% endif %}
>
{% include 'user/books_header.html' with shelf=shelf_tab %}
{% include "snippets/translated_shelf_name.html" with shelf=shelf_tab %}
</a>
</li>
{% endfor %}

View File

@ -443,18 +443,17 @@ class ModelFields(TestCase):
image_file = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg"
)
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
instance = fields.ImageField()
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image.tobytes(),
status=200,
)
with open(image_file, "rb") as image_data:
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image_data.read(),
status=200,
content_type="image/jpeg",
stream=True,
)
loaded_image = instance.field_from_activity("http://www.example.com/image.jpg")
self.assertIsInstance(loaded_image, list)
self.assertIsInstance(loaded_image[1], ContentFile)
@ -465,18 +464,18 @@ class ModelFields(TestCase):
image_file = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg"
)
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
instance = fields.ImageField(activitypub_field="cover", name="cover")
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image.tobytes(),
status=200,
)
with open(image_file, "rb") as image_data:
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image_data.read(),
content_type="image/jpeg",
status=200,
stream=True,
)
book = Edition.objects.create(title="hello")
MockActivity = namedtuple("MockActivity", ("cover"))
@ -491,18 +490,18 @@ class ModelFields(TestCase):
image_file = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg"
)
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
instance = fields.ImageField(activitypub_field="cover", name="cover")
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image.tobytes(),
status=200,
)
with open(image_file, "rb") as image_data:
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=image_data.read(),
status=200,
content_type="image/jpeg",
stream=True,
)
book = Edition.objects.create(title="hello")
MockActivity = namedtuple("MockActivity", ("cover"))
@ -565,18 +564,18 @@ class ModelFields(TestCase):
another_image_file = pathlib.Path(__file__).parent.joinpath(
"../../static/images/logo.png"
)
another_image = Image.open(another_image_file)
another_output = BytesIO()
another_image.save(another_output, format=another_image.format)
instance = fields.ImageField(activitypub_field="cover", name="cover")
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=another_image.tobytes(),
status=200,
)
with open(another_image_file, "rb") as another_image:
responses.add(
responses.GET,
"http://www.example.com/image.jpg",
body=another_image.read(),
status=200,
content_type="image/jpeg",
stream=True,
)
MockActivity = namedtuple("MockActivity", ("cover"))
mock_activity = MockActivity("http://www.example.com/image.jpg")

View File

@ -2,7 +2,6 @@
from uuid import uuid4
from django.contrib.auth.decorators import login_required, permission_required
from django.core.files.base import ContentFile
from django.core.paginator import Paginator
from django.db.models import Avg, Q
from django.http import Http404
@ -144,13 +143,12 @@ def upload_cover(request, book_id):
def set_cover_from_url(url):
"""load it from a url"""
try:
image_file = get_image(url)
image_content, extension = get_image(url)
except: # pylint: disable=bare-except
return None
if not image_file:
if not image_content:
return None
image_name = str(uuid4()) + "." + url.split(".")[-1]
image_content = ContentFile(image_file.content)
image_name = str(uuid4()) + "." + extension
return [image_name, image_content]

View File

@ -19,4 +19,6 @@ class ListItem(View):
form = forms.ListItemForm(request.POST, instance=list_item)
if form.is_valid():
form.save()
else:
raise Exception(form.errors)
return redirect("list", list_item.book_list.id)