Compare commits

...

1 Commits

Author SHA1 Message Date
Timmy Welch
54d733ef74 Support separate cover and store dates in ComicAPI 2023-08-04 22:39:30 -07:00
17 changed files with 205 additions and 125 deletions

View File

@ -20,7 +20,7 @@ import xml.etree.ElementTree as ET
from typing import Any
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata
from comicapi.genericmetadata import Date, GenericMetadata
logger = logging.getLogger(__name__)
@ -85,11 +85,7 @@ class CoMet:
if md.manga is not None and md.manga == "YesAndRightToLeft":
assign("readingDirection", "rtl")
if md.year is not None:
date_str = f"{md.year:04}"
if md.month is not None:
date_str += f"-{md.month:02}"
assign("date", date_str)
assign("date", f"{md.cover_date.year or ''}-{md.cover_date.month or ''}".strip("-"))
assign("coverImage", md.cover_image)
@ -154,7 +150,7 @@ class CoMet:
md.identifier = utils.xlate(get("identifier"))
md.last_mark = utils.xlate(get("lastMark"))
_, md.month, md.year = utils.parse_date_str(utils.xlate(get("date")))
md.cover_date = Date.parse_date(utils.xlate(get("date")))
md.cover_image = utils.xlate(get("coverImage"))

View File

@ -563,7 +563,8 @@ class ComicArchive:
metadata.title = utils.xlate(p.filename_info["title"])
metadata.volume = utils.xlate_int(p.filename_info["volume"])
metadata.volume_count = utils.xlate_int(p.filename_info["volume_count"])
metadata.year = utils.xlate_int(p.filename_info["year"])
metadata.cover_date.year = utils.xlate_int(p.filename_info["year"])
metadata.scan_info = utils.xlate(p.filename_info["remainder"])
metadata.format = "FCBD" if p.filename_info["fcbd"] else None
@ -580,7 +581,7 @@ class ComicArchive:
if fnp.volume:
metadata.volume = utils.xlate_int(fnp.volume)
if fnp.year:
metadata.year = utils.xlate_int(fnp.year)
metadata.cover_date.year = utils.xlate_int(fnp.year)
if fnp.issue_count:
metadata.issue_count = utils.xlate_int(fnp.issue_count)
if fnp.remainder:

View File

@ -21,7 +21,7 @@ from datetime import datetime
from typing import Any, Literal, TypedDict
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata
from comicapi.genericmetadata import Date, GenericMetadata
logger = logging.getLogger(__name__)
@ -85,8 +85,9 @@ class ComicBookInfo:
metadata.title = utils.xlate(cbi["title"])
metadata.issue = utils.xlate(cbi["issue"])
metadata.publisher = utils.xlate(cbi["publisher"])
metadata.month = utils.xlate_int(cbi["publicationMonth"])
metadata.year = utils.xlate_int(cbi["publicationYear"])
metadata.cover_date = Date(utils.xlate_int(cbi["publicationYear"]), utils.xlate_int(cbi["publicationMonth"]))
metadata.issue_count = utils.xlate_int(cbi["numberOfIssues"])
metadata.description = utils.xlate(cbi["comments"])
metadata.genres = utils.split(cbi["genre"], ",")
@ -148,8 +149,8 @@ class ComicBookInfo:
assign("title", utils.xlate(metadata.title))
assign("issue", utils.xlate(metadata.issue))
assign("publisher", utils.xlate(metadata.publisher))
assign("publicationMonth", utils.xlate_int(metadata.month))
assign("publicationYear", utils.xlate_int(metadata.year))
assign("publicationMonth", utils.xlate_int(metadata.cover_date.month))
assign("publicationYear", utils.xlate_int(metadata.cover_date.year))
assign("numberOfIssues", utils.xlate_int(metadata.issue_count))
assign("comments", utils.xlate(metadata.description))
assign("genre", utils.xlate(",".join(metadata.genres)))

View File

