Merge branch 'main' into feat/api/oauth

This commit is contained in:
Sean Molenaar 2024-04-01 22:35:19 +02:00 committed by GitHub
commit d5fb21f330
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 135 additions and 149 deletions

View file

@ -175,11 +175,13 @@ def generate_instance_layer(content_width):
site = models.SiteSettings.objects.get() site = models.SiteSettings.objects.get()
if site.logo_small: if site.logo_small:
logo_img = Image.open(site.logo_small) with Image.open(site.logo_small) as logo_img:
logo_img.load()
else: else:
try: try:
static_path = os.path.join(settings.STATIC_ROOT, "images/logo-small.png") static_path = os.path.join(settings.STATIC_ROOT, "images/logo-small.png")
logo_img = Image.open(static_path) with Image.open(static_path) as logo_img:
logo_img.load()
except FileNotFoundError: except FileNotFoundError:
logo_img = None logo_img = None
@ -211,18 +213,9 @@ def generate_instance_layer(content_width):
def generate_rating_layer(rating, content_width): def generate_rating_layer(rating, content_width):
"""Places components for rating preview""" """Places components for rating preview"""
try: path_star_full = os.path.join(settings.STATIC_ROOT, "images/icons/star-full.png")
icon_star_full = Image.open( path_star_empty = os.path.join(settings.STATIC_ROOT, "images/icons/star-empty.png")
os.path.join(settings.STATIC_ROOT, "images/icons/star-full.png") path_star_half = os.path.join(settings.STATIC_ROOT, "images/icons/star-half.png")
)
icon_star_empty = Image.open(
os.path.join(settings.STATIC_ROOT, "images/icons/star-empty.png")
)
icon_star_half = Image.open(
os.path.join(settings.STATIC_ROOT, "images/icons/star-half.png")
)
except FileNotFoundError:
return None
icon_size = 64 icon_size = 64
icon_margin = 10 icon_margin = 10
@ -237,17 +230,23 @@ def generate_rating_layer(rating, content_width):
position_x = 0 position_x = 0
for _ in range(math.floor(rating)): try:
rating_layer_mask.alpha_composite(icon_star_full, (position_x, 0)) with Image.open(path_star_full) as icon_star_full:
position_x = position_x + icon_size + icon_margin for _ in range(math.floor(rating)):
rating_layer_mask.alpha_composite(icon_star_full, (position_x, 0))
position_x = position_x + icon_size + icon_margin
if math.floor(rating) != math.ceil(rating): if math.floor(rating) != math.ceil(rating):
rating_layer_mask.alpha_composite(icon_star_half, (position_x, 0)) with Image.open(path_star_half) as icon_star_half:
position_x = position_x + icon_size + icon_margin rating_layer_mask.alpha_composite(icon_star_half, (position_x, 0))
position_x = position_x + icon_size + icon_margin
for _ in range(5 - math.ceil(rating)): with Image.open(path_star_empty) as icon_star_empty:
rating_layer_mask.alpha_composite(icon_star_empty, (position_x, 0)) for _ in range(5 - math.ceil(rating)):
position_x = position_x + icon_size + icon_margin rating_layer_mask.alpha_composite(icon_star_empty, (position_x, 0))
position_x = position_x + icon_size + icon_margin
except FileNotFoundError:
return None
rating_layer_mask = rating_layer_mask.getchannel("A") rating_layer_mask = rating_layer_mask.getchannel("A")
rating_layer_mask = ImageOps.invert(rating_layer_mask) rating_layer_mask = ImageOps.invert(rating_layer_mask)
@ -290,7 +289,8 @@ def generate_preview_image(
texts = texts or {} texts = texts or {}
# Cover # Cover
try: try:
inner_img_layer = Image.open(picture) with Image.open(picture) as inner_img_layer:
inner_img_layer.load()
inner_img_layer.thumbnail( inner_img_layer.thumbnail(
(inner_img_width, inner_img_height), Image.Resampling.LANCZOS (inner_img_width, inner_img_height), Image.Resampling.LANCZOS
) )

View file

@ -19,7 +19,6 @@ DOMAIN = env("DOMAIN")
with open("VERSION", encoding="utf-8") as f: with open("VERSION", encoding="utf-8") as f:
version = f.read() version = f.read()
version = version.replace("\n", "") version = version.replace("\n", "")
f.close()
VERSION = version VERSION = version

View file

@ -1,12 +1,10 @@
""" tests the base functionality for activitypub dataclasses """ """ tests the base functionality for activitypub dataclasses """
from io import BytesIO
import json import json
import pathlib import pathlib
from unittest.mock import patch from unittest.mock import patch
from dataclasses import dataclass from dataclasses import dataclass
from django.test import TestCase from django.test import TestCase
from PIL import Image
import responses import responses
from bookwyrm import activitypub from bookwyrm import activitypub
@ -48,13 +46,11 @@ class BaseActivity(TestCase):
# don't try to load the user icon # don't try to load the user icon
del self.userdata["icon"] del self.userdata["icon"]
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file) with open(image_path, "rb") as image_file:
output = BytesIO() self.image_data = image_file.read()
image.save(output, format=image.format)
self.image_data = output.getvalue()
def test_get_representative_not_existing(self, *_): def test_get_representative_not_existing(self, *_):
"""test that an instance representative actor is created if it does not exist""" """test that an instance representative actor is created if it does not exist"""

