Update to settngs 0.3.0
Use the namespace instead of a dictionary Cleanup setting names
This commit is contained in:
parent
e5c3692bb9
commit
440479da8c
@ -42,7 +42,7 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
match_set_list: list[MultipleMatch],
|
||||
style: int,
|
||||
fetch_func: Callable[[IssueResult], GenericMetadata],
|
||||
options: settngs.ConfigValues,
|
||||
options: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
@ -54,10 +54,7 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
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, options.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
@ -245,10 +242,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.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
)
|
||||
|
||||
# now get the particular issue data
|
||||
|
@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, options: settngs.ConfigValues, msg: str) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget, options: settngs.Namespace, msg: str) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "autotagstartwindow.ui", self)
|
||||
@ -40,16 +40,16 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
|
||||
self.cbxSpecifySearchString.setChecked(False)
|
||||
self.cbxSplitWords.setChecked(False)
|
||||
self.sbNameMatchSearchThresh.setValue(self.options["identifier"]["series_match_identify_thresh"])
|
||||
self.sbNameMatchSearchThresh.setValue(self.options.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["comicvine"]["auto_imprint"])
|
||||
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.comicvine_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["comicvine"]["series_match_search_thresh"]
|
||||
self.name_length_match_tolerance = self.options.comicvine_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.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
|
||||
|
||||
if self.cbxSpecifySearchString.isChecked():
|
||||
self.search_string = self.leSearchString.text()
|
||||
|
@ -25,7 +25,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CBLTransformer:
|
||||
def __init__(self, metadata: GenericMetadata, options: settngs.ConfigValues) -> None:
|
||||
def __init__(self, metadata: GenericMetadata, options: settngs.Namespace) -> None:
|
||||
self.metadata = metadata
|
||||
self.options = options
|
||||
|
||||
@ -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.options.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.options.cbl_copy_characters_to_tags:
|
||||
add_string_list_to_tags(self.metadata.characters)
|
||||
|
||||
if self.options["cbl"]["copy_teams_to_tags"]:
|
||||
if self.options.cbl_copy_teams_to_tags:
|
||||
add_string_list_to_tags(self.metadata.teams)
|
||||
|
||||
if self.options["cbl"]["copy_locations_to_tags"]:
|
||||
if self.options.cbl_copy_locations_to_tags:
|
||||
add_string_list_to_tags(self.metadata.locations)
|
||||
|
||||
if self.options["cbl"]["copy_storyarcs_to_tags"]:
|
||||
if self.options.cbl_copy_storyarcs_to_tags:
|
||||
add_string_list_to_tags(self.metadata.story_arc)
|
||||
|
||||
if self.options["cbl"]["copy_notes_to_comments"]:
|
||||
if self.options.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.options.cbl_copy_weblink_to_comments:
|
||||
if self.metadata.web_link is not None:
|
||||
if self.metadata.comments is None:
|
||||
self.metadata.comments = ""
|
||||
|
@ -53,14 +53,14 @@ class CLI:
|
||||
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
||||
return GenericMetadata()
|
||||
|
||||
if self.options["cbl"]["apply_cbl_transform_on_cv_import"]:
|
||||
if self.options.cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options).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.options.runtime_dryrun:
|
||||
for metadata_style in self.options.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"]["terse"]:
|
||||
if self.options.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.options.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["comicvine"]["clear_metadata_on_import"]:
|
||||
if self.options.comicvine_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["comicvine"]["auto_imprint"]:
|
||||
if self.options.comicvine_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"]["show_save_summary"]:
|
||||
if self.options.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"]["show_save_summary"] and not self.options["runtime"]["interactive"]:
|
||||
if not self.options.runtime_summary and not self.options.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.options.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.options.runtime_file_list) > 1
|
||||
|
||||
for f in self.options["runtime"]["file_list"]:
|
||||
for f in self.options.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.options.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.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
self.options.runtime_split_words,
|
||||
)
|
||||
|
||||
md.overlay(f_md)
|
||||
|
||||
for metadata_style in self.options["runtime"]["type"]:
|
||||
for metadata_style in self.options.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.options.runtime_metadata)
|
||||
|
||||
return md
|
||||
|
||||
def print(self, ca: ComicArchive) -> None:
|
||||
if not self.options["runtime"]["type"]:
|
||||
if not self.options.runtime_type:
|
||||
page_count = ca.get_number_of_pages()
|
||||
|
||||
brief = ""
|
||||
@ -246,38 +246,38 @@ class CLI:
|
||||
|
||||
print(brief)
|
||||
|
||||
if self.options["runtime"]["terse"]:
|
||||
if self.options.runtime_quiet:
|
||||
return
|
||||
|
||||
print()
|
||||
|
||||
if not self.options["runtime"]["type"] or MetaDataStyle.CIX in self.options["runtime"]["type"]:
|
||||
if not self.options.runtime_type or MetaDataStyle.CIX in self.options.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.CIX):
|
||||
print("--------- ComicRack tags ---------")
|
||||
try:
|
||||
if self.options["runtime"]["raw"]:
|
||||
if self.options.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.options.runtime_type or MetaDataStyle.CBI in self.options.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.CBI):
|
||||
print("------- ComicBookLover tags -------")
|
||||
try:
|
||||
if self.options["runtime"]["raw"]:
|
||||
if self.options.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.options.runtime_type or MetaDataStyle.COMET in self.options.runtime_type:
|
||||
if ca.has_metadata(MetaDataStyle.COMET):
|
||||
print("----------- CoMet tags -----------")
|
||||
try:
|
||||
if self.options["runtime"]["raw"]:
|
||||
if self.options.runtime_raw:
|
||||
print(ca.read_raw_comet())
|
||||
else:
|
||||
print(ca.read_comet())
|
||||
@ -285,10 +285,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.options.runtime_type:
|
||||
style_name = MetaDataStyle.name[metadata_style]
|
||||
if ca.has_metadata(metadata_style):
|
||||
if not self.options["runtime"]["dryrun"]:
|
||||
if not self.options.runtime_dryrun:
|
||||
if not ca.remove_metadata(metadata_style):
|
||||
print(f"{ca.path}: Tag removal seemed to fail!")
|
||||
else:
|
||||
@ -299,25 +299,25 @@ 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.options.runtime_type:
|
||||
dst_style_name = MetaDataStyle.name[metadata_style]
|
||||
if self.options["runtime"]["no_overwrite"] and ca.has_metadata(metadata_style):
|
||||
if not self.options.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.options.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.options.commands_copy]
|
||||
if ca.has_metadata(self.options.commands_copy):
|
||||
if not self.options.runtime_dryrun:
|
||||
try:
|
||||
md = ca.read_metadata(self.options["commands"]["copy"])
|
||||
md = ca.read_metadata(self.options.commands_copy)
|
||||
except Exception as e:
|
||||
md = GenericMetadata()
|
||||
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
||||
|
||||
if self.options["apply_cbl_transform_on_bulk_operation"] and metadata_style == MetaDataStyle.CBI:
|
||||
if self.options.apply_transform_on_bulk_operation_ndetadata_style == MetaDataStyle.CBI:
|
||||
md = CBLTransformer(md, self.options).apply()
|
||||
|
||||
if not ca.write_metadata(md, metadata_style):
|
||||
@ -330,8 +330,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 self.options["runtime"]["no_overwrite"]:
|
||||
for metadata_style in self.options["runtime"]["type"]:
|
||||
if not self.options.runtime_overwrite:
|
||||
for metadata_style in self.options.runtime_type:
|
||||
if ca.has_metadata(metadata_style):
|
||||
print(f"{ca.path}: Already has {MetaDataStyle.name[metadata_style]} tags. Not overwriting.")
|
||||
return
|
||||
@ -341,26 +341,26 @@ 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.options.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.options.runtime_online:
|
||||
if self.options.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.options.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.options.runtime_issue_id)
|
||||
match_results.no_matches.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.options["cbl"]["apply_cbl_transform_on_cv_import"]:
|
||||
if self.options.cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options).apply()
|
||||
else:
|
||||
if md is None or md.is_empty:
|
||||
@ -371,7 +371,7 @@ class CLI:
|
||||
ii = IssueIdentifier(ca, self.options, self.talker_api)
|
||||
|
||||
def myoutput(text: str) -> None:
|
||||
if self.options["runtime"]["verbose"]:
|
||||
if self.options.runtime_verbose:
|
||||
IssueIdentifier.default_write_output(text)
|
||||
|
||||
# use our overlaid MD struct to search
|
||||
@ -411,7 +411,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.options.runtime_abort_on_low_confidence:
|
||||
logger.error("Online search: Low confidence match. Save aborted")
|
||||
match_results.low_confidence_matches.append(MultipleMatch(ca, matches))
|
||||
return
|
||||
@ -428,7 +428,7 @@ class CLI:
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.options["comicvine"]["clear_metadata_on_import"]:
|
||||
if self.options.comicvine_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -437,7 +437,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options["comicvine"]["auto_imprint"]:
|
||||
if self.options.comicvine_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
# ok, done building our metadata. time to save
|
||||
@ -459,7 +459,7 @@ class CLI:
|
||||
return
|
||||
|
||||
new_ext = "" # default
|
||||
if self.options["filename"]["rename_set_extension_based_on_archive"]:
|
||||
if self.options.filename_rename_set_extension_based_on_archive:
|
||||
if ca.is_sevenzip():
|
||||
new_ext = ".cb7"
|
||||
elif ca.is_zip():
|
||||
@ -469,13 +469,13 @@ class CLI:
|
||||
|
||||
renamer = FileRenamer(
|
||||
md,
|
||||
platform="universal" if self.options["filename"]["rename_strict"] else "auto",
|
||||
replacements=self.options["rename"]["replacements"],
|
||||
platform="universal" if self.options.filename_rename_strict else "auto",
|
||||
replacements=self.options.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.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
|
||||
|
||||
try:
|
||||
new_name = renamer.determine_name(ext=new_ext)
|
||||
@ -487,16 +487,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.options.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.options.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.options.filename_rename_dir if self.options.filename_rename_move_to_dir else None
|
||||
)
|
||||
|
||||
full_path = folder / new_name
|
||||
@ -506,7 +506,7 @@ class CLI:
|
||||
return
|
||||
|
||||
suffix = ""
|
||||
if not self.options["runtime"]["dryrun"]:
|
||||
if not self.options.runtime_dryrun:
|
||||
# rename the file
|
||||
try:
|
||||
ca.rename(utils.unique_file(full_path))
|
||||
@ -529,7 +529,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.options.runtime_abort_on_conflict and new_file.exists():
|
||||
print(msg_hdr + f"{new_file.name} already exists in the that folder.")
|
||||
return
|
||||
|
||||
@ -537,10 +537,10 @@ class CLI:
|
||||
|
||||
delete_success = False
|
||||
export_success = False
|
||||
if not self.options["runtime"]["dryrun"]:
|
||||
if not self.options.runtime_dryrun:
|
||||
if ca.export_as_zip(new_file):
|
||||
export_success = True
|
||||
if self.options["runtime"]["delete_after_zip_export"]:
|
||||
if self.options.runtime_delete_after_zip_export:
|
||||
try:
|
||||
filename_path.unlink(missing_ok=True)
|
||||
delete_success = True
|
||||
@ -552,7 +552,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.options.runtime_delete_after_zip_export:
|
||||
msg += " and delete original."
|
||||
print(msg)
|
||||
return
|
||||
@ -560,7 +560,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.options.runtime_delete_after_zip_export and delete_success:
|
||||
msg += " (Original deleted) "
|
||||
else:
|
||||
msg += "Archive failed to export!"
|
||||
@ -572,35 +572,35 @@ class CLI:
|
||||
logger.error("Cannot find %s", filename)
|
||||
return
|
||||
|
||||
ca = ComicArchive(filename, self.options["general"]["rar_exe_path"], str(graphics_path / "nocover.png"))
|
||||
ca = ComicArchive(filename, self.options.general_rar_exe_path, str(graphics_path / "nocover.png"))
|
||||
|
||||
if not ca.seems_to_be_a_comic_archive():
|
||||
logger.error("Sorry, but %s is not a comic archive!", filename)
|
||||
return
|
||||
|
||||
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.options.commands_delete
|
||||
or self.options.commands_copy
|
||||
or self.options.commands_save
|
||||
or self.options.commands_rename
|
||||
):
|
||||
logger.error("This archive is not writable")
|
||||
return
|
||||
|
||||
if self.options["commands"]["print"]:
|
||||
if self.options.commands_print:
|
||||
self.print(ca)
|
||||
|
||||
elif self.options["commands"]["delete"]:
|
||||
elif self.options.commands_delete:
|
||||
self.delete(ca)
|
||||
|
||||
elif self.options["commands"]["copy"] is not None:
|
||||
elif self.options.commands_copy is not None:
|
||||
self.copy(ca)
|
||||
|
||||
elif self.options["commands"]["save"]:
|
||||
elif self.options.commands_save:
|
||||
self.save(ca, match_results)
|
||||
|
||||
elif self.options["commands"]["rename"]:
|
||||
elif self.options.commands_rename:
|
||||
self.rename(ca)
|
||||
|
||||
elif self.options["commands"]["export_to_zip"]:
|
||||
elif self.options.commands_export_to_zip:
|
||||
self.export(ca)
|
||||
|
@ -116,17 +116,18 @@ def register_options(parser: settngs.Manager) -> None:
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting(
|
||||
"--noabort",
|
||||
"--abort",
|
||||
dest="abort_on_low_confidence",
|
||||
action="store_false",
|
||||
help="""Don't abort save operation when online match\nis of low confidence.\n\n""",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
help="""Abort save operation when online match\nis of low confidence.\n\n""",
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting(
|
||||
"--nosummary",
|
||||
dest="show_save_summary",
|
||||
action="store_false",
|
||||
help="Suppress the default summary after a save operation.\n\n",
|
||||
"--summary",
|
||||
default=True,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Show the summary after a save operation.\n\n",
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting(
|
||||
@ -175,7 +176,8 @@ def register_options(parser: settngs.Manager) -> None:
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting(
|
||||
"--terse",
|
||||
"--quiet",
|
||||
"-q",
|
||||
action="store_true",
|
||||
help="Don't say much (for print mode).",
|
||||
file=False,
|
||||
@ -191,10 +193,11 @@ def register_options(parser: settngs.Manager) -> None:
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting(
|
||||
"--no-overwrite",
|
||||
dest="no_overwrite",
|
||||
action="store_true",
|
||||
help="""Don't modify tag block if it already exists (relevant for -s or -c).""",
|
||||
"--overwrite",
|
||||
dest="overwrite",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
help="""Apply metadata to already tagged archives (relevant for -s or -c).""",
|
||||
file=False,
|
||||
)
|
||||
parser.add_setting("files", nargs="*", file=False)
|
||||
@ -264,78 +267,78 @@ def register_commandline(parser: settngs.Manager) -> None:
|
||||
parser.add_group("runtime", register_options)
|
||||
|
||||
|
||||
def validate_commandline_options(options: settngs.Values, parser: settngs.Manager) -> settngs.Values:
|
||||
def validate_commandline_options(options: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values:
|
||||
|
||||
if options["commands"]["version"]:
|
||||
if options[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["runtime"]["no_gui"] = any(
|
||||
options[0].runtime_no_gui = any(
|
||||
[
|
||||
options["commands"]["print"],
|
||||
options["commands"]["delete"],
|
||||
options["commands"]["save"],
|
||||
options["commands"]["copy"],
|
||||
options["commands"]["rename"],
|
||||
options["commands"]["export_to_zip"],
|
||||
options["commands"]["only_set_cv_key"],
|
||||
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,
|
||||
]
|
||||
)
|
||||
|
||||
if platform.system() == "Windows" and options["runtime"]["glob"]:
|
||||
if platform.system() == "Windows" and options[0].runtime_glob:
|
||||
# no globbing on windows shell, so do it for them
|
||||
import glob
|
||||
|
||||
globs = options["runtime"]["files"]
|
||||
options["runtime"]["files"] = []
|
||||
globs = options[0].runtime_files
|
||||
options[0].runtime_files = []
|
||||
for item in globs:
|
||||
options["runtime"]["files"].extend(glob.glob(item))
|
||||
options[0].runtime_files.extend(glob.glob(item))
|
||||
|
||||
if (
|
||||
options["commands"]["only_set_cv_key"]
|
||||
and options["comicvine"]["cv_api_key"] is None
|
||||
and options["comicvine"]["cv_url"] is None
|
||||
options[0].commands_only_set_cv_key
|
||||
and options[0].comicvine_cv_api_key is None
|
||||
and options[0].comicvine_cv_url is None
|
||||
):
|
||||
parser.exit(message="Key not given!\n", status=1)
|
||||
|
||||
if not options["commands"]["only_set_cv_key"] and options["runtime"]["no_gui"] and not options["runtime"]["files"]:
|
||||
if not options[0].commands_only_set_cv_key and options[0].runtime_no_gui and not options[0].runtime_files:
|
||||
parser.exit(message="Command requires at least one filename!\n", status=1)
|
||||
|
||||
if options["commands"]["delete"] and not options["runtime"]["type"]:
|
||||
if options[0].commands_delete and not options[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to delete with -t\n", status=1)
|
||||
|
||||
if options["commands"]["save"] and not options["runtime"]["type"]:
|
||||
if options[0].commands_save and not options[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to save with -t\n", status=1)
|
||||
|
||||
if options["commands"]["copy"]:
|
||||
if not options["runtime"]["type"]:
|
||||
if options[0].commands_copy:
|
||||
if not options[0].runtime_type:
|
||||
parser.exit(message="Please specify the type to copy to with -t\n", status=1)
|
||||
if len(options["commands"]["copy"]) > 1:
|
||||
if len(options[0].commands_copy) > 1:
|
||||
parser.exit(message="Please specify only one type to copy to with -c\n", status=1)
|
||||
options["commands"]["copy"] = options["commands"]["copy"][0]
|
||||
options[0].commands_copy = options[0].commands_copy[0]
|
||||
|
||||
if options["runtime"]["recursive"]:
|
||||
options["runtime"]["file_list"] = utils.get_recursive_filelist(options["runtime"]["files"])
|
||||
if options[0].runtime_recursive:
|
||||
options[0].runtime_file_list = utils.get_recursive_filelist(options[0].runtime_files)
|
||||
else:
|
||||
options["runtime"]["file_list"] = options["runtime"]["files"]
|
||||
options[0].runtime_file_list = options[0].runtime_files
|
||||
|
||||
# take a crack at finding rar exe, if not set already
|
||||
if options["general"]["rar_exe_path"].strip() in ("", "rar"):
|
||||
if options[0].general_rar_exe_path.strip() in ("", "rar"):
|
||||
if platform.system() == "Windows":
|
||||
# look in some likely places for Windows machines
|
||||
if os.path.exists(r"C:\Program Files\WinRAR\Rar.exe"):
|
||||
options["general"]["rar_exe_path"] = r"C:\Program Files\WinRAR\Rar.exe"
|
||||
options[0].general_rar_exe_path = r"C:\Program Files\WinRAR\Rar.exe"
|
||||
elif os.path.exists(r"C:\Program Files (x86)\WinRAR\Rar.exe"):
|
||||
options["general"]["rar_exe_path"] = r"C:\Program Files (x86)\WinRAR\Rar.exe"
|
||||
options[0].general_rar_exe_path = r"C:\Program Files (x86)\WinRAR\Rar.exe"
|
||||
else:
|
||||
if os.path.exists("/opt/homebrew/bin"):
|
||||
utils.add_to_path("/opt/homebrew/bin")
|
||||
# see if it's in the path of unix user
|
||||
rarpath = utils.which("rar")
|
||||
if rarpath is not None:
|
||||
options["general"]["rar_exe_path"] = "rar"
|
||||
options[0].general_rar_exe_path = "rar"
|
||||
|
||||
return options
|
||||
|
@ -26,17 +26,17 @@ def general(parser: settngs.Manager) -> None:
|
||||
def internal(parser: settngs.Manager) -> None:
|
||||
# automatic settings
|
||||
parser.add_setting("install_id", default=uuid.uuid4().hex, cmdline=False)
|
||||
parser.add_setting("last_selected_save_data_style", default=0, cmdline=False)
|
||||
parser.add_setting("last_selected_load_data_style", default=0, cmdline=False)
|
||||
parser.add_setting("save_data_style", default=0, cmdline=False)
|
||||
parser.add_setting("load_data_style", default=0, cmdline=False)
|
||||
parser.add_setting("last_opened_folder", default="", cmdline=False)
|
||||
parser.add_setting("last_main_window_width", default=0, cmdline=False)
|
||||
parser.add_setting("last_main_window_height", default=0, cmdline=False)
|
||||
parser.add_setting("last_main_window_x", default=0, cmdline=False)
|
||||
parser.add_setting("last_main_window_y", default=0, cmdline=False)
|
||||
parser.add_setting("last_form_side_width", default=-1, cmdline=False)
|
||||
parser.add_setting("last_list_side_width", default=-1, cmdline=False)
|
||||
parser.add_setting("last_filelist_sorted_column", default=-1, cmdline=False)
|
||||
parser.add_setting("last_filelist_sorted_order", default=0, cmdline=False)
|
||||
parser.add_setting("window_width", default=0, cmdline=False)
|
||||
parser.add_setting("window_height", default=0, cmdline=False)
|
||||
parser.add_setting("window_x", default=0, cmdline=False)
|
||||
parser.add_setting("window_y", default=0, cmdline=False)
|
||||
parser.add_setting("form_width", default=-1, cmdline=False)
|
||||
parser.add_setting("list_width", default=-1, cmdline=False)
|
||||
parser.add_setting("sort_column", default=-1, cmdline=False)
|
||||
parser.add_setting("sort_direction", default=0, cmdline=False)
|
||||
|
||||
|
||||
def identifier(parser: settngs.Manager) -> None:
|
||||
@ -155,8 +155,8 @@ def cbl(parser: settngs.Manager) -> None:
|
||||
parser.add_setting("--copy-storyarcs-to-tags", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--copy-notes-to-comments", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--copy-weblink-to-comments", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--apply-cbl-transform-on-cv-import", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--apply-cbl-transform-on-bulk-operation", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--apply-transform-on-import", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting("--apply-transform-on-bulk-operation", default=False, action=argparse.BooleanOptionalAction)
|
||||
|
||||
|
||||
def rename(parser: settngs.Manager) -> None:
|
||||
@ -175,14 +175,16 @@ def rename(parser: settngs.Manager) -> None:
|
||||
help="Attempts to intelligently cleanup whitespace when renaming",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--set-extension-based-on-archive",
|
||||
"--auto-extension",
|
||||
dest="set_extension_based_on_archive",
|
||||
default=True,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Automatically sets the extension based on the archive type e.g. cbr for rar, cbz for zip",
|
||||
)
|
||||
parser.add_setting("--dir", default="", help="The directory to move renamed files to")
|
||||
parser.add_setting(
|
||||
"--move-to-dir",
|
||||
"--move",
|
||||
dest="move_to_dir",
|
||||
default=False,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Enables moving renamed files to a separate directory",
|
||||
@ -231,7 +233,7 @@ def autotag(parser: settngs.Manager) -> None:
|
||||
parser.add_setting("remove_archive_after_successful_match", default=False, cmdline=False)
|
||||
parser.add_setting(
|
||||
"-w",
|
||||
"--wait-on-cv-rate-limit",
|
||||
"--wait-on-rate-limit",
|
||||
dest="wait_and_retry_on_rate_limit",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
@ -239,13 +241,11 @@ def autotag(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_settings(options: dict[str, dict[str, Any]], parser: settngs.Manager) -> dict[str, dict[str, Any]]:
|
||||
options["identifier"]["publisher_filter"] = [
|
||||
x.strip() for x in options["identifier"]["publisher_filter"] if x.strip()
|
||||
]
|
||||
options["rename"]["replacements"] = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in options["rename"]["replacements"][0]],
|
||||
[Replacement(x[0], x[1], x[2]) for x in options["rename"]["replacements"][1]],
|
||||
def validate_settings(options: settngs.Config[settngs.Values], parser: settngs.Manager) -> 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]],
|
||||
)
|
||||
return options
|
||||
|
||||
|
@ -57,10 +57,7 @@ class FileSelectionList(QtWidgets.QWidget):
|
||||
dataColNum = fileColNum
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent: QtWidgets.QWidget,
|
||||
options: settngs.ConfigValues,
|
||||
dirty_flag_verification: Callable[[str, str], bool],
|
||||
self, parent: QtWidgets.QWidget, options: settngs.Namespace, dirty_flag_verification: Callable[[str, str], bool]
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@ -227,7 +224,7 @@ class FileSelectionList(QtWidgets.QWidget):
|
||||
else:
|
||||
QtWidgets.QMessageBox.information(self, "File/Folder Open", "No readable comic archives were found.")
|
||||
|
||||
if rar_added and not utils.which(self.options["general"]["rar_exe_path"] or "rar"):
|
||||
if rar_added and not utils.which(self.options.general_rar_exe_path or "rar"):
|
||||
self.rar_ro_message()
|
||||
|
||||
self.twList.setSortingEnabled(True)
|
||||
@ -281,7 +278,7 @@ class FileSelectionList(QtWidgets.QWidget):
|
||||
if self.is_list_dupe(path):
|
||||
return self.get_current_list_row(path)
|
||||
|
||||
ca = ComicArchive(path, self.options["general"]["rar_exe_path"], str(graphics_path / "nocover.png"))
|
||||
ca = ComicArchive(path, self.options.general_rar_exe_path, str(graphics_path / "nocover.png"))
|
||||
|
||||
if ca.seems_to_be_a_comic_archive():
|
||||
row: int = self.twList.rowCount()
|
||||
|
@ -82,10 +82,12 @@ except ImportError as e:
|
||||
qt_available = False
|
||||
|
||||
|
||||
def open_tagger_window(talker_api: ComicTalker, options: settngs.Config, error: tuple[str, bool] | None) -> None:
|
||||
def open_tagger_window(
|
||||
talker_api: ComicTalker, options: 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 options[0].runtime_darkmode:
|
||||
args.extend(["-platform", "windows:darkmode=2"])
|
||||
args.extend(sys.argv)
|
||||
app = Application(args)
|
||||
@ -95,7 +97,7 @@ def open_tagger_window(talker_api: ComicTalker, options: settngs.Config, error:
|
||||
raise SystemExit(1)
|
||||
|
||||
# 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: options[0].runtime_files.append(x.toLocalFile()))
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
# Set the MacOS dock icon
|
||||
@ -123,7 +125,7 @@ def open_tagger_window(talker_api: ComicTalker, options: settngs.Config, error:
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
try:
|
||||
tagger_window = TaggerWindow(options[0]["runtime"]["files"], options, talker_api)
|
||||
tagger_window = TaggerWindow(options[0].runtime_files, options, talker_api)
|
||||
tagger_window.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png")))
|
||||
tagger_window.show()
|
||||
|
||||
|
@ -72,7 +72,7 @@ class IssueIdentifier:
|
||||
result_one_good_match = 4
|
||||
result_multiple_good_matches = 5
|
||||
|
||||
def __init__(self, comic_archive: ComicArchive, options: settngs.ConfigValues, talker_api: ComicTalker) -> None:
|
||||
def __init__(self, comic_archive: ComicArchive, options: settngs.Namespace, talker_api: ComicTalker) -> None:
|
||||
self.options = options
|
||||
self.talker_api = talker_api
|
||||
self.comic_archive: ComicArchive = comic_archive
|
||||
@ -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 = options.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 options.identifier_publisher_filter]
|
||||
|
||||
self.additional_metadata = GenericMetadata()
|
||||
self.output_function: Callable[[str], None] = IssueIdentifier.default_write_output
|
||||
@ -201,10 +201,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.options.filename_complicated_parser,
|
||||
self.options.filename_remove_c2c,
|
||||
self.options.filename_remove_fcbd,
|
||||
self.options.filename_remove_publisher,
|
||||
)
|
||||
|
||||
working_md = md_from_filename.copy()
|
||||
@ -255,7 +255,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.options.runtime_config.user_cache_dir).fetch(
|
||||
primary_thumb_url, blocking=True
|
||||
)
|
||||
except ImageFetcherException as e:
|
||||
@ -277,7 +277,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.options.runtime_config.user_cache_dir).fetch(
|
||||
alt_url, blocking=True
|
||||
)
|
||||
except ImageFetcherException as e:
|
||||
|
@ -44,7 +44,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
def __init__(
|
||||
self,
|
||||
parent: QtWidgets.QWidget,
|
||||
options: settngs.ConfigValues,
|
||||
options: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
series_id: int,
|
||||
issue_number: str,
|
||||
@ -54,10 +54,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, options.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.coverImageContainer)
|
||||
gridlayout.addWidget(self.coverWidget)
|
||||
|
@ -21,7 +21,6 @@ import logging.handlers
|
||||
import platform
|
||||
import signal
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
import settngs
|
||||
|
||||
@ -50,8 +49,8 @@ logger = logging.getLogger("comictagger")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def update_publishers(options: dict[str, dict[str, Any]]) -> None:
|
||||
json_file = options["runtime"]["config"].user_config_dir / "publishers.json"
|
||||
def update_publishers(options: settngs.Namespace) -> None:
|
||||
json_file = options.runtime_config.user_config_dir / "publishers.json"
|
||||
if json_file.exists():
|
||||
try:
|
||||
utils.update_publishers(json.loads(json_file.read_text("utf-8")))
|
||||
@ -91,23 +90,26 @@ class App:
|
||||
ctoptions.register_settings(self.manager)
|
||||
|
||||
def parse_options(self, config_paths: ctoptions.ComicTaggerPaths) -> None:
|
||||
config, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json")
|
||||
options, definitions = config
|
||||
options = ctoptions.validate_commandline_options(options, self.manager)
|
||||
options = ctoptions.validate_settings(options, self.manager)
|
||||
self.options = settngs.Config(options, definitions)
|
||||
self.options, self.config_load_success = self.manager.parse_config(
|
||||
config_paths.user_config_dir / "settings.json"
|
||||
)
|
||||
self.options = self.manager.get_namespace(self.options)
|
||||
|
||||
self.options = ctoptions.validate_commandline_options(self.options, self.manager)
|
||||
self.options = ctoptions.validate_settings(self.options, self.manager)
|
||||
self.options = self.options
|
||||
|
||||
def initialize_dirs(self) -> None:
|
||||
self.options[0]["runtime"]["config"].user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0]["runtime"]["config"].user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0]["runtime"]["config"].user_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0]["runtime"]["config"].user_state_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0]["runtime"]["config"].user_log_dir.mkdir(parents=True, exist_ok=True)
|
||||
logger.debug("user_data_dir: %s", self.options[0]["runtime"]["config"].user_data_dir)
|
||||
logger.debug("user_config_dir: %s", self.options[0]["runtime"]["config"].user_config_dir)
|
||||
logger.debug("user_cache_dir: %s", self.options[0]["runtime"]["config"].user_cache_dir)
|
||||
logger.debug("user_state_dir: %s", self.options[0]["runtime"]["config"].user_state_dir)
|
||||
logger.debug("user_log_dir: %s", self.options[0]["runtime"]["config"].user_log_dir)
|
||||
self.options[0].runtime_config.user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0].runtime_config.user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0].runtime_config.user_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0].runtime_config.user_state_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0].runtime_config.user_log_dir.mkdir(parents=True, exist_ok=True)
|
||||
logger.debug("user_data_dir: %s", self.options[0].runtime_config.user_data_dir)
|
||||
logger.debug("user_config_dir: %s", self.options[0].runtime_config.user_config_dir)
|
||||
logger.debug("user_cache_dir: %s", self.options[0].runtime_config.user_cache_dir)
|
||||
logger.debug("user_state_dir: %s", self.options[0].runtime_config.user_state_dir)
|
||||
logger.debug("user_log_dir: %s", self.options[0].runtime_config.user_log_dir)
|
||||
|
||||
def main(self) -> None:
|
||||
assert self.options is not None
|
||||
@ -130,18 +132,18 @@ class App:
|
||||
utils.load_publishers()
|
||||
update_publishers(self.options[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.options[0].runtime_no_gui:
|
||||
self.options[0].runtime_no_gui = True
|
||||
logger.warning("PyQt5 is not available. ComicTagger is limited to command-line mode.")
|
||||
|
||||
# manage the CV API key
|
||||
# None comparison is used so that the empty string can unset the value
|
||||
if self.options[0]["comicvine"]["cv_api_key"] is not None or self.options[0]["comicvine"]["cv_url"] is not None:
|
||||
settings_path = self.options[0]["runtime"]["config"].user_config_dir / "settings.json"
|
||||
if self.options[0].comicvine_cv_api_key is not None or self.options[0].comicvine_cv_url is not None:
|
||||
settings_path = self.options[0].runtime_config.user_config_dir / "settings.json"
|
||||
if self.config_load_success:
|
||||
self.manager.save_file(self.options[0], settings_path)
|
||||
|
||||
if self.options[0]["commands"]["only_set_cv_key"]:
|
||||
if self.options[0].commands_only_set_cv_key:
|
||||
if self.config_load_success:
|
||||
print("Key set") # noqa: T201
|
||||
return
|
||||
@ -149,13 +151,13 @@ class App:
|
||||
try:
|
||||
talker_api = ct_api.get_comic_talker("comicvine")( # type: ignore[call-arg]
|
||||
version=version,
|
||||
cache_folder=self.options[0]["runtime"]["config"].user_cache_dir,
|
||||
series_match_thresh=self.options[0]["comicvine"]["series_match_search_thresh"],
|
||||
remove_html_tables=self.options[0]["comicvine"]["remove_html_tables"],
|
||||
use_series_start_as_volume=self.options[0]["comicvine"]["use_series_start_as_volume"],
|
||||
wait_on_ratelimit=self.options[0]["autotag"]["wait_and_retry_on_rate_limit"],
|
||||
api_url=self.options[0]["comicvine"]["cv_url"],
|
||||
api_key=self.options[0]["comicvine"]["cv_api_key"],
|
||||
cache_folder=self.options[0].runtime_config.user_cache_dir,
|
||||
series_match_thresh=self.options[0].comicvine_series_match_search_thresh,
|
||||
remove_html_tables=self.options[0].comicvine_remove_html_tables,
|
||||
use_series_start_as_volume=self.options[0].comicvine_use_series_start_as_volume,
|
||||
wait_on_ratelimit=self.options[0].autotag_wait_and_retry_on_rate_limit,
|
||||
api_url=self.options[0].comicvine_cv_url,
|
||||
api_key=self.options[0].comicvine_cv_api_key,
|
||||
)
|
||||
except TalkerError as e:
|
||||
logger.exception("Unable to load talker")
|
||||
@ -163,10 +165,10 @@ class App:
|
||||
|
||||
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.options[0].runtime_config.user_log_dir}' for more details",
|
||||
True,
|
||||
)
|
||||
if self.options[0]["runtime"]["no_gui"]:
|
||||
if self.options[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)
|
||||
|
@ -47,10 +47,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, options.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
|
@ -61,19 +61,19 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
self.rename_list: list[str] = []
|
||||
|
||||
self.btnSettings.clicked.connect(self.modify_settings)
|
||||
platform = "universal" if self.options[0]["filename"]["rename_strict"] else "auto"
|
||||
self.renamer = FileRenamer(None, platform=platform, replacements=self.options[0]["rename"]["replacements"])
|
||||
platform = "universal" if self.options[0].filename_rename_strict else "auto"
|
||||
self.renamer = FileRenamer(None, platform=platform, replacements=self.options[0].rename_replacements)
|
||||
|
||||
self.do_preview()
|
||||
|
||||
def config_renamer(self, ca: ComicArchive, md: GenericMetadata | None = None) -> str:
|
||||
self.renamer.set_template(self.options[0]["filename"]["rename_template"])
|
||||
self.renamer.set_issue_zero_padding(self.options[0]["filename"]["rename_issue_number_padding"])
|
||||
self.renamer.set_smart_cleanup(self.options[0]["filename"]["rename_use_smart_string_cleanup"])
|
||||
self.renamer.replacements = self.options[0]["rename"]["replacements"]
|
||||
self.renamer.set_template(self.options[0].filename_rename_template)
|
||||
self.renamer.set_issue_zero_padding(self.options[0].filename_rename_issue_number_padding)
|
||||
self.renamer.set_smart_cleanup(self.options[0].filename_rename_use_smart_string_cleanup)
|
||||
self.renamer.replacements = self.options[0].rename_replacements
|
||||
|
||||
new_ext = ca.path.suffix # default
|
||||
if self.options[0]["filename"]["rename_set_extension_based_on_archive"]:
|
||||
if self.options[0].filename_rename_set_extension_based_on_archive:
|
||||
if ca.is_sevenzip():
|
||||
new_ext = ".cb7"
|
||||
elif ca.is_zip():
|
||||
@ -85,13 +85,13 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
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.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
)
|
||||
self.renamer.set_metadata(md)
|
||||
self.renamer.move = self.options[0]["filename"]["rename_move_to_dir"]
|
||||
self.renamer.move = self.options[0].filename_rename_move_to_dir
|
||||
return new_ext
|
||||
|
||||
def do_preview(self) -> None:
|
||||
@ -104,7 +104,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]["filename"]["rename_template"])
|
||||
logger.exception("Invalid format string: %s", self.options[0].filename_rename_template)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
"Invalid format string!",
|
||||
@ -119,7 +119,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
"Formatter failure: %s metadata: %s",
|
||||
self.options[0]["filename"]["rename_template"],
|
||||
self.options[0].filename_rename_template,
|
||||
self.renamer.metadata,
|
||||
)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
@ -197,9 +197,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
|
||||
folder = get_rename_dir(
|
||||
comic[0],
|
||||
self.options[0]["filename"]["rename_dir"]
|
||||
if self.options[0]["filename"]["rename_move_to_dir"]
|
||||
else None,
|
||||
self.options[0].filename_rename_dir if self.options[0].filename_rename_move_to_dir else None,
|
||||
)
|
||||
|
||||
full_path = folder / comic[1]
|
||||
|
@ -269,54 +269,50 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
|
||||
def settings_to_form(self) -> None:
|
||||
# Copy values from settings to form
|
||||
self.leRarExePath.setText(self.options[0]["general"]["rar_exe_path"])
|
||||
self.sbNameMatchIdentifyThresh.setValue(self.options[0]["identifier"]["series_match_identify_thresh"])
|
||||
self.sbNameMatchSearchThresh.setValue(self.options[0]["comicvine"]["series_match_search_thresh"])
|
||||
self.tePublisherFilter.setPlainText("\n".join(self.options[0]["identifier"]["publisher_filter"]))
|
||||
self.leRarExePath.setText(self.options[0].general_rar_exe_path)
|
||||
self.sbNameMatchIdentifyThresh.setValue(self.options[0].identifier_series_match_identify_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.options[0].comicvine_series_match_search_thresh)
|
||||
self.tePublisherFilter.setPlainText("\n".join(self.options[0].identifier_publisher_filter))
|
||||
|
||||
self.cbxCheckForNewVersion.setChecked(self.options[0]["general"]["check_for_new_version"])
|
||||
self.cbxCheckForNewVersion.setChecked(self.options[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.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.switch_parser()
|
||||
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.options[0]["comicvine"]["use_series_start_as_volume"])
|
||||
self.cbxClearFormBeforePopulating.setChecked(
|
||||
self.options[0]["comicvine"]["clear_form_before_populating_from_cv"]
|
||||
)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.options[0]["comicvine"]["remove_html_tables"])
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.options[0].comicvine_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.options[0].comicvine_clear_form_before_populating_from_cv)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.options[0].comicvine_remove_html_tables)
|
||||
|
||||
self.cbxUseFilter.setChecked(self.options[0]["comicvine"]["always_use_publisher_filter"])
|
||||
self.cbxSortByYear.setChecked(self.options[0]["comicvine"]["sort_series_by_year"])
|
||||
self.cbxExactMatches.setChecked(self.options[0]["comicvine"]["exact_series_matches_first"])
|
||||
self.cbxUseFilter.setChecked(self.options[0].comicvine_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.options[0].comicvine_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.options[0].comicvine_exact_series_matches_first)
|
||||
|
||||
self.leKey.setText(self.options[0]["comicvine"]["cv_api_key"])
|
||||
self.leURL.setText(self.options[0]["comicvine"]["cv_url"])
|
||||
self.leKey.setText(self.options[0].comicvine_cv_api_key)
|
||||
self.leURL.setText(self.options[0].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_cbl_transform_on_cv_import"])
|
||||
self.cbxApplyCBLTransformOnBatchOperation.setChecked(
|
||||
self.options[0]["cbl"]["apply_cbl_transform_on_bulk_operation"]
|
||||
)
|
||||
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.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.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)
|
||||
|
||||
for table, replacments in zip(
|
||||
(self.twLiteralReplacements, self.twValueReplacements), self.options[0]["rename"]["replacements"]
|
||||
(self.twLiteralReplacements, self.twValueReplacements), self.options[0].rename_replacements
|
||||
):
|
||||
table.clearContents()
|
||||
for i in reversed(range(table.rowCount())):
|
||||
@ -351,7 +347,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.options[0].rename_template)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
"Invalid format string!",
|
||||
@ -365,7 +361,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.options[0].rename_template, self.renamer.metadata
|
||||
)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
@ -378,71 +374,65 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
# Copy values from form to settings and save
|
||||
self.options[0]["general"]["rar_exe_path"] = str(self.leRarExePath.text())
|
||||
self.options[0].general_rar_exe_path = str(self.leRarExePath.text())
|
||||
|
||||
# make sure rar program is now in the path for the rar class
|
||||
if self.options[0]["general"]["rar_exe_path"]:
|
||||
utils.add_to_path(os.path.dirname(self.options[0]["general"]["rar_exe_path"]))
|
||||
if self.options[0].general_rar_exe_path:
|
||||
utils.add_to_path(os.path.dirname(self.options[0].general_rar_exe_path))
|
||||
|
||||
if not str(self.leIssueNumPadding.text()).isdigit():
|
||||
self.leIssueNumPadding.setText("0")
|
||||
|
||||
self.options[0]["general"]["check_for_new_version"] = self.cbxCheckForNewVersion.isChecked()
|
||||
self.options[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked()
|
||||
|
||||
self.options[0]["identifier"]["series_match_identify_thresh"] = self.sbNameMatchIdentifyThresh.value()
|
||||
self.options[0]["comicvine"]["series_match_search_thresh"] = self.sbNameMatchSearchThresh.value()
|
||||
self.options[0]["identifier"]["publisher_filter"] = [
|
||||
self.options[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value()
|
||||
self.options[0].comicvine_series_match_search_thresh = self.sbNameMatchSearchThresh.value()
|
||||
self.options[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.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.options[0]["comicvine"]["use_series_start_as_volume"] = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.options[0]["comicvine"][
|
||||
"clear_form_before_populating_from_cv"
|
||||
] = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.options[0]["comicvine"]["remove_html_tables"] = self.cbxRemoveHtmlTables.isChecked()
|
||||
self.options[0].comicvine_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.options[0].comicvine_clear_form_before_populating_from_cv = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.options[0].comicvine_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
|
||||
self.options[0]["comicvine"]["always_use_publisher_filter"] = self.cbxUseFilter.isChecked()
|
||||
self.options[0]["comicvine"]["sort_series_by_year"] = self.cbxSortByYear.isChecked()
|
||||
self.options[0]["comicvine"]["exact_series_matches_first"] = self.cbxExactMatches.isChecked()
|
||||
self.options[0].comicvine_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.options[0].comicvine_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.options[0].comicvine_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
|
||||
if self.leKey.text().strip():
|
||||
self.options[0]["comicvine"]["cv_api_key"] = self.leKey.text().strip()
|
||||
self.talker_api.api_key = self.options[0]["comicvine"]["cv_api_key"]
|
||||
self.options[0].comicvine_cv_api_key = self.leKey.text().strip()
|
||||
self.talker_api.api_key = self.options[0].comicvine_cv_api_key
|
||||
|
||||
if self.leURL.text().strip():
|
||||
self.options[0]["comicvine"]["cv_url"] = self.leURL.text().strip()
|
||||
self.talker_api.api_url = self.options[0]["comicvine"]["cv_url"]
|
||||
self.options[0].comicvine_cv_url = self.leURL.text().strip()
|
||||
self.talker_api.api_url = self.options[0].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_cbl_transform_on_cv_import"] = self.cbxApplyCBLTransformOnCVIMport.isChecked()
|
||||
self.options[0]["cbl"][
|
||||
"apply_cbl_transform_on_bulk_operation"
|
||||
] = self.cbxApplyCBLTransformOnBatchOperation.isChecked()
|
||||
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.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.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.options[0]["rename"]["strict"] = self.cbxRenameStrict.isChecked()
|
||||
self.options[0]["rename"]["replacements"] = self.get_replacemnts()
|
||||
self.options[0].rename_strict = self.cbxRenameStrict.isChecked()
|
||||
self.options[0].rename_replacements = self.get_replacemnts()
|
||||
|
||||
settngs.save_file(
|
||||
self.options[0], self.options[1], self.options[0]["runtime"]["config"].user_config_dir / "settings.json"
|
||||
)
|
||||
settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json")
|
||||
self.parent().options = self.options
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
@ -450,8 +440,8 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.select_file(self.leRarExePath, "RAR")
|
||||
|
||||
def clear_cache(self) -> None:
|
||||
ImageFetcher(self.options[0]["runtime"]["config"].cache_folder).clear_cache()
|
||||
ComicCacher(self.options[0]["runtime"]["config"].cache_folder, version).clear_cache()
|
||||
ImageFetcher(self.options[0].runtime_config.cache_folder).clear_cache()
|
||||
ComicCacher(self.options[0].runtime_config.cache_folder, version).clear_cache()
|
||||
QtWidgets.QMessageBox.information(self, self.name, "Cache has been cleared.")
|
||||
|
||||
def test_api_key(self) -> None:
|
||||
|
@ -87,18 +87,16 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
|
||||
uic.loadUi(ui_path / "taggerwindow.ui", self)
|
||||
self.options = options
|
||||
if not options:
|
||||
self.options = ({}, {})
|
||||
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(options[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", options[0].internal_install_id)
|
||||
# send file list to other instance
|
||||
if file_list:
|
||||
socket.write(pickle.dumps(file_list))
|
||||
@ -110,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(options[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(options[0].internal_install_id)
|
||||
ok = self.socketServer.listen(options[0].internal_install_id)
|
||||
if not ok:
|
||||
logger.error(
|
||||
"Cannot start local socket with key [%s]. Reason: %s",
|
||||
options[0]["internal"]["install_id"],
|
||||
options[0].internal_install_id,
|
||||
self.socketServer.errorString(),
|
||||
)
|
||||
sys.exit()
|
||||
@ -139,8 +137,8 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
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"]["last_filelist_sorted_column"],
|
||||
QtCore.Qt.SortOrder(self.options[0]["internal"]["last_filelist_sorted_order"]),
|
||||
self.options[0].internal_sort_column,
|
||||
QtCore.Qt.SortOrder(self.options[0].internal_sort_direction),
|
||||
)
|
||||
|
||||
# we can't specify relative font sizes in the UI designer, so
|
||||
@ -158,13 +156,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 options[0].runtime_type and isinstance(options[0].runtime_type[0], int):
|
||||
# respect the command line option tag type
|
||||
options[0]["internal"]["last_selected_save_data_style"] = options[0]["runtime"]["type"][0]
|
||||
options[0]["internal"]["last_selected_load_data_style"] = options[0]["runtime"]["type"][0]
|
||||
options[0].internal_save_data_style = options[0].runtime_type[0]
|
||||
options[0].internal_load_data_style = options[0].runtime_type[0]
|
||||
|
||||
self.save_data_style = options[0]["internal"]["last_selected_save_data_style"]
|
||||
self.load_data_style = options[0]["internal"]["last_selected_load_data_style"]
|
||||
self.save_data_style = options[0].internal_save_data_style
|
||||
self.load_data_style = options[0].internal_load_data_style
|
||||
|
||||
self.setAcceptDrops(True)
|
||||
self.config_menus()
|
||||
@ -229,13 +227,8 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.show()
|
||||
self.set_app_position()
|
||||
if self.options[0]["internal"]["last_form_side_width"] != -1:
|
||||
self.splitter.setSizes(
|
||||
[
|
||||
self.options[0]["internal"]["last_form_side_width"],
|
||||
self.options[0]["internal"]["last_list_side_width"],
|
||||
]
|
||||
)
|
||||
if self.options[0].internal_form_width != -1:
|
||||
self.splitter.setSizes([self.options[0].internal_form_width, self.options[0].internal_list_width])
|
||||
self.raise_()
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
self.resizeEvent(None)
|
||||
@ -252,7 +245,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.options[0].dialog_show_disclaimer:
|
||||
checked = OptionalMessageDialog.msg(
|
||||
self,
|
||||
"Welcome!",
|
||||
@ -267,9 +260,9 @@ use ComicTagger on local copies of your comics.<br><br>
|
||||
Have fun!
|
||||
""",
|
||||
)
|
||||
self.options[0]["dialog"]["show_disclaimer"] = not checked
|
||||
self.options[0].dialog_show_disclaimer = not checked
|
||||
|
||||
if self.options[0]["general"]["check_for_new_version"]:
|
||||
if self.options[0].general_check_for_new_version:
|
||||
self.check_latest_version_online()
|
||||
|
||||
def open_file_event(self, url: QtCore.QUrl) -> None:
|
||||
@ -282,7 +275,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.options[0].runtime_config.user_log_dir / "ComicTagger.log").read_text("utf-8")
|
||||
except Exception:
|
||||
current_logs = ""
|
||||
root_logger = logging.getLogger()
|
||||
@ -615,10 +608,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.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[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())
|
||||
@ -986,10 +979,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.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
split_words,
|
||||
)
|
||||
if new_metadata is not None:
|
||||
@ -1010,8 +1003,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.options[0].internal_last_opened_folder is not None:
|
||||
dialog.setDirectory(self.options[0].internal_last_opened_folder)
|
||||
|
||||
if not folder_mode:
|
||||
archive_filter = "Comic archive files (*.cbz *.zip *.cbr *.rar *.cb7 *.7z)"
|
||||
@ -1093,10 +1086,10 @@ Have fun!
|
||||
else:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
if new_metadata is not None:
|
||||
if self.options[0]["cbl"]["apply_cbl_transform_on_cv_import"]:
|
||||
if self.options[0].cbl_apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.options[0]).apply()
|
||||
|
||||
if self.options[0]["comicvine"]["clear_form_before_populating_from_cv"]:
|
||||
if self.options[0].comicvine_clear_form_before_populating_from_cv:
|
||||
self.clear_form()
|
||||
|
||||
notes = (
|
||||
@ -1151,7 +1144,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"]["last_selected_load_data_style"] = self.load_data_style
|
||||
self.options[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)
|
||||
@ -1162,7 +1155,7 @@ Have fun!
|
||||
|
||||
def set_save_data_style(self, s: int) -> None:
|
||||
self.save_data_style = self.cbSaveDataStyle.itemData(s)
|
||||
self.options[0]["internal"]["last_selected_save_data_style"] = self.save_data_style
|
||||
self.options[0].internal_save_data_style = self.save_data_style
|
||||
self.update_style_tweaks()
|
||||
self.update_menus()
|
||||
|
||||
@ -1387,14 +1380,9 @@ Have fun!
|
||||
settingswin.result()
|
||||
|
||||
def set_app_position(self) -> None:
|
||||
if self.options[0]["internal"]["last_main_window_width"] != 0:
|
||||
self.move(
|
||||
self.options[0]["internal"]["last_main_window_x"], self.options[0]["internal"]["last_main_window_y"]
|
||||
)
|
||||
self.resize(
|
||||
self.options[0]["internal"]["last_main_window_width"],
|
||||
self.options[0]["internal"]["last_main_window_height"],
|
||||
)
|
||||
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)
|
||||
else:
|
||||
screen = QtGui.QGuiApplication.primaryScreen().geometry()
|
||||
size = self.frameGeometry()
|
||||
@ -1661,10 +1649,7 @@ 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_cbl_transform_on_bulk_operation"]
|
||||
):
|
||||
if dest_style == MetaDataStyle.CBI and self.options[0].cbl_apply_transform_on_bulk_operation:
|
||||
md = CBLTransformer(md, self.options[0]).apply()
|
||||
|
||||
if not ca.write_metadata(md, dest_style):
|
||||
@ -1703,7 +1688,7 @@ Have fun!
|
||||
logger.exception("Save aborted.")
|
||||
|
||||
if not ct_md.is_empty:
|
||||
if self.options[0]["cbl"]["apply_cbl_transform_on_cv_import"]:
|
||||
if self.options[0].cbl_apply_transform_on_import:
|
||||
ct_md = CBLTransformer(ct_md, self.options[0]).apply()
|
||||
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
@ -1733,10 +1718,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.options[0].filename_complicated_parser,
|
||||
self.options[0].filename_remove_c2c,
|
||||
self.options[0].filename_remove_fcbd,
|
||||
self.options[0].filename_remove_publisher,
|
||||
dlg.split_words,
|
||||
)
|
||||
if dlg.ignore_leading_digits_in_filename and md.series is not None:
|
||||
@ -1822,7 +1807,7 @@ Have fun!
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options[0]["comicvine"]["auto_imprint"]:
|
||||
if self.options[0].comicvine_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
if not ca.write_metadata(md, self.save_data_style):
|
||||
@ -2000,19 +1985,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"]["last_main_window_width"] = appsize.width()
|
||||
self.options[0]["internal"]["last_main_window_height"] = appsize.height()
|
||||
self.options[0]["internal"]["last_main_window_x"] = self.x()
|
||||
self.options[0]["internal"]["last_main_window_y"] = self.y()
|
||||
self.options[0]["internal"]["last_form_side_width"] = self.splitter.sizes()[0]
|
||||
self.options[0]["internal"]["last_list_side_width"] = self.splitter.sizes()[1]
|
||||
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.options[0]["internal"]["last_filelist_sorted_column"],
|
||||
self.options[0]["internal"]["last_filelist_sorted_order"],
|
||||
self.options[0].internal_sort_column,
|
||||
self.options[0].internal_sort_direction,
|
||||
) = self.fileSelectionList.get_sorting()
|
||||
settngs.save_file(
|
||||
self.options[0], self.options[1], self.options[0]["runtime"]["config"].user_config_dir / "settings.json"
|
||||
)
|
||||
settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json")
|
||||
|
||||
event.accept()
|
||||
else:
|
||||
@ -2106,7 +2089,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.options[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)
|
||||
@ -2139,12 +2122,12 @@ Have fun!
|
||||
version_checker = VersionChecker()
|
||||
self.version_check_complete(
|
||||
version_checker.get_latest_version(
|
||||
self.options[0]["internal"]["install_id"], self.options[0]["general"]["send_usage_stats"]
|
||||
self.options[0].internal_install_id, self.options[0].general_send_usage_stats
|
||||
)
|
||||
)
|
||||
|
||||
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.options[0].dialog_dont_notify_about_this_version):
|
||||
website = "https://github.com/comictagger/comictagger"
|
||||
checked = OptionalMessageDialog.msg(
|
||||
self,
|
||||
@ -2155,7 +2138,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.options[0].dialog_dont_notify_about_this_version = new_version[0]
|
||||
|
||||
def on_incoming_socket_connection(self) -> None:
|
||||
# Accept connection from other instance.
|
||||
|
@ -111,7 +111,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
|
||||
issue_count: int,
|
||||
cover_index_list: list[int],
|
||||
comic_archive: ComicArchive | None,
|
||||
options: settngs.ConfigValues,
|
||||
options: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
autoselect: bool = False,
|
||||
literal: bool = False,
|
||||
@ -121,7 +121,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "volumeselectionwindow.ui", self)
|
||||
|
||||
self.imageWidget = CoverImageWidget(
|
||||
self.imageContainer, CoverImageWidget.URLMode, options["runtime"]["config"].user_cache_dir, talker_api
|
||||
self.imageContainer, CoverImageWidget.URLMode, options.runtime_config.user_cache_dir, talker_api
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.imageContainer)
|
||||
gridlayout.addWidget(self.imageWidget)
|
||||
@ -156,7 +156,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
|
||||
self.progdialog: QtWidgets.QProgressDialog | None = None
|
||||
self.search_thread: SearchThread | None = None
|
||||
|
||||
self.use_filter = self.options["comicvine"]["always_use_publisher_filter"]
|
||||
self.use_filter = self.options.comicvine_always_use_publisher_filter
|
||||
|
||||
# Load to retrieve settings
|
||||
self.talker_api = talker_api
|
||||
@ -326,11 +326,7 @@ class VolumeSelectionWindow(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["comicvine"]["series_match_search_thresh"],
|
||||
self.talker_api, self.series_name, refresh, self.literal, self.options.comicvine_series_match_search_thresh
|
||||
)
|
||||
self.search_thread.searchComplete.connect(self.search_complete)
|
||||
self.search_thread.progressUpdate.connect(self.search_progress_update)
|
||||
@ -382,7 +378,7 @@ class VolumeSelectionWindow(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.options.identifier_publisher_filter}
|
||||
# use '' as publisher name if None
|
||||
self.ct_search_results = list(
|
||||
filter(
|
||||
@ -398,7 +394,7 @@ class VolumeSelectionWindow(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["comicvine"]["sort_series_by_year"]:
|
||||
if self.options.comicvine_sort_series_by_year:
|
||||
try:
|
||||
self.ct_search_results = sorted(
|
||||
self.ct_search_results,
|
||||
@ -416,7 +412,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
|
||||
logger.exception("bad data error sorting results by count_of_issues")
|
||||
|
||||
# move sanitized matches to the front
|
||||
if self.options["comicvine"]["exact_series_matches_first"]:
|
||||
if self.options.comicvine_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()
|
||||
|
@ -8,7 +8,7 @@ pycountry
|
||||
pyicu; sys_platform == 'linux' or sys_platform == 'darwin'
|
||||
rapidfuzz>=2.12.0
|
||||
requests==2.*
|
||||
settngs==0.2.0
|
||||
settngs==0.3.0
|
||||
text2digits
|
||||
typing_extensions
|
||||
wordninja
|
||||
|
@ -7,8 +7,9 @@ from testing.comicdata import search_results
|
||||
|
||||
|
||||
def test_create_cache(options, mock_version):
|
||||
comictalker.comiccacher.ComicCacher(options["runtime"]["config"].user_cache_dir, mock_version[0])
|
||||
assert (options["runtime"]["config"].user_cache_dir).exists()
|
||||
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_search_results(comic_cache):
|
||||
|
@ -117,7 +117,7 @@ def comicvine_api(
|
||||
|
||||
cv = comictalker.talkers.comicvine.ComicVineTalker(
|
||||
version=mock_version[0],
|
||||
cache_folder=options["runtime"]["config"].user_cache_dir,
|
||||
cache_folder=options[0].runtime_config.user_cache_dir,
|
||||
api_url="",
|
||||
api_key="",
|
||||
series_match_thresh=90,
|
||||
@ -167,13 +167,13 @@ def options(settings_manager, tmp_path):
|
||||
|
||||
comictaggerlib.ctoptions.register_commandline(settings_manager)
|
||||
comictaggerlib.ctoptions.register_settings(settings_manager)
|
||||
defaults = settings_manager.defaults()
|
||||
defaults["runtime"]["config"] = comictaggerlib.ctoptions.ComicTaggerPaths(tmp_path / "config")
|
||||
defaults["runtime"]["config"].user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults["runtime"]["config"].user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults["runtime"]["config"].user_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults["runtime"]["config"].user_state_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults["runtime"]["config"].user_log_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults = settings_manager.get_namespace(settings_manager.defaults())
|
||||
defaults[0].runtime_config = comictaggerlib.ctoptions.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)
|
||||
defaults[0].runtime_config.user_state_dir.mkdir(parents=True, exist_ok=True)
|
||||
defaults[0].runtime_config.user_log_dir.mkdir(parents=True, exist_ok=True)
|
||||
yield defaults
|
||||
|
||||
|
||||
@ -185,4 +185,4 @@ def settings_manager():
|
||||
|
||||
@pytest.fixture
|
||||
def comic_cache(options, mock_version) -> Generator[comictalker.comiccacher.ComicCacher, Any, None]:
|
||||
yield comictalker.comiccacher.ComicCacher(options["runtime"]["config"].user_cache_dir, mock_version[0])
|
||||
yield comictalker.comiccacher.ComicCacher(options[0].runtime_config.user_cache_dir, mock_version[0])
|
||||
|
@ -10,7 +10,8 @@ import testing.comicvine
|
||||
|
||||
|
||||
def test_crop(cbz_double_cover, options, tmp_path, comicvine_api):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, options, comicvine_api)
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, settings, comicvine_api)
|
||||
cropped = ii.crop_cover(cbz_double_cover.archiver.read_file("double_cover.jpg"))
|
||||
original_cover = cbz_double_cover.get_page(0)
|
||||
|
||||
@ -22,14 +23,16 @@ 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):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, options, comicvine_api)
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, 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):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, options, comicvine_api)
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
score = ii.get_issue_cover_match_score(
|
||||
int(
|
||||
comicapi.issuestring.IssueString(
|
||||
@ -50,7 +53,8 @@ def test_get_issue_cover_match_score(cbz, options, comicvine_api):
|
||||
|
||||
|
||||
def test_search(cbz, options, comicvine_api):
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, options, comicvine_api)
|
||||
settings, definitions = options
|
||||
ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api)
|
||||
results = ii.search()
|
||||
cv_expected = {
|
||||
"series": f"{testing.comicvine.cv_volume_result['results']['name']} ({testing.comicvine.cv_volume_result['results']['start_year']})",
|
||||
|
Loading…
Reference in New Issue
Block a user