Tests
Add tests for IssueIdentifier Change tags to a set from a string Add copy and replace convenience functions on GenericMetadata Update deprecated resampling code for Pillow Change comicvine test data to be the same as the test comic Cleanup tests
This commit is contained in:
parent
99030fae6b
commit
6e7660c3d9
@ -98,13 +98,11 @@ class ComicBookInfo:
|
||||
metadata.critical_rating = utils.xlate(cbi["rating"], True)
|
||||
|
||||
metadata.credits = cbi["credits"]
|
||||
metadata.tags = cbi["tags"]
|
||||
metadata.tags = set(cbi["tags"]) if cbi["tags"] is not None else set()
|
||||
|
||||
# make sure credits and tags are at least empty lists and not None
|
||||
if metadata.credits is None:
|
||||
metadata.credits = []
|
||||
if metadata.tags is None:
|
||||
metadata.tags = []
|
||||
|
||||
# need the language string to be ISO
|
||||
if metadata.language is not None:
|
||||
|
@ -20,8 +20,9 @@ possible, however lossy it might be
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import dataclasses
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, TypedDict
|
||||
|
||||
from comicapi import utils
|
||||
@ -65,7 +66,7 @@ class CreditMetadata(TypedDict):
|
||||
primary: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
@dataclasses.dataclass
|
||||
class GenericMetadata:
|
||||
writer_synonyms = ["writer", "plotter", "scripter"]
|
||||
penciller_synonyms = ["artist", "penciller", "penciler", "breakdowns"]
|
||||
@ -115,9 +116,9 @@ class GenericMetadata:
|
||||
teams: str | None = None
|
||||
locations: str | None = None
|
||||
|
||||
credits: list[CreditMetadata] = field(default_factory=list)
|
||||
tags: list[str] = field(default_factory=list)
|
||||
pages: list[ImageMetadata] = field(default_factory=list)
|
||||
credits: list[CreditMetadata] = dataclasses.field(default_factory=list)
|
||||
tags: set[str] = dataclasses.field(default_factory=set)
|
||||
pages: list[ImageMetadata] = dataclasses.field(default_factory=list)
|
||||
|
||||
# Some CoMet-only items
|
||||
price: str | None = None
|
||||
@ -133,6 +134,14 @@ class GenericMetadata:
|
||||
self.is_empty = False
|
||||
break
|
||||
|
||||
def copy(self) -> GenericMetadata:
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def replace(self, /, **kwargs) -> GenericMetadata:
|
||||
tmp = self.copy()
|
||||
tmp.__dict__.update(kwargs)
|
||||
return tmp
|
||||
|
||||
def overlay(self, new_md: GenericMetadata) -> None:
|
||||
"""Overlay a metadata object on this one
|
||||
|
||||
@ -408,7 +417,7 @@ md_test.credits = [
|
||||
CreditMetadata({"primary": False, "person": "Sam Kieth", "role": "Cover"}),
|
||||
CreditMetadata({"primary": False, "person": "Ted Adams", "role": "Editor"}),
|
||||
]
|
||||
md_test.tags = []
|
||||
md_test.tags = set()
|
||||
md_test.pages = [
|
||||
{"Image": 0, "ImageHeight": "1280", "ImageSize": "195977", "ImageWidth": "800", "Type": PageType.FrontCover},
|
||||
{"Image": 1, "ImageHeight": "2039", "ImageSize": "611993", "ImageWidth": "1327"},
|
||||
|
@ -32,7 +32,7 @@ class CBLTransformer:
|
||||
# helper funcs
|
||||
def append_to_tags_if_unique(item: str) -> None:
|
||||
if item.casefold() not in (tag.casefold() for tag in self.metadata.tags):
|
||||
self.metadata.tags.append(item)
|
||||
self.metadata.tags.add(item)
|
||||
|
||||
def add_string_list_to_tags(str_list: str | None) -> None:
|
||||
if str_list:
|
||||
|
@ -49,7 +49,7 @@ class ImageHasher:
|
||||
|
||||
def average_hash(self) -> int:
|
||||
try:
|
||||
image = self.image.resize((self.width, self.height), Image.ANTIALIAS).convert("L")
|
||||
image = self.image.resize((self.width, self.height), Image.Resampling.LANCZOS).convert("L")
|
||||
except Exception:
|
||||
logger.exception("average_hash error")
|
||||
return 0
|
||||
|
@ -26,7 +26,7 @@ import pprint
|
||||
import re
|
||||
import sys
|
||||
import webbrowser
|
||||
from typing import Any, Callable, cast
|
||||
from typing import Any, Callable, Iterable, cast
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import natsort
|
||||
@ -944,8 +944,8 @@ Have fun!
|
||||
tmp = self.teTags.toPlainText()
|
||||
if tmp is not None:
|
||||
|
||||
def strip_list(i: list[str]) -> list[str]:
|
||||
return [x.strip() for x in i]
|
||||
def strip_list(i: Iterable[str]) -> set[str]:
|
||||
return {x.strip() for x in i}
|
||||
|
||||
md.tags = strip_list(tmp.split(","))
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.resulttypes
|
||||
from comicapi import utils
|
||||
@ -55,15 +53,48 @@ select_details = [
|
||||
metadata = [
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(series="test", issue="2", title="never"),
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test, series="test", issue="2", title="never"),
|
||||
comicapi.genericmetadata.md_test.replace(series="test", issue="2", title="never"),
|
||||
),
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(series="", issue="2", title="never"),
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test, series=None, issue="2", title="never"),
|
||||
comicapi.genericmetadata.md_test.replace(series=None, issue="2", title="never"),
|
||||
),
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(),
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test),
|
||||
comicapi.genericmetadata.md_test.copy(),
|
||||
),
|
||||
]
|
||||
|
||||
metadata_keys = [
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(),
|
||||
{
|
||||
"issue_count": 6,
|
||||
"issue_number": "1",
|
||||
"month": 10,
|
||||
"series": "Cory Doctorow's Futuristic Tales of the Here and Now",
|
||||
"year": 2007,
|
||||
},
|
||||
),
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(series="test"),
|
||||
{
|
||||
"issue_count": 6,
|
||||
"issue_number": "1",
|
||||
"month": 10,
|
||||
"series": "test",
|
||||
"year": 2007,
|
||||
},
|
||||
),
|
||||
(
|
||||
comicapi.genericmetadata.GenericMetadata(series="test", issue="3"),
|
||||
{
|
||||
"issue_count": 6,
|
||||
"issue_number": "3",
|
||||
"month": 10,
|
||||
"series": "test",
|
||||
"year": 2007,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
@ -22,16 +22,16 @@ cv_issue_result: dict[str, Any] = {
|
||||
"status_code": 1,
|
||||
"results": {
|
||||
"aliases": None,
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/issue/4000-311811/",
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/issue/4000-140529/",
|
||||
"associated_images": [],
|
||||
"character_credits": [],
|
||||
"character_died_in": [],
|
||||
"concept_credits": [],
|
||||
"cover_date": "2007-12-01",
|
||||
"date_added": "2012-01-18 06:48:56",
|
||||
"date_last_updated": "2012-01-18 17:27:48",
|
||||
"cover_date": "2007-10-01",
|
||||
"date_added": "2008-10-16 05:25:47",
|
||||
"date_last_updated": "2010-06-09 18:05:49",
|
||||
"deck": None,
|
||||
"description": '<p><i>IDW Publishing continues to bring the stories of acclaimed science-fiction author Cory Doctorow to comics, this time offering up "Craphound." Despite the exoskeleton and mouth full of poisonous suckers, Jerry got along with the alien better than with most humans. In fact, Jerry had nicknamed him "Craphound", after their shared love of hunting for unique treasures at garage sales and thrift stores. They were buddies. That is, until Craphound found the old cowboy trunk. Adapted by Dara Naraghi (whose Lifelike debuts this month, too. See previous page for info), with a cover by Eisner-winning artist Paul Pope!</i></p>',
|
||||
"description": "<i>For 12-year-old Anda, getting paid real money to kill the characters of players who were cheating in her favorite online computer game was a win-win situation. Until she found out who was paying her, and what those characters meant to the livelihood of children around the world.</i>",
|
||||
"first_appearance_characters": None,
|
||||
"first_appearance_concepts": None,
|
||||
"first_appearance_locations": None,
|
||||
@ -39,22 +39,22 @@ cv_issue_result: dict[str, Any] = {
|
||||
"first_appearance_storyarcs": None,
|
||||
"first_appearance_teams": None,
|
||||
"has_staff_review": False,
|
||||
"id": 311811,
|
||||
"id": 140529,
|
||||
"image": {
|
||||
"icon_url": "https://comicvine.gamespot.com/a/uploads/square_avatar/11/115179/2165551-cd3.jpg",
|
||||
"medium_url": "https://comicvine.gamespot.com/a/uploads/scale_medium/11/115179/2165551-cd3.jpg",
|
||||
"screen_url": "https://comicvine.gamespot.com/a/uploads/screen_medium/11/115179/2165551-cd3.jpg",
|
||||
"screen_large_url": "https://comicvine.gamespot.com/a/uploads/screen_kubrick/11/115179/2165551-cd3.jpg",
|
||||
"small_url": "https://comicvine.gamespot.com/a/uploads/scale_small/11/115179/2165551-cd3.jpg",
|
||||
"super_url": "https://comicvine.gamespot.com/a/uploads/scale_large/11/115179/2165551-cd3.jpg",
|
||||
"thumb_url": "https://comicvine.gamespot.com/a/uploads/scale_avatar/11/115179/2165551-cd3.jpg",
|
||||
"tiny_url": "https://comicvine.gamespot.com/a/uploads/square_mini/11/115179/2165551-cd3.jpg",
|
||||
"original_url": "https://comicvine.gamespot.com/a/uploads/original/11/115179/2165551-cd3.jpg",
|
||||
"icon_url": "https://comicvine.gamespot.com/a/uploads/square_avatar/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"medium_url": "https://comicvine.gamespot.com/a/uploads/scale_medium/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"screen_url": "https://comicvine.gamespot.com/a/uploads/screen_medium/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"screen_large_url": "https://comicvine.gamespot.com/a/uploads/screen_kubrick/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"small_url": "https://comicvine.gamespot.com/a/uploads/scale_small/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"super_url": "https://comicvine.gamespot.com/a/uploads/scale_large/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"thumb_url": "https://comicvine.gamespot.com/a/uploads/scale_avatar/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"tiny_url": "https://comicvine.gamespot.com/a/uploads/square_mini/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"original_url": "https://comicvine.gamespot.com/a/uploads/original/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"image_tags": "All Images",
|
||||
},
|
||||
"issue_number": "3",
|
||||
"issue_number": "1",
|
||||
"location_credits": [],
|
||||
"name": "Craphound",
|
||||
"name": "Anda's Game",
|
||||
"object_credits": [],
|
||||
"person_credits": [
|
||||
{
|
||||
@ -65,14 +65,35 @@ cv_issue_result: dict[str, Any] = {
|
||||
"role": "writer",
|
||||
},
|
||||
{
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/person/4040-4306/",
|
||||
"id": 4306,
|
||||
"name": "Paul Pope",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/paul-pope/4040-4306/",
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/person/4040-57222/",
|
||||
"id": 57222,
|
||||
"name": "Esteve Polls",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/esteve-polls/4040-57222/",
|
||||
"role": "artist",
|
||||
},
|
||||
{
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/person/4040-48472/",
|
||||
"id": 48472,
|
||||
"name": "Neil Uyetake",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/neil-uyetake/4040-48472/",
|
||||
"role": "letterer",
|
||||
},
|
||||
{
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/person/4040-5329/",
|
||||
"id": 5329,
|
||||
"name": "Sam Kieth",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/sam-kieth/4040-5329/",
|
||||
"role": "cover",
|
||||
},
|
||||
{
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/person/4040-58534/",
|
||||
"id": 58534,
|
||||
"name": "Ted Adams",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/ted-adams/4040-58534/",
|
||||
"role": "editor",
|
||||
},
|
||||
],
|
||||
"site_detail_url": "https://comicvine.gamespot.com/cory-doctorows-futuristic-tales-of-the-here-and-no/4000-311811/",
|
||||
"site_detail_url": "https://comicvine.gamespot.com/cory-doctorows-futuristic-tales-of-the-here-and-no/4000-140529/",
|
||||
"store_date": None,
|
||||
"story_arc_credits": [],
|
||||
"team_credits": [],
|
||||
@ -95,15 +116,33 @@ cv_volume_result: dict[str, Any] = {
|
||||
"number_of_total_results": 1,
|
||||
"status_code": 1,
|
||||
"results": {
|
||||
"count_of_issues": 6,
|
||||
"id": 23437,
|
||||
"name": "Cory Doctorow's Futuristic Tales of the Here and Now",
|
||||
"aliases": None,
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/volume/4050-23437/",
|
||||
"count_of_issues": 6,
|
||||
"date_added": "2008-10-16 05:25:47",
|
||||
"date_last_updated": "2012-01-18 17:21:57",
|
||||
"deck": None,
|
||||
"description": "<p>Writer and <em>BoingBoing.net</em> co-editor <strong>Cory Doctorow</strong> has won acclaim for his science-fiction writing as well as his Creative Commons presentation of his material. Now, IDW Publishing is proud to present six standalone stories adapted from Doctorow's work, each featuring cover art by some of comics' top talents.</p>",
|
||||
"id": 23437,
|
||||
"image": {
|
||||
"icon_url": "https://comicvine.gamespot.com/a/uploads/square_avatar/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"medium_url": "https://comicvine.gamespot.com/a/uploads/scale_medium/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"screen_url": "https://comicvine.gamespot.com/a/uploads/screen_medium/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"screen_large_url": "https://comicvine.gamespot.com/a/uploads/screen_kubrick/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"small_url": "https://comicvine.gamespot.com/a/uploads/scale_small/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"super_url": "https://comicvine.gamespot.com/a/uploads/scale_large/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"thumb_url": "https://comicvine.gamespot.com/a/uploads/scale_avatar/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"tiny_url": "https://comicvine.gamespot.com/a/uploads/square_mini/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"original_url": "https://comicvine.gamespot.com/a/uploads/original/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"image_tags": "All Images",
|
||||
},
|
||||
"name": "Cory Doctorow's Futuristic Tales of the Here and Now",
|
||||
"publisher": {
|
||||
"api_detail_url": "https://comicvine.gamespot.com/api/publisher/4010-1190/",
|
||||
"id": 1190,
|
||||
"name": "IDW Publishing",
|
||||
},
|
||||
"site_detail_url": "https://comicvine.gamespot.com/cory-doctorows-futuristic-tales-of-the-here-and-no/4050-23437/",
|
||||
"start_year": "2007",
|
||||
},
|
||||
"version": "1.0",
|
||||
@ -143,7 +182,7 @@ cv_md = comicapi.genericmetadata.GenericMetadata(
|
||||
alternate_number=None,
|
||||
alternate_count=None,
|
||||
imprint=None,
|
||||
notes="Tagged with ComicTagger 1.4.4a9.dev20 using info from Comic Vine on 2022-07-11 17:42:41. [Issue ID 311811]",
|
||||
notes="Tagged with ComicTagger 1.4.4a9.dev20 using info from Comic Vine on 2022-07-11 17:42:41. [Issue ID 140529]",
|
||||
web_link=cv_issue_result["results"]["site_detail_url"],
|
||||
format=None,
|
||||
manga=None,
|
||||
@ -157,18 +196,10 @@ cv_md = comicapi.genericmetadata.GenericMetadata(
|
||||
teams="",
|
||||
locations="",
|
||||
credits=[
|
||||
{
|
||||
"person": cv_issue_result["results"]["person_credits"][0]["name"],
|
||||
"role": cv_issue_result["results"]["person_credits"][0]["role"].title(),
|
||||
"primary": False,
|
||||
},
|
||||
{
|
||||
"person": cv_issue_result["results"]["person_credits"][1]["name"],
|
||||
"role": cv_issue_result["results"]["person_credits"][1]["role"].title(),
|
||||
"primary": False,
|
||||
},
|
||||
comicapi.genericmetadata.CreditMetadata(person=x["name"], role=x["role"].title(), primary=False)
|
||||
for x in cv_issue_result["results"]["person_credits"]
|
||||
],
|
||||
tags=[],
|
||||
tags=set(),
|
||||
pages=[],
|
||||
price=None,
|
||||
is_version_of=None,
|
||||
@ -182,10 +213,10 @@ cv_md = comicapi.genericmetadata.GenericMetadata(
|
||||
class MockResponse:
|
||||
"""Mocks the response object from requests"""
|
||||
|
||||
def __init__(self, result: dict[str, Any]) -> None:
|
||||
def __init__(self, result: dict[str, Any], content=None) -> None:
|
||||
self.status_code = 200
|
||||
self.result = result
|
||||
self.content = content
|
||||
|
||||
# mock json() method always returns a specific testing dictionary
|
||||
def json(self) -> dict[str, list]:
|
||||
return self.result
|
||||
|
@ -6,7 +6,7 @@ import pytest
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
from testing.filenames import cbz_path, datadir
|
||||
from testing.filenames import datadir
|
||||
|
||||
|
||||
@pytest.mark.xfail(not comicapi.comicarchive.rar_support, reason="rar support")
|
||||
@ -35,43 +35,31 @@ def test_metadata_read(cbz):
|
||||
assert md == comicapi.genericmetadata.md_test
|
||||
|
||||
|
||||
def test_save_cix(tmp_path):
|
||||
comic_path = tmp_path / cbz_path.name
|
||||
shutil.copy(cbz_path, comic_path)
|
||||
def test_save_cix(tmp_comic):
|
||||
md = tmp_comic.read_cix()
|
||||
md.set_default_page_list(tmp_comic.get_number_of_pages())
|
||||
|
||||
c = comicapi.comicarchive.ComicArchive(comic_path)
|
||||
md = c.read_cix()
|
||||
md.set_default_page_list(c.get_number_of_pages())
|
||||
assert tmp_comic.write_cix(md)
|
||||
|
||||
assert c.write_cix(md)
|
||||
|
||||
md = c.read_cix()
|
||||
md = tmp_comic.read_cix()
|
||||
|
||||
|
||||
def test_page_type_save(tmp_path):
|
||||
comic_path = tmp_path / cbz_path.name
|
||||
|
||||
shutil.copy(cbz_path, comic_path)
|
||||
|
||||
c = comicapi.comicarchive.ComicArchive(comic_path)
|
||||
md = c.read_cix()
|
||||
def test_page_type_save(tmp_comic):
|
||||
md = tmp_comic.read_cix()
|
||||
t = md.pages[0]
|
||||
t["Type"] = ""
|
||||
|
||||
assert c.write_cix(md)
|
||||
assert tmp_comic.write_cix(md)
|
||||
|
||||
md = c.read_cix()
|
||||
md = tmp_comic.read_cix()
|
||||
|
||||
|
||||
def test_invalid_zip(tmp_path):
|
||||
comic_path = tmp_path / cbz_path.name
|
||||
def test_invalid_zip(tmp_comic):
|
||||
with open(tmp_comic.path, mode="b+r") as f:
|
||||
f.write(b"PK\000\000")
|
||||
|
||||
with open(cbz_path, mode="b+r") as f:
|
||||
comic_path.write_bytes(b"PK\003\004" + f.read()[4:].replace(b"PK\003\004", b"PK\000\000"))
|
||||
|
||||
c = comicapi.comicarchive.ComicArchive(comic_path)
|
||||
|
||||
assert not c.write_cix(comicapi.genericmetadata.md_test)
|
||||
result = tmp_comic.write_cix(comicapi.genericmetadata.md_test)
|
||||
assert not result
|
||||
|
||||
|
||||
archivers = [
|
||||
@ -86,7 +74,7 @@ archivers = [
|
||||
|
||||
|
||||
@pytest.mark.parametrize("archiver", archivers)
|
||||
def test_copy_to_archive(archiver, tmp_path, cbz):
|
||||
def test_copy_from_archive(archiver, tmp_path, cbz):
|
||||
comic_path = tmp_path / cbz.path.with_suffix("").name
|
||||
|
||||
archive = archiver(comic_path)
|
||||
@ -100,12 +88,3 @@ def test_copy_to_archive(archiver, tmp_path, cbz):
|
||||
|
||||
md = comic_archive.read_cix()
|
||||
assert md == comicapi.genericmetadata.md_test
|
||||
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
md.overlay(comicapi.genericmetadata.md_test)
|
||||
md.series = "test"
|
||||
|
||||
assert comic_archive.write_cix(md)
|
||||
|
||||
test_md = comic_archive.read_cix()
|
||||
assert md == test_md
|
||||
|
@ -8,71 +8,86 @@ import testing.comicvine
|
||||
from testing.comicdata import select_details
|
||||
|
||||
|
||||
def test_fetch_volume_data(comicvine_api, settings, mock_now, comic_cache):
|
||||
def test_search_for_series(comicvine_api, comic_cache):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
volume = ct.fetch_volume_data(23437)
|
||||
volume["start_year"] = int(volume["start_year"])
|
||||
del volume["publisher"]["id"]
|
||||
del volume["publisher"]["api_detail_url"]
|
||||
assert volume == comic_cache.get_volume_info(23437, ct.source_name)
|
||||
results = ct.search_for_series("cory doctorows futuristic tales of the here and now")
|
||||
for r in results:
|
||||
r["image"] = {"super_url": r["image"]["super_url"]}
|
||||
r["start_year"] = int(r["start_year"])
|
||||
del r["publisher"]["id"]
|
||||
del r["publisher"]["api_detail_url"]
|
||||
cache_issues = comic_cache.get_search_results(ct.source_name, "cory doctorows futuristic tales of the here and now")
|
||||
assert results == cache_issues
|
||||
|
||||
|
||||
def test_fetch_issues_by_volume(comicvine_api, settings, comic_cache):
|
||||
def test_fetch_volume_data(comicvine_api, comic_cache):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
issues = ct.fetch_issues_by_volume(23437)
|
||||
result = ct.fetch_volume_data(23437)
|
||||
result["start_year"] = int(result["start_year"])
|
||||
del result["publisher"]["id"]
|
||||
del result["publisher"]["api_detail_url"]
|
||||
assert result == comic_cache.get_volume_info(23437, ct.source_name)
|
||||
|
||||
|
||||
def test_fetch_issues_by_volume(comicvine_api, comic_cache):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
results = ct.fetch_issues_by_volume(23437)
|
||||
cache_issues = comic_cache.get_volume_issues_info(23437, ct.source_name)
|
||||
|
||||
issues[0]["image"] = {"super_url": issues[0]["image"]["super_url"], "thumb_url": issues[0]["image"]["thumb_url"]}
|
||||
del issues[0]["volume"]
|
||||
assert issues == cache_issues
|
||||
for r in results:
|
||||
r["image"] = {"super_url": r["image"]["super_url"], "thumb_url": r["image"]["thumb_url"]}
|
||||
del r["volume"]
|
||||
assert results == cache_issues
|
||||
|
||||
|
||||
def test_fetch_issue_data_by_issue_id(comicvine_api, settings, mock_now, mock_version):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_data_by_issue_id(311811, settings)
|
||||
assert md == testing.comicvine.cv_md
|
||||
result = ct.fetch_issue_data_by_issue_id(140529, settings)
|
||||
assert result == testing.comicvine.cv_md
|
||||
|
||||
|
||||
def test_fetch_issues_by_volume_issue_num_and_year(comicvine_api):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
cv = ct.fetch_issues_by_volume_issue_num_and_year([23437], "3", None)
|
||||
results = ct.fetch_issues_by_volume_issue_num_and_year([23437], "1", None)
|
||||
cv_expected = testing.comicvine.cv_issue_result["results"].copy()
|
||||
testing.comicvine.filter_field_list(
|
||||
cv_expected,
|
||||
{"params": {"field_list": "id,volume,issue_number,name,image,cover_date,site_detail_url,description,aliases"}},
|
||||
)
|
||||
assert cv[0] == cv_expected
|
||||
for r, e in zip(results, [cv_expected]):
|
||||
assert r == e
|
||||
|
||||
|
||||
cv_issue = [
|
||||
(23437, "3", testing.comicvine.cv_md),
|
||||
(23437, "", comicapi.genericmetadata.GenericMetadata()),
|
||||
(23437, "", testing.comicvine.cv_md),
|
||||
(23437, "1", testing.comicvine.cv_md),
|
||||
(23437, "0", comicapi.genericmetadata.GenericMetadata()),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("volume_id, issue_number, result_md", cv_issue)
|
||||
def test_fetch_issue_data(comicvine_api, settings, mock_now, mock_version, volume_id, issue_number, result_md):
|
||||
@pytest.mark.parametrize("volume_id, issue_number, expected", cv_issue)
|
||||
def test_fetch_issue_data(comicvine_api, settings, mock_now, mock_version, volume_id, issue_number, expected):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_data(volume_id, issue_number, settings)
|
||||
assert md == result_md
|
||||
results = ct.fetch_issue_data(volume_id, issue_number, settings)
|
||||
assert results == expected
|
||||
|
||||
|
||||
# @pytest.mark.parametrize("volume_id, issue_number, result_md", cv_issue)
|
||||
def test_fetch_issue_select_details(comicvine_api, settings, mock_now, mock_version):
|
||||
def test_fetch_issue_select_details(comicvine_api, mock_now, mock_version):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_select_details(311811)
|
||||
res = {
|
||||
result = ct.fetch_issue_select_details(140529)
|
||||
expected = {
|
||||
"cover_date": testing.comicvine.cv_issue_result["results"]["cover_date"],
|
||||
"site_detail_url": testing.comicvine.cv_issue_result["results"]["site_detail_url"],
|
||||
"image_url": testing.comicvine.cv_issue_result["results"]["image"]["super_url"],
|
||||
"thumb_image_url": testing.comicvine.cv_issue_result["results"]["image"]["thumb_url"],
|
||||
}
|
||||
assert md == res
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("details", select_details)
|
||||
def test_issue_select_details(comic_cache, details):
|
||||
expected = details.copy()
|
||||
del expected["issue_id"]
|
||||
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
ct.cache_issue_select_details(
|
||||
issue_id=details["issue_id"],
|
||||
@ -81,6 +96,6 @@ def test_issue_select_details(comic_cache, details):
|
||||
cover_date=details["cover_date"],
|
||||
page_url=details["site_detail_url"],
|
||||
)
|
||||
det = details.copy()
|
||||
del det["issue_id"]
|
||||
assert det == comic_cache.get_issue_select_details(details["issue_id"], ct.source_name)
|
||||
result = comic_cache.get_issue_select_details(details["issue_id"], ct.source_name)
|
||||
|
||||
assert result == expected
|
||||
|
@ -1,12 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import copy
|
||||
import datetime
|
||||
import io
|
||||
import shutil
|
||||
import unittest.mock
|
||||
from typing import Any, Generator
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from PIL import Image
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
@ -23,6 +26,27 @@ def cbz():
|
||||
yield comicapi.comicarchive.ComicArchive(filenames.cbz_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmp_comic(tmp_path):
|
||||
shutil.copy(filenames.cbz_path, tmp_path)
|
||||
yield comicapi.comicarchive.ComicArchive(tmp_path / filenames.cbz_path.name)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cbz_double_cover(tmp_path, tmp_comic):
|
||||
|
||||
cover = Image.open(io.BytesIO(tmp_comic.get_page(0)))
|
||||
|
||||
other_page = Image.open(io.BytesIO(tmp_comic.get_page(tmp_comic.get_number_of_pages() - 1)))
|
||||
|
||||
double_cover = Image.new("RGB", (cover.width * 2, cover.height))
|
||||
double_cover.paste(other_page, (0, 0))
|
||||
double_cover.paste(cover, (cover.width, 0))
|
||||
|
||||
tmp_comic.archiver.write_file("double_cover.jpg", double_cover.tobytes("jpeg", "RGB"))
|
||||
yield tmp_comic
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def no_requests(monkeypatch) -> None:
|
||||
"""Remove requests.sessions.Session.request for all tests."""
|
||||
@ -30,16 +54,24 @@ def no_requests(monkeypatch) -> None:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def comicvine_api(monkeypatch) -> unittest.mock.Mock:
|
||||
def comicvine_api(monkeypatch, cbz, comic_cache) -> unittest.mock.Mock:
|
||||
# Any arguments may be passed and mock_get() will always return our
|
||||
# mocked object, which only has the .json() method or None for invalid urls.
|
||||
|
||||
def make_list(cv_result):
|
||||
cv_list = copy.deepcopy(cv_result)
|
||||
if isinstance(cv_list["results"], dict):
|
||||
cv_list["results"] = [cv_list["results"]]
|
||||
return cv_list
|
||||
|
||||
def mock_get(*args, **kwargs):
|
||||
|
||||
if args:
|
||||
if args[0].startswith("https://comicvine.gamespot.com/api/volume/4050-23437"):
|
||||
return comicvine.MockResponse(comicvine.cv_volume_result)
|
||||
if args[0].startswith("https://comicvine.gamespot.com/api/issue/4000-311811"):
|
||||
cv_result = copy.deepcopy(comicvine.cv_volume_result)
|
||||
comicvine.filter_field_list(cv_result["results"], kwargs)
|
||||
return comicvine.MockResponse(cv_result)
|
||||
if args[0].startswith("https://comicvine.gamespot.com/api/issue/4000-140529"):
|
||||
return comicvine.MockResponse(comicvine.cv_issue_result)
|
||||
if (
|
||||
args[0].startswith("https://comicvine.gamespot.com/api/issues/")
|
||||
@ -47,11 +79,32 @@ def comicvine_api(monkeypatch) -> unittest.mock.Mock:
|
||||
and "filter" in kwargs["params"]
|
||||
and "23437" in kwargs["params"]["filter"]
|
||||
):
|
||||
cv_list = comicvine.cv_issue_result.copy()
|
||||
cv_list["results"] = cv_list["results"].copy()
|
||||
comicvine.filter_field_list(cv_list["results"], kwargs)
|
||||
cv_list["results"] = [cv_list["results"]]
|
||||
cv_list = make_list(comicvine.cv_issue_result)
|
||||
for cv in cv_list["results"]:
|
||||
comicvine.filter_field_list(cv, kwargs)
|
||||
return comicvine.MockResponse(cv_list)
|
||||
if (
|
||||
args[0].startswith("https://comicvine.gamespot.com/api/search")
|
||||
and "params" in kwargs
|
||||
and "resources" in kwargs["params"]
|
||||
and "volume" == kwargs["params"]["resources"]
|
||||
):
|
||||
cv_list = make_list(comicvine.cv_volume_result)
|
||||
for cv in cv_list["results"]:
|
||||
comicvine.filter_field_list(cv, kwargs)
|
||||
return comicvine.MockResponse(cv_list)
|
||||
if (
|
||||
args[0]
|
||||
== "https://comicvine.gamespot.com/a/uploads/scale_large/0/574/585444-109004_20080707014047_large.jpg"
|
||||
):
|
||||
return comicvine.MockResponse({}, cbz.get_page(0))
|
||||
if (
|
||||
args[0]
|
||||
== "https://comicvine.gamespot.com/a/uploads/scale_avatar/0/574/585444-109004_20080707014047_large.jpg"
|
||||
):
|
||||
thumb = Image.open(io.BytesIO(cbz.get_page(0)))
|
||||
thumb.resize((105, 160), Image.Resampling.LANCZOS)
|
||||
return comicvine.MockResponse({}, thumb.tobytes("jpeg", "RGB"))
|
||||
return comicvine.MockResponse(comicvine.cv_not_found)
|
||||
|
||||
m_get = unittest.mock.Mock(side_effect=mock_get)
|
||||
@ -86,7 +139,7 @@ def mock_version(monkeypatch):
|
||||
|
||||
@pytest.fixture
|
||||
def md():
|
||||
yield dataclasses.replace(comicapi.genericmetadata.md_test)
|
||||
yield comicapi.genericmetadata.md_test.copy()
|
||||
|
||||
|
||||
# manually seeds publishers
|
||||
|
@ -26,7 +26,7 @@ def test_add_credit():
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
|
||||
md.add_credit(person="test", role="writer", primary=False)
|
||||
md.credits == [{"person": "test", "role": "writer", "primary": False}]
|
||||
assert md.credits == [comicapi.genericmetadata.CreditMetadata(person="test", role="writer", primary=False)]
|
||||
|
||||
|
||||
def test_add_credit_primary():
|
||||
@ -34,7 +34,7 @@ def test_add_credit_primary():
|
||||
|
||||
md.add_credit(person="test", role="writer", primary=False)
|
||||
md.add_credit(person="test", role="writer", primary=True)
|
||||
md.credits == [{"person": "test", "role": "writer", "primary": True}]
|
||||
assert md.credits == [comicapi.genericmetadata.CreditMetadata(person="test", role="writer", primary=True)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("role, expected", credits)
|
||||
|
75
tests/issueidentifier_test.py
Normal file
75
tests/issueidentifier_test.py
Normal file
@ -0,0 +1,75 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.issuestring
|
||||
import comictaggerlib.comicvinetalker
|
||||
import comictaggerlib.issueidentifier
|
||||
import testing.comicdata
|
||||
import testing.comicvine
|
||||
|
||||
|
||||
def test_crop(cbz_double_cover, settings, tmp_path):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, settings)
|
||||
cropped = ii.crop_cover(cbz_double_cover.archiver.read_file("double_cover.jpg"))
|
||||
original_cover = cbz_double_cover.get_page(0)
|
||||
|
||||
original_hash = ii.calculate_hash(original_cover)
|
||||
cropped_hash = ii.calculate_hash(cropped)
|
||||
|
||||
assert original_hash == cropped_hash
|
||||
|
||||
|
||||
@pytest.mark.parametrize("additional_md, expected", testing.comicdata.metadata_keys)
|
||||
def test_get_search_keys(cbz, settings, additional_md, expected):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings)
|
||||
ii.set_additional_metadata(additional_md)
|
||||
|
||||
assert expected == ii.get_search_keys()
|
||||
|
||||
|
||||
def test_get_issue_cover_match_score(cbz, settings, comicvine_api):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings)
|
||||
score = ii.get_issue_cover_match_score(
|
||||
comictaggerlib.comicvinetalker.ComicVineTalker(),
|
||||
int(
|
||||
comicapi.issuestring.IssueString(
|
||||
cbz.read_metadata(comicapi.comicarchive.MetaDataStyle.CIX).issue
|
||||
).as_float()
|
||||
),
|
||||
"https://comicvine.gamespot.com/a/uploads/scale_large/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"https://comicvine.gamespot.com/a/uploads/scale_avatar/0/574/585444-109004_20080707014047_large.jpg",
|
||||
"https://comicvine.gamespot.com/cory-doctorows-futuristic-tales-of-the-here-and-no/4000-140529/",
|
||||
[ii.calculate_hash(cbz.get_page(0))],
|
||||
)
|
||||
expected = {
|
||||
"hash": 1747255366011518976,
|
||||
"score": 0,
|
||||
"url": "https://comicvine.gamespot.com/a/uploads/scale_large/0/574/585444-109004_20080707014047_large.jpg",
|
||||
}
|
||||
assert expected == score
|
||||
|
||||
|
||||
def test_search(cbz, settings, comicvine_api):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings)
|
||||
results = ii.search()
|
||||
cv_expected = {
|
||||
"series": f"{testing.comicvine.cv_volume_result['results']['name']} ({testing.comicvine.cv_volume_result['results']['start_year']})",
|
||||
"distance": 0,
|
||||
"issue_number": testing.comicvine.cv_issue_result["results"]["issue_number"],
|
||||
"cv_issue_count": testing.comicvine.cv_volume_result["results"]["count_of_issues"],
|
||||
"issue_title": testing.comicvine.cv_issue_result["results"]["name"],
|
||||
"issue_id": testing.comicvine.cv_issue_result["results"]["id"],
|
||||
"volume_id": testing.comicvine.cv_volume_result["results"]["id"],
|
||||
"month": testing.comicvine.date[1],
|
||||
"year": testing.comicvine.date[2],
|
||||
"publisher": testing.comicvine.cv_volume_result["results"]["publisher"]["name"],
|
||||
"image_url": testing.comicvine.cv_issue_result["results"]["image"]["super_url"],
|
||||
"thumb_url": testing.comicvine.cv_issue_result["results"]["image"]["thumb_url"],
|
||||
"page_url": testing.comicvine.cv_issue_result["results"]["site_detail_url"],
|
||||
"description": testing.comicvine.cv_issue_result["results"]["description"],
|
||||
}
|
||||
for r, e in zip(results, [cv_expected]):
|
||||
del r["url_image_hash"]
|
||||
assert r == e
|
Loading…
Reference in New Issue
Block a user