View file

@ -9,7 +9,6 @@ from bookwyrm.importers import CalibreImporter
from bookwyrm.models.import_job import handle_imported_book from bookwyrm.models.import_job import handle_imported_book
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -20,8 +19,13 @@ class CalibreImport(TestCase):
"""use a test csv""" """use a test csv"""
self.importer = CalibreImporter() self.importer = CalibreImporter()
datafile = pathlib.Path(__file__).parent.joinpath("../data/calibre.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/calibre.csv")
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -16,7 +16,6 @@ def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC) return datetime.datetime(*args, tzinfo=pytz.UTC)
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -27,8 +26,13 @@ class GoodreadsImport(TestCase):
"""use a test csv""" """use a test csv"""
self.importer = GoodreadsImporter() self.importer = GoodreadsImporter()
datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -19,7 +19,6 @@ def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC) return datetime.datetime(*args, tzinfo=pytz.UTC)
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -30,8 +29,13 @@ class GenericImporter(TestCase):
"""use a test csv""" """use a test csv"""
self.importer = Importer() self.importer = Importer()
datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/generic.csv")
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -16,7 +16,6 @@ def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC) return datetime.datetime(*args, tzinfo=pytz.UTC)
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -29,8 +28,13 @@ class LibrarythingImport(TestCase):
datafile = pathlib.Path(__file__).parent.joinpath("../data/librarything.tsv") datafile = pathlib.Path(__file__).parent.joinpath("../data/librarything.tsv")
# Librarything generates latin encoded exports... # Librarything generates latin encoded exports...
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -16,7 +16,6 @@ def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC) return datetime.datetime(*args, tzinfo=pytz.UTC)
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -27,8 +26,13 @@ class OpenLibraryImport(TestCase):
"""use a test csv""" """use a test csv"""
self.importer = OpenLibraryImporter() self.importer = OpenLibraryImporter()
datafile = pathlib.Path(__file__).parent.joinpath("../data/openlibrary.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/openlibrary.csv")
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -16,7 +16,6 @@ def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC) return datetime.datetime(*args, tzinfo=pytz.UTC)
# pylint: disable=consider-using-with
@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
@ -27,8 +26,13 @@ class StorygraphImport(TestCase):
"""use a test csv""" """use a test csv"""
self.importer = StorygraphImporter() self.importer = StorygraphImporter()
datafile = pathlib.Path(__file__).parent.joinpath("../data/storygraph.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/storygraph.csv")
# pylint: disable-next=consider-using-with
self.csv = open(datafile, "r", encoding=self.importer.encoding) self.csv = open(datafile, "r", encoding=self.importer.encoding)
def tearDown(self):
"""close test csv"""
self.csv.close()
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
"""populate database""" """populate database"""

View file

@ -1,12 +1,9 @@
""" testing models """ """ testing models """
from io import BytesIO
import pathlib import pathlib
import pytest import pytest
from dateutil.parser import parse from dateutil.parser import parse
from PIL import Image
from django.core.files.base import ContentFile
from django.test import TestCase from django.test import TestCase
from django.utils import timezone from django.utils import timezone
@ -130,15 +127,13 @@ class Book(TestCase):
) )
def test_thumbnail_fields(self): def test_thumbnail_fields(self):
"""Just hit them""" """Just hit them"""
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
book = models.Edition.objects.create(title="hello") book = models.Edition.objects.create(title="hello")
book.cover.save("test.jpg", ContentFile(output.getvalue())) with open(image_path, "rb") as image_file:
book.cover.save("test.jpg", image_file)
self.assertIsNotNone(book.cover_bw_book_xsmall_webp.url) self.assertIsNotNone(book.cover_bw_book_xsmall_webp.url)
self.assertIsNotNone(book.cover_bw_book_xsmall_jpg.url) self.assertIsNotNone(book.cover_bw_book_xsmall_jpg.url)

