Consolidate preparing metadata for save
This commit is contained in:
parent
996397b9d5
commit
a681abb854
@ -29,7 +29,7 @@ from comictaggerlib.ctsettings import ct_ns
|
||||
from comictaggerlib.resulttypes import IssueResult, Result
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.comictalker import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -240,8 +240,15 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
# now get the particular issue data
|
||||
self.current_match_set.md = ct_md = self.fetch_func(match)
|
||||
if ct_md is None:
|
||||
|
||||
try:
|
||||
self.current_match_set.md = ct_md = self.fetch_func(match)
|
||||
except TalkerError as e:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
QtWidgets.QMessageBox.critical(self, f"{e.source} {e.code_name} Error", f"{e}")
|
||||
return
|
||||
|
||||
if ct_md is None or ct_md.is_empty:
|
||||
QtWidgets.QMessageBox.critical(self, "Network Issue", "Could not retrieve issue details!")
|
||||
return
|
||||
|
||||
|
@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class CBLTransformer:
|
||||
def __init__(self, metadata: GenericMetadata, config: ct_ns) -> None:
|
||||
self.metadata = metadata
|
||||
self.metadata = metadata.copy()
|
||||
self.config = config
|
||||
|
||||
def apply(self) -> GenericMetadata:
|
||||
|
@ -24,22 +24,20 @@ import os
|
||||
import pathlib
|
||||
import sys
|
||||
from collections.abc import Collection
|
||||
from datetime import datetime
|
||||
from typing import Any, TextIO
|
||||
|
||||
from comicapi import utils
|
||||
from comicapi.comicarchive import ComicArchive
|
||||
from comicapi.comicarchive import metadata_styles as md_styles
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comictaggerlib import ctversion
|
||||
from comictaggerlib.cbltransformer import CBLTransformer
|
||||
from comictaggerlib.ctsettings import ct_ns
|
||||
from comictaggerlib.filerenamer import FileRenamer, get_rename_dir
|
||||
from comictaggerlib.graphics import graphics_path
|
||||
from comictaggerlib.issueidentifier import IssueIdentifier
|
||||
from comictaggerlib.md import prepare_metadata
|
||||
from comictaggerlib.resulttypes import Action, IssueResult, MatchStatus, OnlineMatchResults, Result, Status
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
from comictalker.talker_utils import cleanup_html
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -104,7 +102,8 @@ class CLI:
|
||||
self.batch_mode = len(self.config.Runtime_Options__files) > 1
|
||||
|
||||
for f in self.config.Runtime_Options__files:
|
||||
results.append(self.process_file_cli(self.config.Commands__command, f, match_results))
|
||||
res, match_results = self.process_file_cli(self.config.Commands__command, f, match_results)
|
||||
results.append(res)
|
||||
if results[-1].status != Status.success:
|
||||
return_code = 3
|
||||
if self.config.Runtime_Options__json:
|
||||
@ -180,19 +179,8 @@ class CLI:
|
||||
ca = ComicArchive(match_set.original_path)
|
||||
md = self.create_local_metadata(ca)
|
||||
ct_md = self.actual_issue_data_fetch(match_set.online_results[int(i) - 1].issue_id)
|
||||
if self.config.Issue_Identifier__clear_metadata:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.current_talker().name} on"
|
||||
f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {ct_md.issue_id}]"
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.config.Issue_Identifier__auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
match_set.md = md
|
||||
match_set.md = prepare_metadata(md, ct_md, self.config)
|
||||
|
||||
self.actual_metadata_save(ca, md)
|
||||
|
||||
@ -387,16 +375,19 @@ class CLI:
|
||||
res.status = status
|
||||
return res
|
||||
|
||||
def save(self, ca: ComicArchive, match_results: OnlineMatchResults) -> Result:
|
||||
def save(self, ca: ComicArchive, match_results: OnlineMatchResults) -> tuple[Result, OnlineMatchResults]:
|
||||
if not self.config.Runtime_Options__overwrite:
|
||||
for style in self.config.Runtime_Options__type:
|
||||
if ca.has_metadata(style):
|
||||
self.output(f"{ca.path}: Already has {md_styles[style].name()} tags. Not overwriting.")
|
||||
return Result(
|
||||
Action.save,
|
||||
original_path=ca.path,
|
||||
status=Status.existing_tags,
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
return (
|
||||
Result(
|
||||
Action.save,
|
||||
original_path=ca.path,
|
||||
status=Status.existing_tags,
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
),
|
||||
match_results,
|
||||
)
|
||||
|
||||
if self.batch_mode:
|
||||
@ -409,6 +400,8 @@ class CLI:
|
||||
|
||||
matches: list[IssueResult] = []
|
||||
# now, search online
|
||||
|
||||
ct_md = GenericMetadata()
|
||||
if self.config.Runtime_Options__online:
|
||||
if self.config.Runtime_Options__issue_id is not None:
|
||||
# we were given the actual issue ID to search with
|
||||
@ -423,9 +416,9 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.fetch_data_failures.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
if ct_md is None:
|
||||
if ct_md is None or ct_md.is_empty:
|
||||
logger.error("No match for ID %s was found.", self.config.Runtime_Options__issue_id)
|
||||
res = Result(
|
||||
Action.save,
|
||||
@ -435,10 +428,8 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.no_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
if self.config.Comic_Book_Lover__apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.config).apply()
|
||||
else:
|
||||
if md is None or md.is_empty:
|
||||
logger.error("No metadata given to search online with!")
|
||||
@ -450,7 +441,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.no_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
ii = IssueIdentifier(ca, self.config, self.current_talker())
|
||||
|
||||
@ -493,7 +484,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.low_confidence_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
logger.error("Online search: Multiple good matches. Save aborted")
|
||||
res = Result(
|
||||
@ -505,7 +496,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.multiple_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
if low_confidence and self.config.Runtime_Options__abort_on_low_confidence:
|
||||
logger.error("Online search: Low confidence match. Save aborted")
|
||||
res = Result(
|
||||
@ -517,7 +508,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.low_confidence_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
if not found_match:
|
||||
logger.error("Online search: No match found. Save aborted")
|
||||
res = Result(
|
||||
@ -529,7 +520,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.no_matches.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
# we got here, so we have a single match
|
||||
|
||||
@ -545,24 +536,7 @@ class CLI:
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
match_results.fetch_data_failures.append(res)
|
||||
return res
|
||||
|
||||
if self.config.Issue_Identifier__clear_metadata:
|
||||
md = GenericMetadata()
|
||||
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.current_talker().name} on"
|
||||
+ f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {ct_md.issue_id}]"
|
||||
)
|
||||
md.overlay(
|
||||
ct_md.replace(
|
||||
notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger"),
|
||||
description=cleanup_html(ct_md.description, self.config.Sources__remove_html_tables),
|
||||
)
|
||||
)
|
||||
|
||||
if self.config.Issue_Identifier__auto_imprint:
|
||||
md.fix_publisher()
|
||||
return res, match_results
|
||||
|
||||
res = Result(
|
||||
Action.save,
|
||||
@ -570,7 +544,7 @@ class CLI:
|
||||
original_path=ca.path,
|
||||
online_results=matches,
|
||||
match_status=MatchStatus.good_match,
|
||||
md=md,
|
||||
md=prepare_metadata(md, ct_md, self.config),
|
||||
tags_written=self.config.Runtime_Options__type,
|
||||
)
|
||||
# ok, done building our metadata. time to save
|
||||
@ -579,7 +553,7 @@ class CLI:
|
||||
else:
|
||||
res.status = Status.write_failure
|
||||
match_results.write_failures.append(res)
|
||||
return res
|
||||
return res, match_results
|
||||
|
||||
def rename(self, ca: ComicArchive) -> Result:
|
||||
original_path = ca.path
|
||||
@ -697,36 +671,38 @@ class CLI:
|
||||
|
||||
return Result(Action.export, Status.success, ca.path, new_file)
|
||||
|
||||
def process_file_cli(self, command: Action, filename: str, match_results: OnlineMatchResults) -> Result:
|
||||
def process_file_cli(
|
||||
self, command: Action, filename: str, match_results: OnlineMatchResults
|
||||
) -> tuple[Result, OnlineMatchResults]:
|
||||
if not os.path.lexists(filename):
|
||||
logger.error("Cannot find %s", filename)
|
||||
return Result(command, Status.read_failure, pathlib.Path(filename))
|
||||
return Result(command, Status.read_failure, pathlib.Path(filename)), match_results
|
||||
|
||||
ca = ComicArchive(filename, str(graphics_path / "nocover.png"))
|
||||
|
||||
if not ca.seems_to_be_a_comic_archive():
|
||||
logger.error("Sorry, but %s is not a comic archive!", filename)
|
||||
return Result(Action.rename, Status.read_failure, ca.path)
|
||||
return Result(Action.rename, Status.read_failure, ca.path), match_results
|
||||
|
||||
if not ca.is_writable() and (command in (Action.delete, Action.copy, Action.save, Action.rename)):
|
||||
logger.error("This archive is not writable")
|
||||
return Result(command, Status.write_permission_failure, ca.path)
|
||||
return Result(command, Status.write_permission_failure, ca.path), match_results
|
||||
|
||||
if command == Action.print:
|
||||
return self.print(ca)
|
||||
return self.print(ca), match_results
|
||||
|
||||
elif command == Action.delete:
|
||||
return self.delete(ca)
|
||||
return self.delete(ca), match_results
|
||||
|
||||
elif command == Action.copy is not None:
|
||||
return self.copy(ca)
|
||||
return self.copy(ca), match_results
|
||||
|
||||
elif command == Action.save:
|
||||
return self.save(ca, match_results)
|
||||
|
||||
elif command == Action.rename:
|
||||
return self.rename(ca)
|
||||
return self.rename(ca), match_results
|
||||
|
||||
elif command == Action.export:
|
||||
return self.export(ca)
|
||||
return Result(None, Status.read_failure, ca.path) # type: ignore[arg-type]
|
||||
return self.export(ca), match_results
|
||||
return Result(None, Status.read_failure, ca.path), match_results # type: ignore[arg-type]
|
||||
|
34
comictaggerlib/md.py
Normal file
34
comictaggerlib/md.py
Normal file
@ -0,0 +1,34 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from comicapi import utils
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comictaggerlib import ctversion
|
||||
from comictaggerlib.cbltransformer import CBLTransformer
|
||||
from comictaggerlib.ctsettings.settngs_namespace import SettngsNS
|
||||
from comictalker.talker_utils import cleanup_html
|
||||
|
||||
|
||||
def prepare_metadata(md: GenericMetadata, new_md: GenericMetadata, opts: SettngsNS) -> GenericMetadata:
|
||||
if opts.Comic_Book_Lover__apply_transform_on_import:
|
||||
new_md = CBLTransformer(new_md, opts).apply()
|
||||
|
||||
final_md = md.copy()
|
||||
if opts.Issue_Identifier__clear_metadata:
|
||||
final_md = GenericMetadata()
|
||||
|
||||
final_md.overlay(new_md)
|
||||
assert final_md.tag_origin
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {final_md.tag_origin.name} on"
|
||||
f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {final_md.issue_id}]"
|
||||
)
|
||||
final_md.replace(
|
||||
notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger"),
|
||||
description=cleanup_html(md.description, opts.Sources__remove_html_tables),
|
||||
)
|
||||
|
||||
if opts.Issue_Identifier__auto_imprint:
|
||||
md.fix_publisher()
|
||||
return final_md
|
@ -80,7 +80,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
if self.config[0].File_Rename__auto_extension:
|
||||
new_ext = ca.extension()
|
||||
|
||||
if md is None:
|
||||
if md is None or md.is_empty:
|
||||
md = ca.read_metadata(self.data_style)
|
||||
if md.is_empty:
|
||||
md = ca.metadata_from_filename(
|
||||
|
@ -25,8 +25,7 @@ import platform
|
||||
import re
|
||||
import sys
|
||||
import webbrowser
|
||||
from datetime import datetime
|
||||
from typing import Any, Callable
|
||||
from typing import Any, Callable, cast
|
||||
|
||||
import natsort
|
||||
import settngs
|
||||
@ -52,18 +51,18 @@ from comictaggerlib.fileselectionlist import FileSelectionList
|
||||
from comictaggerlib.graphics import graphics_path
|
||||
from comictaggerlib.issueidentifier import IssueIdentifier
|
||||
from comictaggerlib.logwindow import LogWindow
|
||||
from comictaggerlib.md import prepare_metadata
|
||||
from comictaggerlib.optionalmsgdialog import OptionalMessageDialog
|
||||
from comictaggerlib.pagebrowser import PageBrowserWindow
|
||||
from comictaggerlib.pagelisteditor import PageListEditor
|
||||
from comictaggerlib.renamewindow import RenameWindow
|
||||
from comictaggerlib.resulttypes import Action, IssueResult, MatchStatus, OnlineMatchResults, Result, Status
|
||||
from comictaggerlib.resulttypes import Action, MatchStatus, OnlineMatchResults, Result, Status
|
||||
from comictaggerlib.seriesselectionwindow import SeriesSelectionWindow
|
||||
from comictaggerlib.settingswindow import SettingsWindow
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import center_window_on_parent, enable_widget, reduce_widget_font_size
|
||||
from comictaggerlib.versionchecker import VersionChecker
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
from comictalker.talker_utils import cleanup_html
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -1148,33 +1147,18 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
except TalkerError as e:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
QtWidgets.QMessageBox.critical(self, f"{e.source} {e.code_name} Error", f"{e}")
|
||||
else:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
if new_metadata is not None:
|
||||
if self.config[0].Comic_Book_Lover__apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.config[0]).apply()
|
||||
return
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
if self.config[0].Issue_Identifier__clear_metadata:
|
||||
self.clear_form()
|
||||
if new_metadata is None or new_metadata.is_empty:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, "Search", f"Could not find an issue {selector.issue_number} for that series"
|
||||
)
|
||||
return
|
||||
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.current_talker().name} on"
|
||||
f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {new_metadata.issue_id}]"
|
||||
)
|
||||
self.metadata.overlay(
|
||||
new_metadata.replace(
|
||||
notes=utils.combine_notes(self.metadata.notes, notes, "Tagged with ComicTagger"),
|
||||
description=cleanup_html(
|
||||
new_metadata.description, self.config[0].Sources__remove_html_tables
|
||||
),
|
||||
)
|
||||
)
|
||||
# Now push the new combined data into the edit controls
|
||||
self.metadata_to_form()
|
||||
else:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, "Search", f"Could not find an issue {selector.issue_number} for that series"
|
||||
)
|
||||
self.metadata = prepare_metadata(self.metadata, new_metadata, self.config[0])
|
||||
# Now push the new combined data into the edit controls
|
||||
self.metadata_to_form()
|
||||
|
||||
def commit_metadata(self) -> None:
|
||||
if self.metadata is not None and self.comic_archive is not None:
|
||||
@ -1716,24 +1700,6 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
dlg.setWindowTitle("Tag Copy Summary")
|
||||
dlg.exec()
|
||||
|
||||
def actual_issue_data_fetch(self, match: IssueResult) -> GenericMetadata:
|
||||
# now get the particular issue data OR series data
|
||||
ct_md = GenericMetadata()
|
||||
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
|
||||
|
||||
try:
|
||||
ct_md = self.current_talker().fetch_comic_data(match.issue_id)
|
||||
except TalkerError:
|
||||
logger.exception("Save aborted.")
|
||||
|
||||
if not ct_md.is_empty:
|
||||
if self.config[0].Comic_Book_Lover__apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.config[0]).apply()
|
||||
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
return ct_md
|
||||
|
||||
def auto_tag_log(self, text: str) -> None:
|
||||
if self.atprogdialog is not None:
|
||||
self.atprogdialog.textEdit.append(text.rstrip())
|
||||
@ -1871,8 +1837,18 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
self.auto_tag_log("Online search: Low confidence match, but saving anyways, as indicated...\n")
|
||||
|
||||
# now get the particular issue data
|
||||
ct_md = self.actual_issue_data_fetch(matches[0])
|
||||
if ct_md is None:
|
||||
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
|
||||
|
||||
try:
|
||||
|
||||
ct_md = self.current_talker().fetch_comic_data(matches[0].issue_id)
|
||||
except TalkerError:
|
||||
logger.exception("Save aborted.")
|
||||
return False, match_results
|
||||
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
if ct_md is None or ct_md.is_empty:
|
||||
match_results.fetch_data_failures.append(
|
||||
Result(
|
||||
Action.save,
|
||||
@ -1884,17 +1860,11 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
)
|
||||
|
||||
if ct_md is not None:
|
||||
temp_opts = cast(ct_ns, settngs.get_namespace(self.config, True, True, True, False)[0])
|
||||
if dlg.cbxRemoveMetadata.isChecked():
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.current_talker().name} on"
|
||||
f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {ct_md.issue_id}]"
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
temp_opts.Issue_Identifier__clear_metadata
|
||||
|
||||
if self.config[0].Issue_Identifier__auto_imprint:
|
||||
md.fix_publisher()
|
||||
md = prepare_metadata(md, ct_md, temp_opts)
|
||||
|
||||
res = Result(
|
||||
Action.save,
|
||||
@ -2036,7 +2006,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
self,
|
||||
match_results.multiple_matches,
|
||||
styles,
|
||||
self.actual_issue_data_fetch,
|
||||
lambda match: self.current_talker().fetch_comic_data(match.issue_id),
|
||||
self.config[0],
|
||||
self.current_talker(),
|
||||
)
|
||||
|
@ -37,6 +37,8 @@ def cleanup_html(string: str | None, remove_html_tables: bool = False) -> str:
|
||||
"""Cleans HTML code from any text. Will remove any HTML tables with remove_html_tables"""
|
||||
if string is None:
|
||||
return ""
|
||||
if "<" not in string:
|
||||
return string
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
# find any tables
|
||||
|
Loading…
Reference in New Issue
Block a user