Skip to content

Commit

Permalink
Add Mapping for Series Format (#135)
Browse files Browse the repository at this point in the history
* Add mapping for series formats
* Add test for series format mapping
  • Loading branch information
bpepple authored Nov 29, 2024
1 parent e8c48b7 commit 0d23b46
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
46 changes: 41 additions & 5 deletions darkseid/metroninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class MetronInfo:
}
)

# Ratings Mapping
unknown_synonyms = frozenset({"rating pending", "unknown"})
everyone_synonyms = frozenset(
{"everyone", "everyone 10+", "g", "kids to adults", "early childhood"}
Expand All @@ -143,6 +144,19 @@ class MetronInfo:
mature_synonyms = frozenset({"adults only 18+", "mature 17+", "r18+", "m"})
explicit_synonyms = frozenset({"x18+"})

# Series Format Mapping
annual_synonyms = frozenset({"annual"})
digital_chapter_synonyms = frozenset({"digital chapter", "digital"})
graphic_novel_synonyms = frozenset({"graphic novel"})
hardcover_synonyms = frozenset({"hardcover", "hard-cover"})
limited_series_synonyms = frozenset({"limited series"})
omnibus_synonyms = frozenset({"omnibus"})
one_shot_synonyms = frozenset({"1 shot", "1-shot", "fcbd", "one shot", "one-shot", "preview"})
single_issue_synonyms = frozenset(
{"single issue", "magazine", "series", "giant", "giant size", "giant-size"}
)
trade_paperback_synonyms = frozenset({"trade paperback", "tpb", "trade paper back"})

def metadata_from_string(self, string: str) -> Metadata:
"""Convert an XML string to a Metadata object.
Expand Down Expand Up @@ -208,6 +222,28 @@ def _valid_age_rating(cls, val: AgeRatings | None = None) -> str | None:
return rating
return None

@classmethod
def _valid_series_format(cls, val: str | None) -> str | None:
if not val or val is None:
return None

format_mapping = {
"Annual": cls.annual_synonyms,
"Digital Chapter": cls.digital_chapter_synonyms,
"Graphic Novel": cls.graphic_novel_synonyms,
"Hardcover": cls.hardcover_synonyms,
"Limited Series": cls.limited_series_synonyms,
"Omnibus": cls.omnibus_synonyms,
"One-Shot": cls.one_shot_synonyms,
"Single Issue": cls.single_issue_synonyms,
"Trade Paperback": cls.trade_paperback_synonyms,
}
lower_val = val.lower()
return next(
(fmt for fmt, synonyms in format_mapping.items() if lower_val in synonyms),
None,
)

@staticmethod
def _get_or_create_element(parent: ET.Element, tag: str) -> ET.Element:
element = parent.find(tag)
Expand Down Expand Up @@ -293,8 +329,8 @@ def _assign_publisher(root: ET.Element, publisher: Publisher) -> None:
)
imprint_node.text = publisher.imprint.name

@staticmethod
def _assign_series(root: ET.Element, series: Series) -> None:
@classmethod
def _assign_series(cls, root: ET.Element, series: Series) -> None: # NOQA: C901
if series is None:
return
series_node = MetronInfo._get_or_create_element(root, "Series")
Expand All @@ -315,9 +351,9 @@ def _assign_series(root: ET.Element, series: Series) -> None:
create_sub_element(series_node, "SortName").text = series.sort_name
if series.volume is not None:
create_sub_element(series_node, "Volume").text = str(series.volume)
create_sub_element(series_node, "Format").text = (
series.format if series.format in MetronInfo.mix_series_format else "Single Issue"
)
series_fmt = cls._valid_series_format(series.format)
if series_fmt is not None:
create_sub_element(series_node, "Format").text = series_fmt
if series.start_year:
create_sub_element(series_node, "StartYear").text = str(series.start_year)
if series.issue_count:
Expand Down
43 changes: 43 additions & 0 deletions tests/test_metroninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,49 @@ def test_valid_info_source(metron_info, val, expected_result):
assert result == expected_result


@pytest.mark.parametrize(
("val", "expected"),
[
("Annual", "Annual"), # happy path
("Digital Chapter", "Digital Chapter"), # happy path
("Graphic Novel", "Graphic Novel"), # happy path
("Hardcover", "Hardcover"), # happy path
("Limited Series", "Limited Series"), # happy path
("Omnibus", "Omnibus"), # happy path
("One-Shot", "One-Shot"), # happy path
("Single Issue", "Single Issue"), # happy path
("Trade Paperback", "Trade Paperback"), # happy path
("", None), # edge case: empty string
(None, None), # edge case: None value
("Unknown Format", None), # edge case: unknown format
("annual", "Annual"), # edge case: case insensitivity
("ANNUAL", "Annual"), # edge case: uppercase
],
ids=[
"valid_annual",
"valid_digital_chapter",
"valid_graphic_novel",
"valid_hardcover",
"valid_limited_series",
"valid_omnibus",
"valid_one_shot",
"valid_single_issue",
"valid_trade_paperback",
"empty_string",
"none_value",
"unknown_format",
"case_insensitivity_lower",
"case_insensitivity_upper",
],
)
def test_valid_series_format(metron_info, val, expected):
# Act
result = metron_info._valid_series_format(val) # NOQA: SLF001

# Assert
assert result == expected


@pytest.mark.parametrize(
("val", "expected_result"),
[
Expand Down

0 comments on commit 0d23b46

Please sign in to comment.