View file

@ -1,5 +1,4 @@
""" testing models """ """ testing models """
from io import BytesIO
from collections import namedtuple from collections import namedtuple
from dataclasses import dataclass from dataclasses import dataclass
import datetime import datetime
@ -10,7 +9,6 @@ from typing import List
from unittest import expectedFailure from unittest import expectedFailure
from unittest.mock import patch from unittest.mock import patch
from PIL import Image
import responses import responses
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -420,13 +418,11 @@ class ModelFields(TestCase):
user = User.objects.create_user( user = User.objects.create_user(
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
) )
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file) with open(image_path, "rb") as image_file:
output = BytesIO() user.avatar.save("test.jpg", image_file)
image.save(output, format=image.format)
user.avatar.save("test.jpg", ContentFile(output.getvalue()))
instance = fields.ImageField() instance = fields.ImageField()
@ -516,30 +512,25 @@ class ModelFields(TestCase):
@responses.activate @responses.activate
def test_image_field_set_field_from_activity_no_overwrite_with_cover(self, *_): def test_image_field_set_field_from_activity_no_overwrite_with_cover(self, *_):
"""update a model instance from an activitypub object""" """update a model instance from an activitypub object"""
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file) another_image_path = pathlib.Path(__file__).parent.joinpath(
output = BytesIO()
image.save(output, format=image.format)
another_image_file = pathlib.Path(__file__).parent.joinpath(
"../../static/images/logo.png" "../../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") instance = fields.ImageField(activitypub_field="cover", name="cover")
responses.add( with open(another_image_path, "rb") as another_image_file:
responses.GET, responses.add(
"http://www.example.com/image.jpg", responses.GET,
body=another_image.tobytes(), "http://www.example.com/image.jpg",
status=200, body=another_image_file.read(),
) status=200,
)
book = Edition.objects.create(title="hello") book = Edition.objects.create(title="hello")
book.cover.save("test.jpg", ContentFile(output.getvalue())) with open(image_path, "rb") as image_file:
book.cover.save("test.jpg", image_file)
cover_size = book.cover.size cover_size = book.cover.size
self.assertIsNotNone(cover_size) self.assertIsNotNone(cover_size)
@ -553,24 +544,22 @@ class ModelFields(TestCase):
@responses.activate @responses.activate
def test_image_field_set_field_from_activity_with_overwrite_with_cover(self, *_): def test_image_field_set_field_from_activity_with_overwrite_with_cover(self, *_):
"""update a model instance from an activitypub object""" """update a model instance from an activitypub object"""
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
book = Edition.objects.create(title="hello") book = Edition.objects.create(title="hello")
book.cover.save("test.jpg", ContentFile(output.getvalue())) with open(image_path, "rb") as image_file:
book.cover.save("test.jpg", image_file)
cover_size = book.cover.size cover_size = book.cover.size
self.assertIsNotNone(cover_size) self.assertIsNotNone(cover_size)
another_image_file = pathlib.Path(__file__).parent.joinpath( another_image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/logo.png" "../../static/images/logo.png"
) )
instance = fields.ImageField(activitypub_field="cover", name="cover") instance = fields.ImageField(activitypub_field="cover", name="cover")
with open(another_image_file, "rb") as another_image: with open(another_image_path, "rb") as another_image:
responses.add( responses.add(
responses.GET, responses.GET,
"http://www.example.com/image.jpg", "http://www.example.com/image.jpg",

View file

@ -1,16 +1,13 @@
""" testing models """ """ testing models """
from unittest.mock import patch from unittest.mock import patch
from io import BytesIO
import pathlib import pathlib
import re import re
from django.http import Http404 from django.http import Http404
from django.core.files.base import ContentFile
from django.db import IntegrityError from django.db import IntegrityError
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.test import TestCase from django.test import TestCase
from django.utils import timezone from django.utils import timezone
from PIL import Image
import responses import responses
from bookwyrm import activitypub, models, settings from bookwyrm import activitypub, models, settings
@ -51,14 +48,14 @@ class Status(TestCase):
"""individual test setup""" """individual test setup"""
self.anonymous_user = AnonymousUser self.anonymous_user = AnonymousUser
self.anonymous_user.is_authenticated = False self.anonymous_user.is_authenticated = False
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file) with (
output = BytesIO() patch("bookwyrm.models.Status.broadcast"),
with patch("bookwyrm.models.Status.broadcast"): open(image_path, "rb") as image_file,
image.save(output, format=image.format) ):
self.book.cover.save("test.jpg", ContentFile(output.getvalue())) self.book.cover.save("test.jpg", image_file)
def test_status_generated_fields(self, *_): def test_status_generated_fields(self, *_):
"""setting remote id""" """setting remote id"""

View file

@ -21,20 +21,20 @@ from bookwyrm.preview_images import (
# pylint: disable=unused-argument # pylint: disable=unused-argument
# pylint: disable=missing-function-docstring # pylint: disable=missing-function-docstring
# pylint: disable=consider-using-with
class PreviewImages(TestCase): class PreviewImages(TestCase):
"""every response to a get request, html or json""" """every response to a get request, html or json"""
def setUp(self): def setUp(self):
"""we need basic test data and mocks""" """we need basic test data and mocks"""
self.factory = RequestFactory() self.factory = RequestFactory()
avatar_file = pathlib.Path(__file__).parent.joinpath( avatar_path = pathlib.Path(__file__).parent.joinpath(
"../static/images/no_cover.jpg" "../static/images/no_cover.jpg"
) )
with ( with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
patch("bookwyrm.activitystreams.populate_stream_task.delay"), patch("bookwyrm.activitystreams.populate_stream_task.delay"),
patch("bookwyrm.lists_stream.populate_lists_task.delay"), patch("bookwyrm.lists_stream.populate_lists_task.delay"),
open(avatar_path, "rb") as avatar_file,
): ):
self.local_user = models.User.objects.create_user( self.local_user = models.User.objects.create_user(
"possum@local.com", "possum@local.com",
@ -43,8 +43,8 @@ class PreviewImages(TestCase):
local=True, local=True,
localname="possum", localname="possum",
avatar=SimpleUploadedFile( avatar=SimpleUploadedFile(
avatar_file, avatar_path,
open(avatar_file, "rb").read(), avatar_file.read(),
content_type="image/jpeg", content_type="image/jpeg",
), ),
) )
@ -68,6 +68,7 @@ class PreviewImages(TestCase):
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
patch("bookwyrm.activitystreams.populate_stream_task.delay"), patch("bookwyrm.activitystreams.populate_stream_task.delay"),
patch("bookwyrm.lists_stream.populate_lists_task.delay"), patch("bookwyrm.lists_stream.populate_lists_task.delay"),
open(avatar_path, "rb") as avatar_file,
): ):
self.remote_user_with_preview = models.User.objects.create_user( self.remote_user_with_preview = models.User.objects.create_user(
"badger@your.domain.here", "badger@your.domain.here",
@ -78,8 +79,8 @@ class PreviewImages(TestCase):
inbox="https://example.com/users/badger/inbox", inbox="https://example.com/users/badger/inbox",
outbox="https://example.com/users/badger/outbox", outbox="https://example.com/users/badger/outbox",
avatar=SimpleUploadedFile( avatar=SimpleUploadedFile(
avatar_file, avatar_path,
open(avatar_file, "rb").read(), avatar_file.read(),
content_type="image/jpeg", content_type="image/jpeg",
), ),
) )
@ -96,7 +97,7 @@ class PreviewImages(TestCase):
settings.ENABLE_PREVIEW_IMAGES = True settings.ENABLE_PREVIEW_IMAGES = True
def test_generate_preview_image(self, *args, **kwargs): def test_generate_preview_image(self, *args, **kwargs):
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../static/images/no_cover.jpg" "../static/images/no_cover.jpg"
) )
@ -105,7 +106,7 @@ class PreviewImages(TestCase):
"text_three": "@possum@local.com", "text_three": "@possum@local.com",
} }
result = generate_preview_image(texts=texts, picture=image_file, rating=5) result = generate_preview_image(texts=texts, picture=image_path, rating=5)
self.assertIsInstance(result, Image.Image) self.assertIsInstance(result, Image.Image)
self.assertEqual( self.assertEqual(
result.size, (settings.PREVIEW_IMG_WIDTH, settings.PREVIEW_IMG_HEIGHT) result.size, (settings.PREVIEW_IMG_WIDTH, settings.PREVIEW_IMG_HEIGHT)

View file

@ -1,5 +1,4 @@
""" test for app action functionality """ """ test for app action functionality """
import os
import json import json
from unittest.mock import patch from unittest.mock import patch
@ -179,7 +178,6 @@ class FederationViews(TestCase):
self.assertEqual(server.application_type, "coolsoft") self.assertEqual(server.application_type, "coolsoft")
self.assertEqual(server.status, "blocked") self.assertEqual(server.status, "blocked")
# pylint: disable=consider-using-with
def test_import_blocklist(self): def test_import_blocklist(self):
"""load a json file with a list of servers to block""" """load a json file with a list of servers to block"""
server = models.FederatedServer.objects.create(server_name="hi.there.com") server = models.FederatedServer.objects.create(server_name="hi.there.com")
@ -191,14 +189,13 @@ class FederationViews(TestCase):
{"instance": "hi.there.com", "url": "https://explanation.url"}, # existing {"instance": "hi.there.com", "url": "https://explanation.url"}, # existing
{"a": "b"}, # invalid {"a": "b"}, # invalid
] ]
json.dump(data, open("file.json", "w")) # pylint: disable=unspecified-encoding
view = views.ImportServerBlocklist.as_view() view = views.ImportServerBlocklist.as_view()
request = self.factory.post( request = self.factory.post(
"", "",
{ {
"json_file": SimpleUploadedFile( "json_file": SimpleUploadedFile(
"file.json", open("file.json", "rb").read() "file.json", json.dumps(data).encode("utf-8")
) )
}, },
) )
@ -214,6 +211,3 @@ class FederationViews(TestCase):
created = models.FederatedServer.objects.get(server_name="server.name") created = models.FederatedServer.objects.get(server_name="server.name")
self.assertEqual(created.status, "blocked") self.assertEqual(created.status, "blocked")
self.assertEqual(created.notes, "https://explanation.url") self.assertEqual(created.notes, "https://explanation.url")
# remove file.json after test
os.remove("file.json")

