Convert GenericMetadata to a dataclass
dataclasses allow for simple comparison and object creation Add more tests
This commit is contained in:
parent
cb5b321539
commit
3d84af3746
@ -21,6 +21,7 @@ possible, however lossy it might be
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, TypedDict
|
||||
|
||||
from comicapi import utils
|
||||
@ -64,6 +65,7 @@ class CreditMetadata(TypedDict):
|
||||
primary: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class GenericMetadata:
|
||||
writer_synonyms = ["writer", "plotter", "scripter"]
|
||||
penciller_synonyms = ["artist", "penciller", "penciler", "breakdowns"]
|
||||
@ -73,59 +75,63 @@ class GenericMetadata:
|
||||
cover_synonyms = ["cover", "covers", "coverartist", "cover artist"]
|
||||
editor_synonyms = ["editor"]
|
||||
|
||||
def __init__(self) -> None:
|
||||
is_empty: bool = True
|
||||
tag_origin: str | None = None
|
||||
|
||||
self.is_empty: bool = True
|
||||
self.tag_origin: str | None = None
|
||||
series: str | None = None
|
||||
issue: str | None = None
|
||||
title: str | None = None
|
||||
publisher: str | None = None
|
||||
month: int | None = None
|
||||
year: int | None = None
|
||||
day: int | None = None
|
||||
issue_count: int | None = None
|
||||
volume: int | None = None
|
||||
genre: str | None = None
|
||||
language: str | None = None # 2 letter iso code
|
||||
comments: str | None = None # use same way as Summary in CIX
|
||||
|
||||
self.series: str | None = None
|
||||
self.issue: str | None = None
|
||||
self.title: str | None = None
|
||||
self.publisher: str | None = None
|
||||
self.month: int | None = None
|
||||
self.year: int | None = None
|
||||
self.day: int | None = None
|
||||
self.issue_count: int | None = None
|
||||
self.volume: int | None = None
|
||||
self.genre: str | None = None
|
||||
self.language: str | None = None # 2 letter iso code
|
||||
self.comments: str | None = None # use same way as Summary in CIX
|
||||
volume_count: int | None = None
|
||||
critical_rating: float | None = None # rating in cbl; CommunityRating in CIX
|
||||
country: str | None = None
|
||||
|
||||
self.volume_count: int | None = None
|
||||
self.critical_rating: float | None = None # rating in cbl; CommunityRating in CIX
|
||||
self.country: str | None = None
|
||||
alternate_series: str | None = None
|
||||
alternate_number: str | None = None
|
||||
alternate_count: int | None = None
|
||||
imprint: str | None = None
|
||||
notes: str | None = None
|
||||
web_link: str | None = None
|
||||
format: str | None = None
|
||||
manga: str | None = None
|
||||
black_and_white: bool | None = None
|
||||
page_count: int | None = None
|
||||
maturity_rating: str | None = None
|
||||
|
||||
self.alternate_series: str | None = None
|
||||
self.alternate_number: str | None = None
|
||||
self.alternate_count: int | None = None
|
||||
self.imprint: str | None = None
|
||||
self.notes: str | None = None
|
||||
self.web_link: str | None = None
|
||||
self.format: str | None = None
|
||||
self.manga: str | None = None
|
||||
self.black_and_white: bool | None = None
|
||||
self.page_count: int | None = None
|
||||
self.maturity_rating: str | None = None
|
||||
story_arc: str | None = None
|
||||
series_group: str | None = None
|
||||
scan_info: str | None = None
|
||||
|
||||
self.story_arc: str | None = None
|
||||
self.series_group: str | None = None
|
||||
self.scan_info: str | None = None
|
||||
characters: str | None = None
|
||||
teams: str | None = None
|
||||
locations: str | None = None
|
||||
|
||||
self.characters: str | None = None
|
||||
self.teams: str | None = None
|
||||
self.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)
|
||||
|
||||
self.credits: list[CreditMetadata] = []
|
||||
self.tags: list[str] = []
|
||||
self.pages: list[ImageMetadata] = []
|
||||
# Some CoMet-only items
|
||||
price: str | None = None
|
||||
is_version_of: str | None = None
|
||||
rights: str | None = None
|
||||
identifier: str | None = None
|
||||
last_mark: str | None = None
|
||||
cover_image: str | None = None
|
||||
|
||||
# Some CoMet-only items
|
||||
self.price: str | None = None
|
||||
self.is_version_of: str | None = None
|
||||
self.rights: str | None = None
|
||||
self.identifier: str | None = None
|
||||
self.last_mark: str | None = None
|
||||
self.cover_image: str | None = None
|
||||
def __post_init__(self):
|
||||
for key, value in self.__dict__.items():
|
||||
if value and key != "is_empty":
|
||||
self.is_empty = False
|
||||
break
|
||||
|
||||
def overlay(self, new_md: GenericMetadata) -> None:
|
||||
"""Overlay a metadata object on this one
|
||||
|
@ -48,9 +48,7 @@ def test_metadata_read():
|
||||
thisdir / "data" / "Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz"
|
||||
)
|
||||
md = c.read_cix()
|
||||
md_dict = md.__dict__
|
||||
md_test_dict = comicapi.genericmetadata.md_test.__dict__
|
||||
assert md_dict == md_test_dict
|
||||
assert md == comicapi.genericmetadata.md_test
|
||||
|
||||
|
||||
def test_save_cix(tmp_path):
|
||||
@ -118,9 +116,7 @@ def test_copy_to_archive(archiver, tmp_path):
|
||||
assert set(cbz.archiver.get_filename_list()) == set(comic_archive.archiver.get_filename_list())
|
||||
|
||||
md = comic_archive.read_cix()
|
||||
md_dict = md.__dict__
|
||||
md_test_dict = comicapi.genericmetadata.md_test.__dict__
|
||||
assert md_dict == md_test_dict
|
||||
assert md == comicapi.genericmetadata.md_test
|
||||
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
md.overlay(comicapi.genericmetadata.md_test)
|
||||
@ -129,6 +125,4 @@ def test_copy_to_archive(archiver, tmp_path):
|
||||
assert comic_archive.write_cix(md)
|
||||
|
||||
test_md = comic_archive.read_cix()
|
||||
md_dict = md.__dict__
|
||||
test_md_dict = test_md.__dict__
|
||||
assert md_dict == test_md_dict
|
||||
assert md == test_md
|
||||
|
62
tests/genericmetadata_test.py
Normal file
62
tests/genericmetadata_test.py
Normal file
@ -0,0 +1,62 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
||||
import comicapi.genericmetadata
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def md():
|
||||
yield dataclasses.replace(comicapi.genericmetadata.md_test)
|
||||
|
||||
|
||||
stuff = [
|
||||
(
|
||||
{"series": "test", "issue": "2", "title": "never"},
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test, series="test", issue="2", title="never"),
|
||||
),
|
||||
(
|
||||
{"series": "", "issue": "2", "title": "never"},
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test, series=None, issue="2", title="never"),
|
||||
),
|
||||
(
|
||||
{},
|
||||
dataclasses.replace(comicapi.genericmetadata.md_test),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("replaced, expected", stuff)
|
||||
def test_metadata_overlay(md: comicapi.genericmetadata.GenericMetadata, replaced, expected):
|
||||
md_overlay = comicapi.genericmetadata.GenericMetadata(**replaced)
|
||||
md.overlay(md_overlay)
|
||||
|
||||
assert md == expected
|
||||
|
||||
|
||||
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}]
|
||||
|
||||
|
||||
def test_add_credit_primary():
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
|
||||
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}]
|
||||
|
||||
|
||||
credits = [
|
||||
("writer", "Dara Naraghi"),
|
||||
("writeR", "Dara Naraghi"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("role, expected", credits)
|
||||
def test_get_primary_credit(md, role, expected):
|
||||
assert md.get_primary_credit(role) == expected
|
@ -13,6 +13,7 @@ issues = [
|
||||
("22.BEY", 22.0, "022.BEY"),
|
||||
("22A", 22.0, "022A"),
|
||||
("22-A", 22.0, "022-A"),
|
||||
("", None, ""),
|
||||
]
|
||||
|
||||
|
||||
|
56
tests/utils_test.py
Normal file
56
tests/utils_test.py
Normal file
@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import comicapi.utils
|
||||
|
||||
|
||||
def test_recursive_list_with_file(tmp_path) -> None:
|
||||
foo_png = tmp_path / "foo.png"
|
||||
foo_png.write_text("not a png")
|
||||
|
||||
temp_folder = tmp_path / "bar"
|
||||
temp_folder.mkdir()
|
||||
temp_file = temp_folder / "test.cbz"
|
||||
temp_file.write_text("not a zip")
|
||||
|
||||
temp_folder2 = tmp_path / "bar" / "baz" / "something else"
|
||||
temp_folder2.mkdir(parents=True)
|
||||
temp_cbr = temp_folder2 / "bar.cbr"
|
||||
temp_cbr.write_text("not a rar")
|
||||
|
||||
temp_txt = tmp_path / "info.txt"
|
||||
temp_txt.write_text("this is here")
|
||||
|
||||
expected_result = {str(foo_png), str(temp_cbr), str(temp_file), str(temp_txt)}
|
||||
result = set(comicapi.utils.get_recursive_filelist([tmp_path]))
|
||||
|
||||
assert result == expected_result
|
||||
|
||||
|
||||
values = [
|
||||
({"data": "", "is_int": False, "is_float": False}, None),
|
||||
({"data": None, "is_int": False, "is_float": False}, None),
|
||||
({"data": None, "is_int": True, "is_float": False}, None),
|
||||
({"data": " ", "is_int": True, "is_float": False}, None),
|
||||
({"data": "", "is_int": True, "is_float": False}, None),
|
||||
({"data": "9", "is_int": False, "is_float": False}, "9"),
|
||||
({"data": 9, "is_int": False, "is_float": False}, "9"),
|
||||
({"data": 9, "is_int": True, "is_float": False}, 9),
|
||||
({"data": "9", "is_int": True, "is_float": False}, 9),
|
||||
({"data": 9.3, "is_int": True, "is_float": False}, 9),
|
||||
({"data": "9.3", "is_int": True, "is_float": False}, 9),
|
||||
({"data": "9.", "is_int": True, "is_float": False}, 9),
|
||||
({"data": " 9 . 3 l", "is_int": True, "is_float": False}, 9),
|
||||
({"data": 9, "is_int": False, "is_float": True}, 9.0),
|
||||
({"data": "9", "is_int": False, "is_float": True}, 9.0),
|
||||
({"data": 9.3, "is_int": False, "is_float": True}, 9.3),
|
||||
({"data": "9.3", "is_int": False, "is_float": True}, 9.3),
|
||||
({"data": "9.", "is_int": False, "is_float": True}, 9.0),
|
||||
({"data": " 9 . 3 l", "is_int": False, "is_float": True}, 9.3),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value, result", values)
|
||||
def test_xlate(value, result):
|
||||
assert comicapi.utils.xlate(**value) == result
|
Loading…
Reference in New Issue
Block a user