Use consistent naming for settings
config: always values setting: always the definition/description not the value
This commit is contained in:
parent
ba4b779145
commit
ad68726e1d
@ -40,19 +40,19 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
match_set_list: list[MultipleMatch],
|
||||
style: int,
|
||||
fetch_func: Callable[[IssueResult], GenericMetadata],
|
||||
options: settngs.Namespace,
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "matchselectionwindow.ui", self)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
|
||||
self.current_match_set: MultipleMatch = match_set_list[0]
|
||||
|
||||
self.altCoverWidget = CoverImageWidget(
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
@ -240,10 +240,10 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
md = ca.read_metadata(self._style)
|
||||
if md.is_empty:
|
||||
md = ca.metadata_from_filename(
|
||||
self.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
self.config.filename_complicated_parser,
|
||||
self.config.filename_remove_c2c,
|
||||
self.config.filename_remove_fcbd,
|
||||
self.config.filename_remove_publisher,
|
||||
)
|
||||
|
||||
# now get the particular issue data
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""A PyQT4 dialog to confirm and set options for auto-tag"""
|
||||
"""A PyQT4 dialog to confirm and set config for auto-tag"""
|
||||
#
|
||||
# Copyright 2012-2014 Anthony Beville
|
||||
#
|
||||
@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, options: settngs.Namespace, msg: str) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget, config: settngs.Namespace, msg: str) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "autotagstartwindow.ui", self)
|
||||
@ -36,20 +36,20 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
QtCore.Qt.WindowType(self.windowFlags() & ~QtCore.Qt.WindowType.WindowContextHelpButtonHint)
|
||||
)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
|
||||
self.cbxSpecifySearchString.setChecked(False)
|
||||
self.cbxSplitWords.setChecked(False)
|
||||
self.sbNameMatchSearchThresh.setValue(self.options.identifier_series_match_identify_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.config.identifier_series_match_identify_thresh)
|
||||
self.leSearchString.setEnabled(False)
|
||||
|
||||
self.cbxSaveOnLowConfidence.setChecked(self.options.autotag_save_on_low_confidence)
|
||||
self.cbxDontUseYear.setChecked(self.options.autotag_dont_use_year_when_identifying)
|
||||
self.cbxAssumeIssueOne.setChecked(self.options.autotag_assume_1_if_no_issue_num)
|
||||
self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.options.autotag_ignore_leading_numbers_in_filename)
|
||||
self.cbxRemoveAfterSuccess.setChecked(self.options.autotag_remove_archive_after_successful_match)
|
||||
self.cbxWaitForRateLimit.setChecked(self.options.autotag_wait_and_retry_on_rate_limit)
|
||||
self.cbxAutoImprint.setChecked(self.options.talkers_auto_imprint)
|
||||
self.cbxSaveOnLowConfidence.setChecked(self.config.autotag_save_on_low_confidence)
|
||||
self.cbxDontUseYear.setChecked(self.config.autotag_dont_use_year_when_identifying)
|
||||
self.cbxAssumeIssueOne.setChecked(self.config.autotag_assume_1_if_no_issue_num)
|
||||
self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.config.autotag_ignore_leading_numbers_in_filename)
|
||||
self.cbxRemoveAfterSuccess.setChecked(self.config.autotag_remove_archive_after_successful_match)
|
||||
self.cbxWaitForRateLimit.setChecked(self.config.autotag_wait_and_retry_on_rate_limit)
|
||||
self.cbxAutoImprint.setChecked(self.config.talkers_auto_imprint)
|
||||
|
||||
nlmt_tip = """<html>The <b>Name Match Ratio Threshold: Auto-Identify</b> is for eliminating automatic
|
||||
search matches that are too long compared to your series name search. The lower
|
||||
@ -75,7 +75,7 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
self.remove_after_success = False
|
||||
self.wait_and_retry_on_rate_limit = False
|
||||
self.search_string = ""
|
||||
self.name_length_match_tolerance = self.options.talkers_series_match_search_thresh
|
||||
self.name_length_match_tolerance = self.config.talkers_series_match_search_thresh
|
||||
self.split_words = self.cbxSplitWords.isChecked()
|
||||
|
||||
def search_string_toggle(self) -> None:
|
||||
@ -95,12 +95,12 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
self.split_words = self.cbxSplitWords.isChecked()
|
||||
|
||||
# persist some settings
|
||||
self.options.autotag_save_on_low_confidence = self.auto_save_on_low
|
||||
self.options.autotag_dont_use_year_when_identifying = self.dont_use_year
|
||||
self.options.autotag_assume_1_if_no_issue_num = self.assume_issue_one
|
||||
self.options.autotag_ignore_leading_numbers_in_filename = self.ignore_leading_digits_in_filename
|
||||
self.options.autotag_remove_archive_after_successful_match = self.remove_after_success
|
||||
self.options.autotag_wait_and_retry_on_rate_limit = self.wait_and_retry_on_rate_limit
|
||||
self.config.autotag_save_on_low_confidence = self.auto_save_on_low
|
||||
self.config.autotag_dont_use_year_when_identifying = self.dont_use_year
|
||||
self.config.autotag_assume_1_if_no_issue_num = self.assume_issue_one
|
||||
self.config.autotag_ignore_leading_numbers_in_filename = self.ignore_leading_digits_in_filename
|
||||
self.config.autotag_remove_archive_after_successful_match = self.remove_after_success
|
||||
self.config.autotag_wait_and_retry_on_rate_limit = self.wait_and_retry_on_rate_limit
|
||||
|
||||
if self.cbxSpecifySearchString.isChecked():
|
||||
self.search_string = self.leSearchString.text()
|
||||
|
@ -25,9 +25,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CBLTransformer:
|
||||
def __init__(self, metadata: GenericMetadata, options: settngs.Namespace) -> None:
|
||||
def __init__(self, metadata: GenericMetadata, config: settngs.Namespace) -> None:
|
||||
self.metadata = metadata
|
||||
self.options = options
|
||||
self.config = config
|
||||
|
||||
def apply(self) -> GenericMetadata:
|
||||
# helper funcs
|
||||
@ -41,7 +41,7 @@ class CBLTransformer:
|
||||
for item in items:
|
||||
append_to_tags_if_unique(item)
|
||||
|
||||
if self.options.cbl_assume_lone_credit_is_primary:
|
||||
if self.config.cbl_assume_lone_credit_is_primary:
|
||||
|
||||
# helper
|
||||
def set_lone_primary(role_list: list[str]) -> tuple[CreditMetadata | None, int]:
|
||||
@ -68,19 +68,19 @@ class CBLTransformer:
|
||||
c["primary"] = False
|
||||
self.metadata.add_credit(c["person"], "Artist", True)
|
||||
|
||||
if self.options.cbl_copy_characters_to_tags:
|
||||
if self.config.cbl_copy_characters_to_tags:
|
||||
add_string_list_to_tags(self.metadata.characters)
|
||||
|
||||
if self.options.cbl_copy_teams_to_tags:
|
||||
if self.config.cbl_copy_teams_to_tags:
|
||||
add_string_list_to_tags(self.metadata.teams)
|
||||
|
||||
if self.options.cbl_copy_locations_to_tags:
|
||||
if self.config.cbl_copy_locations_to_tags:
|
||||
add_string_list_to_tags(self.metadata.locations)
|
||||
|
||||
if self.options.cbl_copy_storyarcs_to_tags:
|
||||
if self.config.cbl_copy_storyarcs_to_tags:
|
||||
add_string_list_to_tags(self.metadata.story_arc)
|
||||
|
||||
if self.options.cbl_copy_notes_to_comments:
|
||||
if self.config.cbl_copy_notes_to_comments:
|
||||
if self.metadata.notes is not None:
|
||||
if self.metadata.comments is None:
|
||||
self.metadata.comments = ""
|
||||
@ -89,7 +89,7 @@ class CBLTransformer:
|
||||
if self.metadata.notes not in self.metadata.comments:
|
||||
self.metadata.comments += self.metadata.notes
|
||||
|
||||
if self.options.cbl_copy_weblink_to_comments:
|
||||
if self.config.cbl_copy_weblink_to_comments:
|
||||
if self.metadata.web_link is not None:
|
||||
if self.metadata.comments is None:
|
||||
self.metadata.comments = ""
|
||||
|
@ -40,8 +40,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CLI:
|
||||
def __init__(self, options: settngs.Values, talker_api: ComicTalker):
|
||||
self.options = options
|
||||
def __init__(self, config: settngs.Values, talker_api: ComicTalker):
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.batch_mode = False
|
||||
|
||||
@ -53,14 +53,14 @@ class CLI:
|
||||
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
||||
return GenericMetadata()
|
||||
|
||||
if self.options.cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options).apply()
|
||||
if self.config.cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.config).apply()
|
||||
|
||||
return ct_md
|
||||
|
||||
def actual_metadata_save(self, ca: ComicArchive, md: GenericMetadata) -> bool:
|
||||
if not self.options.runtime_dryrun:
|
||||
for metadata_style in self.options.runtime_type:
|
||||
if not self.config.runtime_dryrun:
|
||||
for metadata_style in self.config.runtime_type:
|
||||
# write out the new data
|
||||
if not ca.write_metadata(md, metadata_style):
|
||||
logger.error("The tag save seemed to fail for style: %s!", MetaDataStyle.name[metadata_style])
|
||||
@ -69,7 +69,7 @@ class CLI:
|
||||
print("Save complete.")
|
||||
logger.info("Save complete.")
|
||||
else:
|
||||
if self.options.runtime_quiet:
|
||||
if self.config.runtime_quiet:
|
||||
logger.info("dry-run option was set, so nothing was written")
|
||||
print("dry-run option was set, so nothing was written")
|
||||
else:
|
||||
@ -97,7 +97,7 @@ class CLI:
|
||||
m["issue_title"],
|
||||
)
|
||||
)
|
||||
if self.options.runtime_interactive:
|
||||
if self.config.runtime_interactive:
|
||||
while True:
|
||||
i = input("Choose a match #, or 's' to skip: ")
|
||||
if (i.isdigit() and int(i) in range(1, len(match_set.matches) + 1)) or i == "s":
|
||||
@ -108,7 +108,7 @@ class CLI:
|
||||
ca = match_set.ca
|
||||
md = self.create_local_metadata(ca)
|
||||
ct_md = self.actual_issue_data_fetch(match_set.matches[int(i) - 1]["issue_id"])
|
||||
if self.options.talkers_clear_metadata_on_import:
|
||||
if self.config.talkers_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -117,14 +117,14 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options.talkers_auto_imprint:
|
||||
if self.config.talkers_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
self.actual_metadata_save(ca, md)
|
||||
|
||||
def post_process_matches(self, match_results: OnlineMatchResults) -> None:
|
||||
# now go through the match results
|
||||
if self.options.runtime_summary:
|
||||
if self.config.runtime_summary:
|
||||
if len(match_results.good_matches) > 0:
|
||||
print("\nSuccessful matches:\n------------------")
|
||||
for f in match_results.good_matches:
|
||||
@ -145,7 +145,7 @@ class CLI:
|
||||
for f in match_results.fetch_data_failures:
|
||||
print(f)
|
||||
|
||||
if not self.options.runtime_summary and not self.options.runtime_interactive:
|
||||
if not self.config.runtime_summary and not self.config.runtime_interactive:
|
||||
# just quit if we're not interactive or showing the summary
|
||||
return
|
||||
|
||||
@ -165,14 +165,14 @@ class CLI:
|
||||
self.display_match_set_for_choice(label, match_set)
|
||||
|
||||
def run(self) -> None:
|
||||
if len(self.options.runtime_file_list) < 1:
|
||||
if len(self.config.runtime_file_list) < 1:
|
||||
logger.error("You must specify at least one filename. Use the -h option for more info")
|
||||
return
|
||||
|
||||
match_results = OnlineMatchResults()
|
||||
self.batch_mode = len(self.options.runtime_file_list) > 1
|
||||
self.batch_mode = len(self.config.runtime_file_list) > 1
|
||||
|
||||
for f in self.options.runtime_file_list:
|
||||
for f in self.config.runtime_file_list:
|
||||
self.process_file_cli(f, match_results)
|
||||
sys.stdout.flush()
|
||||
|
||||
@ -183,18 +183,18 @@ class CLI:
|
||||
md.set_default_page_list(ca.get_number_of_pages())
|
||||
|
||||
# now, overlay the parsed filename info
|
||||
if self.options.runtime_parse_filename:
|
||||
if self.config.runtime_parse_filename:
|
||||
f_md = ca.metadata_from_filename(
|
||||
self.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
self.options.runtime_split_words,
|
||||
self.config.filename_complicated_parser,
|
||||
self.config.filename_remove_c2c,
|
||||
self.config.filename_remove_fcbd,
|
||||
self.config.filename_remove_publisher,
|
||||
self.config.runtime_split_words,
|
||||
)
|
||||
|
||||
md.overlay(f_md)
|
||||
|
||||
for metadata_style in self.options.runtime_type:
|
||||
for metadata_style in self.config.runtime_type:
|
||||
if ca.has_metadata(metadata_style):
|
||||
try:
|
||||
t_md = ca.read_metadata(metadata_style)
|
||||
@ -204,12 +204,12 @@ class CLI:
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
# finally, use explicit stuff
|
||||
md.overlay(self.options.runtime_metadata)
|
||||
md.overlay(self.config.runtime_metadata)
|
||||
|
||||
return md
|
||||
|
||||
def print(self, ca: ComicArchive) -> None:
|
||||
if not self.options.runtime_type:
|
||||
if not self.config.runtime_type:
|
||||
page_count = ca.get_number_of_pages()
|
||||
|
||||
brief = ""
|
||||
@ -239,38 +239,38 @@ class CLI:
|
||||
|
||||
print(brief)
|
||||
|
||||
if self.options.runtime_quiet:
|
||||
if self.config.runtime_quiet:
|
||||
return
|
||||
|
||||
print()
|
||||
|
||||
if not self.options.runtime_type or MetaDataStyle.CIX in self.options.runtime_type:
|
||||
if not self.config.runtime_type or MetaDataStyle.CIX in self.config.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.CIX):
|
||||
print("--------- ComicRack tags ---------")
|
||||
try:
|
||||
if self.options.runtime_raw:
|
||||
if self.config.runtime_raw:
|
||||
print(ca.read_raw_cix())
|
||||
else:
|
||||
print(ca.read_cix())
|
||||
except Exception as e:
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
if not self.options.runtime_type or MetaDataStyle.CBI in self.options.runtime_type:
|
||||
if not self.config.runtime_type or MetaDataStyle.CBI in self.config.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.CBI):
|
||||
print("------- ComicBookLover tags -------")
|
||||
try:
|
||||
if self.options.runtime_raw:
|
||||
if self.config.runtime_raw:
|
||||
pprint(json.loads(ca.read_raw_cbi()))
|
||||
else:
|
||||
print(ca.read_cbi())
|
||||
except Exception as e:
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
if not self.options.runtime_type or MetaDataStyle.COMET in self.options.runtime_type:
|
||||
if not self.config.runtime_type or MetaDataStyle.COMET in self.config.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.COMET):
|
||||
print("----------- CoMet tags -----------")
|
||||
try:
|
||||
if self.options.runtime_raw:
|
||||
if self.config.runtime_raw:
|
||||
print(ca.read_raw_comet())
|
||||
else:
|
||||
print(ca.read_comet())
|
||||
@ -278,10 +278,10 @@ class CLI:
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
def delete(self, ca: ComicArchive) -> None:
|
||||
for metadata_style in self.options.runtime_type:
|
||||
for metadata_style in self.config.runtime_type:
|
||||
style_name = MetaDataStyle.name[metadata_style]
|
||||
if ca.has_metadata(metadata_style):
|
||||
if not self.options.runtime_dryrun:
|
||||
if not self.config.runtime_dryrun:
|
||||
if not ca.remove_metadata(metadata_style):
|
||||
print(f"{ca.path}: Tag removal seemed to fail!")
|
||||
else:
|
||||
@ -292,26 +292,26 @@ class CLI:
|
||||
print(f"{ca.path}: This archive doesn't have {style_name} tags to remove.")
|
||||
|
||||
def copy(self, ca: ComicArchive) -> None:
|
||||
for metadata_style in self.options.runtime_type:
|
||||
for metadata_style in self.config.runtime_type:
|
||||
dst_style_name = MetaDataStyle.name[metadata_style]
|
||||
if not self.options.runtime_overwrite and ca.has_metadata(metadata_style):
|
||||
if not self.config.runtime_overwrite and ca.has_metadata(metadata_style):
|
||||
print(f"{ca.path}: Already has {dst_style_name} tags. Not overwriting.")
|
||||
return
|
||||
if self.options.commands_copy == metadata_style:
|
||||
if self.config.commands_copy == metadata_style:
|
||||
print(f"{ca.path}: Destination and source are same: {dst_style_name}. Nothing to do.")
|
||||
return
|
||||
|
||||
src_style_name = MetaDataStyle.name[self.options.commands_copy]
|
||||
if ca.has_metadata(self.options.commands_copy):
|
||||
if not self.options.runtime_dryrun:
|
||||
src_style_name = MetaDataStyle.name[self.config.commands_copy]
|
||||
if ca.has_metadata(self.config.commands_copy):
|
||||
if not self.config.runtime_dryrun:
|
||||
try:
|
||||
md = ca.read_metadata(self.options.commands_copy)
|
||||
md = ca.read_metadata(self.config.commands_copy)
|
||||
except Exception as e:
|
||||
md = GenericMetadata()
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
if self.options.apply_transform_on_bulk_operation_ndetadata_style == MetaDataStyle.CBI:
|
||||
md = CBLTransformer(md, self.options).apply()
|
||||
if self.config.apply_transform_on_bulk_operation_ndetadata_style == MetaDataStyle.CBI:
|
||||
md = CBLTransformer(md, self.config).apply()
|
||||
|
||||
if not ca.write_metadata(md, metadata_style):
|
||||
print(f"{ca.path}: Tag copy seemed to fail!")
|
||||
@ -323,8 +323,8 @@ class CLI:
|
||||
print(f"{ca.path}: This archive doesn't have {src_style_name} tags to copy.")
|
||||
|
||||
def save(self, ca: ComicArchive, match_results: OnlineMatchResults) -> None:
|
||||
if not self.options.runtime_overwrite:
|
||||
for metadata_style in self.options.runtime_type:
|
||||
if not self.config.runtime_overwrite:
|
||||
for metadata_style in self.config.runtime_type:
|
||||
if ca.has_metadata(metadata_style):
|
||||
print(f"{ca.path}: Already has {MetaDataStyle.name[metadata_style]} tags. Not overwriting.")
|
||||
return
|
||||
@ -334,37 +334,37 @@ class CLI:
|
||||
|
||||
md = self.create_local_metadata(ca)
|
||||
if md.issue is None or md.issue == "":
|
||||
if self.options.runtime_assume_issue_one:
|
||||
if self.config.runtime_assume_issue_one:
|
||||
md.issue = "1"
|
||||
|
||||
# now, search online
|
||||
if self.options.runtime_online:
|
||||
if self.options.runtime_issue_id is not None:
|
||||
if self.config.runtime_online:
|
||||
if self.config.runtime_issue_id is not None:
|
||||
# we were given the actual issue ID to search with
|
||||
try:
|
||||
ct_md = self.talker_api.fetch_comic_data(self.options.runtime_issue_id)
|
||||
ct_md = self.talker_api.fetch_comic_data(self.config.runtime_issue_id)
|
||||
except TalkerError as e:
|
||||
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if ct_md is None:
|
||||
logger.error("No match for ID %s was found.", self.options.runtime_issue_id)
|
||||
logger.error("No match for ID %s was found.", self.config.runtime_issue_id)
|
||||
match_results.no_matches.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.options.cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options).apply()
|
||||
if self.config.cbl_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!")
|
||||
match_results.no_matches.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
ii = IssueIdentifier(ca, self.options, self.talker_api)
|
||||
ii = IssueIdentifier(ca, self.config, self.talker_api)
|
||||
|
||||
def myoutput(text: str) -> None:
|
||||
if self.options.runtime_verbose:
|
||||
if self.config.runtime_verbose:
|
||||
IssueIdentifier.default_write_output(text)
|
||||
|
||||
# use our overlaid MD struct to search
|
||||
@ -404,7 +404,7 @@ class CLI:
|
||||
logger.error("Online search: Multiple good matches. Save aborted")
|
||||
match_results.multiple_matches.append(MultipleMatch(ca, matches))
|
||||
return
|
||||
if low_confidence and self.options.runtime_abort_on_low_confidence:
|
||||
if low_confidence and self.config.runtime_abort_on_low_confidence:
|
||||
logger.error("Online search: Low confidence match. Save aborted")
|
||||
match_results.low_confidence_matches.append(MultipleMatch(ca, matches))
|
||||
return
|
||||
@ -421,7 +421,7 @@ class CLI:
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.options.talkers_clear_metadata_on_import:
|
||||
if self.config.talkers_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -430,7 +430,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options.talkers_auto_imprint:
|
||||
if self.config.talkers_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
# ok, done building our metadata. time to save
|
||||
@ -452,18 +452,18 @@ class CLI:
|
||||
return
|
||||
|
||||
new_ext = "" # default
|
||||
if self.options.filename_rename_set_extension_based_on_archive:
|
||||
if self.config.filename_rename_set_extension_based_on_archive:
|
||||
new_ext = ca.extension()
|
||||
|
||||
renamer = FileRenamer(
|
||||
md,
|
||||
platform="universal" if self.options.filename_rename_strict else "auto",
|
||||
replacements=self.options.rename_replacements,
|
||||
platform="universal" if self.config.filename_rename_strict else "auto",
|
||||
replacements=self.config.rename_replacements,
|
||||
)
|
||||
renamer.set_template(self.options.filename_rename_template)
|
||||
renamer.set_issue_zero_padding(self.options.filename_rename_issue_number_padding)
|
||||
renamer.set_smart_cleanup(self.options.filename_rename_use_smart_string_cleanup)
|
||||
renamer.move = self.options.filename_rename_move_to_dir
|
||||
renamer.set_template(self.config.filename_rename_template)
|
||||
renamer.set_issue_zero_padding(self.config.filename_rename_issue_number_padding)
|
||||
renamer.set_smart_cleanup(self.config.filename_rename_use_smart_string_cleanup)
|
||||
renamer.move = self.config.filename_rename_move_to_dir
|
||||
|
||||
try:
|
||||
new_name = renamer.determine_name(ext=new_ext)
|
||||
@ -475,16 +475,16 @@ class CLI:
|
||||
"Please consult the template help in the settings "
|
||||
"and the documentation on the format at "
|
||||
"https://docs.python.org/3/library/string.html#format-string-syntax",
|
||||
self.options.filename_rename_template,
|
||||
self.config.filename_rename_template,
|
||||
)
|
||||
return
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Formatter failure: %s metadata: %s", self.options.filename_rename_template, renamer.metadata
|
||||
"Formatter failure: %s metadata: %s", self.config.filename_rename_template, renamer.metadata
|
||||
)
|
||||
|
||||
folder = get_rename_dir(
|
||||
ca, self.options.filename_rename_dir if self.options.filename_rename_move_to_dir else None
|
||||
ca, self.config.filename_rename_dir if self.config.filename_rename_move_to_dir else None
|
||||
)
|
||||
|
||||
full_path = folder / new_name
|
||||
@ -494,7 +494,7 @@ class CLI:
|
||||
return
|
||||
|
||||
suffix = ""
|
||||
if not self.options.runtime_dryrun:
|
||||
if not self.config.runtime_dryrun:
|
||||
# rename the file
|
||||
try:
|
||||
ca.rename(utils.unique_file(full_path))
|
||||
@ -517,7 +517,7 @@ class CLI:
|
||||
filename_path = ca.path
|
||||
new_file = filename_path.with_suffix(".cbz")
|
||||
|
||||
if self.options.runtime_abort_on_conflict and new_file.exists():
|
||||
if self.config.runtime_abort_on_conflict and new_file.exists():
|
||||
print(msg_hdr + f"{new_file.name} already exists in the that folder.")
|
||||
return
|
||||
|
||||
@ -525,10 +525,10 @@ class CLI:
|
||||
|
||||
delete_success = False
|
||||
export_success = False
|
||||
if not self.options.runtime_dryrun:
|
||||
if not self.config.runtime_dryrun:
|
||||
if ca.export_as_zip(new_file):
|
||||
export_success = True
|
||||
if self.options.runtime_delete_after_zip_export:
|
||||
if self.config.runtime_delete_after_zip_export:
|
||||
try:
|
||||
filename_path.unlink(missing_ok=True)
|
||||
delete_success = True
|
||||
@ -540,7 +540,7 @@ class CLI:
|
||||
new_file.unlink(missing_ok=True)
|
||||
else:
|
||||
msg = msg_hdr + f"Dry-run: Would try to create {os.path.split(new_file)[1]}"
|
||||
if self.options.runtime_delete_after_zip_export:
|
||||
if self.config.runtime_delete_after_zip_export:
|
||||
msg += " and delete original."
|
||||
print(msg)
|
||||
return
|
||||
@ -548,7 +548,7 @@ class CLI:
|
||||
msg = msg_hdr
|
||||
if export_success:
|
||||
msg += f"Archive exported successfully to: {os.path.split(new_file)[1]}"
|
||||
if self.options.runtime_delete_after_zip_export and delete_success:
|
||||
if self.config.runtime_delete_after_zip_export and delete_success:
|
||||
msg += " (Original deleted) "
|
||||
else:
|
||||
msg += "Archive failed to export!"
|
||||
@ -567,28 +567,28 @@ class CLI:
|
||||
return
|
||||
|
||||
if not ca.is_writable() and (
|
||||
self.options.commands_delete
|
||||
or self.options.commands_copy
|
||||
or self.options.commands_save
|
||||
or self.options.commands_rename
|
||||
self.config.commands_delete
|
||||
or self.config.commands_copy
|
||||
or self.config.commands_save
|
||||
or self.config.commands_rename
|
||||
):
|
||||
logger.error("This archive is not writable")
|
||||
return
|
||||
|
||||
if self.options.commands_print:
|
||||
if self.config.commands_print:
|
||||
self.print(ca)
|
||||
|
||||
elif self.options.commands_delete:
|
||||
elif self.config.commands_delete:
|
||||
self.delete(ca)
|
||||
|
||||
elif self.options.commands_copy is not None:
|
||||
elif self.config.commands_copy is not None:
|
||||
self.copy(ca)
|
||||
|
||||
elif self.options.commands_save:
|
||||
elif self.config.commands_save:
|
||||
self.save(ca, match_results)
|
||||
|
||||
elif self.options.commands_rename:
|
||||
elif self.config.commands_rename:
|
||||
self.rename(ca)
|
||||
|
||||
elif self.options.commands_export_to_zip:
|
||||
elif self.config.commands_export_to_zip:
|
||||
self.export(ca)
|
||||
|
@ -1,21 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from comictaggerlib.ctoptions.cmdline import initial_cmd_line_parser, register_commandline, validate_commandline_options
|
||||
from comictaggerlib.ctoptions.file import register_settings, validate_settings
|
||||
from comictaggerlib.ctoptions.plugin import register_plugin_settings, validate_plugin_settings
|
||||
from comictaggerlib.ctoptions.types import ComicTaggerPaths
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
|
||||
talker_plugins: dict[str, ComicTalker] = {}
|
||||
|
||||
__all__ = [
|
||||
"initial_cmd_line_parser",
|
||||
"register_commandline",
|
||||
"register_settings",
|
||||
"register_plugin_settings",
|
||||
"register_talker_settings",
|
||||
"validate_commandline_options",
|
||||
"validate_settings",
|
||||
"validate_plugin_settings",
|
||||
"ComicTaggerPaths",
|
||||
]
|
24
comictaggerlib/ctsettings/__init__.py
Normal file
24
comictaggerlib/ctsettings/__init__.py
Normal file
@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from comictaggerlib.ctsettings.commandline import (
|
||||
initial_commandline_parser,
|
||||
register_commandline_settings,
|
||||
validate_commandline_settings,
|
||||
)
|
||||
from comictaggerlib.ctsettings.file import register_file_settings, validate_file_settings
|
||||
from comictaggerlib.ctsettings.plugin import register_plugin_settings, validate_plugin_settings
|
||||
from comictaggerlib.ctsettings.types import ComicTaggerPaths
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
|
||||
talkers: dict[str, ComicTalker] = {}
|
||||
|
||||
__all__ = [
|
||||
"initial_commandline_parser",
|
||||
"register_commandline_settings",
|
||||
"register_file_settings",
|
||||
"register_plugin_settings",
|
||||
"validate_commandline_settings",
|
||||
"validate_file_settings",
|
||||
"validate_plugin_settings",
|
||||
"ComicTaggerPaths",
|
||||
]
|
@ -1,4 +1,4 @@
|
||||
"""CLI options class for ComicTagger app"""
|
||||
"""CLI settings for ComicTagger"""
|
||||
#
|
||||
# Copyright 2012-2014 Anthony Beville
|
||||
#
|
||||
@ -25,14 +25,14 @@ import settngs
|
||||
from comicapi import utils
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comictaggerlib import ctversion
|
||||
from comictaggerlib.ctoptions.types import ComicTaggerPaths, metadata_type, parse_metadata_from_string
|
||||
from comictaggerlib.ctsettings.types import ComicTaggerPaths, metadata_type, parse_metadata_from_string
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def initial_cmd_line_parser() -> argparse.ArgumentParser:
|
||||
def initial_commandline_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
# Ensure this stays up to date with register_options
|
||||
# Ensure this stays up to date with register_settings
|
||||
parser.add_argument(
|
||||
"--config",
|
||||
help="Config directory defaults to ~/.ComicTagger\non Linux/Mac and %%APPDATA%% on Windows\n",
|
||||
@ -49,7 +49,7 @@ def initial_cmd_line_parser() -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def register_options(parser: settngs.Manager) -> None:
|
||||
def register_settings(parser: settngs.Manager) -> None:
|
||||
parser.add_setting(
|
||||
"--config",
|
||||
help="Config directory defaults to ~/.Config/ComicTagger\non Linux, ~/Library/Application Support/ComicTagger on Mac and %%APPDATA%%\\ComicTagger on Windows\n",
|
||||
@ -262,68 +262,61 @@ def register_commands(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def register_commandline(parser: settngs.Manager) -> None:
|
||||
def register_commandline_settings(parser: settngs.Manager) -> None:
|
||||
parser.add_group("commands", register_commands, True)
|
||||
parser.add_group("runtime", register_options)
|
||||
parser.add_group("runtime", register_settings)
|
||||
|
||||
|
||||
def validate_commandline_options(options: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values:
|
||||
def validate_commandline_settings(config: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values:
|
||||
|
||||
if options[0].commands_version:
|
||||
if config[0].commands_version:
|
||||
parser.exit(
|
||||
status=1,
|
||||
message=f"ComicTagger {ctversion.version}: Copyright (c) 2012-2022 ComicTagger Team\n"
|
||||
"Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n",
|
||||
)
|
||||
|
||||
options[0].runtime_no_gui = any(
|
||||
config[0].runtime_no_gui = any(
|
||||
[
|
||||
options[0].commands_print,
|
||||
options[0].commands_delete,
|
||||
options[0].commands_save,
|
||||
options[0].commands_copy,
|
||||
options[0].commands_rename,
|
||||
options[0].commands_export_to_zip,
|
||||
options[0].commands_only_set_cv_key,
|
||||
config[0].commands_print,
|
||||
config[0].commands_delete,
|
||||
config[0].commands_save,
|
||||
config[0].commands_copy,
|
||||
config[0].commands_rename,
|
||||
config[0].commands_export_to_zip,
|
||||
config[0].commands_only_set_cv_key,
|
||||
]
|
||||
)
|
||||
|
||||
if platform.system() == "Windows" and options[0].runtime_glob:
|
||||
if platform.system() == "Windows" and config[0].runtime_glob:
|
||||
# no globbing on windows shell, so do it for them
|
||||
import glob
|
||||
|
||||
globs = options[0].runtime_files
|
||||
options[0].runtime_files = []
|
||||
globs = config[0].runtime_files
|
||||
config[0].runtime_files = []
|
||||
for item in globs:
|
||||
options[0].runtime_files.extend(glob.glob(item))
|
||||
config[0].runtime_files.extend(glob.glob(item))
|
||||
|
||||
if (
|
||||
options[0].commands_only_set_cv_key
|
||||
and options[0].talker_comicvine_cv_api_key is None
|
||||
and options[0].talker_comicvine_cv_url is None
|
||||
):
|
||||
parser.exit(message="Key not given!\n", status=1)
|
||||
|
||||
if not options[0].commands_only_set_cv_key and options[0].runtime_no_gui and not options[0].runtime_files:
|
||||
if not config[0].commands_only_set_cv_key and config[0].runtime_no_gui and not config[0].runtime_files:
|
||||
parser.exit(message="Command requires at least one filename!\n", status=1)
|
||||
|
||||
if options[0].commands_delete and not options[0].runtime_type:
|
||||
if config[0].commands_delete and not config[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to delete with -t\n", status=1)
|
||||
|
||||
if options[0].commands_save and not options[0].runtime_type:
|
||||
if config[0].commands_save and not config[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to save with -t\n", status=1)
|
||||
|
||||
if options[0].commands_copy:
|
||||
if not options[0].runtime_type:
|
||||
if config[0].commands_copy:
|
||||
if not config[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to copy to with -t\n", status=1)
|
||||
if len(options[0].commands_copy) > 1:
|
||||
if len(config[0].commands_copy) > 1:
|
||||
parser.exit(message="Please specify only one type to copy to with -c\n", status=1)
|
||||
options[0].commands_copy = options[0].commands_copy[0]
|
||||
config[0].commands_copy = config[0].commands_copy[0]
|
||||
|
||||
if options[0].runtime_recursive:
|
||||
options[0].runtime_file_list = utils.get_recursive_filelist(options[0].runtime_files)
|
||||
if config[0].runtime_recursive:
|
||||
config[0].runtime_file_list = utils.get_recursive_filelist(config[0].runtime_files)
|
||||
else:
|
||||
options[0].runtime_file_list = options[0].runtime_files
|
||||
config[0].runtime_file_list = config[0].runtime_files
|
||||
|
||||
# take a crack at finding rar exe if it's not in the path
|
||||
if not utils.which("rar"):
|
||||
@ -337,4 +330,4 @@ def validate_commandline_options(options: settngs.Config[settngs.Values], parser
|
||||
if os.path.exists("/opt/homebrew/bin"):
|
||||
utils.add_to_path("/opt/homebrew/bin")
|
||||
|
||||
return options
|
||||
return config
|
@ -6,7 +6,7 @@ from typing import Any
|
||||
|
||||
import settngs
|
||||
|
||||
from comictaggerlib.ctoptions.types import AppendAction
|
||||
from comictaggerlib.ctsettings.types import AppendAction
|
||||
from comictaggerlib.defaults import DEFAULT_REPLACEMENTS, Replacement, Replacements
|
||||
|
||||
|
||||
@ -225,16 +225,16 @@ def autotag(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_settings(options: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]:
|
||||
options[0].identifier_publisher_filter = [x.strip() for x in options[0].identifier_publisher_filter if x.strip()]
|
||||
options[0].rename_replacements = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in options[0].rename_replacements[0]],
|
||||
[Replacement(x[0], x[1], x[2]) for x in options[0].rename_replacements[1]],
|
||||
def validate_file_settings(config: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]:
|
||||
config[0].identifier_publisher_filter = [x.strip() for x in config[0].identifier_publisher_filter if x.strip()]
|
||||
config[0].rename_replacements = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in config[0].rename_replacements[0]],
|
||||
[Replacement(x[0], x[1], x[2]) for x in config[0].rename_replacements[1]],
|
||||
)
|
||||
return options
|
||||
return config
|
||||
|
||||
|
||||
def register_settings(parser: settngs.Manager) -> None:
|
||||
def register_file_settings(parser: settngs.Manager) -> None:
|
||||
parser.add_group("general", general, False)
|
||||
parser.add_group("internal", internal, False)
|
||||
parser.add_group("identifier", identifier, False)
|
@ -6,7 +6,7 @@ import os
|
||||
import settngs
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comictaggerlib.ctoptions
|
||||
import comictaggerlib.ctsettings
|
||||
|
||||
logger = logging.getLogger("comictagger")
|
||||
|
||||
@ -24,17 +24,17 @@ def archiver(manager: settngs.Manager) -> None:
|
||||
|
||||
|
||||
def register_talker_settings(manager: settngs.Manager) -> None:
|
||||
for talker_name, talker in comictaggerlib.ctoptions.talker_plugins.items():
|
||||
for talker_name, talker in comictaggerlib.ctsettings.talkers.items():
|
||||
try:
|
||||
manager.add_persistent_group("talker_" + talker_name, talker.register_settings, False)
|
||||
except Exception:
|
||||
logger.exception("Failed to register settings for %s", talker_name)
|
||||
|
||||
|
||||
def validate_archive_settings(options: settngs.Config) -> settngs.Config:
|
||||
if "archiver" not in options[1]:
|
||||
return options
|
||||
cfg = settngs.normalize_config(options, file=True, cmdline=True, defaults=False)
|
||||
def validate_archive_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]:
|
||||
if "archiver" not in config[1]:
|
||||
return config
|
||||
cfg = settngs.normalize_config(config, file=True, cmdline=True, defaults=False)
|
||||
for archiver in comicapi.comicarchive.archivers:
|
||||
exe_name = settngs.sanitize_name(archiver.exe)
|
||||
if (
|
||||
@ -47,28 +47,29 @@ def validate_archive_settings(options: settngs.Config) -> settngs.Config:
|
||||
else:
|
||||
archiver.exe = cfg[0]["archiver"][exe_name]
|
||||
|
||||
return options
|
||||
return config
|
||||
|
||||
|
||||
def validate_talker_settings(options: settngs.Config) -> settngs.Config:
|
||||
def validate_talker_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]:
|
||||
# Apply talker settings from config file
|
||||
for talker_name, talker in list(comictaggerlib.ctoptions.talker_plugins.items()):
|
||||
cfg = settngs.normalize_config(config, True, True)
|
||||
for talker_name, talker in list(comictaggerlib.ctsettings.talkers.items()):
|
||||
try:
|
||||
talker.parse_settings(options[0]["talker_" + talker_name])
|
||||
talker.parse_settings(cfg[0]["talker_" + talker_name])
|
||||
except Exception as e:
|
||||
# Remove talker as we failed to apply the settings
|
||||
del comictaggerlib.ctoptions.talker_plugins[talker_name]
|
||||
del comictaggerlib.ctsettings.talkers[talker_name]
|
||||
logger.exception("Failed to initialize talker settings: %s", e)
|
||||
|
||||
return options
|
||||
return config
|
||||
|
||||
|
||||
def validate_plugin_settings(options: settngs.Config) -> settngs.Config:
|
||||
options = validate_archive_settings(options)
|
||||
options = validate_talker_settings(options)
|
||||
return options
|
||||
def validate_plugin_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]:
|
||||
config = validate_archive_settings(config)
|
||||
config = validate_talker_settings(config)
|
||||
return config
|
||||
|
||||
|
||||
def register_plugin_settings(manager: settngs.Manager):
|
||||
def register_plugin_settings(manager: settngs.Manager) -> None:
|
||||
manager.add_persistent_group("archiver", archiver, False)
|
||||
register_talker_settings(manager)
|
@ -57,13 +57,13 @@ class FileSelectionList(QtWidgets.QWidget):
|
||||
dataColNum = fileColNum
|
||||
|
||||
def __init__(
|
||||
self, parent: QtWidgets.QWidget, options: settngs.Namespace, dirty_flag_verification: Callable[[str, str], bool]
|
||||
self, parent: QtWidgets.QWidget, config: settngs.Namespace, dirty_flag_verification: Callable[[str, str], bool]
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "fileselectionlist.ui", self)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
|
||||
reduce_widget_font_size(self.twList)
|
||||
|
||||
|
@ -83,11 +83,11 @@ except ImportError as e:
|
||||
|
||||
|
||||
def open_tagger_window(
|
||||
talker_api: ComicTalker, options: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None
|
||||
talker_api: ComicTalker | None, config: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None
|
||||
) -> None:
|
||||
os.environ["QtWidgets.QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
|
||||
args = []
|
||||
if options[0].runtime_darkmode:
|
||||
if config[0].runtime_darkmode:
|
||||
args.extend(["-platform", "windows:darkmode=2"])
|
||||
args.extend(sys.argv)
|
||||
app = Application(args)
|
||||
@ -96,8 +96,10 @@ def open_tagger_window(
|
||||
if error[1]:
|
||||
raise SystemExit(1)
|
||||
|
||||
assert talker_api is not None
|
||||
|
||||
# needed to catch initial open file events (macOS)
|
||||
app.openFileRequest.connect(lambda x: options[0].runtime_files.append(x.toLocalFile()))
|
||||
app.openFileRequest.connect(lambda x: config[0].runtime_files.append(x.toLocalFile()))
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
# Set the MacOS dock icon
|
||||
@ -125,7 +127,7 @@ def open_tagger_window(
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
try:
|
||||
tagger_window = TaggerWindow(options[0].runtime_files, options, talker_api)
|
||||
tagger_window = TaggerWindow(config[0].runtime_files, config, talker_api)
|
||||
tagger_window.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png")))
|
||||
tagger_window.show()
|
||||
|
||||
|
@ -72,8 +72,8 @@ class IssueIdentifier:
|
||||
result_one_good_match = 4
|
||||
result_multiple_good_matches = 5
|
||||
|
||||
def __init__(self, comic_archive: ComicArchive, options: settngs.Namespace, talker_api: ComicTalker) -> None:
|
||||
self.options = options
|
||||
def __init__(self, comic_archive: ComicArchive, config: settngs.Namespace, talker_api: ComicTalker) -> None:
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.comic_archive: ComicArchive = comic_archive
|
||||
self.image_hasher = 1
|
||||
@ -96,10 +96,10 @@ class IssueIdentifier:
|
||||
|
||||
# used to eliminate series names that are too long based on our search
|
||||
# string
|
||||
self.series_match_thresh = options.identifier_series_match_identify_thresh
|
||||
self.series_match_thresh = config.identifier_series_match_identify_thresh
|
||||
|
||||
# used to eliminate unlikely publishers
|
||||
self.publisher_filter = [s.strip().casefold() for s in options.identifier_publisher_filter]
|
||||
self.publisher_filter = [s.strip().casefold() for s in config.identifier_publisher_filter]
|
||||
|
||||
self.additional_metadata = GenericMetadata()
|
||||
self.output_function: Callable[[str], None] = IssueIdentifier.default_write_output
|
||||
@ -241,10 +241,10 @@ class IssueIdentifier:
|
||||
|
||||
# try to get some metadata from filename
|
||||
md_from_filename = ca.metadata_from_filename(
|
||||
self.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
self.config.filename_complicated_parser,
|
||||
self.config.filename_remove_c2c,
|
||||
self.config.filename_remove_fcbd,
|
||||
self.config.filename_remove_publisher,
|
||||
)
|
||||
|
||||
working_md = md_from_filename.copy()
|
||||
@ -294,7 +294,7 @@ class IssueIdentifier:
|
||||
return Score(score=0, url="", hash=0)
|
||||
|
||||
try:
|
||||
url_image_data = ImageFetcher(self.options.runtime_config.user_cache_dir).fetch(
|
||||
url_image_data = ImageFetcher(self.config.runtime_config.user_cache_dir).fetch(
|
||||
primary_img_url, blocking=True
|
||||
)
|
||||
except ImageFetcherException as e:
|
||||
@ -316,7 +316,7 @@ class IssueIdentifier:
|
||||
if use_remote_alternates:
|
||||
for alt_url in alt_urls:
|
||||
try:
|
||||
alt_url_image_data = ImageFetcher(self.options.runtime_config.user_cache_dir).fetch(
|
||||
alt_url_image_data = ImageFetcher(self.config.runtime_config.user_cache_dir).fetch(
|
||||
alt_url, blocking=True
|
||||
)
|
||||
except ImageFetcherException as e:
|
||||
@ -505,7 +505,7 @@ class IssueIdentifier:
|
||||
if narrow_cover_hash is not None:
|
||||
hash_list.append(narrow_cover_hash)
|
||||
|
||||
cropped_border = self.crop_border(cover_image_data, self.options.identifier_border_crop_percent)
|
||||
cropped_border = self.crop_border(cover_image_data, self.config.identifier_border_crop_percent)
|
||||
if cropped_border is not None:
|
||||
hash_list.append(self.calculate_hash(cropped_border))
|
||||
logger.info("Adding cropped cover to the hashlist")
|
||||
|
@ -42,7 +42,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
def __init__(
|
||||
self,
|
||||
parent: QtWidgets.QWidget,
|
||||
options: settngs.Namespace,
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
series_id: str,
|
||||
issue_number: str,
|
||||
@ -52,7 +52,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "issueselectionwindow.ui", self)
|
||||
|
||||
self.coverWidget = CoverImageWidget(
|
||||
self.coverImageContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api
|
||||
self.coverImageContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.coverImageContainer)
|
||||
gridlayout.addWidget(self.coverWidget)
|
||||
@ -71,18 +71,18 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
|
||||
self.series_id = series_id
|
||||
self.issue_id: str = ""
|
||||
self.options = options
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.url_fetch_thread = None
|
||||
self.issue_list: list[ComicIssue] = []
|
||||
|
||||
# Display talker logo and set url
|
||||
self.lblIssuesSourceName.setText(talker_api.static_options.attribution_string)
|
||||
self.lblIssuesSourceName.setText(talker_api.static_config.attribution_string)
|
||||
|
||||
self.imageIssuesSourceWidget = CoverImageWidget(
|
||||
self.imageIssuesSourceLogo,
|
||||
CoverImageWidget.URLMode,
|
||||
options.runtime_config.user_cache_dir,
|
||||
config.runtime_config.user_cache_dir,
|
||||
talker_api,
|
||||
False,
|
||||
)
|
||||
|
@ -20,16 +20,14 @@ import json
|
||||
import logging.handlers
|
||||
import signal
|
||||
import sys
|
||||
from collections.abc import Mapping
|
||||
|
||||
import settngs
|
||||
|
||||
import comicapi
|
||||
import comictalker.comictalkerapi as ct_api
|
||||
from comictaggerlib import cli, ctoptions
|
||||
from comictaggerlib import cli, ctsettings
|
||||
from comictaggerlib.ctversion import version
|
||||
from comictaggerlib.log import setup_logging
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
|
||||
if sys.version_info < (3, 10):
|
||||
import importlib_metadata
|
||||
@ -49,8 +47,8 @@ logger = logging.getLogger("comictagger")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def update_publishers(options: settngs.Namespace) -> None:
|
||||
json_file = options.runtime_config.user_config_dir / "publishers.json"
|
||||
def update_publishers(config: settngs.Namespace) -> None:
|
||||
json_file = config.runtime_config.user_config_dir / "publishers.json"
|
||||
if json_file.exists():
|
||||
try:
|
||||
comicapi.utils.update_publishers(json.loads(json_file.read_text("utf-8")))
|
||||
@ -62,49 +60,48 @@ class App:
|
||||
"""docstring for App"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.options = settngs.Config({}, {})
|
||||
self.initial_arg_parser = ctoptions.initial_cmd_line_parser()
|
||||
self.config = settngs.Config({}, {})
|
||||
self.initial_arg_parser = ctsettings.initial_commandline_parser()
|
||||
self.config_load_success = False
|
||||
self.talker_plugins: Mapping[str, ComicTalker] = {}
|
||||
|
||||
def run(self) -> None:
|
||||
opts = self.initialize()
|
||||
self.initialize_dirs(opts.config)
|
||||
self.load_plugins(opts)
|
||||
self.register_options()
|
||||
self.options = self.parse_options(opts.config)
|
||||
conf = self.initialize()
|
||||
self.initialize_dirs(conf.config)
|
||||
self.load_plugins(conf)
|
||||
self.register_settings()
|
||||
self.config = self.parse_settings(conf.config)
|
||||
|
||||
self.main()
|
||||
|
||||
def load_plugins(self, opts) -> None:
|
||||
comicapi.comicarchive.load_archive_plugins()
|
||||
ctoptions.talker_plugins = ct_api.get_talkers(version, opts.config.user_cache_dir)
|
||||
ctsettings.talkers = ct_api.get_talkers(version, opts.config.user_cache_dir)
|
||||
|
||||
def initialize(self) -> argparse.Namespace:
|
||||
opts, _ = self.initial_arg_parser.parse_known_args()
|
||||
assert opts is not None
|
||||
setup_logging(opts.verbose, opts.config.user_log_dir)
|
||||
return opts
|
||||
conf, _ = self.initial_arg_parser.parse_known_args()
|
||||
assert conf is not None
|
||||
setup_logging(conf.verbose, conf.config.user_log_dir)
|
||||
return conf
|
||||
|
||||
def register_options(self) -> None:
|
||||
def register_settings(self) -> None:
|
||||
self.manager = settngs.Manager(
|
||||
"""A utility for reading and writing metadata to comic archives.\n\n\nIf no options are given, %(prog)s will run in windowed mode.""",
|
||||
"For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki",
|
||||
)
|
||||
ctoptions.register_commandline(self.manager)
|
||||
ctoptions.register_settings(self.manager)
|
||||
ctoptions.register_plugin_settings(self.manager)
|
||||
ctsettings.register_commandline_settings(self.manager)
|
||||
ctsettings.register_file_settings(self.manager)
|
||||
ctsettings.register_plugin_settings(self.manager)
|
||||
|
||||
def parse_options(self, config_paths: ctoptions.ComicTaggerPaths) -> settngs.Config:
|
||||
options, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json")
|
||||
options = self.manager.get_namespace(options)
|
||||
def parse_settings(self, config_paths: ctsettings.ComicTaggerPaths) -> settngs.Config:
|
||||
config, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json")
|
||||
config = self.manager.get_namespace(config)
|
||||
|
||||
options = ctoptions.validate_commandline_options(options, self.manager)
|
||||
options = ctoptions.validate_settings(options)
|
||||
options = ctoptions.validate_plugin_settings(options)
|
||||
return options
|
||||
config = ctsettings.validate_commandline_settings(config, self.manager)
|
||||
config = ctsettings.validate_file_settings(config)
|
||||
config = ctsettings.validate_plugin_settings(config)
|
||||
return config
|
||||
|
||||
def initialize_dirs(self, paths: ctoptions.ComicTaggerPaths) -> None:
|
||||
def initialize_dirs(self, paths: ctsettings.ComicTaggerPaths) -> None:
|
||||
paths.user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
paths.user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
paths.user_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
@ -117,8 +114,8 @@ class App:
|
||||
logger.debug("user_log_dir: %s", paths.user_log_dir)
|
||||
|
||||
def main(self) -> None:
|
||||
assert self.options is not None
|
||||
# options already loaded
|
||||
assert self.config is not None
|
||||
# config already loaded
|
||||
error = None
|
||||
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
@ -128,40 +125,48 @@ class App:
|
||||
logger.debug("%s\t%s", pkg.metadata["Name"], pkg.metadata["Version"])
|
||||
|
||||
comicapi.utils.load_publishers()
|
||||
update_publishers(self.options[0])
|
||||
update_publishers(self.config[0])
|
||||
|
||||
if not qt_available and not self.options[0].runtime_no_gui:
|
||||
self.options[0].runtime_no_gui = True
|
||||
if not qt_available and not self.config[0].runtime_no_gui:
|
||||
self.config[0].runtime_no_gui = True
|
||||
logger.warning("PyQt5 is not available. ComicTagger is limited to command-line mode.")
|
||||
|
||||
if self.options[0].commands_only_set_cv_key:
|
||||
# manage the CV API key
|
||||
# None comparison is used so that the empty string can unset the value
|
||||
if self.config[0].talker_comicvine_cv_api_key is not None or self.config[0].talker_comicvine_cv_url is not None:
|
||||
settings_path = self.config[0].runtime_config.user_config_dir / "settings.json"
|
||||
if self.config_load_success:
|
||||
self.manager.save_file(self.config[0], settings_path)
|
||||
|
||||
if self.config[0].commands_only_set_cv_key:
|
||||
if self.config_load_success:
|
||||
print("Key set") # noqa: T201
|
||||
return
|
||||
|
||||
try:
|
||||
talker_api = self.talker_plugins[self.options[0].talkers_source]
|
||||
talker_api = ctsettings.talkers[self.config[0].talkers_source]
|
||||
except Exception as e:
|
||||
logger.exception(f"Unable to load talker {self.options[0].talkers_source}")
|
||||
# TODO error True can be changed to False after the talker settings menu generation is in
|
||||
error = (f"Unable to load talker {self.options[0].talkers_source}: {e}", True)
|
||||
logger.exception(f"Unable to load talker {self.config[0].talkers_source}")
|
||||
error = (f"Unable to load talker {self.config[0].talkers_source}: {e}", True)
|
||||
talker_api = None
|
||||
|
||||
if not self.config_load_success:
|
||||
error = (
|
||||
f"Failed to load settings, check the log located in '{self.options[0].runtime_config.user_log_dir}' for more details",
|
||||
f"Failed to load settings, check the log located in '{self.config[0].runtime_config.user_log_dir}' for more details",
|
||||
True,
|
||||
)
|
||||
|
||||
if self.options[0].runtime_no_gui:
|
||||
if self.config[0].runtime_no_gui:
|
||||
if error and error[1]:
|
||||
print(f"A fatal error occurred please check the log for more information: {error[0]}") # noqa: T201
|
||||
raise SystemExit(1)
|
||||
assert talker_api is not None
|
||||
try:
|
||||
cli.CLI(self.options[0], talker_api).run()
|
||||
cli.CLI(self.config[0], talker_api).run()
|
||||
except Exception:
|
||||
logger.exception("CLI mode failed")
|
||||
else:
|
||||
gui.open_tagger_window(talker_api, self.options, error)
|
||||
gui.open_tagger_window(talker_api, self.config, error)
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -37,7 +37,7 @@ class MatchSelectionWindow(QtWidgets.QDialog):
|
||||
parent: QtWidgets.QWidget,
|
||||
matches: list[IssueResult],
|
||||
comic_archive: ComicArchive,
|
||||
options: settngs.Values,
|
||||
config: settngs.Values,
|
||||
talker_api: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
@ -45,7 +45,7 @@ class MatchSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "matchselectionwindow.ui", self)
|
||||
|
||||
self.altCoverWidget = CoverImageWidget(
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
|
@ -38,7 +38,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
parent: QtWidgets.QWidget,
|
||||
comic_archive_list: list[ComicArchive],
|
||||
data_style: int,
|
||||
options: settngs.Config,
|
||||
config: settngs.Config,
|
||||
talker_api: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
@ -54,39 +54,39 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
)
|
||||
)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.comic_archive_list = comic_archive_list
|
||||
self.data_style = data_style
|
||||
self.rename_list: list[str] = []
|
||||
|
||||
self.btnSettings.clicked.connect(self.modify_settings)
|
||||
platform = "universal" if self.options[0].rename_strict else "auto"
|
||||
self.renamer = FileRenamer(None, platform=platform, replacements=self.options[0].rename_replacements)
|
||||
platform = "universal" if self.config[0].rename_strict else "auto"
|
||||
self.renamer = FileRenamer(None, platform=platform, replacements=self.config[0].rename_replacements)
|
||||
|
||||
self.do_preview()
|
||||
|
||||
def config_renamer(self, ca: ComicArchive, md: GenericMetadata | None = None) -> str:
|
||||
self.renamer.set_template(self.options[0].rename_template)
|
||||
self.renamer.set_issue_zero_padding(self.options[0].rename_issue_number_padding)
|
||||
self.renamer.set_smart_cleanup(self.options[0].rename_use_smart_string_cleanup)
|
||||
self.renamer.replacements = self.options[0].rename_replacements
|
||||
self.renamer.set_template(self.config[0].rename_template)
|
||||
self.renamer.set_issue_zero_padding(self.config[0].rename_issue_number_padding)
|
||||
self.renamer.set_smart_cleanup(self.config[0].rename_use_smart_string_cleanup)
|
||||
self.renamer.replacements = self.config[0].rename_replacements
|
||||
|
||||
new_ext = ca.path.suffix # default
|
||||
if self.options[0].filename_rename_set_extension_based_on_archive:
|
||||
if self.config[0].filename_rename_set_extension_based_on_archive:
|
||||
new_ext = ca.extension()
|
||||
|
||||
if md is None:
|
||||
md = ca.read_metadata(self.data_style)
|
||||
if md.is_empty:
|
||||
md = ca.metadata_from_filename(
|
||||
self.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
self.config[0].filename_complicated_parser,
|
||||
self.config[0].filename_remove_c2c,
|
||||
self.config[0].filename_remove_fcbd,
|
||||
self.config[0].filename_remove_publisher,
|
||||
)
|
||||
self.renamer.set_metadata(md)
|
||||
self.renamer.move = self.options[0].rename_move_to_dir
|
||||
self.renamer.move = self.config[0].rename_move_to_dir
|
||||
return new_ext
|
||||
|
||||
def do_preview(self) -> None:
|
||||
@ -99,7 +99,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
try:
|
||||
new_name = self.renamer.determine_name(new_ext)
|
||||
except ValueError as e:
|
||||
logger.exception("Invalid format string: %s", self.options[0].rename_template)
|
||||
logger.exception("Invalid format string: %s", self.config[0].rename_template)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
"Invalid format string!",
|
||||
@ -114,7 +114,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
"Formatter failure: %s metadata: %s",
|
||||
self.options[0].rename_template,
|
||||
self.config[0].rename_template,
|
||||
self.renamer.metadata,
|
||||
)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
@ -162,7 +162,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
self.twList.setSortingEnabled(True)
|
||||
|
||||
def modify_settings(self) -> None:
|
||||
settingswin = SettingsWindow(self, self.options, self.talker_api)
|
||||
settingswin = SettingsWindow(self, self.config, self.talker_api)
|
||||
settingswin.setModal(True)
|
||||
settingswin.show_rename_tab()
|
||||
settingswin.exec()
|
||||
@ -192,7 +192,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
|
||||
folder = get_rename_dir(
|
||||
comic[0],
|
||||
self.options[0].rename_dir if self.options[0].rename_move_to_dir else None,
|
||||
self.config[0].rename_dir if self.config[0].rename_move_to_dir else None,
|
||||
)
|
||||
|
||||
full_path = folder / comic[1]
|
||||
|
@ -111,7 +111,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
issue_count: int,
|
||||
cover_index_list: list[int],
|
||||
comic_archive: ComicArchive | None,
|
||||
options: settngs.Namespace,
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
autoselect: bool = False,
|
||||
literal: bool = False,
|
||||
@ -121,7 +121,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "seriesselectionwindow.ui", self)
|
||||
|
||||
self.imageWidget = CoverImageWidget(
|
||||
self.imageContainer, CoverImageWidget.URLMode, options.runtime_config.user_cache_dir, talker_api
|
||||
self.imageContainer, CoverImageWidget.URLMode, config.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.imageContainer)
|
||||
gridlayout.addWidget(self.imageWidget)
|
||||
@ -138,7 +138,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
)
|
||||
)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
self.series_name = series_name
|
||||
self.issue_number = issue_number
|
||||
self.issue_id: str = ""
|
||||
@ -156,18 +156,18 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.progdialog: QtWidgets.QProgressDialog | None = None
|
||||
self.search_thread: SearchThread | None = None
|
||||
|
||||
self.use_filter = self.options.talkers_always_use_publisher_filter
|
||||
self.use_filter = self.config.talkers_always_use_publisher_filter
|
||||
|
||||
# Load to retrieve settings
|
||||
self.talker_api = talker_api
|
||||
|
||||
# Display talker logo and set url
|
||||
self.lblSourceName.setText(talker_api.static_options.attribution_string)
|
||||
self.lblSourceName.setText(talker_api.static_config.attribution_string)
|
||||
|
||||
self.imageSourceWidget = CoverImageWidget(
|
||||
self.imageSourceLogo,
|
||||
CoverImageWidget.URLMode,
|
||||
options.runtime_config.user_cache_dir,
|
||||
config.runtime_config.user_cache_dir,
|
||||
talker_api,
|
||||
False,
|
||||
)
|
||||
@ -224,7 +224,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.iddialog.rejected.connect(self.identify_cancel)
|
||||
self.iddialog.show()
|
||||
|
||||
self.ii = IssueIdentifier(self.comic_archive, self.options, self.talker_api)
|
||||
self.ii = IssueIdentifier(self.comic_archive, self.config, self.talker_api)
|
||||
|
||||
md = GenericMetadata()
|
||||
md.series = self.series_name
|
||||
@ -298,7 +298,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
|
||||
if choices:
|
||||
selector = MatchSelectionWindow(
|
||||
self, matches, self.comic_archive, talker_api=self.talker_api, options=self.options
|
||||
self, matches, self.comic_archive, talker_api=self.talker_api, config=self.config
|
||||
)
|
||||
selector.setModal(True)
|
||||
selector.exec()
|
||||
@ -315,7 +315,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.show_issues()
|
||||
|
||||
def show_issues(self) -> None:
|
||||
selector = IssueSelectionWindow(self, self.options, self.talker_api, self.series_id, self.issue_number)
|
||||
selector = IssueSelectionWindow(self, self.config, self.talker_api, self.series_id, self.issue_number)
|
||||
title = ""
|
||||
for record in self.ct_search_results:
|
||||
if record.id == self.series_id:
|
||||
@ -343,7 +343,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
def perform_query(self, refresh: bool = False) -> None:
|
||||
|
||||
self.search_thread = SearchThread(
|
||||
self.talker_api, self.series_name, refresh, self.literal, self.options.talkers_series_match_search_thresh
|
||||
self.talker_api, self.series_name, refresh, self.literal, self.config.talkers_series_match_search_thresh
|
||||
)
|
||||
self.search_thread.searchComplete.connect(self.search_complete)
|
||||
self.search_thread.progressUpdate.connect(self.search_progress_update)
|
||||
@ -395,7 +395,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
# filter the publishers if enabled set
|
||||
if self.use_filter:
|
||||
try:
|
||||
publisher_filter = {s.strip().casefold() for s in self.options.identifier_publisher_filter}
|
||||
publisher_filter = {s.strip().casefold() for s in self.config.identifier_publisher_filter}
|
||||
# use '' as publisher name if None
|
||||
self.ct_search_results = list(
|
||||
filter(
|
||||
@ -410,7 +410,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
# compare as str in case extra chars ie. '1976?'
|
||||
# - missing (none) values being converted to 'None' - consistent with prior behaviour in v1.2.3
|
||||
# sort by start_year if set
|
||||
if self.options.talkers_sort_series_by_year:
|
||||
if self.config.talkers_sort_series_by_year:
|
||||
try:
|
||||
self.ct_search_results = sorted(
|
||||
self.ct_search_results,
|
||||
@ -428,7 +428,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
logger.exception("bad data error sorting results by count_of_issues")
|
||||
|
||||
# move sanitized matches to the front
|
||||
if self.options.talkers_exact_series_matches_first:
|
||||
if self.config.talkers_exact_series_matches_first:
|
||||
try:
|
||||
sanitized = utils.sanitize_title(self.series_name, False).casefold()
|
||||
sanitized_no_articles = utils.sanitize_title(self.series_name, True).casefold()
|
||||
|
@ -130,7 +130,7 @@ Spider-Geddon #1 - New Players; Check In
|
||||
|
||||
|
||||
class SettingsWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, options: settngs.Config, talker_api: ComicTalker) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget, config: settngs.Config, talker_api: ComicTalker) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "settingswindow.ui", self)
|
||||
@ -139,7 +139,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
QtCore.Qt.WindowType(self.windowFlags() & ~QtCore.Qt.WindowType.WindowContextHelpButtonHint)
|
||||
)
|
||||
|
||||
self.options = options
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.name = "Settings"
|
||||
|
||||
@ -269,53 +269,53 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
|
||||
def settings_to_form(self) -> None:
|
||||
# Copy values from settings to form
|
||||
if "archiver" in self.options[1] and "rar" in self.options[1]["archiver"]:
|
||||
self.leRarExePath.setText(getattr(self.options[0], self.options[1]["archiver"]["rar"].internal_name))
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]:
|
||||
self.leRarExePath.setText(getattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name))
|
||||
else:
|
||||
self.leRarExePath.setEnabled(False)
|
||||
self.sbNameMatchIdentifyThresh.setValue(self.options[0].identifier_series_match_identify_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.options[0].talkers_series_match_search_thresh)
|
||||
self.tePublisherFilter.setPlainText("\n".join(self.options[0].identifier_publisher_filter))
|
||||
self.sbNameMatchIdentifyThresh.setValue(self.config[0].identifier_series_match_identify_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.config[0].talkers_series_match_search_thresh)
|
||||
self.tePublisherFilter.setPlainText("\n".join(self.config[0].identifier_publisher_filter))
|
||||
|
||||
self.cbxCheckForNewVersion.setChecked(self.options[0].general_check_for_new_version)
|
||||
self.cbxCheckForNewVersion.setChecked(self.config[0].general_check_for_new_version)
|
||||
|
||||
self.cbxComplicatedParser.setChecked(self.options[0].filename_complicated_parser)
|
||||
self.cbxRemoveC2C.setChecked(self.options[0].filename_remove_c2c)
|
||||
self.cbxRemoveFCBD.setChecked(self.options[0].filename_remove_fcbd)
|
||||
self.cbxRemovePublisher.setChecked(self.options[0].filename_remove_publisher)
|
||||
self.cbxComplicatedParser.setChecked(self.config[0].filename_complicated_parser)
|
||||
self.cbxRemoveC2C.setChecked(self.config[0].filename_remove_c2c)
|
||||
self.cbxRemoveFCBD.setChecked(self.config[0].filename_remove_fcbd)
|
||||
self.cbxRemovePublisher.setChecked(self.config[0].filename_remove_publisher)
|
||||
self.switch_parser()
|
||||
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.options[0].talker_comicvine_cv_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.options[0].talkers_clear_form_before_populating)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.options[0].talker_comicvine_cv_remove_html_tables)
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.config[0].talker_comicvine_cv_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.config[0].talkers_clear_form_before_populating)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.config[0].talker_comicvine_cv_remove_html_tables)
|
||||
|
||||
self.cbxUseFilter.setChecked(self.options[0].talkers_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.options[0].talkers_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.options[0].talkers_exact_series_matches_first)
|
||||
self.cbxUseFilter.setChecked(self.config[0].talkers_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.config[0].talkers_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.config[0].talkers_exact_series_matches_first)
|
||||
|
||||
self.leKey.setText(self.options[0].talker_comicvine_cv_api_key)
|
||||
self.leURL.setText(self.options[0].talker_comicvine_cv_url)
|
||||
self.leKey.setText(self.config[0].talker_comicvine_cv_api_key)
|
||||
self.leURL.setText(self.config[0].talker_comicvine_cv_url)
|
||||
|
||||
self.cbxAssumeLoneCreditIsPrimary.setChecked(self.options[0].cbl_assume_lone_credit_is_primary)
|
||||
self.cbxCopyCharactersToTags.setChecked(self.options[0].cbl_copy_characters_to_tags)
|
||||
self.cbxCopyTeamsToTags.setChecked(self.options[0].cbl_copy_teams_to_tags)
|
||||
self.cbxCopyLocationsToTags.setChecked(self.options[0].cbl_copy_locations_to_tags)
|
||||
self.cbxCopyStoryArcsToTags.setChecked(self.options[0].cbl_copy_storyarcs_to_tags)
|
||||
self.cbxCopyNotesToComments.setChecked(self.options[0].cbl_copy_notes_to_comments)
|
||||
self.cbxCopyWebLinkToComments.setChecked(self.options[0].cbl_copy_weblink_to_comments)
|
||||
self.cbxApplyCBLTransformOnCVIMport.setChecked(self.options[0].cbl_apply_transform_on_import)
|
||||
self.cbxApplyCBLTransformOnBatchOperation.setChecked(self.options[0].cbl_apply_transform_on_bulk_operation)
|
||||
self.cbxAssumeLoneCreditIsPrimary.setChecked(self.config[0].cbl_assume_lone_credit_is_primary)
|
||||
self.cbxCopyCharactersToTags.setChecked(self.config[0].cbl_copy_characters_to_tags)
|
||||
self.cbxCopyTeamsToTags.setChecked(self.config[0].cbl_copy_teams_to_tags)
|
||||
self.cbxCopyLocationsToTags.setChecked(self.config[0].cbl_copy_locations_to_tags)
|
||||
self.cbxCopyStoryArcsToTags.setChecked(self.config[0].cbl_copy_storyarcs_to_tags)
|
||||
self.cbxCopyNotesToComments.setChecked(self.config[0].cbl_copy_notes_to_comments)
|
||||
self.cbxCopyWebLinkToComments.setChecked(self.config[0].cbl_copy_weblink_to_comments)
|
||||
self.cbxApplyCBLTransformOnCVIMport.setChecked(self.config[0].cbl_apply_transform_on_import)
|
||||
self.cbxApplyCBLTransformOnBatchOperation.setChecked(self.config[0].cbl_apply_transform_on_bulk_operation)
|
||||
|
||||
self.leRenameTemplate.setText(self.options[0].rename_template)
|
||||
self.leIssueNumPadding.setText(str(self.options[0].rename_issue_number_padding))
|
||||
self.cbxSmartCleanup.setChecked(self.options[0].rename_use_smart_string_cleanup)
|
||||
self.cbxChangeExtension.setChecked(self.options[0].rename_set_extension_based_on_archive)
|
||||
self.cbxMoveFiles.setChecked(self.options[0].rename_move_to_dir)
|
||||
self.leDirectory.setText(self.options[0].rename_dir)
|
||||
self.cbxRenameStrict.setChecked(self.options[0].rename_strict)
|
||||
self.leRenameTemplate.setText(self.config[0].rename_template)
|
||||
self.leIssueNumPadding.setText(str(self.config[0].rename_issue_number_padding))
|
||||
self.cbxSmartCleanup.setChecked(self.config[0].rename_use_smart_string_cleanup)
|
||||
self.cbxChangeExtension.setChecked(self.config[0].rename_set_extension_based_on_archive)
|
||||
self.cbxMoveFiles.setChecked(self.config[0].rename_move_to_dir)
|
||||
self.leDirectory.setText(self.config[0].rename_dir)
|
||||
self.cbxRenameStrict.setChecked(self.config[0].rename_strict)
|
||||
|
||||
for table, replacments in zip(
|
||||
(self.twLiteralReplacements, self.twValueReplacements), self.options[0].rename_replacements
|
||||
(self.twLiteralReplacements, self.twValueReplacements), self.config[0].rename_replacements
|
||||
):
|
||||
table.clearContents()
|
||||
for i in reversed(range(table.rowCount())):
|
||||
@ -350,7 +350,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.rename_test()
|
||||
if self.rename_error is not None:
|
||||
if isinstance(self.rename_error, ValueError):
|
||||
logger.exception("Invalid format string: %s", self.options[0].rename_template)
|
||||
logger.exception("Invalid format string: %s", self.config[0].rename_template)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
"Invalid format string!",
|
||||
@ -364,7 +364,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
return
|
||||
else:
|
||||
logger.exception(
|
||||
"Formatter failure: %s metadata: %s", self.options[0].rename_template, self.renamer.metadata
|
||||
"Formatter failure: %s metadata: %s", self.config[0].rename_template, self.renamer.metadata
|
||||
)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
@ -377,75 +377,75 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
# Copy values from form to settings and save
|
||||
if "archiver" in self.options[1] and "rar" in self.options[1]["archiver"]:
|
||||
setattr(self.options[0], self.options[1]["archiver"]["rar"].internal_name, str(self.leRarExePath.text()))
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]:
|
||||
setattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name, str(self.leRarExePath.text()))
|
||||
|
||||
# make sure rar program is now in the path for the rar class
|
||||
if self.options[0].archivers_rar:
|
||||
if self.config[0].archivers_rar:
|
||||
utils.add_to_path(os.path.dirname(str(self.leRarExePath.text())))
|
||||
|
||||
if not str(self.leIssueNumPadding.text()).isdigit():
|
||||
self.leIssueNumPadding.setText("0")
|
||||
|
||||
self.options[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked()
|
||||
self.config[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked()
|
||||
|
||||
self.options[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value()
|
||||
self.options[0].talkers_series_match_search_thresh = self.sbNameMatchSearchThresh.value()
|
||||
self.options[0].identifier_publisher_filter = [
|
||||
self.config[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value()
|
||||
self.config[0].talkers_series_match_search_thresh = self.sbNameMatchSearchThresh.value()
|
||||
self.config[0].identifier_publisher_filter = [
|
||||
x.strip() for x in str(self.tePublisherFilter.toPlainText()).splitlines() if x.strip()
|
||||
]
|
||||
|
||||
self.options[0].filename_complicated_parser = self.cbxComplicatedParser.isChecked()
|
||||
self.options[0].filename_remove_c2c = self.cbxRemoveC2C.isChecked()
|
||||
self.options[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked()
|
||||
self.options[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked()
|
||||
self.config[0].filename_complicated_parser = self.cbxComplicatedParser.isChecked()
|
||||
self.config[0].filename_remove_c2c = self.cbxRemoveC2C.isChecked()
|
||||
self.config[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked()
|
||||
self.config[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked()
|
||||
|
||||
self.options[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.options[0].talkers_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.options[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
self.config[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.config[0].talkers_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.config[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
|
||||
self.options[0].talkers_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.options[0].talkers_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.options[0].talkers_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
self.config[0].talkers_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.config[0].talkers_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.config[0].talkers_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
|
||||
if self.leKey.text().strip():
|
||||
self.options[0].talker_comicvine_cv_api_key = self.leKey.text().strip()
|
||||
self.talker_api.api_key = self.options[0].talker_comicvine_cv_api_key
|
||||
self.config[0].talker_comicvine_cv_api_key = self.leKey.text().strip()
|
||||
self.talker_api.api_key = self.config[0].talker_comicvine_cv_api_key
|
||||
|
||||
if self.leURL.text().strip():
|
||||
self.options[0].talker_comicvine_cv_url = self.leURL.text().strip()
|
||||
self.talker_api.api_url = self.options[0].talker_comicvine_cv_url
|
||||
self.config[0].talker_comicvine_cv_url = self.leURL.text().strip()
|
||||
self.talker_api.api_url = self.config[0].talker_comicvine_cv_url
|
||||
|
||||
self.options[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
|
||||
self.options[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked()
|
||||
self.options[0].cbl_copy_teams_to_tags = self.cbxCopyTeamsToTags.isChecked()
|
||||
self.options[0].cbl_copy_locations_to_tags = self.cbxCopyLocationsToTags.isChecked()
|
||||
self.options[0].cbl_copy_storyarcs_to_tags = self.cbxCopyStoryArcsToTags.isChecked()
|
||||
self.options[0].cbl_copy_notes_to_comments = self.cbxCopyNotesToComments.isChecked()
|
||||
self.options[0].cbl_copy_weblink_to_comments = self.cbxCopyWebLinkToComments.isChecked()
|
||||
self.options[0].cbl_apply_transform_on_import = self.cbxApplyCBLTransformOnCVIMport.isChecked()
|
||||
self.options[0].cbl_apply_transform_on_bulk_operation = self.cbxApplyCBLTransformOnBatchOperation.isChecked()
|
||||
self.config[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
|
||||
self.config[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked()
|
||||
self.config[0].cbl_copy_teams_to_tags = self.cbxCopyTeamsToTags.isChecked()
|
||||
self.config[0].cbl_copy_locations_to_tags = self.cbxCopyLocationsToTags.isChecked()
|
||||
self.config[0].cbl_copy_storyarcs_to_tags = self.cbxCopyStoryArcsToTags.isChecked()
|
||||
self.config[0].cbl_copy_notes_to_comments = self.cbxCopyNotesToComments.isChecked()
|
||||
self.config[0].cbl_copy_weblink_to_comments = self.cbxCopyWebLinkToComments.isChecked()
|
||||
self.config[0].cbl_apply_transform_on_import = self.cbxApplyCBLTransformOnCVIMport.isChecked()
|
||||
self.config[0].cbl_apply_transform_on_bulk_operation = self.cbxApplyCBLTransformOnBatchOperation.isChecked()
|
||||
|
||||
self.options[0].rename_template = str(self.leRenameTemplate.text())
|
||||
self.options[0].rename_issue_number_padding = int(self.leIssueNumPadding.text())
|
||||
self.options[0].rename_use_smart_string_cleanup = self.cbxSmartCleanup.isChecked()
|
||||
self.options[0].rename_set_extension_based_on_archive = self.cbxChangeExtension.isChecked()
|
||||
self.options[0].rename_move_to_dir = self.cbxMoveFiles.isChecked()
|
||||
self.options[0].rename_dir = self.leDirectory.text()
|
||||
self.config[0].rename_template = str(self.leRenameTemplate.text())
|
||||
self.config[0].rename_issue_number_padding = int(self.leIssueNumPadding.text())
|
||||
self.config[0].rename_use_smart_string_cleanup = self.cbxSmartCleanup.isChecked()
|
||||
self.config[0].rename_set_extension_based_on_archive = self.cbxChangeExtension.isChecked()
|
||||
self.config[0].rename_move_to_dir = self.cbxMoveFiles.isChecked()
|
||||
self.config[0].rename_dir = self.leDirectory.text()
|
||||
|
||||
self.options[0].rename_strict = self.cbxRenameStrict.isChecked()
|
||||
self.options[0].rename_replacements = self.get_replacemnts()
|
||||
self.config[0].rename_strict = self.cbxRenameStrict.isChecked()
|
||||
self.config[0].rename_replacements = self.get_replacemnts()
|
||||
|
||||
settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json")
|
||||
self.parent().options = self.options
|
||||
settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json")
|
||||
self.parent().config = self.config
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
def select_rar(self) -> None:
|
||||
self.select_file(self.leRarExePath, "RAR")
|
||||
|
||||
def clear_cache(self) -> None:
|
||||
ImageFetcher(self.options[0].runtime_config.user_cache_dir).clear_cache()
|
||||
ComicCacher(self.options[0].runtime_config.user_cache_dir, version).clear_cache()
|
||||
ImageFetcher(self.config[0].runtime_config.user_cache_dir).clear_cache()
|
||||
ComicCacher(self.config[0].runtime_config.user_cache_dir, version).clear_cache()
|
||||
QtWidgets.QMessageBox.information(self, self.name, "Cache has been cleared.")
|
||||
|
||||
def test_api_key(self) -> None:
|
||||
@ -455,7 +455,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
QtWidgets.QMessageBox.warning(self, "API Key Test", "Key is NOT valid.")
|
||||
|
||||
def reset_settings(self) -> None:
|
||||
self.options = settngs.Config(settngs.defaults(self.options[1]), self.options[1])
|
||||
self.config = settngs.Config(settngs.defaults(self.config[1]), self.config[1])
|
||||
self.settings_to_form()
|
||||
QtWidgets.QMessageBox.information(self, self.name, self.name + " have been returned to default values.")
|
||||
|
||||
|
@ -79,24 +79,24 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
def __init__(
|
||||
self,
|
||||
file_list: list[str],
|
||||
options: settngs.Config,
|
||||
config: settngs.Config,
|
||||
talker_api: ComicTalker,
|
||||
parent: QtWidgets.QWidget | None = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "taggerwindow.ui", self)
|
||||
self.options = options
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.log_window = self.setup_logger()
|
||||
|
||||
# prevent multiple instances
|
||||
socket = QtNetwork.QLocalSocket(self)
|
||||
socket.connectToServer(options[0].internal_install_id)
|
||||
socket.connectToServer(config[0].internal_install_id)
|
||||
alive = socket.waitForConnected(3000)
|
||||
if alive:
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.info("Another application with key [%s] is already running", options[0].internal_install_id)
|
||||
logger.info("Another application with key [%s] is already running", config[0].internal_install_id)
|
||||
# send file list to other instance
|
||||
if file_list:
|
||||
socket.write(pickle.dumps(file_list))
|
||||
@ -108,15 +108,15 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
# listen on a socket to prevent multiple instances
|
||||
self.socketServer = QtNetwork.QLocalServer(self)
|
||||
self.socketServer.newConnection.connect(self.on_incoming_socket_connection)
|
||||
ok = self.socketServer.listen(options[0].internal_install_id)
|
||||
ok = self.socketServer.listen(config[0].internal_install_id)
|
||||
if not ok:
|
||||
if self.socketServer.serverError() == QtNetwork.QAbstractSocket.SocketError.AddressInUseError:
|
||||
self.socketServer.removeServer(options[0].internal_install_id)
|
||||
ok = self.socketServer.listen(options[0].internal_install_id)
|
||||
self.socketServer.removeServer(config[0].internal_install_id)
|
||||
ok = self.socketServer.listen(config[0].internal_install_id)
|
||||
if not ok:
|
||||
logger.error(
|
||||
"Cannot start local socket with key [%s]. Reason: %s",
|
||||
options[0].internal_install_id,
|
||||
config[0].internal_install_id,
|
||||
self.socketServer.errorString(),
|
||||
)
|
||||
sys.exit()
|
||||
@ -130,14 +130,14 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
grid_layout = QtWidgets.QGridLayout(self.tabPages)
|
||||
grid_layout.addWidget(self.page_list_editor)
|
||||
|
||||
self.fileSelectionList = FileSelectionList(self.widgetListHolder, self.options[0], self.dirty_flag_verification)
|
||||
self.fileSelectionList = FileSelectionList(self.widgetListHolder, self.config[0], self.dirty_flag_verification)
|
||||
grid_layout = QtWidgets.QGridLayout(self.widgetListHolder)
|
||||
grid_layout.addWidget(self.fileSelectionList)
|
||||
|
||||
self.fileSelectionList.selectionChanged.connect(self.file_list_selection_changed)
|
||||
self.fileSelectionList.listCleared.connect(self.file_list_cleared)
|
||||
self.fileSelectionList.set_sorting(
|
||||
self.options[0].internal_sort_column, QtCore.Qt.SortOrder(self.options[0].internal_sort_direction)
|
||||
self.config[0].internal_sort_column, QtCore.Qt.SortOrder(self.config[0].internal_sort_direction)
|
||||
)
|
||||
|
||||
# we can't specify relative font sizes in the UI designer, so
|
||||
@ -155,13 +155,13 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png")))
|
||||
|
||||
if options[0].runtime_type and isinstance(options[0].runtime_type[0], int):
|
||||
if config[0].runtime_type and isinstance(config[0].runtime_type[0], int):
|
||||
# respect the command line option tag type
|
||||
options[0].internal_save_data_style = options[0].runtime_type[0]
|
||||
options[0].internal_load_data_style = options[0].runtime_type[0]
|
||||
config[0].internal_save_data_style = config[0].runtime_type[0]
|
||||
config[0].internal_load_data_style = config[0].runtime_type[0]
|
||||
|
||||
self.save_data_style = options[0].internal_save_data_style
|
||||
self.load_data_style = options[0].internal_load_data_style
|
||||
self.save_data_style = config[0].internal_save_data_style
|
||||
self.load_data_style = config[0].internal_load_data_style
|
||||
|
||||
self.setAcceptDrops(True)
|
||||
self.config_menus()
|
||||
@ -226,8 +226,8 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.show()
|
||||
self.set_app_position()
|
||||
if self.options[0].internal_form_width != -1:
|
||||
self.splitter.setSizes([self.options[0].internal_form_width, self.options[0].internal_list_width])
|
||||
if self.config[0].internal_form_width != -1:
|
||||
self.splitter.setSizes([self.config[0].internal_form_width, self.config[0].internal_list_width])
|
||||
self.raise_()
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
self.resizeEvent(None)
|
||||
@ -244,7 +244,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
if len(file_list) != 0:
|
||||
self.fileSelectionList.add_path_list(file_list)
|
||||
|
||||
if self.options[0].dialog_show_disclaimer:
|
||||
if self.config[0].dialog_show_disclaimer:
|
||||
checked = OptionalMessageDialog.msg(
|
||||
self,
|
||||
"Welcome!",
|
||||
@ -259,9 +259,9 @@ use ComicTagger on local copies of your comics.<br><br>
|
||||
Have fun!
|
||||
""",
|
||||
)
|
||||
self.options[0].dialog_show_disclaimer = not checked
|
||||
self.config[0].dialog_show_disclaimer = not checked
|
||||
|
||||
if self.options[0].general_check_for_new_version:
|
||||
if self.config[0].general_check_for_new_version:
|
||||
self.check_latest_version_online()
|
||||
|
||||
def open_file_event(self, url: QtCore.QUrl) -> None:
|
||||
@ -274,7 +274,7 @@ Have fun!
|
||||
|
||||
def setup_logger(self) -> ApplicationLogWindow:
|
||||
try:
|
||||
current_logs = (self.options[0].runtime_config.user_log_dir / "ComicTagger.log").read_text("utf-8")
|
||||
current_logs = (self.config[0].runtime_config.user_log_dir / "ComicTagger.log").read_text("utf-8")
|
||||
except Exception:
|
||||
current_logs = ""
|
||||
root_logger = logging.getLogger()
|
||||
@ -479,7 +479,7 @@ Have fun!
|
||||
f"You have selected {non_zip_count} archive(s) to export to Zip format. "
|
||||
""" New archives will be created in the same folder as the original.
|
||||
|
||||
Please choose options below, and select OK.
|
||||
Please choose config below, and select OK.
|
||||
"""
|
||||
),
|
||||
)
|
||||
@ -607,10 +607,10 @@ Have fun!
|
||||
def actual_load_current_archive(self) -> None:
|
||||
if self.metadata.is_empty and self.comic_archive is not None:
|
||||
self.metadata = self.comic_archive.metadata_from_filename(
|
||||
self.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
self.config[0].filename_complicated_parser,
|
||||
self.config[0].filename_remove_c2c,
|
||||
self.config[0].filename_remove_fcbd,
|
||||
self.config[0].filename_remove_publisher,
|
||||
)
|
||||
if len(self.metadata.pages) == 0 and self.comic_archive is not None:
|
||||
self.metadata.set_default_page_list(self.comic_archive.get_number_of_pages())
|
||||
@ -969,10 +969,10 @@ Have fun!
|
||||
# copy the form onto metadata object
|
||||
self.form_to_metadata()
|
||||
new_metadata = self.comic_archive.metadata_from_filename(
|
||||
self.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
self.config[0].filename_complicated_parser,
|
||||
self.config[0].filename_remove_c2c,
|
||||
self.config[0].filename_remove_fcbd,
|
||||
self.config[0].filename_remove_publisher,
|
||||
split_words,
|
||||
)
|
||||
if new_metadata is not None:
|
||||
@ -993,8 +993,8 @@ Have fun!
|
||||
else:
|
||||
dialog.setFileMode(QtWidgets.QFileDialog.FileMode.ExistingFiles)
|
||||
|
||||
if self.options[0].internal_last_opened_folder is not None:
|
||||
dialog.setDirectory(self.options[0].internal_last_opened_folder)
|
||||
if self.config[0].internal_last_opened_folder is not None:
|
||||
dialog.setDirectory(self.config[0].internal_last_opened_folder)
|
||||
|
||||
if not folder_mode:
|
||||
archive_filter = "Comic archive files (*.cbz *.zip *.cbr *.rar *.cb7 *.7z)"
|
||||
@ -1044,7 +1044,7 @@ Have fun!
|
||||
issue_count,
|
||||
cover_index_list,
|
||||
self.comic_archive,
|
||||
self.options[0],
|
||||
self.config[0],
|
||||
self.talker_api,
|
||||
autoselect,
|
||||
literal,
|
||||
@ -1072,10 +1072,10 @@ Have fun!
|
||||
else:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
if new_metadata is not None:
|
||||
if self.options[0].cbl_apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.options[0]).apply()
|
||||
if self.config[0].cbl_apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.config[0]).apply()
|
||||
|
||||
if self.options[0].talkers_clear_form_before_populating:
|
||||
if self.config[0].talkers_clear_form_before_populating:
|
||||
self.clear_form()
|
||||
|
||||
notes = (
|
||||
@ -1130,7 +1130,7 @@ Have fun!
|
||||
"Change Tag Read Style", "If you change read tag style now, data in the form will be lost. Are you sure?"
|
||||
):
|
||||
self.load_data_style = self.cbLoadDataStyle.itemData(s)
|
||||
self.options[0].internal_load_data_style = self.load_data_style
|
||||
self.config[0].internal_load_data_style = self.load_data_style
|
||||
self.update_menus()
|
||||
if self.comic_archive is not None:
|
||||
self.load_archive(self.comic_archive)
|
||||
@ -1141,7 +1141,7 @@ Have fun!
|
||||
|
||||
def set_save_data_style(self, s: int) -> None:
|
||||
self.save_data_style = self.cbSaveDataStyle.itemData(s)
|
||||
self.options[0].internal_save_data_style = self.save_data_style
|
||||
self.config[0].internal_save_data_style = self.save_data_style
|
||||
self.update_style_tweaks()
|
||||
self.update_menus()
|
||||
|
||||
@ -1360,15 +1360,15 @@ Have fun!
|
||||
|
||||
def show_settings(self) -> None:
|
||||
|
||||
settingswin = SettingsWindow(self, self.options, self.talker_api)
|
||||
settingswin = SettingsWindow(self, self.config, self.talker_api)
|
||||
settingswin.setModal(True)
|
||||
settingswin.exec()
|
||||
settingswin.result()
|
||||
|
||||
def set_app_position(self) -> None:
|
||||
if self.options[0].internal_window_width != 0:
|
||||
self.move(self.options[0].internal_window_x, self.options[0].internal_window_y)
|
||||
self.resize(self.options[0].internal_window_width, self.options[0].internal_window_height)
|
||||
if self.config[0].internal_window_width != 0:
|
||||
self.move(self.config[0].internal_window_x, self.config[0].internal_window_y)
|
||||
self.resize(self.config[0].internal_window_width, self.config[0].internal_window_height)
|
||||
else:
|
||||
screen = QtGui.QGuiApplication.primaryScreen().geometry()
|
||||
size = self.frameGeometry()
|
||||
@ -1635,8 +1635,8 @@ Have fun!
|
||||
if ca.has_metadata(src_style) and ca.is_writable():
|
||||
md = ca.read_metadata(src_style)
|
||||
|
||||
if dest_style == MetaDataStyle.CBI and self.options[0].cbl_apply_transform_on_bulk_operation:
|
||||
md = CBLTransformer(md, self.options[0]).apply()
|
||||
if dest_style == MetaDataStyle.CBI and self.config[0].cbl_apply_transform_on_bulk_operation:
|
||||
md = CBLTransformer(md, self.config[0]).apply()
|
||||
|
||||
if not ca.write_metadata(md, dest_style):
|
||||
failed_list.append(ca.path)
|
||||
@ -1674,8 +1674,8 @@ Have fun!
|
||||
logger.exception("Save aborted.")
|
||||
|
||||
if not ct_md.is_empty:
|
||||
if self.options[0].cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options[0]).apply()
|
||||
if self.config[0].cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.config[0]).apply()
|
||||
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
|
||||
@ -1694,7 +1694,7 @@ Have fun!
|
||||
self, ca: ComicArchive, match_results: OnlineMatchResults, dlg: AutoTagStartWindow
|
||||
) -> tuple[bool, OnlineMatchResults]:
|
||||
success = False
|
||||
ii = IssueIdentifier(ca, self.options[0], self.talker_api)
|
||||
ii = IssueIdentifier(ca, self.config[0], self.talker_api)
|
||||
|
||||
# read in metadata, and parse file name if not there
|
||||
try:
|
||||
@ -1704,10 +1704,10 @@ Have fun!
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
if md.is_empty:
|
||||
md = ca.metadata_from_filename(
|
||||
self.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
self.config[0].filename_complicated_parser,
|
||||
self.config[0].filename_remove_c2c,
|
||||
self.config[0].filename_remove_fcbd,
|
||||
self.config[0].filename_remove_publisher,
|
||||
dlg.split_words,
|
||||
)
|
||||
if dlg.ignore_leading_digits_in_filename and md.series is not None:
|
||||
@ -1793,7 +1793,7 @@ Have fun!
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options[0].talkers_auto_imprint:
|
||||
if self.config[0].talkers_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
if not ca.write_metadata(md, self.save_data_style):
|
||||
@ -1822,10 +1822,10 @@ Have fun!
|
||||
|
||||
atstartdlg = AutoTagStartWindow(
|
||||
self,
|
||||
self.options[0],
|
||||
self.config[0],
|
||||
(
|
||||
f"You have selected {len(ca_list)} archive(s) to automatically identify and write {MetaDataStyle.name[style]} tags to."
|
||||
"\n\nPlease choose options below, and select OK to Auto-Tag."
|
||||
"\n\nPlease choose config below, and select OK to Auto-Tag."
|
||||
),
|
||||
)
|
||||
|
||||
@ -1925,7 +1925,7 @@ Have fun!
|
||||
match_results.multiple_matches,
|
||||
style,
|
||||
self.actual_issue_data_fetch,
|
||||
self.options[0],
|
||||
self.config[0],
|
||||
self.talker_api,
|
||||
)
|
||||
matchdlg.setModal(True)
|
||||
@ -1971,17 +1971,17 @@ Have fun!
|
||||
f"Exit {self.appName}", "If you quit now, data in the form will be lost. Are you sure?"
|
||||
):
|
||||
appsize = self.size()
|
||||
self.options[0].internal_window_width = appsize.width()
|
||||
self.options[0].internal_window_height = appsize.height()
|
||||
self.options[0].internal_window_x = self.x()
|
||||
self.options[0].internal_window_y = self.y()
|
||||
self.options[0].internal_form_width = self.splitter.sizes()[0]
|
||||
self.options[0].internal_list_width = self.splitter.sizes()[1]
|
||||
self.config[0].internal_window_width = appsize.width()
|
||||
self.config[0].internal_window_height = appsize.height()
|
||||
self.config[0].internal_window_x = self.x()
|
||||
self.config[0].internal_window_y = self.y()
|
||||
self.config[0].internal_form_width = self.splitter.sizes()[0]
|
||||
self.config[0].internal_list_width = self.splitter.sizes()[1]
|
||||
(
|
||||
self.options[0].internal_sort_column,
|
||||
self.options[0].internal_sort_direction,
|
||||
self.config[0].internal_sort_column,
|
||||
self.config[0].internal_sort_direction,
|
||||
) = self.fileSelectionList.get_sorting()
|
||||
settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json")
|
||||
settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json")
|
||||
|
||||
event.accept()
|
||||
else:
|
||||
@ -2030,7 +2030,7 @@ Have fun!
|
||||
|
||||
def apply_cbl_transform(self) -> None:
|
||||
self.form_to_metadata()
|
||||
self.metadata = CBLTransformer(self.metadata, self.options[0]).apply()
|
||||
self.metadata = CBLTransformer(self.metadata, self.config[0]).apply()
|
||||
self.metadata_to_form()
|
||||
|
||||
def recalc_page_dimensions(self) -> None:
|
||||
@ -2056,7 +2056,7 @@ Have fun!
|
||||
"File Rename", "If you rename files now, unsaved data in the form will be lost. Are you sure?"
|
||||
):
|
||||
|
||||
dlg = RenameWindow(self, ca_list, self.load_data_style, self.options, self.talker_api)
|
||||
dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.talker_api)
|
||||
dlg.setModal(True)
|
||||
if dlg.exec() and self.comic_archive is not None:
|
||||
self.fileSelectionList.update_selected_rows()
|
||||
@ -2075,7 +2075,7 @@ Have fun!
|
||||
QtCore.QTimer.singleShot(1, self.fileSelectionList.revert_selection)
|
||||
return
|
||||
|
||||
self.options[0].internal_last_opened_folder = os.path.abspath(os.path.split(comic_archive.path)[0])
|
||||
self.config[0].internal_last_opened_folder = os.path.abspath(os.path.split(comic_archive.path)[0])
|
||||
self.comic_archive = comic_archive
|
||||
try:
|
||||
self.metadata = self.comic_archive.read_metadata(self.load_data_style)
|
||||
@ -2106,10 +2106,10 @@ Have fun!
|
||||
|
||||
def check_latest_version_online(self) -> None:
|
||||
version_checker = VersionChecker()
|
||||
self.version_check_complete(version_checker.get_latest_version(self.options[0].internal_install_id))
|
||||
self.version_check_complete(version_checker.get_latest_version(self.config[0].internal_install_id))
|
||||
|
||||
def version_check_complete(self, new_version: tuple[str, str]) -> None:
|
||||
if new_version[0] not in (self.version, self.options[0].dialog_dont_notify_about_this_version):
|
||||
if new_version[0] not in (self.version, self.config[0].dialog_dont_notify_about_this_version):
|
||||
website = "https://github.com/comictagger/comictagger"
|
||||
checked = OptionalMessageDialog.msg(
|
||||
self,
|
||||
@ -2120,7 +2120,7 @@ Have fun!
|
||||
"Don't tell me about this version again",
|
||||
)
|
||||
if checked:
|
||||
self.options[0].dialog_dont_notify_about_this_version = new_version[0]
|
||||
self.config[0].dialog_dont_notify_about_this_version = new_version[0]
|
||||
|
||||
def on_incoming_socket_connection(self) -> None:
|
||||
# Accept connection from other instance.
|
||||
|
@ -37,7 +37,7 @@ class SourceDetails:
|
||||
self.logo = logo
|
||||
|
||||
|
||||
class SourceStaticOptions:
|
||||
class SourceStaticSettings:
|
||||
def __init__(
|
||||
self,
|
||||
website: str = "",
|
||||
@ -143,7 +143,7 @@ class ComicTalker:
|
||||
def __init__(self, version: str, cache_folder: pathlib.Path) -> None:
|
||||
# Identity name for the information source etc.
|
||||
self.source_details = SourceDetails()
|
||||
self.static_options = SourceStaticOptions()
|
||||
self.static_config = SourceStaticSettings()
|
||||
self.cache_folder = cache_folder
|
||||
self.version = version
|
||||
self.api_key: str = ""
|
||||
|
@ -34,7 +34,7 @@ from comicapi.genericmetadata import GenericMetadata
|
||||
from comicapi.issuestring import IssueString
|
||||
from comictalker.comiccacher import ComicCacher
|
||||
from comictalker.resulttypes import ComicIssue, ComicSeries, Credit
|
||||
from comictalker.talkerbase import ComicTalker, SourceDetails, SourceStaticOptions, TalkerDataError, TalkerNetworkError
|
||||
from comictalker.talkerbase import ComicTalker, SourceDetails, SourceStaticSettings, TalkerDataError, TalkerNetworkError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -165,7 +165,7 @@ class ComicVineTalker(ComicTalker):
|
||||
ident="comicvine",
|
||||
logo="https://comicvine.gamespot.com/a/bundles/comicvinesite/images/logo.png",
|
||||
)
|
||||
self.static_options = SourceStaticOptions(
|
||||
self.static_config = SourceStaticSettings(
|
||||
website="https://comicvine.gamespot.com/",
|
||||
attribution_string="Metadata provided by <a href='https://comicvine.gamespot.com/'>Comic Vine</a>",
|
||||
has_issues=True,
|
||||
|
@ -123,7 +123,7 @@ def test_invalid_zip(tmp_comic):
|
||||
|
||||
archivers = [
|
||||
pytest.param(x.load(), marks=pytest.mark.xfail(not (x.load().enabled), reason="archiver not enabled"))
|
||||
for x in entry_points(group="comicapi_archivers")
|
||||
for x in entry_points(group="comicapi.archiver")
|
||||
]
|
||||
|
||||
|
||||
|
@ -6,10 +6,10 @@ import comictalker.comiccacher
|
||||
from testing.comicdata import search_results
|
||||
|
||||
|
||||
def test_create_cache(options, mock_version):
|
||||
settings, definitions = options
|
||||
comictalker.comiccacher.ComicCacher(settings.runtime_config.user_cache_dir, mock_version[0])
|
||||
assert (settings.runtime_config.user_cache_dir).exists()
|
||||
def test_create_cache(config, mock_version):
|
||||
config, definitions = config
|
||||
comictalker.comiccacher.ComicCacher(config.runtime_config.user_cache_dir, mock_version[0])
|
||||
assert (config.runtime_config.user_cache_dir).exists()
|
||||
|
||||
|
||||
def test_search_results(comic_cache):
|
||||
@ -25,9 +25,5 @@ def test_search_results(comic_cache):
|
||||
def test_series_info(comic_cache, series_info):
|
||||
comic_cache.add_series_info(series_record=series_info, source_name="test")
|
||||
vi = series_info.copy()
|
||||
# del vi["description"]
|
||||
# del vi["image_url"]
|
||||
cache_result = comic_cache.get_series_info(series_id=series_info.id, source_name="test")
|
||||
# del cache_result["description"]
|
||||
# del cache_result["image_url"]
|
||||
assert vi == cache_result
|
||||
|
@ -14,7 +14,7 @@ from PIL import Image
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.ctoptions
|
||||
import comictaggerlib.ctsettings
|
||||
import comictalker.comiccacher
|
||||
import comictalker.comictalkerapi
|
||||
import comictalker.talkers.comicvine
|
||||
@ -56,9 +56,7 @@ def no_requests(monkeypatch) -> None:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def comicvine_api(
|
||||
monkeypatch, cbz, comic_cache, mock_version, options
|
||||
) -> comictalker.talkers.comicvine.ComicVineTalker:
|
||||
def comicvine_api(monkeypatch, cbz, comic_cache, mock_version, config) -> comictalker.talkers.comicvine.ComicVineTalker:
|
||||
# Any arguments may be passed and mock_get() will always return our
|
||||
# mocked object, which only has the .json() method or None for invalid urls.
|
||||
|
||||
@ -118,7 +116,7 @@ def comicvine_api(
|
||||
|
||||
cv = comictalker.talkers.comicvine.ComicVineTalker(
|
||||
version=mock_version[0],
|
||||
cache_folder=options[0].runtime_config.user_cache_dir,
|
||||
cache_folder=config[0].runtime_config.user_cache_dir,
|
||||
)
|
||||
return cv
|
||||
|
||||
@ -158,12 +156,12 @@ def seed_all_publishers(monkeypatch):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def options(settings_manager, tmp_path):
|
||||
def config(settings_manager, tmp_path):
|
||||
|
||||
comictaggerlib.ctoptions.register_commandline(settings_manager)
|
||||
comictaggerlib.ctoptions.register_settings(settings_manager)
|
||||
comictaggerlib.ctsettings.register_commandline_settings(settings_manager)
|
||||
comictaggerlib.ctsettings.register_file_settings(settings_manager)
|
||||
defaults = settings_manager.get_namespace(settings_manager.defaults())
|
||||
defaults[0].runtime_config = comictaggerlib.ctoptions.ComicTaggerPaths(tmp_path / "config")
|
||||
defaults[0].runtime_config = comictaggerlib.ctsettings.ComicTaggerPaths(tmp_path / "config")
|
||||
defaults[0].runtime_config.user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults[0].runtime_config.user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults[0].runtime_config.user_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
@ -179,5 +177,5 @@ def settings_manager():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def comic_cache(options, mock_version) -> Generator[comictalker.comiccacher.ComicCacher, Any, None]:
|
||||
yield comictalker.comiccacher.ComicCacher(options[0].runtime_config.user_cache_dir, mock_version[0])
|
||||
def comic_cache(config, mock_version) -> Generator[comictalker.comiccacher.ComicCacher, Any, None]:
|
||||
yield comictalker.comiccacher.ComicCacher(config[0].runtime_config.user_cache_dir, mock_version[0])
|
||||
|
@ -12,9 +12,9 @@ import testing.comicdata
|
||||
import testing.comicvine
|
||||
|
||||
|
||||
def test_crop(cbz_double_cover, options, tmp_path, comicvine_api):
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, settings, comicvine_api)
|
||||
def test_crop(cbz_double_cover, config, tmp_path, comicvine_api):
|
||||
config, definitions = config
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, config, comicvine_api)
|
||||
cropped = ii.crop_cover(cbz_double_cover.archiver.read_file("double_cover.jpg"))
|
||||
original_cover = cbz_double_cover.get_page(0)
|
||||
|
||||
@ -25,17 +25,17 @@ def test_crop(cbz_double_cover, options, tmp_path, comicvine_api):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("additional_md, expected", testing.comicdata.metadata_keys)
|
||||
def test_get_search_keys(cbz, options, additional_md, expected, comicvine_api):
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
def test_get_search_keys(cbz, config, additional_md, expected, comicvine_api):
|
||||
config, definitions = config
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api)
|
||||
ii.set_additional_metadata(additional_md)
|
||||
|
||||
assert expected == ii.get_search_keys()
|
||||
|
||||
|
||||
def test_get_issue_cover_match_score(cbz, options, comicvine_api):
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
def test_get_issue_cover_match_score(cbz, config, comicvine_api):
|
||||
config, definitions = config
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api)
|
||||
score = ii.get_issue_cover_match_score(
|
||||
int(
|
||||
comicapi.issuestring.IssueString(
|
||||
@ -54,9 +54,9 @@ def test_get_issue_cover_match_score(cbz, options, comicvine_api):
|
||||
assert expected == score
|
||||
|
||||
|
||||
def test_search(cbz, options, comicvine_api):
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
def test_search(cbz, config, comicvine_api):
|
||||
config, definitions = config
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api)
|
||||
results = ii.search()
|
||||
cv_expected = {
|
||||
"series": f"{testing.comicvine.cv_volume_result['results']['name']} ({testing.comicvine.cv_volume_result['results']['start_year']})",
|
||||
@ -78,9 +78,9 @@ def test_search(cbz, options, comicvine_api):
|
||||
assert r == e
|
||||
|
||||
|
||||
def test_crop_border(cbz, options, comicvine_api):
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
def test_crop_border(cbz, config, comicvine_api):
|
||||
config, definitions = config
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api)
|
||||
|
||||
# This creates a white square centered on a black background
|
||||
bg = Image.new("RGBA", (100, 100), (0, 0, 0, 255))
|
||||
|
Loading…
Reference in New Issue
Block a user