View file

@ -1,8 +1,6 @@
""" test for app action functionality """ """ test for app action functionality """
from io import BytesIO
import pathlib import pathlib
from unittest.mock import patch from unittest.mock import patch
from PIL import Image
import responses import responses
@ -161,15 +159,15 @@ class BookViews(TestCase):
def test_upload_cover_file(self): def test_upload_cover_file(self):
"""add a cover via file upload""" """add a cover via file upload"""
self.assertFalse(self.book.cover) self.assertFalse(self.book.cover)
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../../static/images/default_avi.jpg" "../../../static/images/default_avi.jpg"
) )
form = forms.CoverForm(instance=self.book) form = forms.CoverForm(instance=self.book)
# pylint: disable=consider-using-with with open(image_path, "rb") as image_file:
form.data["cover"] = SimpleUploadedFile( form.data["cover"] = SimpleUploadedFile(
image_file, open(image_file, "rb").read(), content_type="image/jpeg" image_path, image_file.read(), content_type="image/jpeg"
) )
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.local_user request.user = self.local_user
@ -296,16 +294,14 @@ class BookViews(TestCase):
def _setup_cover_url(): def _setup_cover_url():
"""creates cover url mock""" """creates cover url mock"""
cover_url = "http://example.com" cover_url = "http://example.com"
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../../static/images/default_avi.jpg" "../../../static/images/default_avi.jpg"
) )
image = Image.open(image_file) with open(image_path, "rb") as image_file:
output = BytesIO() responses.add(
image.save(output, format=image.format) responses.GET,
responses.add( cover_url,
responses.GET, body=image_file.read(),
cover_url, status=200,
body=output.getvalue(), )
status=200,
)
return cover_url return cover_url

