full dates in serialization. remainder in square brackets. tests for serializer

This commit is contained in:
AJ Slater 2024-02-21 18:08:50 -08:00
parent 4b9015878d
commit 439a904c54
5 changed files with 94 additions and 18 deletions

View File

@ -105,10 +105,14 @@ _MONTH_NUMERIC_RE_EXP = r"(?P<month>0?\d|1[0-2]?)"
_MONTH_RE_EXP = r"(" + _MONTH_ALPHA_RE_EXP + r"|" + _MONTH_NUMERIC_RE_EXP + r")" _MONTH_RE_EXP = r"(" + _MONTH_ALPHA_RE_EXP + r"|" + _MONTH_NUMERIC_RE_EXP + r")"
_ALPHA_MONTH_RANGE = ( _ALPHA_MONTH_RANGE = (
r"\b" r"\b"
+ r"(" + r"|".join(MONTHS) + r")" + r"("
+ r"|".join(MONTHS)
+ r")"
+ r"(" + r"("
+ r"\.?-" + r"\.?-"
+ r"(" + r"|".join(MONTHS) + r")" + r"("
+ r"|".join(MONTHS)
+ r")"
+ r")\b" + r")\b"
) )
print(_ALPHA_MONTH_RANGE) print(_ALPHA_MONTH_RANGE)

View File

@ -1,5 +1,8 @@
"""Unparse comic filenames.""" """Unparse comic filenames."""
from collections.abc import Callable, Mapping from collections.abc import Callable, Mapping, Sequence
from contextlib import suppress
from calendar import month_abbr
from types import MappingProxyType
def issue_formatter(issue: str) -> str: def issue_formatter(issue: str) -> str:
@ -18,18 +21,39 @@ _PAREN_FMT: str = "({})"
_FILENAME_FORMAT_TAGS: tuple[tuple[str, str | Callable], ...] = ( _FILENAME_FORMAT_TAGS: tuple[tuple[str, str | Callable], ...] = (
("series", "{}"), ("series", "{}"),
("volume", "v{}"), ("volume", "v{}"),
("volume_count", "(of {:03})"),
("issue", issue_formatter), ("issue", issue_formatter),
("issue_count", "(of {:03})"), ("issue_count", "(of {:03})"),
("year", _PAREN_FMT), ("date", _PAREN_FMT),
("title", "{}"), ("title", "{}"),
("publisher", _PAREN_FMT),
("original_format", _PAREN_FMT), ("original_format", _PAREN_FMT),
("scan_info", _PAREN_FMT), ("scan_info", _PAREN_FMT),
) )
_EMPTY_VALUES: tuple[None, str] = (None, "") _EMPTY_VALUES: tuple[None, str] = (None, "")
_DEFAULT_EXT = "cbz" _DEFAULT_EXT = "cbz"
_DATE_KEYS = ("year", "month", "day")
class ComicFilenameSerializer: class ComicFilenameSerializer:
def _add_date(self) -> None:
if "date" in self.metadata:
return
parts = []
for key in _DATE_KEYS:
if part := self.metadata.get(key):
if key == "month" and not parts:
with suppress(TypeError):
part = month_abbr[int(part)]
parts.append(part)
if key == "month" and not parts:
# noop if only day.
break
if parts:
date = "-".join(parts)
self.metadata = MappingProxyType({**self.metadata, "date": date})
def _tokenize_tag(self, tag: str, fmt: str | Callable) -> str: def _tokenize_tag(self, tag: str, fmt: str | Callable) -> str:
val = self.metadata.get(tag) val = self.metadata.get(tag)
if val in _EMPTY_VALUES: if val in _EMPTY_VALUES:
@ -38,22 +62,30 @@ class ComicFilenameSerializer:
token = final_fmt.format(val).strip() token = final_fmt.format(val).strip()
return token return token
def _add_remainder(self) -> str:
if remainders := self.metadata.get("remainders"):
if isinstance(remainders, Sequence):
remainder = " ".join(remainders)
else:
remainder = str(remainders)
return f"[{remainder}]"
return ""
def serialize(self) -> str: def serialize(self) -> str:
"""Get our preferred basename from a metadata dict.""" """Get our preferred basename from a metadata dict."""
self._add_date()
tokens = [] tokens = []
for tag, fmt in _FILENAME_FORMAT_TAGS: for tag, fmt in _FILENAME_FORMAT_TAGS:
if token := self._tokenize_tag(tag, fmt): if token := self._tokenize_tag(tag, fmt):
tokens.append(token) tokens.append(token)
fn = " ".join(tokens) fn = " ".join(tokens)
if remainders := self.metadata.get("remainders"): fn += self._add_remainder()
# TODO make token and add before join?
remainder = " ".join(remainders)
# TODO oh this is the - delineated remainder :(
fn += f" - {remainder}"
if self._ext: if self._ext:
fn += "." + self.metadata.get("ext", _DEFAULT_EXT) ext = self.metadata.get("ext", _DEFAULT_EXT)
fn += f".{ext}"
return fn return fn