@ -21,7 +21,7 @@ from typing import Any, cast
from xml.etree.ElementTree import ElementTree
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata, ImageMetadata
from comicapi.genericmetadata import Date, GenericMetadata, ImageMetadata
logger = logging.getLogger(__name__)
@ -99,9 +99,10 @@ class ComicInfoXml:
assign("AlternateCount", md.alternate_count)
assign("Summary", md.description)
assign("Notes", md.notes)
assign("Year", md.year)
assign("Month", md.month)
assign("Day", md.day)
assign("Year", md.cover_date.year)
assign("Month", md.cover_date.month)
assign("Day", md.cover_date.day)
# need to specially process the credits, since they are structured
# differently than CIX
@ -203,9 +204,9 @@ class ComicInfoXml:
md.alternate_count = utils.xlate_int(get("AlternateCount"))
md.description = utils.xlate(get("Summary"))
md.notes = utils.xlate(get("Notes"))
md.year = utils.xlate_int(get("Year"))
md.month = utils.xlate_int(get("Month"))
md.day = utils.xlate_int(get("Day"))
md.cover_date = Date(utils.xlate_int(get("Year")), utils.xlate_int(get("Month")), utils.xlate_int(get("Day")))
md.publisher = utils.xlate(get("Publisher"))
md.imprint = utils.xlate(get("Imprint"))
md.genres = utils.split(get("Genre"), ",")

View File