View file

@ -81,13 +81,13 @@ class ImportViews(TestCase):
form.data["source"] = "Goodreads" form.data["source"] = "Goodreads"
form.data["privacy"] = "public" form.data["privacy"] = "public"
form.data["include_reviews"] = False form.data["include_reviews"] = False
csv_file = pathlib.Path(__file__).parent.joinpath("../../data/goodreads.csv") csv_path = pathlib.Path(__file__).parent.joinpath("../../data/goodreads.csv")
form.data["csv_file"] = SimpleUploadedFile( with open(csv_path, "rb") as csv_file:
# pylint: disable=consider-using-with form.data["csv_file"] = SimpleUploadedFile(
csv_file, csv_path,
open(csv_file, "rb").read(), csv_file.read(),
content_type="text/csv", content_type="text/csv",
) )
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.local_user request.user = self.local_user

View file

@ -47,16 +47,16 @@ class ImportUserViews(TestCase):
view = views.UserImport.as_view() view = views.UserImport.as_view()
form = forms.ImportUserForm() form = forms.ImportUserForm()
archive_file = pathlib.Path(__file__).parent.joinpath( archive_path = pathlib.Path(__file__).parent.joinpath(
"../../data/bookwyrm_account_export.tar.gz" "../../data/bookwyrm_account_export.tar.gz"
) )
form.data["archive_file"] = SimpleUploadedFile( with open(archive_path, "rb") as archive_file:
# pylint: disable=consider-using-with form.data["archive_file"] = SimpleUploadedFile(
archive_file, archive_path,
open(archive_file, "rb").read(), archive_file.read(),
content_type="application/gzip", content_type="application/gzip",
) )
form.data["include_user_settings"] = "" form.data["include_user_settings"] = ""
form.data["include_goals"] = "on" form.data["include_goals"] = "on"