View File

@ -1,5 +1,8 @@
"""Test filenames with human parsed correct results.""" """Test filenames with human parsed correct results."""
from types import MappingProxyType
TEST_COMIC_FIELDS = { TEST_COMIC_FIELDS = {
"series": "Long Series Name", "series": "Long Series Name",
"issue": "001", "issue": "001",
@ -30,7 +33,7 @@ TEST_COMIC_VOL_ONLY = {
"ext": "cbr", "ext": "cbr",
} }
# Working with 0.1.0 # Tests for 0.1.0
FNS = { FNS = {
"Night of 1000 Wolves 001 (2013).cbz": { "Night of 1000 Wolves 001 (2013).cbz": {
"series": "Night of 1000 Wolves", "series": "Night of 1000 Wolves",
@ -239,7 +242,7 @@ FNS = {
}, },
} }
# Fixed with 0.2.0 # Tests for 0.2.0
FNS.update( FNS.update(
{ {
# Philosopy change regarding dashes. # Philosopy change regarding dashes.
@ -442,6 +445,34 @@ FNS.update(
}, },
} }
) )
PARSE_FNS = MappingProxyType(FNS)
SERIALIZE_FNS = MappingProxyType(
{
"Long Series Name #001 (2000) Title (TPB) (Releaser).cbz": TEST_COMIC_FIELDS,
"Long Series Name v1 #001 "
"(2000) Title (TPB) (Releaser & Releaser-Releaser).cbr": TEST_COMIC_VOL_ONLY,
"Series Name (2000-12-31).cbz": {
"series": "Series Name",
"year": "2000",
"month": "12",
"day": "31",
"ext": "cbz",
},
"Series Name (2000-12).cbz": {
"series": "Series Name",
"year": "2000",
"month": "12",
"ext": "cbz",
},
"Series Name (Dec-31).cbz": {
"series": "Series Name",
"month": "12",
"day": "31",
"ext": "cbz",
},
}
)
# first_key, first_val = NEW.popitem() # first_key, first_val = NEW.popitem()
# FNS[first_key] = first_val # FNS[first_key] = first_val

View File

@ -1,18 +1,14 @@
"""Tests for filename parsing.""" """Tests for filename parsing."""
from pprint import pprint from pprint import pprint
from types import MappingProxyType
import pytest import pytest
from deepdiff.diff import DeepDiff from deepdiff.diff import DeepDiff
from comicfn2dict import ComicFilenameParser from comicfn2dict import ComicFilenameParser
from tests.comic_filenames import FNS from tests.comic_filenames import PARSE_FNS
ALL_FIELDS = frozenset({"series", "volume", "issue", "issue_count", "year", "ext"})
FIELD_SCHEMA = MappingProxyType({key: None for key in ALL_FIELDS})
@pytest.mark.parametrize("item", FNS.items()) @pytest.mark.parametrize("item", PARSE_FNS.items())
def test_parse_filename(item): def test_parse_filename(item):
"""Test filename parsing.""" """Test filename parsing."""
fn, defined_fields = item fn, defined_fields = item

View File

@ -0,0 +1,13 @@
"""Tests for filename parsing."""
import pytest
from comicfn2dict import ComicFilenameSerializer
from tests.comic_filenames import SERIALIZE_FNS
@pytest.mark.parametrize("item", SERIALIZE_FNS.items())
def test_serialize_dict(item):
"""Test metadata serialization."""
test_fn, md = item
fn = ComicFilenameSerializer(md).serialize()
assert test_fn == fn