@ -20,6 +20,7 @@ possible, however lossy it might be
# limitations under the License.
from __future__ import annotations
import calendar
import copy
import dataclasses
import logging
@ -91,6 +92,62 @@ class TagOrigin(NamedTuple):
name: str
@dataclasses.dataclass
class Date:
year: int | None = None
month: int | None = None
day: int | None = None
month_name: str = dataclasses.field(init=False, repr=False, default="")
month_abbr: str = dataclasses.field(init=False, repr=False, default="")
@classmethod
def parse_date(cls, date_str: str | None) -> Date:
day = None
month = None
year = None
if date_str:
parts = date_str.split("-")
year = utils.xlate_int(parts[0])
if len(parts) > 1:
month = utils.xlate_int(parts[1])
if len(parts) > 2:
day = utils.xlate_int(parts[2])
return Date(year, month, day)
def __str__(self) -> str:
date_str = ""
if self.year is not None:
date_str = f"{self.year:04}"
if self.month is not None:
date_str += f"-{self.month:02}"
if self.day is not None:
date_str += f"-{self.day:02}"
return date_str
def copy(self) -> Date:
return copy.deepcopy(self)
def replace(self, /, **kwargs: Any) -> Date:
tmp = self.copy()
tmp.__dict__.update(kwargs)
return tmp
# We hijack the month property in order to update the month_name and month_abbr attributes
@property # type: ignore[no-redef]
def month(self) -> int: # noqa: F811
return self.__dict__["month"]
@month.setter
def month(self, month: int | None):
if month is None:
self.__dict__["month_name"] = ""
self.__dict__["month_abbr"] = ""
else:
self.__dict__["month_name"] = calendar.month_name[month]
self.__dict__["month_abbr"] = calendar.month_abbr[month]
self.__dict__["month"] = month
@dataclasses.dataclass
class GenericMetadata:
writer_synonyms = ["writer", "plotter", "scripter"]
@ -112,9 +169,8 @@ class GenericMetadata:
title: str | None = None
title_aliases: list[str] = dataclasses.field(default_factory=list)
publisher: str | None = None
month: int | None = None
year: int | None = None
day: int | None = None
cover_date: Date = Date(None, None, None)
store_date: Date = Date(None, None, None)
issue_count: int | None = None
volume: int | None = None
genres: list[str] = dataclasses.field(default_factory=list)
@ -172,6 +228,25 @@ class GenericMetadata:
tmp.__dict__.update(kwargs)
return tmp
def _assign(self, cur: str, new: Any) -> None:
if new is not None:
if isinstance(new, str) and not new:
setattr(self, cur, None)
elif isinstance(new, list) and len(new) == 0:
pass
elif isinstance(new, Date):
date = getattr(self, cur)
if date is None:
date = Date(None, None, None)
GenericMetadata._assign(date, "day", new.day)
GenericMetadata._assign(date, "month", new.month)
GenericMetadata._assign(date, "year", new.year)
else:
setattr(self, cur, new)
def overlay(self, new_md: GenericMetadata) -> None:
"""Overlay a metadata object on this one
@ -179,51 +254,41 @@ class GenericMetadata:
to this one.
"""
def assign(cur: str, new: Any) -> None:
if new is not None:
if isinstance(new, str) and len(new) == 0:
setattr(self, cur, None)
elif isinstance(new, list) and len(new) == 0:
pass
else:
setattr(self, cur, new)
if not new_md.is_empty:
self.is_empty = False
assign("series", new_md.series)
assign("series_id", new_md.series_id)
assign("issue", new_md.issue)
assign("issue_id", new_md.issue_id)
assign("issue_count", new_md.issue_count)
assign("title", new_md.title)
assign("publisher", new_md.publisher)
assign("day", new_md.day)
assign("month", new_md.month)
assign("year", new_md.year)
assign("volume", new_md.volume)
assign("volume_count", new_md.volume_count)
assign("language", new_md.language)
assign("country", new_md.country)
assign("critical_rating", new_md.critical_rating)
assign("alternate_series", new_md.alternate_series)
assign("alternate_number", new_md.alternate_number)
assign("alternate_count", new_md.alternate_count)
assign("imprint", new_md.imprint)
assign("web_link", new_md.web_link)
assign("format", new_md.format)
assign("manga", new_md.manga)
assign("black_and_white", new_md.black_and_white)
assign("maturity_rating", new_md.maturity_rating)
assign("scan_info", new_md.scan_info)
assign("description", new_md.description)
assign("notes", new_md.notes)
self._assign("series", new_md.series)
self._assign("series_id", new_md.series_id)
self._assign("issue", new_md.issue)
self._assign("issue_id", new_md.issue_id)
self._assign("issue_count", new_md.issue_count)
self._assign("title", new_md.title)
self._assign("publisher", new_md.publisher)
self._assign("cover_date", new_md.cover_date)
self._assign("store_date", new_md.store_date)
self._assign("volume", new_md.volume)
self._assign("volume_count", new_md.volume_count)
self._assign("language", new_md.language)
self._assign("country", new_md.country)
self._assign("critical_rating", new_md.critical_rating)
self._assign("alternate_series", new_md.alternate_series)
self._assign("alternate_number", new_md.alternate_number)
self._assign("alternate_count", new_md.alternate_count)
self._assign("imprint", new_md.imprint)
self._assign("web_link", new_md.web_link)
self._assign("format", new_md.format)
self._assign("manga", new_md.manga)
self._assign("black_and_white", new_md.black_and_white)
self._assign("maturity_rating", new_md.maturity_rating)
self._assign("scan_info", new_md.scan_info)
self._assign("description", new_md.description)
self._assign("notes", new_md.notes)
assign("price", new_md.price)
assign("is_version_of", new_md.is_version_of)
assign("rights", new_md.rights)
assign("identifier", new_md.identifier)
assign("last_mark", new_md.last_mark)
self._assign("price", new_md.price)
self._assign("is_version_of", new_md.is_version_of)
self._assign("rights", new_md.rights)
self._assign("identifier", new_md.identifier)
self._assign("last_mark", new_md.last_mark)
self.overlay_credits(new_md.credits)
# TODO
@ -233,16 +298,16 @@ class GenericMetadata:
# For now, go the easy route, where any overlay
# value wipes out the whole list
assign("series_aliases", new_md.series_aliases)
assign("title_aliases", new_md.title_aliases)
assign("genres", new_md.genres)
assign("story_arcs", new_md.story_arcs)
assign("series_groups", new_md.series_groups)
assign("characters", new_md.characters)
assign("teams", new_md.teams)
assign("locations", new_md.locations)
assign("tags", new_md.tags)
assign("pages", new_md.pages)
self._assign("series_aliases", new_md.series_aliases)
self._assign("title_aliases", new_md.title_aliases)
self._assign("genres", new_md.genres)
self._assign("story_arcs", new_md.story_arcs)
self._assign("series_groups", new_md.series_groups)
self._assign("characters", new_md.characters)
self._assign("teams", new_md.teams)
self._assign("locations", new_md.locations)
self._assign("tags", new_md.tags)
self._assign("pages", new_md.pages)
def overlay_credits(self, new_credits: list[Credit]) -> None:
for c in new_credits:
@ -412,9 +477,7 @@ md_test: GenericMetadata = GenericMetadata(
issue_id="140529",
title="Anda's Game",
publisher="IDW Publishing",
month=10,
year=2007,
day=1,
cover_date=Date(month=10, year=2007, day=1),
issue_count=6,
volume=1,
genres=["Sci-Fi"],

View File

@ -15,7 +15,6 @@
# limitations under the License.
from __future__ import annotations
import calendar
import logging
import os
import pathlib
@ -221,12 +220,8 @@ class FileRenamer:
for role in ["writer", "penciller", "inker", "colorist", "letterer", "cover artist", "editor"]:
md_dict[role] = md.get_primary_credit(role)
if (isinstance(md.month, int) or isinstance(md.month, str) and md.month.isdigit()) and 0 < int(md.month) < 13:
md_dict["month_name"] = calendar.month_name[int(md.month)]
md_dict["month_abbr"] = calendar.month_abbr[int(md.month)]
else:
md_dict["month_name"] = ""
md_dict["month_abbr"] = ""
date = getattr(md, "cover_date")
md_dict.update(vars(date))
new_basename = ""
for component in pathlib.PureWindowsPath(template).parts:

View File

@ -221,8 +221,8 @@ class IssueIdentifier:
search_keys = SearchKeys(
series=self.additional_metadata.series,
issue_number=self.additional_metadata.issue,
year=self.additional_metadata.year,
month=self.additional_metadata.month,
year=self.additional_metadata.cover_date.year,
month=self.additional_metadata.cover_date.month,
issue_count=self.additional_metadata.issue_count,
)
return search_keys
@ -257,8 +257,8 @@ class IssueIdentifier:
search_keys = SearchKeys(
series=working_md.series,
issue_number=working_md.issue,
year=working_md.year,
month=working_md.month,
year=working_md.cover_date.year,
month=working_md.cover_date.month,
issue_count=working_md.issue_count,
)
@ -525,8 +525,8 @@ class IssueIdentifier:
"issue_title": issue.title or "",
"issue_id": issue.issue_id or "",
"series_id": series.id,
"month": issue.month,
"year": issue.year,
"month": issue.cover_date.month,
"year": issue.cover_date.year,
"publisher": None,
"image_url": image_url,
"alt_image_urls": alt_urls,

View File

@ -165,10 +165,10 @@ class IssueSelectionWindow(QtWidgets.QDialog):
self.twList.setItem(row, 0, item)
item_text = ""
if issue.year is not None:
item_text = f"{issue.year:04}"
if issue.month is not None:
item_text = f"{issue.month:02}"
if issue.cover_date.year is not None:
item_text = f"{issue.cover_date.year:04}"
if issue.cover_date.month is not None:
item_text = f"{issue.cover_date.month:02}"
qtw_item = QtWidgets.QTableWidgetItem(item_text)
qtw_item.setData(QtCore.Qt.ItemDataRole.ToolTipRole, item_text)

View File

@ -245,7 +245,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
md = GenericMetadata()
md.series = self.series_name
md.issue = self.issue_number
md.year = self.year
md.cover_date.year = self.year
md.issue_count = self.issue_count
self.ii.set_additional_metadata(md)

View File

@ -794,9 +794,11 @@ class TaggerWindow(QtWidgets.QMainWindow):
assign_text(self.leVolumeCount, md.volume_count)
assign_text(self.leTitle, md.title)
assign_text(self.lePublisher, md.publisher)
assign_text(self.lePubMonth, md.month)
assign_text(self.lePubYear, md.year)
assign_text(self.lePubDay, md.day)
assign_text(self.lePubMonth, md.cover_date.month)
assign_text(self.lePubYear, md.cover_date.year)
assign_text(self.lePubDay, md.cover_date.day)
assign_text(self.leGenre, ",".join(md.genres))
assign_text(self.leImprint, md.imprint)
assign_text(self.teComments, md.description)
@ -908,9 +910,9 @@ class TaggerWindow(QtWidgets.QMainWindow):
md.issue_count = utils.xlate_int(self.leIssueCount.text())
md.volume = utils.xlate_int(self.leVolumeNum.text())
md.volume_count = utils.xlate_int(self.leVolumeCount.text())
md.month = utils.xlate_int(self.lePubMonth.text())
md.year = utils.xlate_int(self.lePubYear.text())
md.day = utils.xlate_int(self.lePubDay.text())
md.cover_date.month = utils.xlate_int(self.lePubMonth.text())
md.cover_date.year = utils.xlate_int(self.lePubYear.text())
md.cover_date.day = utils.xlate_int(self.lePubDay.text())
md.alternate_count = utils.xlate_int(self.leAltIssueCount.text())
md.series = utils.xlate(self.leSeries.text())
@ -1723,7 +1725,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
return False, match_results
if dlg.dont_use_year:
md.year = None
md.cover_date.year = None
if md.issue is None or md.issue == "":
if dlg.assume_issue_one:
md.issue = "1"

View File

@ -24,7 +24,7 @@ import sqlite3
from typing import Any, cast
from comicapi import utils
from comicapi.genericmetadata import ComicSeries, Credit, GenericMetadata, TagOrigin
from comicapi.genericmetadata import ComicSeries, Credit, Date, GenericMetadata, TagOrigin
logger = logging.getLogger(__name__)
@ -114,6 +114,7 @@ class ComicCacher:
+ "image_url TEXT,"
+ "thumb_url TEXT,"
+ "cover_date TEXT,"
+ "store_date TEXT,"
+ "site_detail_url TEXT,"
+ "description TEXT,"
+ "aliases TEXT," # Newline separated
@ -219,7 +220,8 @@ class ComicCacher:
"issue_number": issue.issue,
"volume": issue.volume,
"site_detail_url": issue.web_link,
"cover_date": f"{issue.year}-{issue.month}-{issue.day}",
"cover_date": str(issue.cover_date),
"store_date": str(issue.store_date),
"image_url": issue.cover_image,
"description": issue.description,
"timestamp": timestamp,
@ -436,7 +438,8 @@ class ComicCacher:
cover_image=row["image_url"],
credits=credits,
critical_rating=row["critical_rating"],
day=day,
cover_date=Date.parse_date(row["cover_date"]),
store_date=Date.parse_date(row["store_date"]),
description=row["description"],
genres=utils.split(row["genres"], "\n"),
issue=row["issue_number"],
@ -446,7 +449,6 @@ class ComicCacher:
locations=utils.split(row["locations"], "\n"),
manga=row["manga"],
maturity_rating=row["maturity_rating"],
month=month,
publisher=series.publisher,
series=series.name,
series_aliases=series.aliases,
@ -459,7 +461,6 @@ class ComicCacher:
volume=row["volume"],
volume_count=series.count_of_volumes,
web_link=row["site_detail_url"],
year=year,
),
row["complete"],
)