View file

@ -96,13 +96,13 @@ class EditUserViews(TestCase):
form.data["email"] = "wow@email.com" form.data["email"] = "wow@email.com"
form.data["default_post_privacy"] = "public" form.data["default_post_privacy"] = "public"
form.data["preferred_timezone"] = "UTC" form.data["preferred_timezone"] = "UTC"
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../../static/images/no_cover.jpg" "../../../static/images/no_cover.jpg"
) )
# pylint: disable=consider-using-with with open(image_path, "rb") as image_file:
form.data["avatar"] = SimpleUploadedFile( form.data["avatar"] = SimpleUploadedFile(
image_file, open(image_file, "rb").read(), content_type="image/jpeg" image_path, image_file.read(), content_type="image/jpeg"
) )
request = self.factory.post("", form.data) request = self.factory.post("", form.data)
request.user = self.local_user request.user = self.local_user
@ -119,12 +119,12 @@ class EditUserViews(TestCase):
def test_crop_avatar(self, _): def test_crop_avatar(self, _):
"""reduce that image size""" """reduce that image size"""
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../../static/images/no_cover.jpg" "../../../static/images/no_cover.jpg"
) )
image = Image.open(image_file)
result = views.preferences.edit_user.crop_avatar(image) with Image.open(image_path) as image:
result = views.preferences.edit_user.crop_avatar(image)
self.assertIsInstance(result, ContentFile) self.assertIsInstance(result, ContentFile)
image_result = Image.open(result) with Image.open(result) as image_result:
self.assertEqual(image_result.size, (120, 120)) self.assertEqual(image_result.size, (120, 120))

View file

@ -1,10 +1,7 @@
""" test for app action functionality """ """ test for app action functionality """
from io import BytesIO
from unittest.mock import patch from unittest.mock import patch
import pathlib import pathlib
from PIL import Image
from django.core.files.base import ContentFile
from django.http import Http404 from django.http import Http404
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.test import TestCase from django.test import TestCase
@ -142,12 +139,9 @@ class FeedViews(TestCase):
"""there are so many views, this just makes sure it LOADS""" """there are so many views, this just makes sure it LOADS"""
view = views.Status.as_view() view = views.Status.as_view()
image_file = pathlib.Path(__file__).parent.joinpath( image_path = pathlib.Path(__file__).parent.joinpath(
"../../static/images/default_avi.jpg" "../../static/images/default_avi.jpg"
) )
image = Image.open(image_file)
output = BytesIO()
image.save(output, format=image.format)
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
status = models.Review.objects.create( status = models.Review.objects.create(
content="hi", content="hi",
@ -157,7 +151,8 @@ class FeedViews(TestCase):
attachment = models.Image.objects.create( attachment = models.Image.objects.create(
status=status, caption="alt text here" status=status, caption="alt text here"
) )
attachment.image.save("test.jpg", ContentFile(output.getvalue())) with open(image_path, "rb") as image_file:
attachment.image.save("test.jpg", image_file)
request = self.factory.get("") request = self.factory.get("")
request.user = self.local_user request.user = self.local_user