View File

@ -30,7 +30,7 @@ from pyrate_limiter import Limiter, RequestRate
from typing_extensions import Required, TypedDict
from comicapi import utils
from comicapi.genericmetadata import ComicSeries, GenericMetadata, TagOrigin
from comicapi.genericmetadata import ComicSeries, Date, GenericMetadata, TagOrigin
from comicapi.issuestring import IssueString
from comictalker import talker_utils
from comictalker.comiccacher import ComicCacher
@ -110,6 +110,7 @@ class CVIssue(TypedDict, total=False):
character_died_in: None
concept_credits: list[CVCredit]
cover_date: str
store_date: str
date_added: str
date_last_updated: str
deck: None
@ -129,7 +130,6 @@ class CVIssue(TypedDict, total=False):
object_credits: list[CVCredit]
person_credits: list[CVPersonCredit]
site_detail_url: str
store_date: str
story_arc_credits: list[CVCredit]
team_credits: list[CVCredit]
team_disbanded_in: None
@ -353,7 +353,7 @@ class ComicVineTalker(ComicTalker):
params: dict[str, str | int] = { # CV uses volume to mean series
"api_key": self.api_key,
"format": "json",
"field_list": "id,volume,issue_number,name,image,cover_date,site_detail_url,description,aliases,associated_images",
"field_list": "id,volume,issue_number,name,image,cover_date,store_date,site_detail_url,description,aliases,associated_images",
"filter": flt,
}
@ -605,6 +605,8 @@ class ComicVineTalker(ComicTalker):
web_link=utils.xlate(issue.get("site_detail_url")),
series=utils.xlate(series.name),
series_aliases=series.aliases,
cover_date=Date.parse_date(issue.get("cover_date", "")),
store_date=Date.parse_date(issue.get("store_date", "")),
)
if issue.get("image") is None:
md.cover_image = ""
@ -640,8 +642,8 @@ class ComicVineTalker(ComicTalker):
series = self._fetch_series_data(issue["volume"]["id"])
if issue.get("cover_date"):
md.day, md.month, md.year = utils.parse_date_str(issue.get("cover_date"))
md.cover_date.day, md.cover_date.month, md.cover_date.year = utils.parse_date_str(issue.get("cover_date"))
elif series.start_year:
md.year = utils.xlate_int(series.start_year)
md.cover_date.year = utils.xlate_int(series.start_year)
return md

View File

@ -173,9 +173,8 @@ date = utils.parse_date_str(cv_issue_result["results"]["cover_date"])
comic_issue_result = comicapi.genericmetadata.GenericMetadata(
tag_origin=comicapi.genericmetadata.TagOrigin("comicvine", "Comic Vine"),
title_aliases=cv_issue_result["results"]["aliases"] or [],
month=date[1],
year=date[2],
day=date[0],
cover_date=comicapi.genericmetadata.Date.parse_date(cv_issue_result["results"]["cover_date"]),
store_date=comicapi.genericmetadata.Date.parse_date(cv_issue_result["results"]["store_date"]),
description=cv_issue_result["results"]["description"],
publisher=cv_volume_result["results"]["publisher"]["name"],
issue_count=cv_volume_result["results"]["count_of_issues"],
@ -198,9 +197,7 @@ cv_md = comicapi.genericmetadata.GenericMetadata(
issue=cv_issue_result["results"]["issue_number"],
title=cv_issue_result["results"]["name"],
publisher=cv_volume_result["results"]["publisher"]["name"],
month=date[1],
year=date[2],
day=date[0],
cover_date=comicapi.genericmetadata.Date.parse_date(cv_issue_result["results"]["cover_date"]),
issue_count=cv_volume_result["results"]["count_of_issues"],
volume=None,
genres=[],

View File

@ -703,6 +703,20 @@ for p in names:
fnames.append(tuple(pp))
rnames = [
(
"{series} {month_name}",
False,
"universal",
"Cory Doctorow's Futuristic Tales of the Here and Now October.cbz",
does_not_raise(),
),
(
"{series} {month_abbr}",
False,
"universal",
"Cory Doctorow's Futuristic Tales of the Here and Now Oct.cbz",
does_not_raise(),
),
(
"{series!c} {price} {year}", # Capitalize
False,

View File

@ -145,8 +145,8 @@ def md():
@pytest.fixture
def md_saved():
yield comicapi.genericmetadata.md_test.replace(tag_origin=None, issue_id=None, series_id=None)
def md_saved(md):
yield md.replace(tag_origin=None, issue_id=None, series_id=None)
# manually seeds publishers

View File

@ -5,6 +5,9 @@ import io
import pytest
from PIL import Image
import comicapi.comicarchive
import comicapi.genericmetadata
import comicapi.issuestring
import comictaggerlib.issueidentifier
import testing.comicdata
import testing.comicvine
@ -60,8 +63,12 @@ def test_search(cbz, config, comicvine_api):
"issue_title": testing.comicvine.cv_issue_result["results"]["name"],
"issue_id": str(testing.comicvine.cv_issue_result["results"]["id"]),
"series_id": str(testing.comicvine.cv_volume_result["results"]["id"]),
"month": testing.comicvine.date[1],
"year": testing.comicvine.date[2],
"month": comicapi.genericmetadata.Date.parse_date(
testing.comicvine.cv_issue_result["results"]["cover_date"]
).month,
"year": comicapi.genericmetadata.Date.parse_date(
testing.comicvine.cv_issue_result["results"]["cover_date"]
).year,
"publisher": testing.comicvine.cv_volume_result["results"]["publisher"]["name"],
"image_url": testing.comicvine.cv_issue_result["results"]["image"]["super_url"],
"description": testing.comicvine.cv_issue_result["results"]["description"],

View File

@ -17,7 +17,7 @@ def test_cbi(md_saved):
string = CBI.string_from_metadata(comicapi.genericmetadata.md_test)
md = CBI.metadata_from_string(string)
md_test = md_saved.replace(
day=None,
cover_date=md_saved.cover_date.replace(day=None),
page_count=None,
maturity_rating=None,
story_arcs=[],
@ -44,7 +44,7 @@ def test_comet(md_saved):
string = CBI.string_from_metadata(comicapi.genericmetadata.md_test)
md = CBI.metadata_from_string(string)
md_test = md_saved.replace(
day=None,
cover_date=md_saved.cover_date.replace(day=None),
story_arcs=[],
series_groups=[],
scan_info=None,