From ad68726e1d2af0dd1de38e27ac0edf0f569996b4 Mon Sep 17 00:00:00 2001 From: Timmy Welch Date: Tue, 31 Jan 2023 20:21:39 -0800 Subject: [PATCH] Use consistent naming for settings config: always values setting: always the definition/description not the value --- comictaggerlib/autotagmatchwindow.py | 14 +- comictaggerlib/autotagstartwindow.py | 36 ++-- comictaggerlib/cbltransformer.py | 18 +- comictaggerlib/cli.py | 164 +++++++++--------- comictaggerlib/ctoptions/__init__.py | 21 --- comictaggerlib/ctsettings/__init__.py | 24 +++ .../cmdline.py => ctsettings/commandline.py} | 71 ++++---- .../{ctoptions => ctsettings}/file.py | 16 +- .../{ctoptions => ctsettings}/plugin.py | 35 ++-- .../{ctoptions => ctsettings}/types.py | 0 comictaggerlib/fileselectionlist.py | 4 +- comictaggerlib/gui.py | 10 +- comictaggerlib/issueidentifier.py | 22 +-- comictaggerlib/issueselectionwindow.py | 10 +- comictaggerlib/main.py | 93 +++++----- comictaggerlib/matchselectionwindow.py | 4 +- comictaggerlib/renamewindow.py | 36 ++-- comictaggerlib/seriesselectionwindow.py | 26 +-- comictaggerlib/settingswindow.py | 164 +++++++++--------- comictaggerlib/taggerwindow.py | 140 +++++++-------- comictalker/talkerbase.py | 4 +- comictalker/talkers/comicvine.py | 4 +- tests/comicarchive_test.py | 2 +- tests/comiccacher_test.py | 12 +- tests/conftest.py | 20 +-- tests/issueidentifier_test.py | 30 ++-- 26 files changed, 489 insertions(+), 491 deletions(-) delete mode 100644 comictaggerlib/ctoptions/__init__.py create mode 100644 comictaggerlib/ctsettings/__init__.py rename comictaggerlib/{ctoptions/cmdline.py => ctsettings/commandline.py} (83%) rename comictaggerlib/{ctoptions => ctsettings}/file.py (94%) rename comictaggerlib/{ctoptions => ctsettings}/plugin.py (62%) rename comictaggerlib/{ctoptions => ctsettings}/types.py (100%) diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py index c0d8db8..29cd789 100644 --- a/comictaggerlib/autotagmatchwindow.py +++ b/comictaggerlib/autotagmatchwindow.py @@ -40,19 +40,19 @@ class AutoTagMatchWindow(QtWidgets.QDialog): match_set_list: list[MultipleMatch], style: int, fetch_func: Callable[[IssueResult], GenericMetadata], - options: settngs.Namespace, + config: settngs.Namespace, talker_api: ComicTalker, ) -> None: super().__init__(parent) uic.loadUi(ui_path / "matchselectionwindow.ui", self) - self.options = options + self.config = config self.current_match_set: MultipleMatch = match_set_list[0] self.altCoverWidget = CoverImageWidget( - self.altCoverContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api + self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api ) gridlayout = QtWidgets.QGridLayout(self.altCoverContainer) gridlayout.addWidget(self.altCoverWidget) @@ -240,10 +240,10 @@ class AutoTagMatchWindow(QtWidgets.QDialog): md = ca.read_metadata(self._style) if md.is_empty: md = ca.metadata_from_filename( - self.options.filename_complicated_parser, - self.options.filename_remove_c2c, - self.options.filename_remove_fcbd, - self.options.filename_remove_publisher, + self.config.filename_complicated_parser, + self.config.filename_remove_c2c, + self.config.filename_remove_fcbd, + self.config.filename_remove_publisher, ) # now get the particular issue data diff --git a/comictaggerlib/autotagstartwindow.py b/comictaggerlib/autotagstartwindow.py index c7d6750..5a20530 100644 --- a/comictaggerlib/autotagstartwindow.py +++ b/comictaggerlib/autotagstartwindow.py @@ -1,4 +1,4 @@ -"""A PyQT4 dialog to confirm and set options for auto-tag""" +"""A PyQT4 dialog to confirm and set config for auto-tag""" # # Copyright 2012-2014 Anthony Beville # @@ -26,7 +26,7 @@ logger = logging.getLogger(__name__) class AutoTagStartWindow(QtWidgets.QDialog): - def __init__(self, parent: QtWidgets.QWidget, options: settngs.Namespace, msg: str) -> None: + def __init__(self, parent: QtWidgets.QWidget, config: settngs.Namespace, msg: str) -> None: super().__init__(parent) uic.loadUi(ui_path / "autotagstartwindow.ui", self) @@ -36,20 +36,20 @@ class AutoTagStartWindow(QtWidgets.QDialog): QtCore.Qt.WindowType(self.windowFlags() & ~QtCore.Qt.WindowType.WindowContextHelpButtonHint) ) - self.options = options + self.config = config self.cbxSpecifySearchString.setChecked(False) self.cbxSplitWords.setChecked(False) - self.sbNameMatchSearchThresh.setValue(self.options.identifier_series_match_identify_thresh) + self.sbNameMatchSearchThresh.setValue(self.config.identifier_series_match_identify_thresh) self.leSearchString.setEnabled(False) - self.cbxSaveOnLowConfidence.setChecked(self.options.autotag_save_on_low_confidence) - self.cbxDontUseYear.setChecked(self.options.autotag_dont_use_year_when_identifying) - self.cbxAssumeIssueOne.setChecked(self.options.autotag_assume_1_if_no_issue_num) - self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.options.autotag_ignore_leading_numbers_in_filename) - self.cbxRemoveAfterSuccess.setChecked(self.options.autotag_remove_archive_after_successful_match) - self.cbxWaitForRateLimit.setChecked(self.options.autotag_wait_and_retry_on_rate_limit) - self.cbxAutoImprint.setChecked(self.options.talkers_auto_imprint) + self.cbxSaveOnLowConfidence.setChecked(self.config.autotag_save_on_low_confidence) + self.cbxDontUseYear.setChecked(self.config.autotag_dont_use_year_when_identifying) + self.cbxAssumeIssueOne.setChecked(self.config.autotag_assume_1_if_no_issue_num) + self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.config.autotag_ignore_leading_numbers_in_filename) + self.cbxRemoveAfterSuccess.setChecked(self.config.autotag_remove_archive_after_successful_match) + self.cbxWaitForRateLimit.setChecked(self.config.autotag_wait_and_retry_on_rate_limit) + self.cbxAutoImprint.setChecked(self.config.talkers_auto_imprint) nlmt_tip = """The Name Match Ratio Threshold: Auto-Identify is for eliminating automatic search matches that are too long compared to your series name search. The lower @@ -75,7 +75,7 @@ class AutoTagStartWindow(QtWidgets.QDialog): self.remove_after_success = False self.wait_and_retry_on_rate_limit = False self.search_string = "" - self.name_length_match_tolerance = self.options.talkers_series_match_search_thresh + self.name_length_match_tolerance = self.config.talkers_series_match_search_thresh self.split_words = self.cbxSplitWords.isChecked() def search_string_toggle(self) -> None: @@ -95,12 +95,12 @@ class AutoTagStartWindow(QtWidgets.QDialog): self.split_words = self.cbxSplitWords.isChecked() # persist some settings - self.options.autotag_save_on_low_confidence = self.auto_save_on_low - self.options.autotag_dont_use_year_when_identifying = self.dont_use_year - self.options.autotag_assume_1_if_no_issue_num = self.assume_issue_one - self.options.autotag_ignore_leading_numbers_in_filename = self.ignore_leading_digits_in_filename - self.options.autotag_remove_archive_after_successful_match = self.remove_after_success - self.options.autotag_wait_and_retry_on_rate_limit = self.wait_and_retry_on_rate_limit + self.config.autotag_save_on_low_confidence = self.auto_save_on_low + self.config.autotag_dont_use_year_when_identifying = self.dont_use_year + self.config.autotag_assume_1_if_no_issue_num = self.assume_issue_one + self.config.autotag_ignore_leading_numbers_in_filename = self.ignore_leading_digits_in_filename + self.config.autotag_remove_archive_after_successful_match = self.remove_after_success + self.config.autotag_wait_and_retry_on_rate_limit = self.wait_and_retry_on_rate_limit if self.cbxSpecifySearchString.isChecked(): self.search_string = self.leSearchString.text() diff --git a/comictaggerlib/cbltransformer.py b/comictaggerlib/cbltransformer.py index 16d5c6f..5bff6b8 100644 --- a/comictaggerlib/cbltransformer.py +++ b/comictaggerlib/cbltransformer.py @@ -25,9 +25,9 @@ logger = logging.getLogger(__name__) class CBLTransformer: - def __init__(self, metadata: GenericMetadata, options: settngs.Namespace) -> None: + def __init__(self, metadata: GenericMetadata, config: settngs.Namespace) -> None: self.metadata = metadata - self.options = options + self.config = config def apply(self) -> GenericMetadata: # helper funcs @@ -41,7 +41,7 @@ class CBLTransformer: for item in items: append_to_tags_if_unique(item) - if self.options.cbl_assume_lone_credit_is_primary: + if self.config.cbl_assume_lone_credit_is_primary: # helper def set_lone_primary(role_list: list[str]) -> tuple[CreditMetadata | None, int]: @@ -68,19 +68,19 @@ class CBLTransformer: c["primary"] = False self.metadata.add_credit(c["person"], "Artist", True) - if self.options.cbl_copy_characters_to_tags: + if self.config.cbl_copy_characters_to_tags: add_string_list_to_tags(self.metadata.characters) - if self.options.cbl_copy_teams_to_tags: + if self.config.cbl_copy_teams_to_tags: add_string_list_to_tags(self.metadata.teams) - if self.options.cbl_copy_locations_to_tags: + if self.config.cbl_copy_locations_to_tags: add_string_list_to_tags(self.metadata.locations) - if self.options.cbl_copy_storyarcs_to_tags: + if self.config.cbl_copy_storyarcs_to_tags: add_string_list_to_tags(self.metadata.story_arc) - if self.options.cbl_copy_notes_to_comments: + if self.config.cbl_copy_notes_to_comments: if self.metadata.notes is not None: if self.metadata.comments is None: self.metadata.comments = "" @@ -89,7 +89,7 @@ class CBLTransformer: if self.metadata.notes not in self.metadata.comments: self.metadata.comments += self.metadata.notes - if self.options.cbl_copy_weblink_to_comments: + if self.config.cbl_copy_weblink_to_comments: if self.metadata.web_link is not None: if self.metadata.comments is None: self.metadata.comments = "" diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py index 08d826f..bd49c52 100644 --- a/comictaggerlib/cli.py +++ b/comictaggerlib/cli.py @@ -40,8 +40,8 @@ logger = logging.getLogger(__name__) class CLI: - def __init__(self, options: settngs.Values, talker_api: ComicTalker): - self.options = options + def __init__(self, config: settngs.Values, talker_api: ComicTalker): + self.config = config self.talker_api = talker_api self.batch_mode = False @@ -53,14 +53,14 @@ class CLI: logger.exception(f"Error retrieving issue details. Save aborted.\n{e}") return GenericMetadata() - if self.options.cbl_apply_transform_on_import: - ct_md = CBLTransformer(ct_md, self.options).apply() + if self.config.cbl_apply_transform_on_import: + ct_md = CBLTransformer(ct_md, self.config).apply() return ct_md def actual_metadata_save(self, ca: ComicArchive, md: GenericMetadata) -> bool: - if not self.options.runtime_dryrun: - for metadata_style in self.options.runtime_type: + if not self.config.runtime_dryrun: + for metadata_style in self.config.runtime_type: # write out the new data if not ca.write_metadata(md, metadata_style): logger.error("The tag save seemed to fail for style: %s!", MetaDataStyle.name[metadata_style]) @@ -69,7 +69,7 @@ class CLI: print("Save complete.") logger.info("Save complete.") else: - if self.options.runtime_quiet: + if self.config.runtime_quiet: logger.info("dry-run option was set, so nothing was written") print("dry-run option was set, so nothing was written") else: @@ -97,7 +97,7 @@ class CLI: m["issue_title"], ) ) - if self.options.runtime_interactive: + if self.config.runtime_interactive: while True: i = input("Choose a match #, or 's' to skip: ") if (i.isdigit() and int(i) in range(1, len(match_set.matches) + 1)) or i == "s": @@ -108,7 +108,7 @@ class CLI: ca = match_set.ca md = self.create_local_metadata(ca) ct_md = self.actual_issue_data_fetch(match_set.matches[int(i) - 1]["issue_id"]) - if self.options.talkers_clear_metadata_on_import: + if self.config.talkers_clear_metadata_on_import: md = ct_md else: notes = ( @@ -117,14 +117,14 @@ class CLI: ) md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger"))) - if self.options.talkers_auto_imprint: + if self.config.talkers_auto_imprint: md.fix_publisher() self.actual_metadata_save(ca, md) def post_process_matches(self, match_results: OnlineMatchResults) -> None: # now go through the match results - if self.options.runtime_summary: + if self.config.runtime_summary: if len(match_results.good_matches) > 0: print("\nSuccessful matches:\n------------------") for f in match_results.good_matches: @@ -145,7 +145,7 @@ class CLI: for f in match_results.fetch_data_failures: print(f) - if not self.options.runtime_summary and not self.options.runtime_interactive: + if not self.config.runtime_summary and not self.config.runtime_interactive: # just quit if we're not interactive or showing the summary return @@ -165,14 +165,14 @@ class CLI: self.display_match_set_for_choice(label, match_set) def run(self) -> None: - if len(self.options.runtime_file_list) < 1: + if len(self.config.runtime_file_list) < 1: logger.error("You must specify at least one filename. Use the -h option for more info") return match_results = OnlineMatchResults() - self.batch_mode = len(self.options.runtime_file_list) > 1 + self.batch_mode = len(self.config.runtime_file_list) > 1 - for f in self.options.runtime_file_list: + for f in self.config.runtime_file_list: self.process_file_cli(f, match_results) sys.stdout.flush() @@ -183,18 +183,18 @@ class CLI: md.set_default_page_list(ca.get_number_of_pages()) # now, overlay the parsed filename info - if self.options.runtime_parse_filename: + if self.config.runtime_parse_filename: f_md = ca.metadata_from_filename( - self.options.filename_complicated_parser, - self.options.filename_remove_c2c, - self.options.filename_remove_fcbd, - self.options.filename_remove_publisher, - self.options.runtime_split_words, + self.config.filename_complicated_parser, + self.config.filename_remove_c2c, + self.config.filename_remove_fcbd, + self.config.filename_remove_publisher, + self.config.runtime_split_words, ) md.overlay(f_md) - for metadata_style in self.options.runtime_type: + for metadata_style in self.config.runtime_type: if ca.has_metadata(metadata_style): try: t_md = ca.read_metadata(metadata_style) @@ -204,12 +204,12 @@ class CLI: logger.error("Failed to load metadata for %s: %s", ca.path, e) # finally, use explicit stuff - md.overlay(self.options.runtime_metadata) + md.overlay(self.config.runtime_metadata) return md def print(self, ca: ComicArchive) -> None: - if not self.options.runtime_type: + if not self.config.runtime_type: page_count = ca.get_number_of_pages() brief = "" @@ -239,38 +239,38 @@ class CLI: print(brief) - if self.options.runtime_quiet: + if self.config.runtime_quiet: return print() - if not self.options.runtime_type or MetaDataStyle.CIX in self.options.runtime_type: + if not self.config.runtime_type or MetaDataStyle.CIX in self.config.runtime_type: if ca.has_metadata(MetaDataStyle.CIX): print("--------- ComicRack tags ---------") try: - if self.options.runtime_raw: + if self.config.runtime_raw: print(ca.read_raw_cix()) else: print(ca.read_cix()) except Exception as e: logger.error("Failed to load metadata for %s: %s", ca.path, e) - if not self.options.runtime_type or MetaDataStyle.CBI in self.options.runtime_type: + if not self.config.runtime_type or MetaDataStyle.CBI in self.config.runtime_type: if ca.has_metadata(MetaDataStyle.CBI): print("------- ComicBookLover tags -------") try: - if self.options.runtime_raw: + if self.config.runtime_raw: pprint(json.loads(ca.read_raw_cbi())) else: print(ca.read_cbi()) except Exception as e: logger.error("Failed to load metadata for %s: %s", ca.path, e) - if not self.options.runtime_type or MetaDataStyle.COMET in self.options.runtime_type: + if not self.config.runtime_type or MetaDataStyle.COMET in self.config.runtime_type: if ca.has_metadata(MetaDataStyle.COMET): print("----------- CoMet tags -----------") try: - if self.options.runtime_raw: + if self.config.runtime_raw: print(ca.read_raw_comet()) else: print(ca.read_comet()) @@ -278,10 +278,10 @@ class CLI: logger.error("Failed to load metadata for %s: %s", ca.path, e) def delete(self, ca: ComicArchive) -> None: - for metadata_style in self.options.runtime_type: + for metadata_style in self.config.runtime_type: style_name = MetaDataStyle.name[metadata_style] if ca.has_metadata(metadata_style): - if not self.options.runtime_dryrun: + if not self.config.runtime_dryrun: if not ca.remove_metadata(metadata_style): print(f"{ca.path}: Tag removal seemed to fail!") else: @@ -292,26 +292,26 @@ class CLI: print(f"{ca.path}: This archive doesn't have {style_name} tags to remove.") def copy(self, ca: ComicArchive) -> None: - for metadata_style in self.options.runtime_type: + for metadata_style in self.config.runtime_type: dst_style_name = MetaDataStyle.name[metadata_style] - if not self.options.runtime_overwrite and ca.has_metadata(metadata_style): + if not self.config.runtime_overwrite and ca.has_metadata(metadata_style): print(f"{ca.path}: Already has {dst_style_name} tags. Not overwriting.") return - if self.options.commands_copy == metadata_style: + if self.config.commands_copy == metadata_style: print(f"{ca.path}: Destination and source are same: {dst_style_name}. Nothing to do.") return - src_style_name = MetaDataStyle.name[self.options.commands_copy] - if ca.has_metadata(self.options.commands_copy): - if not self.options.runtime_dryrun: + src_style_name = MetaDataStyle.name[self.config.commands_copy] + if ca.has_metadata(self.config.commands_copy): + if not self.config.runtime_dryrun: try: - md = ca.read_metadata(self.options.commands_copy) + md = ca.read_metadata(self.config.commands_copy) except Exception as e: md = GenericMetadata() logger.error("Failed to load metadata for %s: %s", ca.path, e) - if self.options.apply_transform_on_bulk_operation_ndetadata_style == MetaDataStyle.CBI: - md = CBLTransformer(md, self.options).apply() + if self.config.apply_transform_on_bulk_operation_ndetadata_style == MetaDataStyle.CBI: + md = CBLTransformer(md, self.config).apply() if not ca.write_metadata(md, metadata_style): print(f"{ca.path}: Tag copy seemed to fail!") @@ -323,8 +323,8 @@ class CLI: print(f"{ca.path}: This archive doesn't have {src_style_name} tags to copy.") def save(self, ca: ComicArchive, match_results: OnlineMatchResults) -> None: - if not self.options.runtime_overwrite: - for metadata_style in self.options.runtime_type: + if not self.config.runtime_overwrite: + for metadata_style in self.config.runtime_type: if ca.has_metadata(metadata_style): print(f"{ca.path}: Already has {MetaDataStyle.name[metadata_style]} tags. Not overwriting.") return @@ -334,37 +334,37 @@ class CLI: md = self.create_local_metadata(ca) if md.issue is None or md.issue == "": - if self.options.runtime_assume_issue_one: + if self.config.runtime_assume_issue_one: md.issue = "1" # now, search online - if self.options.runtime_online: - if self.options.runtime_issue_id is not None: + if self.config.runtime_online: + if self.config.runtime_issue_id is not None: # we were given the actual issue ID to search with try: - ct_md = self.talker_api.fetch_comic_data(self.options.runtime_issue_id) + ct_md = self.talker_api.fetch_comic_data(self.config.runtime_issue_id) except TalkerError as e: logger.exception(f"Error retrieving issue details. Save aborted.\n{e}") match_results.fetch_data_failures.append(str(ca.path.absolute())) return if ct_md is None: - logger.error("No match for ID %s was found.", self.options.runtime_issue_id) + logger.error("No match for ID %s was found.", self.config.runtime_issue_id) match_results.no_matches.append(str(ca.path.absolute())) return - if self.options.cbl_apply_transform_on_import: - ct_md = CBLTransformer(ct_md, self.options).apply() + if self.config.cbl_apply_transform_on_import: + ct_md = CBLTransformer(ct_md, self.config).apply() else: if md is None or md.is_empty: logger.error("No metadata given to search online with!") match_results.no_matches.append(str(ca.path.absolute())) return - ii = IssueIdentifier(ca, self.options, self.talker_api) + ii = IssueIdentifier(ca, self.config, self.talker_api) def myoutput(text: str) -> None: - if self.options.runtime_verbose: + if self.config.runtime_verbose: IssueIdentifier.default_write_output(text) # use our overlaid MD struct to search @@ -404,7 +404,7 @@ class CLI: logger.error("Online search: Multiple good matches. Save aborted") match_results.multiple_matches.append(MultipleMatch(ca, matches)) return - if low_confidence and self.options.runtime_abort_on_low_confidence: + if low_confidence and self.config.runtime_abort_on_low_confidence: logger.error("Online search: Low confidence match. Save aborted") match_results.low_confidence_matches.append(MultipleMatch(ca, matches)) return @@ -421,7 +421,7 @@ class CLI: match_results.fetch_data_failures.append(str(ca.path.absolute())) return - if self.options.talkers_clear_metadata_on_import: + if self.config.talkers_clear_metadata_on_import: md = ct_md else: notes = ( @@ -430,7 +430,7 @@ class CLI: ) md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger"))) - if self.options.talkers_auto_imprint: + if self.config.talkers_auto_imprint: md.fix_publisher() # ok, done building our metadata. time to save @@ -452,18 +452,18 @@ class CLI: return new_ext = "" # default - if self.options.filename_rename_set_extension_based_on_archive: + if self.config.filename_rename_set_extension_based_on_archive: new_ext = ca.extension() renamer = FileRenamer( md, - platform="universal" if self.options.filename_rename_strict else "auto", - replacements=self.options.rename_replacements, + platform="universal" if self.config.filename_rename_strict else "auto", + replacements=self.config.rename_replacements, ) - renamer.set_template(self.options.filename_rename_template) - renamer.set_issue_zero_padding(self.options.filename_rename_issue_number_padding) - renamer.set_smart_cleanup(self.options.filename_rename_use_smart_string_cleanup) - renamer.move = self.options.filename_rename_move_to_dir + renamer.set_template(self.config.filename_rename_template) + renamer.set_issue_zero_padding(self.config.filename_rename_issue_number_padding) + renamer.set_smart_cleanup(self.config.filename_rename_use_smart_string_cleanup) + renamer.move = self.config.filename_rename_move_to_dir try: new_name = renamer.determine_name(ext=new_ext) @@ -475,16 +475,16 @@ class CLI: "Please consult the template help in the settings " "and the documentation on the format at " "https://docs.python.org/3/library/string.html#format-string-syntax", - self.options.filename_rename_template, + self.config.filename_rename_template, ) return except Exception: logger.exception( - "Formatter failure: %s metadata: %s", self.options.filename_rename_template, renamer.metadata + "Formatter failure: %s metadata: %s", self.config.filename_rename_template, renamer.metadata ) folder = get_rename_dir( - ca, self.options.filename_rename_dir if self.options.filename_rename_move_to_dir else None + ca, self.config.filename_rename_dir if self.config.filename_rename_move_to_dir else None ) full_path = folder / new_name @@ -494,7 +494,7 @@ class CLI: return suffix = "" - if not self.options.runtime_dryrun: + if not self.config.runtime_dryrun: # rename the file try: ca.rename(utils.unique_file(full_path)) @@ -517,7 +517,7 @@ class CLI: filename_path = ca.path new_file = filename_path.with_suffix(".cbz") - if self.options.runtime_abort_on_conflict and new_file.exists(): + if self.config.runtime_abort_on_conflict and new_file.exists(): print(msg_hdr + f"{new_file.name} already exists in the that folder.") return @@ -525,10 +525,10 @@ class CLI: delete_success = False export_success = False - if not self.options.runtime_dryrun: + if not self.config.runtime_dryrun: if ca.export_as_zip(new_file): export_success = True - if self.options.runtime_delete_after_zip_export: + if self.config.runtime_delete_after_zip_export: try: filename_path.unlink(missing_ok=True) delete_success = True @@ -540,7 +540,7 @@ class CLI: new_file.unlink(missing_ok=True) else: msg = msg_hdr + f"Dry-run: Would try to create {os.path.split(new_file)[1]}" - if self.options.runtime_delete_after_zip_export: + if self.config.runtime_delete_after_zip_export: msg += " and delete original." print(msg) return @@ -548,7 +548,7 @@ class CLI: msg = msg_hdr if export_success: msg += f"Archive exported successfully to: {os.path.split(new_file)[1]}" - if self.options.runtime_delete_after_zip_export and delete_success: + if self.config.runtime_delete_after_zip_export and delete_success: msg += " (Original deleted) " else: msg += "Archive failed to export!" @@ -567,28 +567,28 @@ class CLI: return if not ca.is_writable() and ( - self.options.commands_delete - or self.options.commands_copy - or self.options.commands_save - or self.options.commands_rename + self.config.commands_delete + or self.config.commands_copy + or self.config.commands_save + or self.config.commands_rename ): logger.error("This archive is not writable") return - if self.options.commands_print: + if self.config.commands_print: self.print(ca) - elif self.options.commands_delete: + elif self.config.commands_delete: self.delete(ca) - elif self.options.commands_copy is not None: + elif self.config.commands_copy is not None: self.copy(ca) - elif self.options.commands_save: + elif self.config.commands_save: self.save(ca, match_results) - elif self.options.commands_rename: + elif self.config.commands_rename: self.rename(ca) - elif self.options.commands_export_to_zip: + elif self.config.commands_export_to_zip: self.export(ca) diff --git a/comictaggerlib/ctoptions/__init__.py b/comictaggerlib/ctoptions/__init__.py deleted file mode 100644 index b0f090f..0000000 --- a/comictaggerlib/ctoptions/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import annotations - -from comictaggerlib.ctoptions.cmdline import initial_cmd_line_parser, register_commandline, validate_commandline_options -from comictaggerlib.ctoptions.file import register_settings, validate_settings -from comictaggerlib.ctoptions.plugin import register_plugin_settings, validate_plugin_settings -from comictaggerlib.ctoptions.types import ComicTaggerPaths -from comictalker.talkerbase import ComicTalker - -talker_plugins: dict[str, ComicTalker] = {} - -__all__ = [ - "initial_cmd_line_parser", - "register_commandline", - "register_settings", - "register_plugin_settings", - "register_talker_settings", - "validate_commandline_options", - "validate_settings", - "validate_plugin_settings", - "ComicTaggerPaths", -] diff --git a/comictaggerlib/ctsettings/__init__.py b/comictaggerlib/ctsettings/__init__.py new file mode 100644 index 0000000..a186759 --- /dev/null +++ b/comictaggerlib/ctsettings/__init__.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from comictaggerlib.ctsettings.commandline import ( + initial_commandline_parser, + register_commandline_settings, + validate_commandline_settings, +) +from comictaggerlib.ctsettings.file import register_file_settings, validate_file_settings +from comictaggerlib.ctsettings.plugin import register_plugin_settings, validate_plugin_settings +from comictaggerlib.ctsettings.types import ComicTaggerPaths +from comictalker.talkerbase import ComicTalker + +talkers: dict[str, ComicTalker] = {} + +__all__ = [ + "initial_commandline_parser", + "register_commandline_settings", + "register_file_settings", + "register_plugin_settings", + "validate_commandline_settings", + "validate_file_settings", + "validate_plugin_settings", + "ComicTaggerPaths", +] diff --git a/comictaggerlib/ctoptions/cmdline.py b/comictaggerlib/ctsettings/commandline.py similarity index 83% rename from comictaggerlib/ctoptions/cmdline.py rename to comictaggerlib/ctsettings/commandline.py index 6d872ed..ccb3956 100644 --- a/comictaggerlib/ctoptions/cmdline.py +++ b/comictaggerlib/ctsettings/commandline.py @@ -1,4 +1,4 @@ -"""CLI options class for ComicTagger app""" +"""CLI settings for ComicTagger""" # # Copyright 2012-2014 Anthony Beville # @@ -25,14 +25,14 @@ import settngs from comicapi import utils from comicapi.genericmetadata import GenericMetadata from comictaggerlib import ctversion -from comictaggerlib.ctoptions.types import ComicTaggerPaths, metadata_type, parse_metadata_from_string +from comictaggerlib.ctsettings.types import ComicTaggerPaths, metadata_type, parse_metadata_from_string logger = logging.getLogger(__name__) -def initial_cmd_line_parser() -> argparse.ArgumentParser: +def initial_commandline_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(add_help=False) - # Ensure this stays up to date with register_options + # Ensure this stays up to date with register_settings parser.add_argument( "--config", help="Config directory defaults to ~/.ComicTagger\non Linux/Mac and %%APPDATA%% on Windows\n", @@ -49,7 +49,7 @@ def initial_cmd_line_parser() -> argparse.ArgumentParser: return parser -def register_options(parser: settngs.Manager) -> None: +def register_settings(parser: settngs.Manager) -> None: parser.add_setting( "--config", help="Config directory defaults to ~/.Config/ComicTagger\non Linux, ~/Library/Application Support/ComicTagger on Mac and %%APPDATA%%\\ComicTagger on Windows\n", @@ -262,68 +262,61 @@ def register_commands(parser: settngs.Manager) -> None: ) -def register_commandline(parser: settngs.Manager) -> None: +def register_commandline_settings(parser: settngs.Manager) -> None: parser.add_group("commands", register_commands, True) - parser.add_group("runtime", register_options) + parser.add_group("runtime", register_settings) -def validate_commandline_options(options: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values: +def validate_commandline_settings(config: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values: - if options[0].commands_version: + if config[0].commands_version: parser.exit( status=1, message=f"ComicTagger {ctversion.version}: Copyright (c) 2012-2022 ComicTagger Team\n" "Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n", ) - options[0].runtime_no_gui = any( + config[0].runtime_no_gui = any( [ - options[0].commands_print, - options[0].commands_delete, - options[0].commands_save, - options[0].commands_copy, - options[0].commands_rename, - options[0].commands_export_to_zip, - options[0].commands_only_set_cv_key, + config[0].commands_print, + config[0].commands_delete, + config[0].commands_save, + config[0].commands_copy, + config[0].commands_rename, + config[0].commands_export_to_zip, + config[0].commands_only_set_cv_key, ] ) - if platform.system() == "Windows" and options[0].runtime_glob: + if platform.system() == "Windows" and config[0].runtime_glob: # no globbing on windows shell, so do it for them import glob - globs = options[0].runtime_files - options[0].runtime_files = [] + globs = config[0].runtime_files + config[0].runtime_files = [] for item in globs: - options[0].runtime_files.extend(glob.glob(item)) + config[0].runtime_files.extend(glob.glob(item)) - if ( - options[0].commands_only_set_cv_key - and options[0].talker_comicvine_cv_api_key is None - and options[0].talker_comicvine_cv_url is None - ): - parser.exit(message="Key not given!\n", status=1) - - if not options[0].commands_only_set_cv_key and options[0].runtime_no_gui and not options[0].runtime_files: + if not config[0].commands_only_set_cv_key and config[0].runtime_no_gui and not config[0].runtime_files: parser.exit(message="Command requires at least one filename!\n", status=1) - if options[0].commands_delete and not options[0].runtime_type: + if config[0].commands_delete and not config[0].runtime_type: parser.exit(message="Please specify the type to delete with -t\n", status=1) - if options[0].commands_save and not options[0].runtime_type: + if config[0].commands_save and not config[0].runtime_type: parser.exit(message="Please specify the type to save with -t\n", status=1) - if options[0].commands_copy: - if not options[0].runtime_type: + if config[0].commands_copy: + if not config[0].runtime_type: parser.exit(message="Please specify the type to copy to with -t\n", status=1) - if len(options[0].commands_copy) > 1: + if len(config[0].commands_copy) > 1: parser.exit(message="Please specify only one type to copy to with -c\n", status=1) - options[0].commands_copy = options[0].commands_copy[0] + config[0].commands_copy = config[0].commands_copy[0] - if options[0].runtime_recursive: - options[0].runtime_file_list = utils.get_recursive_filelist(options[0].runtime_files) + if config[0].runtime_recursive: + config[0].runtime_file_list = utils.get_recursive_filelist(config[0].runtime_files) else: - options[0].runtime_file_list = options[0].runtime_files + config[0].runtime_file_list = config[0].runtime_files # take a crack at finding rar exe if it's not in the path if not utils.which("rar"): @@ -337,4 +330,4 @@ def validate_commandline_options(options: settngs.Config[settngs.Values], parser if os.path.exists("/opt/homebrew/bin"): utils.add_to_path("/opt/homebrew/bin") - return options + return config diff --git a/comictaggerlib/ctoptions/file.py b/comictaggerlib/ctsettings/file.py similarity index 94% rename from comictaggerlib/ctoptions/file.py rename to comictaggerlib/ctsettings/file.py index 3d739d8..c9cb4ff 100644 --- a/comictaggerlib/ctoptions/file.py +++ b/comictaggerlib/ctsettings/file.py @@ -6,7 +6,7 @@ from typing import Any import settngs -from comictaggerlib.ctoptions.types import AppendAction +from comictaggerlib.ctsettings.types import AppendAction from comictaggerlib.defaults import DEFAULT_REPLACEMENTS, Replacement, Replacements @@ -225,16 +225,16 @@ def autotag(parser: settngs.Manager) -> None: ) -def validate_settings(options: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]: - options[0].identifier_publisher_filter = [x.strip() for x in options[0].identifier_publisher_filter if x.strip()] - options[0].rename_replacements = Replacements( - [Replacement(x[0], x[1], x[2]) for x in options[0].rename_replacements[0]], - [Replacement(x[0], x[1], x[2]) for x in options[0].rename_replacements[1]], +def validate_file_settings(config: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]: + config[0].identifier_publisher_filter = [x.strip() for x in config[0].identifier_publisher_filter if x.strip()] + config[0].rename_replacements = Replacements( + [Replacement(x[0], x[1], x[2]) for x in config[0].rename_replacements[0]], + [Replacement(x[0], x[1], x[2]) for x in config[0].rename_replacements[1]], ) - return options + return config -def register_settings(parser: settngs.Manager) -> None: +def register_file_settings(parser: settngs.Manager) -> None: parser.add_group("general", general, False) parser.add_group("internal", internal, False) parser.add_group("identifier", identifier, False) diff --git a/comictaggerlib/ctoptions/plugin.py b/comictaggerlib/ctsettings/plugin.py similarity index 62% rename from comictaggerlib/ctoptions/plugin.py rename to comictaggerlib/ctsettings/plugin.py index 430bc70..84fbb90 100644 --- a/comictaggerlib/ctoptions/plugin.py +++ b/comictaggerlib/ctsettings/plugin.py @@ -6,7 +6,7 @@ import os import settngs import comicapi.comicarchive -import comictaggerlib.ctoptions +import comictaggerlib.ctsettings logger = logging.getLogger("comictagger") @@ -24,17 +24,17 @@ def archiver(manager: settngs.Manager) -> None: def register_talker_settings(manager: settngs.Manager) -> None: - for talker_name, talker in comictaggerlib.ctoptions.talker_plugins.items(): + for talker_name, talker in comictaggerlib.ctsettings.talkers.items(): try: manager.add_persistent_group("talker_" + talker_name, talker.register_settings, False) except Exception: logger.exception("Failed to register settings for %s", talker_name) -def validate_archive_settings(options: settngs.Config) -> settngs.Config: - if "archiver" not in options[1]: - return options - cfg = settngs.normalize_config(options, file=True, cmdline=True, defaults=False) +def validate_archive_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]: + if "archiver" not in config[1]: + return config + cfg = settngs.normalize_config(config, file=True, cmdline=True, defaults=False) for archiver in comicapi.comicarchive.archivers: exe_name = settngs.sanitize_name(archiver.exe) if ( @@ -47,28 +47,29 @@ def validate_archive_settings(options: settngs.Config) -> settngs.Config: else: archiver.exe = cfg[0]["archiver"][exe_name] - return options + return config -def validate_talker_settings(options: settngs.Config) -> settngs.Config: +def validate_talker_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]: # Apply talker settings from config file - for talker_name, talker in list(comictaggerlib.ctoptions.talker_plugins.items()): + cfg = settngs.normalize_config(config, True, True) + for talker_name, talker in list(comictaggerlib.ctsettings.talkers.items()): try: - talker.parse_settings(options[0]["talker_" + talker_name]) + talker.parse_settings(cfg[0]["talker_" + talker_name]) except Exception as e: # Remove talker as we failed to apply the settings - del comictaggerlib.ctoptions.talker_plugins[talker_name] + del comictaggerlib.ctsettings.talkers[talker_name] logger.exception("Failed to initialize talker settings: %s", e) - return options + return config -def validate_plugin_settings(options: settngs.Config) -> settngs.Config: - options = validate_archive_settings(options) - options = validate_talker_settings(options) - return options +def validate_plugin_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]: + config = validate_archive_settings(config) + config = validate_talker_settings(config) + return config -def register_plugin_settings(manager: settngs.Manager): +def register_plugin_settings(manager: settngs.Manager) -> None: manager.add_persistent_group("archiver", archiver, False) register_talker_settings(manager) diff --git a/comictaggerlib/ctoptions/types.py b/comictaggerlib/ctsettings/types.py similarity index 100% rename from comictaggerlib/ctoptions/types.py rename to comictaggerlib/ctsettings/types.py diff --git a/comictaggerlib/fileselectionlist.py b/comictaggerlib/fileselectionlist.py index db2abab..27d9c1f 100644 --- a/comictaggerlib/fileselectionlist.py +++ b/comictaggerlib/fileselectionlist.py @@ -57,13 +57,13 @@ class FileSelectionList(QtWidgets.QWidget): dataColNum = fileColNum def __init__( - self, parent: QtWidgets.QWidget, options: settngs.Namespace, dirty_flag_verification: Callable[[str, str], bool] + self, parent: QtWidgets.QWidget, config: settngs.Namespace, dirty_flag_verification: Callable[[str, str], bool] ) -> None: super().__init__(parent) uic.loadUi(ui_path / "fileselectionlist.ui", self) - self.options = options + self.config = config reduce_widget_font_size(self.twList) diff --git a/comictaggerlib/gui.py b/comictaggerlib/gui.py index f3ad995..1e7dbb8 100644 --- a/comictaggerlib/gui.py +++ b/comictaggerlib/gui.py @@ -83,11 +83,11 @@ except ImportError as e: def open_tagger_window( - talker_api: ComicTalker, options: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None + talker_api: ComicTalker | None, config: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None ) -> None: os.environ["QtWidgets.QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" args = [] - if options[0].runtime_darkmode: + if config[0].runtime_darkmode: args.extend(["-platform", "windows:darkmode=2"]) args.extend(sys.argv) app = Application(args) @@ -96,8 +96,10 @@ def open_tagger_window( if error[1]: raise SystemExit(1) + assert talker_api is not None + # needed to catch initial open file events (macOS) - app.openFileRequest.connect(lambda x: options[0].runtime_files.append(x.toLocalFile())) + app.openFileRequest.connect(lambda x: config[0].runtime_files.append(x.toLocalFile())) if platform.system() == "Darwin": # Set the MacOS dock icon @@ -125,7 +127,7 @@ def open_tagger_window( QtWidgets.QApplication.processEvents() try: - tagger_window = TaggerWindow(options[0].runtime_files, options, talker_api) + tagger_window = TaggerWindow(config[0].runtime_files, config, talker_api) tagger_window.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png"))) tagger_window.show() diff --git a/comictaggerlib/issueidentifier.py b/comictaggerlib/issueidentifier.py index dade198..66c9155 100644 --- a/comictaggerlib/issueidentifier.py +++ b/comictaggerlib/issueidentifier.py @@ -72,8 +72,8 @@ class IssueIdentifier: result_one_good_match = 4 result_multiple_good_matches = 5 - def __init__(self, comic_archive: ComicArchive, options: settngs.Namespace, talker_api: ComicTalker) -> None: - self.options = options + def __init__(self, comic_archive: ComicArchive, config: settngs.Namespace, talker_api: ComicTalker) -> None: + self.config = config self.talker_api = talker_api self.comic_archive: ComicArchive = comic_archive self.image_hasher = 1 @@ -96,10 +96,10 @@ class IssueIdentifier: # used to eliminate series names that are too long based on our search # string - self.series_match_thresh = options.identifier_series_match_identify_thresh + self.series_match_thresh = config.identifier_series_match_identify_thresh # used to eliminate unlikely publishers - self.publisher_filter = [s.strip().casefold() for s in options.identifier_publisher_filter] + self.publisher_filter = [s.strip().casefold() for s in config.identifier_publisher_filter] self.additional_metadata = GenericMetadata() self.output_function: Callable[[str], None] = IssueIdentifier.default_write_output @@ -241,10 +241,10 @@ class IssueIdentifier: # try to get some metadata from filename md_from_filename = ca.metadata_from_filename( - self.options.filename_complicated_parser, - self.options.filename_remove_c2c, - self.options.filename_remove_fcbd, - self.options.filename_remove_publisher, + self.config.filename_complicated_parser, + self.config.filename_remove_c2c, + self.config.filename_remove_fcbd, + self.config.filename_remove_publisher, ) working_md = md_from_filename.copy() @@ -294,7 +294,7 @@ class IssueIdentifier: return Score(score=0, url="", hash=0) try: - url_image_data = ImageFetcher(self.options.runtime_config.user_cache_dir).fetch( + url_image_data = ImageFetcher(self.config.runtime_config.user_cache_dir).fetch( primary_img_url, blocking=True ) except ImageFetcherException as e: @@ -316,7 +316,7 @@ class IssueIdentifier: if use_remote_alternates: for alt_url in alt_urls: try: - alt_url_image_data = ImageFetcher(self.options.runtime_config.user_cache_dir).fetch( + alt_url_image_data = ImageFetcher(self.config.runtime_config.user_cache_dir).fetch( alt_url, blocking=True ) except ImageFetcherException as e: @@ -505,7 +505,7 @@ class IssueIdentifier: if narrow_cover_hash is not None: hash_list.append(narrow_cover_hash) - cropped_border = self.crop_border(cover_image_data, self.options.identifier_border_crop_percent) + cropped_border = self.crop_border(cover_image_data, self.config.identifier_border_crop_percent) if cropped_border is not None: hash_list.append(self.calculate_hash(cropped_border)) logger.info("Adding cropped cover to the hashlist") diff --git a/comictaggerlib/issueselectionwindow.py b/comictaggerlib/issueselectionwindow.py index 12cc245..04cb51e 100644 --- a/comictaggerlib/issueselectionwindow.py +++ b/comictaggerlib/issueselectionwindow.py @@ -42,7 +42,7 @@ class IssueSelectionWindow(QtWidgets.QDialog): def __init__( self, parent: QtWidgets.QWidget, - options: settngs.Namespace, + config: settngs.Namespace, talker_api: ComicTalker, series_id: str, issue_number: str, @@ -52,7 +52,7 @@ class IssueSelectionWindow(QtWidgets.QDialog): uic.loadUi(ui_path / "issueselectionwindow.ui", self) self.coverWidget = CoverImageWidget( - self.coverImageContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api + self.coverImageContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api ) gridlayout = QtWidgets.QGridLayout(self.coverImageContainer) gridlayout.addWidget(self.coverWidget) @@ -71,18 +71,18 @@ class IssueSelectionWindow(QtWidgets.QDialog): self.series_id = series_id self.issue_id: str = "" - self.options = options + self.config = config self.talker_api = talker_api self.url_fetch_thread = None self.issue_list: list[ComicIssue] = [] # Display talker logo and set url - self.lblIssuesSourceName.setText(talker_api.static_options.attribution_string) + self.lblIssuesSourceName.setText(talker_api.static_config.attribution_string) self.imageIssuesSourceWidget = CoverImageWidget( self.imageIssuesSourceLogo, CoverImageWidget.URLMode, - options.runtime_config.user_cache_dir, + config.runtime_config.user_cache_dir, talker_api, False, ) diff --git a/comictaggerlib/main.py b/comictaggerlib/main.py index 5733d3f..2a92774 100644 --- a/comictaggerlib/main.py +++ b/comictaggerlib/main.py @@ -20,16 +20,14 @@ import json import logging.handlers import signal import sys -from collections.abc import Mapping import settngs import comicapi import comictalker.comictalkerapi as ct_api -from comictaggerlib import cli, ctoptions +from comictaggerlib import cli, ctsettings from comictaggerlib.ctversion import version from comictaggerlib.log import setup_logging -from comictalker.talkerbase import ComicTalker if sys.version_info < (3, 10): import importlib_metadata @@ -49,8 +47,8 @@ logger = logging.getLogger("comictagger") logger.setLevel(logging.DEBUG) -def update_publishers(options: settngs.Namespace) -> None: - json_file = options.runtime_config.user_config_dir / "publishers.json" +def update_publishers(config: settngs.Namespace) -> None: + json_file = config.runtime_config.user_config_dir / "publishers.json" if json_file.exists(): try: comicapi.utils.update_publishers(json.loads(json_file.read_text("utf-8"))) @@ -62,49 +60,48 @@ class App: """docstring for App""" def __init__(self) -> None: - self.options = settngs.Config({}, {}) - self.initial_arg_parser = ctoptions.initial_cmd_line_parser() + self.config = settngs.Config({}, {}) + self.initial_arg_parser = ctsettings.initial_commandline_parser() self.config_load_success = False - self.talker_plugins: Mapping[str, ComicTalker] = {} def run(self) -> None: - opts = self.initialize() - self.initialize_dirs(opts.config) - self.load_plugins(opts) - self.register_options() - self.options = self.parse_options(opts.config) + conf = self.initialize() + self.initialize_dirs(conf.config) + self.load_plugins(conf) + self.register_settings() + self.config = self.parse_settings(conf.config) self.main() def load_plugins(self, opts) -> None: comicapi.comicarchive.load_archive_plugins() - ctoptions.talker_plugins = ct_api.get_talkers(version, opts.config.user_cache_dir) + ctsettings.talkers = ct_api.get_talkers(version, opts.config.user_cache_dir) def initialize(self) -> argparse.Namespace: - opts, _ = self.initial_arg_parser.parse_known_args() - assert opts is not None - setup_logging(opts.verbose, opts.config.user_log_dir) - return opts + conf, _ = self.initial_arg_parser.parse_known_args() + assert conf is not None + setup_logging(conf.verbose, conf.config.user_log_dir) + return conf - def register_options(self) -> None: + def register_settings(self) -> None: self.manager = settngs.Manager( """A utility for reading and writing metadata to comic archives.\n\n\nIf no options are given, %(prog)s will run in windowed mode.""", "For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki", ) - ctoptions.register_commandline(self.manager) - ctoptions.register_settings(self.manager) - ctoptions.register_plugin_settings(self.manager) + ctsettings.register_commandline_settings(self.manager) + ctsettings.register_file_settings(self.manager) + ctsettings.register_plugin_settings(self.manager) - def parse_options(self, config_paths: ctoptions.ComicTaggerPaths) -> settngs.Config: - options, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json") - options = self.manager.get_namespace(options) + def parse_settings(self, config_paths: ctsettings.ComicTaggerPaths) -> settngs.Config: + config, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json") + config = self.manager.get_namespace(config) - options = ctoptions.validate_commandline_options(options, self.manager) - options = ctoptions.validate_settings(options) - options = ctoptions.validate_plugin_settings(options) - return options + config = ctsettings.validate_commandline_settings(config, self.manager) + config = ctsettings.validate_file_settings(config) + config = ctsettings.validate_plugin_settings(config) + return config - def initialize_dirs(self, paths: ctoptions.ComicTaggerPaths) -> None: + def initialize_dirs(self, paths: ctsettings.ComicTaggerPaths) -> None: paths.user_data_dir.mkdir(parents=True, exist_ok=True) paths.user_config_dir.mkdir(parents=True, exist_ok=True) paths.user_cache_dir.mkdir(parents=True, exist_ok=True) @@ -117,8 +114,8 @@ class App: logger.debug("user_log_dir: %s", paths.user_log_dir) def main(self) -> None: - assert self.options is not None - # options already loaded + assert self.config is not None + # config already loaded error = None signal.signal(signal.SIGINT, signal.SIG_DFL) @@ -128,40 +125,48 @@ class App: logger.debug("%s\t%s", pkg.metadata["Name"], pkg.metadata["Version"]) comicapi.utils.load_publishers() - update_publishers(self.options[0]) + update_publishers(self.config[0]) - if not qt_available and not self.options[0].runtime_no_gui: - self.options[0].runtime_no_gui = True + if not qt_available and not self.config[0].runtime_no_gui: + self.config[0].runtime_no_gui = True logger.warning("PyQt5 is not available. ComicTagger is limited to command-line mode.") - if self.options[0].commands_only_set_cv_key: + # manage the CV API key + # None comparison is used so that the empty string can unset the value + if self.config[0].talker_comicvine_cv_api_key is not None or self.config[0].talker_comicvine_cv_url is not None: + settings_path = self.config[0].runtime_config.user_config_dir / "settings.json" + if self.config_load_success: + self.manager.save_file(self.config[0], settings_path) + + if self.config[0].commands_only_set_cv_key: if self.config_load_success: print("Key set") # noqa: T201 return try: - talker_api = self.talker_plugins[self.options[0].talkers_source] + talker_api = ctsettings.talkers[self.config[0].talkers_source] except Exception as e: - logger.exception(f"Unable to load talker {self.options[0].talkers_source}") - # TODO error True can be changed to False after the talker settings menu generation is in - error = (f"Unable to load talker {self.options[0].talkers_source}: {e}", True) + logger.exception(f"Unable to load talker {self.config[0].talkers_source}") + error = (f"Unable to load talker {self.config[0].talkers_source}: {e}", True) + talker_api = None if not self.config_load_success: error = ( - f"Failed to load settings, check the log located in '{self.options[0].runtime_config.user_log_dir}' for more details", + f"Failed to load settings, check the log located in '{self.config[0].runtime_config.user_log_dir}' for more details", True, ) - if self.options[0].runtime_no_gui: + if self.config[0].runtime_no_gui: if error and error[1]: print(f"A fatal error occurred please check the log for more information: {error[0]}") # noqa: T201 raise SystemExit(1) + assert talker_api is not None try: - cli.CLI(self.options[0], talker_api).run() + cli.CLI(self.config[0], talker_api).run() except Exception: logger.exception("CLI mode failed") else: - gui.open_tagger_window(talker_api, self.options, error) + gui.open_tagger_window(talker_api, self.config, error) def main(): diff --git a/comictaggerlib/matchselectionwindow.py b/comictaggerlib/matchselectionwindow.py index 0ce2764..ed8864d 100644 --- a/comictaggerlib/matchselectionwindow.py +++ b/comictaggerlib/matchselectionwindow.py @@ -37,7 +37,7 @@ class MatchSelectionWindow(QtWidgets.QDialog): parent: QtWidgets.QWidget, matches: list[IssueResult], comic_archive: ComicArchive, - options: settngs.Values, + config: settngs.Values, talker_api: ComicTalker, ) -> None: super().__init__(parent) @@ -45,7 +45,7 @@ class MatchSelectionWindow(QtWidgets.QDialog): uic.loadUi(ui_path / "matchselectionwindow.ui", self) self.altCoverWidget = CoverImageWidget( - self.altCoverContainer, CoverImageWidget.AltCoverMode, options.runtime_config.user_cache_dir, talker_api + self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api ) gridlayout = QtWidgets.QGridLayout(self.altCoverContainer) gridlayout.addWidget(self.altCoverWidget) diff --git a/comictaggerlib/renamewindow.py b/comictaggerlib/renamewindow.py index a856ef5..5bd643d 100644 --- a/comictaggerlib/renamewindow.py +++ b/comictaggerlib/renamewindow.py @@ -38,7 +38,7 @@ class RenameWindow(QtWidgets.QDialog): parent: QtWidgets.QWidget, comic_archive_list: list[ComicArchive], data_style: int, - options: settngs.Config, + config: settngs.Config, talker_api: ComicTalker, ) -> None: super().__init__(parent) @@ -54,39 +54,39 @@ class RenameWindow(QtWidgets.QDialog): ) ) - self.options = options + self.config = config self.talker_api = talker_api self.comic_archive_list = comic_archive_list self.data_style = data_style self.rename_list: list[str] = [] self.btnSettings.clicked.connect(self.modify_settings) - platform = "universal" if self.options[0].rename_strict else "auto" - self.renamer = FileRenamer(None, platform=platform, replacements=self.options[0].rename_replacements) + platform = "universal" if self.config[0].rename_strict else "auto" + self.renamer = FileRenamer(None, platform=platform, replacements=self.config[0].rename_replacements) self.do_preview() def config_renamer(self, ca: ComicArchive, md: GenericMetadata | None = None) -> str: - self.renamer.set_template(self.options[0].rename_template) - self.renamer.set_issue_zero_padding(self.options[0].rename_issue_number_padding) - self.renamer.set_smart_cleanup(self.options[0].rename_use_smart_string_cleanup) - self.renamer.replacements = self.options[0].rename_replacements + self.renamer.set_template(self.config[0].rename_template) + self.renamer.set_issue_zero_padding(self.config[0].rename_issue_number_padding) + self.renamer.set_smart_cleanup(self.config[0].rename_use_smart_string_cleanup) + self.renamer.replacements = self.config[0].rename_replacements new_ext = ca.path.suffix # default - if self.options[0].filename_rename_set_extension_based_on_archive: + if self.config[0].filename_rename_set_extension_based_on_archive: new_ext = ca.extension() if md is None: md = ca.read_metadata(self.data_style) if md.is_empty: md = ca.metadata_from_filename( - self.options[0].filename_complicated_parser, - self.options[0].filename_remove_c2c, - self.options[0].filename_remove_fcbd, - self.options[0].filename_remove_publisher, + self.config[0].filename_complicated_parser, + self.config[0].filename_remove_c2c, + self.config[0].filename_remove_fcbd, + self.config[0].filename_remove_publisher, ) self.renamer.set_metadata(md) - self.renamer.move = self.options[0].rename_move_to_dir + self.renamer.move = self.config[0].rename_move_to_dir return new_ext def do_preview(self) -> None: @@ -99,7 +99,7 @@ class RenameWindow(QtWidgets.QDialog): try: new_name = self.renamer.determine_name(new_ext) except ValueError as e: - logger.exception("Invalid format string: %s", self.options[0].rename_template) + logger.exception("Invalid format string: %s", self.config[0].rename_template) QtWidgets.QMessageBox.critical( self, "Invalid format string!", @@ -114,7 +114,7 @@ class RenameWindow(QtWidgets.QDialog): except Exception as e: logger.exception( "Formatter failure: %s metadata: %s", - self.options[0].rename_template, + self.config[0].rename_template, self.renamer.metadata, ) QtWidgets.QMessageBox.critical( @@ -162,7 +162,7 @@ class RenameWindow(QtWidgets.QDialog): self.twList.setSortingEnabled(True) def modify_settings(self) -> None: - settingswin = SettingsWindow(self, self.options, self.talker_api) + settingswin = SettingsWindow(self, self.config, self.talker_api) settingswin.setModal(True) settingswin.show_rename_tab() settingswin.exec() @@ -192,7 +192,7 @@ class RenameWindow(QtWidgets.QDialog): folder = get_rename_dir( comic[0], - self.options[0].rename_dir if self.options[0].rename_move_to_dir else None, + self.config[0].rename_dir if self.config[0].rename_move_to_dir else None, ) full_path = folder / comic[1] diff --git a/comictaggerlib/seriesselectionwindow.py b/comictaggerlib/seriesselectionwindow.py index 5bcad3b..96a127a 100644 --- a/comictaggerlib/seriesselectionwindow.py +++ b/comictaggerlib/seriesselectionwindow.py @@ -111,7 +111,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): issue_count: int, cover_index_list: list[int], comic_archive: ComicArchive | None, - options: settngs.Namespace, + config: settngs.Namespace, talker_api: ComicTalker, autoselect: bool = False, literal: bool = False, @@ -121,7 +121,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): uic.loadUi(ui_path / "seriesselectionwindow.ui", self) self.imageWidget = CoverImageWidget( - self.imageContainer, CoverImageWidget.URLMode, options.runtime_config.user_cache_dir, talker_api + self.imageContainer, CoverImageWidget.URLMode, config.runtime_config.user_cache_dir, talker_api ) gridlayout = QtWidgets.QGridLayout(self.imageContainer) gridlayout.addWidget(self.imageWidget) @@ -138,7 +138,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): ) ) - self.options = options + self.config = config self.series_name = series_name self.issue_number = issue_number self.issue_id: str = "" @@ -156,18 +156,18 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.progdialog: QtWidgets.QProgressDialog | None = None self.search_thread: SearchThread | None = None - self.use_filter = self.options.talkers_always_use_publisher_filter + self.use_filter = self.config.talkers_always_use_publisher_filter # Load to retrieve settings self.talker_api = talker_api # Display talker logo and set url - self.lblSourceName.setText(talker_api.static_options.attribution_string) + self.lblSourceName.setText(talker_api.static_config.attribution_string) self.imageSourceWidget = CoverImageWidget( self.imageSourceLogo, CoverImageWidget.URLMode, - options.runtime_config.user_cache_dir, + config.runtime_config.user_cache_dir, talker_api, False, ) @@ -224,7 +224,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.iddialog.rejected.connect(self.identify_cancel) self.iddialog.show() - self.ii = IssueIdentifier(self.comic_archive, self.options, self.talker_api) + self.ii = IssueIdentifier(self.comic_archive, self.config, self.talker_api) md = GenericMetadata() md.series = self.series_name @@ -298,7 +298,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): if choices: selector = MatchSelectionWindow( - self, matches, self.comic_archive, talker_api=self.talker_api, options=self.options + self, matches, self.comic_archive, talker_api=self.talker_api, config=self.config ) selector.setModal(True) selector.exec() @@ -315,7 +315,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.show_issues() def show_issues(self) -> None: - selector = IssueSelectionWindow(self, self.options, self.talker_api, self.series_id, self.issue_number) + selector = IssueSelectionWindow(self, self.config, self.talker_api, self.series_id, self.issue_number) title = "" for record in self.ct_search_results: if record.id == self.series_id: @@ -343,7 +343,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): def perform_query(self, refresh: bool = False) -> None: self.search_thread = SearchThread( - self.talker_api, self.series_name, refresh, self.literal, self.options.talkers_series_match_search_thresh + self.talker_api, self.series_name, refresh, self.literal, self.config.talkers_series_match_search_thresh ) self.search_thread.searchComplete.connect(self.search_complete) self.search_thread.progressUpdate.connect(self.search_progress_update) @@ -395,7 +395,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): # filter the publishers if enabled set if self.use_filter: try: - publisher_filter = {s.strip().casefold() for s in self.options.identifier_publisher_filter} + publisher_filter = {s.strip().casefold() for s in self.config.identifier_publisher_filter} # use '' as publisher name if None self.ct_search_results = list( filter( @@ -410,7 +410,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): # compare as str in case extra chars ie. '1976?' # - missing (none) values being converted to 'None' - consistent with prior behaviour in v1.2.3 # sort by start_year if set - if self.options.talkers_sort_series_by_year: + if self.config.talkers_sort_series_by_year: try: self.ct_search_results = sorted( self.ct_search_results, @@ -428,7 +428,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): logger.exception("bad data error sorting results by count_of_issues") # move sanitized matches to the front - if self.options.talkers_exact_series_matches_first: + if self.config.talkers_exact_series_matches_first: try: sanitized = utils.sanitize_title(self.series_name, False).casefold() sanitized_no_articles = utils.sanitize_title(self.series_name, True).casefold() diff --git a/comictaggerlib/settingswindow.py b/comictaggerlib/settingswindow.py index e866562..0ab691f 100644 --- a/comictaggerlib/settingswindow.py +++ b/comictaggerlib/settingswindow.py @@ -130,7 +130,7 @@ Spider-Geddon #1 - New Players; Check In class SettingsWindow(QtWidgets.QDialog): - def __init__(self, parent: QtWidgets.QWidget, options: settngs.Config, talker_api: ComicTalker) -> None: + def __init__(self, parent: QtWidgets.QWidget, config: settngs.Config, talker_api: ComicTalker) -> None: super().__init__(parent) uic.loadUi(ui_path / "settingswindow.ui", self) @@ -139,7 +139,7 @@ class SettingsWindow(QtWidgets.QDialog): QtCore.Qt.WindowType(self.windowFlags() & ~QtCore.Qt.WindowType.WindowContextHelpButtonHint) ) - self.options = options + self.config = config self.talker_api = talker_api self.name = "Settings" @@ -269,53 +269,53 @@ class SettingsWindow(QtWidgets.QDialog): def settings_to_form(self) -> None: # Copy values from settings to form - if "archiver" in self.options[1] and "rar" in self.options[1]["archiver"]: - self.leRarExePath.setText(getattr(self.options[0], self.options[1]["archiver"]["rar"].internal_name)) + if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]: + self.leRarExePath.setText(getattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name)) else: self.leRarExePath.setEnabled(False) - self.sbNameMatchIdentifyThresh.setValue(self.options[0].identifier_series_match_identify_thresh) - self.sbNameMatchSearchThresh.setValue(self.options[0].talkers_series_match_search_thresh) - self.tePublisherFilter.setPlainText("\n".join(self.options[0].identifier_publisher_filter)) + self.sbNameMatchIdentifyThresh.setValue(self.config[0].identifier_series_match_identify_thresh) + self.sbNameMatchSearchThresh.setValue(self.config[0].talkers_series_match_search_thresh) + self.tePublisherFilter.setPlainText("\n".join(self.config[0].identifier_publisher_filter)) - self.cbxCheckForNewVersion.setChecked(self.options[0].general_check_for_new_version) + self.cbxCheckForNewVersion.setChecked(self.config[0].general_check_for_new_version) - self.cbxComplicatedParser.setChecked(self.options[0].filename_complicated_parser) - self.cbxRemoveC2C.setChecked(self.options[0].filename_remove_c2c) - self.cbxRemoveFCBD.setChecked(self.options[0].filename_remove_fcbd) - self.cbxRemovePublisher.setChecked(self.options[0].filename_remove_publisher) + self.cbxComplicatedParser.setChecked(self.config[0].filename_complicated_parser) + self.cbxRemoveC2C.setChecked(self.config[0].filename_remove_c2c) + self.cbxRemoveFCBD.setChecked(self.config[0].filename_remove_fcbd) + self.cbxRemovePublisher.setChecked(self.config[0].filename_remove_publisher) self.switch_parser() - self.cbxUseSeriesStartAsVolume.setChecked(self.options[0].talker_comicvine_cv_use_series_start_as_volume) - self.cbxClearFormBeforePopulating.setChecked(self.options[0].talkers_clear_form_before_populating) - self.cbxRemoveHtmlTables.setChecked(self.options[0].talker_comicvine_cv_remove_html_tables) + self.cbxUseSeriesStartAsVolume.setChecked(self.config[0].talker_comicvine_cv_use_series_start_as_volume) + self.cbxClearFormBeforePopulating.setChecked(self.config[0].talkers_clear_form_before_populating) + self.cbxRemoveHtmlTables.setChecked(self.config[0].talker_comicvine_cv_remove_html_tables) - self.cbxUseFilter.setChecked(self.options[0].talkers_always_use_publisher_filter) - self.cbxSortByYear.setChecked(self.options[0].talkers_sort_series_by_year) - self.cbxExactMatches.setChecked(self.options[0].talkers_exact_series_matches_first) + self.cbxUseFilter.setChecked(self.config[0].talkers_always_use_publisher_filter) + self.cbxSortByYear.setChecked(self.config[0].talkers_sort_series_by_year) + self.cbxExactMatches.setChecked(self.config[0].talkers_exact_series_matches_first) - self.leKey.setText(self.options[0].talker_comicvine_cv_api_key) - self.leURL.setText(self.options[0].talker_comicvine_cv_url) + self.leKey.setText(self.config[0].talker_comicvine_cv_api_key) + self.leURL.setText(self.config[0].talker_comicvine_cv_url) - self.cbxAssumeLoneCreditIsPrimary.setChecked(self.options[0].cbl_assume_lone_credit_is_primary) - self.cbxCopyCharactersToTags.setChecked(self.options[0].cbl_copy_characters_to_tags) - self.cbxCopyTeamsToTags.setChecked(self.options[0].cbl_copy_teams_to_tags) - self.cbxCopyLocationsToTags.setChecked(self.options[0].cbl_copy_locations_to_tags) - self.cbxCopyStoryArcsToTags.setChecked(self.options[0].cbl_copy_storyarcs_to_tags) - self.cbxCopyNotesToComments.setChecked(self.options[0].cbl_copy_notes_to_comments) - self.cbxCopyWebLinkToComments.setChecked(self.options[0].cbl_copy_weblink_to_comments) - self.cbxApplyCBLTransformOnCVIMport.setChecked(self.options[0].cbl_apply_transform_on_import) - self.cbxApplyCBLTransformOnBatchOperation.setChecked(self.options[0].cbl_apply_transform_on_bulk_operation) + self.cbxAssumeLoneCreditIsPrimary.setChecked(self.config[0].cbl_assume_lone_credit_is_primary) + self.cbxCopyCharactersToTags.setChecked(self.config[0].cbl_copy_characters_to_tags) + self.cbxCopyTeamsToTags.setChecked(self.config[0].cbl_copy_teams_to_tags) + self.cbxCopyLocationsToTags.setChecked(self.config[0].cbl_copy_locations_to_tags) + self.cbxCopyStoryArcsToTags.setChecked(self.config[0].cbl_copy_storyarcs_to_tags) + self.cbxCopyNotesToComments.setChecked(self.config[0].cbl_copy_notes_to_comments) + self.cbxCopyWebLinkToComments.setChecked(self.config[0].cbl_copy_weblink_to_comments) + self.cbxApplyCBLTransformOnCVIMport.setChecked(self.config[0].cbl_apply_transform_on_import) + self.cbxApplyCBLTransformOnBatchOperation.setChecked(self.config[0].cbl_apply_transform_on_bulk_operation) - self.leRenameTemplate.setText(self.options[0].rename_template) - self.leIssueNumPadding.setText(str(self.options[0].rename_issue_number_padding)) - self.cbxSmartCleanup.setChecked(self.options[0].rename_use_smart_string_cleanup) - self.cbxChangeExtension.setChecked(self.options[0].rename_set_extension_based_on_archive) - self.cbxMoveFiles.setChecked(self.options[0].rename_move_to_dir) - self.leDirectory.setText(self.options[0].rename_dir) - self.cbxRenameStrict.setChecked(self.options[0].rename_strict) + self.leRenameTemplate.setText(self.config[0].rename_template) + self.leIssueNumPadding.setText(str(self.config[0].rename_issue_number_padding)) + self.cbxSmartCleanup.setChecked(self.config[0].rename_use_smart_string_cleanup) + self.cbxChangeExtension.setChecked(self.config[0].rename_set_extension_based_on_archive) + self.cbxMoveFiles.setChecked(self.config[0].rename_move_to_dir) + self.leDirectory.setText(self.config[0].rename_dir) + self.cbxRenameStrict.setChecked(self.config[0].rename_strict) for table, replacments in zip( - (self.twLiteralReplacements, self.twValueReplacements), self.options[0].rename_replacements + (self.twLiteralReplacements, self.twValueReplacements), self.config[0].rename_replacements ): table.clearContents() for i in reversed(range(table.rowCount())): @@ -350,7 +350,7 @@ class SettingsWindow(QtWidgets.QDialog): self.rename_test() if self.rename_error is not None: if isinstance(self.rename_error, ValueError): - logger.exception("Invalid format string: %s", self.options[0].rename_template) + logger.exception("Invalid format string: %s", self.config[0].rename_template) QtWidgets.QMessageBox.critical( self, "Invalid format string!", @@ -364,7 +364,7 @@ class SettingsWindow(QtWidgets.QDialog): return else: logger.exception( - "Formatter failure: %s metadata: %s", self.options[0].rename_template, self.renamer.metadata + "Formatter failure: %s metadata: %s", self.config[0].rename_template, self.renamer.metadata ) QtWidgets.QMessageBox.critical( self, @@ -377,75 +377,75 @@ class SettingsWindow(QtWidgets.QDialog): ) # Copy values from form to settings and save - if "archiver" in self.options[1] and "rar" in self.options[1]["archiver"]: - setattr(self.options[0], self.options[1]["archiver"]["rar"].internal_name, str(self.leRarExePath.text())) + if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]: + setattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name, str(self.leRarExePath.text())) # make sure rar program is now in the path for the rar class - if self.options[0].archivers_rar: + if self.config[0].archivers_rar: utils.add_to_path(os.path.dirname(str(self.leRarExePath.text()))) if not str(self.leIssueNumPadding.text()).isdigit(): self.leIssueNumPadding.setText("0") - self.options[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked() + self.config[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked() - self.options[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value() - self.options[0].talkers_series_match_search_thresh = self.sbNameMatchSearchThresh.value() - self.options[0].identifier_publisher_filter = [ + self.config[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value() + self.config[0].talkers_series_match_search_thresh = self.sbNameMatchSearchThresh.value() + self.config[0].identifier_publisher_filter = [ x.strip() for x in str(self.tePublisherFilter.toPlainText()).splitlines() if x.strip() ] - self.options[0].filename_complicated_parser = self.cbxComplicatedParser.isChecked() - self.options[0].filename_remove_c2c = self.cbxRemoveC2C.isChecked() - self.options[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked() - self.options[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked() + self.config[0].filename_complicated_parser = self.cbxComplicatedParser.isChecked() + self.config[0].filename_remove_c2c = self.cbxRemoveC2C.isChecked() + self.config[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked() + self.config[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked() - self.options[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked() - self.options[0].talkers_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked() - self.options[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked() + self.config[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked() + self.config[0].talkers_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked() + self.config[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked() - self.options[0].talkers_always_use_publisher_filter = self.cbxUseFilter.isChecked() - self.options[0].talkers_sort_series_by_year = self.cbxSortByYear.isChecked() - self.options[0].talkers_exact_series_matches_first = self.cbxExactMatches.isChecked() + self.config[0].talkers_always_use_publisher_filter = self.cbxUseFilter.isChecked() + self.config[0].talkers_sort_series_by_year = self.cbxSortByYear.isChecked() + self.config[0].talkers_exact_series_matches_first = self.cbxExactMatches.isChecked() if self.leKey.text().strip(): - self.options[0].talker_comicvine_cv_api_key = self.leKey.text().strip() - self.talker_api.api_key = self.options[0].talker_comicvine_cv_api_key + self.config[0].talker_comicvine_cv_api_key = self.leKey.text().strip() + self.talker_api.api_key = self.config[0].talker_comicvine_cv_api_key if self.leURL.text().strip(): - self.options[0].talker_comicvine_cv_url = self.leURL.text().strip() - self.talker_api.api_url = self.options[0].talker_comicvine_cv_url + self.config[0].talker_comicvine_cv_url = self.leURL.text().strip() + self.talker_api.api_url = self.config[0].talker_comicvine_cv_url - self.options[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked() - self.options[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked() - self.options[0].cbl_copy_teams_to_tags = self.cbxCopyTeamsToTags.isChecked() - self.options[0].cbl_copy_locations_to_tags = self.cbxCopyLocationsToTags.isChecked() - self.options[0].cbl_copy_storyarcs_to_tags = self.cbxCopyStoryArcsToTags.isChecked() - self.options[0].cbl_copy_notes_to_comments = self.cbxCopyNotesToComments.isChecked() - self.options[0].cbl_copy_weblink_to_comments = self.cbxCopyWebLinkToComments.isChecked() - self.options[0].cbl_apply_transform_on_import = self.cbxApplyCBLTransformOnCVIMport.isChecked() - self.options[0].cbl_apply_transform_on_bulk_operation = self.cbxApplyCBLTransformOnBatchOperation.isChecked() + self.config[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked() + self.config[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked() + self.config[0].cbl_copy_teams_to_tags = self.cbxCopyTeamsToTags.isChecked() + self.config[0].cbl_copy_locations_to_tags = self.cbxCopyLocationsToTags.isChecked() + self.config[0].cbl_copy_storyarcs_to_tags = self.cbxCopyStoryArcsToTags.isChecked() + self.config[0].cbl_copy_notes_to_comments = self.cbxCopyNotesToComments.isChecked() + self.config[0].cbl_copy_weblink_to_comments = self.cbxCopyWebLinkToComments.isChecked() + self.config[0].cbl_apply_transform_on_import = self.cbxApplyCBLTransformOnCVIMport.isChecked() + self.config[0].cbl_apply_transform_on_bulk_operation = self.cbxApplyCBLTransformOnBatchOperation.isChecked() - self.options[0].rename_template = str(self.leRenameTemplate.text()) - self.options[0].rename_issue_number_padding = int(self.leIssueNumPadding.text()) - self.options[0].rename_use_smart_string_cleanup = self.cbxSmartCleanup.isChecked() - self.options[0].rename_set_extension_based_on_archive = self.cbxChangeExtension.isChecked() - self.options[0].rename_move_to_dir = self.cbxMoveFiles.isChecked() - self.options[0].rename_dir = self.leDirectory.text() + self.config[0].rename_template = str(self.leRenameTemplate.text()) + self.config[0].rename_issue_number_padding = int(self.leIssueNumPadding.text()) + self.config[0].rename_use_smart_string_cleanup = self.cbxSmartCleanup.isChecked() + self.config[0].rename_set_extension_based_on_archive = self.cbxChangeExtension.isChecked() + self.config[0].rename_move_to_dir = self.cbxMoveFiles.isChecked() + self.config[0].rename_dir = self.leDirectory.text() - self.options[0].rename_strict = self.cbxRenameStrict.isChecked() - self.options[0].rename_replacements = self.get_replacemnts() + self.config[0].rename_strict = self.cbxRenameStrict.isChecked() + self.config[0].rename_replacements = self.get_replacemnts() - settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json") - self.parent().options = self.options + settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json") + self.parent().config = self.config QtWidgets.QDialog.accept(self) def select_rar(self) -> None: self.select_file(self.leRarExePath, "RAR") def clear_cache(self) -> None: - ImageFetcher(self.options[0].runtime_config.user_cache_dir).clear_cache() - ComicCacher(self.options[0].runtime_config.user_cache_dir, version).clear_cache() + ImageFetcher(self.config[0].runtime_config.user_cache_dir).clear_cache() + ComicCacher(self.config[0].runtime_config.user_cache_dir, version).clear_cache() QtWidgets.QMessageBox.information(self, self.name, "Cache has been cleared.") def test_api_key(self) -> None: @@ -455,7 +455,7 @@ class SettingsWindow(QtWidgets.QDialog): QtWidgets.QMessageBox.warning(self, "API Key Test", "Key is NOT valid.") def reset_settings(self) -> None: - self.options = settngs.Config(settngs.defaults(self.options[1]), self.options[1]) + self.config = settngs.Config(settngs.defaults(self.config[1]), self.config[1]) self.settings_to_form() QtWidgets.QMessageBox.information(self, self.name, self.name + " have been returned to default values.") diff --git a/comictaggerlib/taggerwindow.py b/comictaggerlib/taggerwindow.py index edc9a99..e708347 100644 --- a/comictaggerlib/taggerwindow.py +++ b/comictaggerlib/taggerwindow.py @@ -79,24 +79,24 @@ class TaggerWindow(QtWidgets.QMainWindow): def __init__( self, file_list: list[str], - options: settngs.Config, + config: settngs.Config, talker_api: ComicTalker, parent: QtWidgets.QWidget | None = None, ) -> None: super().__init__(parent) uic.loadUi(ui_path / "taggerwindow.ui", self) - self.options = options + self.config = config self.talker_api = talker_api self.log_window = self.setup_logger() # prevent multiple instances socket = QtNetwork.QLocalSocket(self) - socket.connectToServer(options[0].internal_install_id) + socket.connectToServer(config[0].internal_install_id) alive = socket.waitForConnected(3000) if alive: logger.setLevel(logging.INFO) - logger.info("Another application with key [%s] is already running", options[0].internal_install_id) + logger.info("Another application with key [%s] is already running", config[0].internal_install_id) # send file list to other instance if file_list: socket.write(pickle.dumps(file_list)) @@ -108,15 +108,15 @@ class TaggerWindow(QtWidgets.QMainWindow): # listen on a socket to prevent multiple instances self.socketServer = QtNetwork.QLocalServer(self) self.socketServer.newConnection.connect(self.on_incoming_socket_connection) - ok = self.socketServer.listen(options[0].internal_install_id) + ok = self.socketServer.listen(config[0].internal_install_id) if not ok: if self.socketServer.serverError() == QtNetwork.QAbstractSocket.SocketError.AddressInUseError: - self.socketServer.removeServer(options[0].internal_install_id) - ok = self.socketServer.listen(options[0].internal_install_id) + self.socketServer.removeServer(config[0].internal_install_id) + ok = self.socketServer.listen(config[0].internal_install_id) if not ok: logger.error( "Cannot start local socket with key [%s]. Reason: %s", - options[0].internal_install_id, + config[0].internal_install_id, self.socketServer.errorString(), ) sys.exit() @@ -130,14 +130,14 @@ class TaggerWindow(QtWidgets.QMainWindow): grid_layout = QtWidgets.QGridLayout(self.tabPages) grid_layout.addWidget(self.page_list_editor) - self.fileSelectionList = FileSelectionList(self.widgetListHolder, self.options[0], self.dirty_flag_verification) + self.fileSelectionList = FileSelectionList(self.widgetListHolder, self.config[0], self.dirty_flag_verification) grid_layout = QtWidgets.QGridLayout(self.widgetListHolder) grid_layout.addWidget(self.fileSelectionList) self.fileSelectionList.selectionChanged.connect(self.file_list_selection_changed) self.fileSelectionList.listCleared.connect(self.file_list_cleared) self.fileSelectionList.set_sorting( - self.options[0].internal_sort_column, QtCore.Qt.SortOrder(self.options[0].internal_sort_direction) + self.config[0].internal_sort_column, QtCore.Qt.SortOrder(self.config[0].internal_sort_direction) ) # we can't specify relative font sizes in the UI designer, so @@ -155,13 +155,13 @@ class TaggerWindow(QtWidgets.QMainWindow): self.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png"))) - if options[0].runtime_type and isinstance(options[0].runtime_type[0], int): + if config[0].runtime_type and isinstance(config[0].runtime_type[0], int): # respect the command line option tag type - options[0].internal_save_data_style = options[0].runtime_type[0] - options[0].internal_load_data_style = options[0].runtime_type[0] + config[0].internal_save_data_style = config[0].runtime_type[0] + config[0].internal_load_data_style = config[0].runtime_type[0] - self.save_data_style = options[0].internal_save_data_style - self.load_data_style = options[0].internal_load_data_style + self.save_data_style = config[0].internal_save_data_style + self.load_data_style = config[0].internal_load_data_style self.setAcceptDrops(True) self.config_menus() @@ -226,8 +226,8 @@ class TaggerWindow(QtWidgets.QMainWindow): self.show() self.set_app_position() - if self.options[0].internal_form_width != -1: - self.splitter.setSizes([self.options[0].internal_form_width, self.options[0].internal_list_width]) + if self.config[0].internal_form_width != -1: + self.splitter.setSizes([self.config[0].internal_form_width, self.config[0].internal_list_width]) self.raise_() QtCore.QCoreApplication.processEvents() self.resizeEvent(None) @@ -244,7 +244,7 @@ class TaggerWindow(QtWidgets.QMainWindow): if len(file_list) != 0: self.fileSelectionList.add_path_list(file_list) - if self.options[0].dialog_show_disclaimer: + if self.config[0].dialog_show_disclaimer: checked = OptionalMessageDialog.msg( self, "Welcome!", @@ -259,9 +259,9 @@ use ComicTagger on local copies of your comics.

Have fun! """, ) - self.options[0].dialog_show_disclaimer = not checked + self.config[0].dialog_show_disclaimer = not checked - if self.options[0].general_check_for_new_version: + if self.config[0].general_check_for_new_version: self.check_latest_version_online() def open_file_event(self, url: QtCore.QUrl) -> None: @@ -274,7 +274,7 @@ Have fun! def setup_logger(self) -> ApplicationLogWindow: try: - current_logs = (self.options[0].runtime_config.user_log_dir / "ComicTagger.log").read_text("utf-8") + current_logs = (self.config[0].runtime_config.user_log_dir / "ComicTagger.log").read_text("utf-8") except Exception: current_logs = "" root_logger = logging.getLogger() @@ -479,7 +479,7 @@ Have fun! f"You have selected {non_zip_count} archive(s) to export to Zip format. " """ New archives will be created in the same folder as the original. - Please choose options below, and select OK. + Please choose config below, and select OK. """ ), ) @@ -607,10 +607,10 @@ Have fun! def actual_load_current_archive(self) -> None: if self.metadata.is_empty and self.comic_archive is not None: self.metadata = self.comic_archive.metadata_from_filename( - self.options[0].filename_complicated_parser, - self.options[0].filename_remove_c2c, - self.options[0].filename_remove_fcbd, - self.options[0].filename_remove_publisher, + self.config[0].filename_complicated_parser, + self.config[0].filename_remove_c2c, + self.config[0].filename_remove_fcbd, + self.config[0].filename_remove_publisher, ) if len(self.metadata.pages) == 0 and self.comic_archive is not None: self.metadata.set_default_page_list(self.comic_archive.get_number_of_pages()) @@ -969,10 +969,10 @@ Have fun! # copy the form onto metadata object self.form_to_metadata() new_metadata = self.comic_archive.metadata_from_filename( - self.options[0].filename_complicated_parser, - self.options[0].filename_remove_c2c, - self.options[0].filename_remove_fcbd, - self.options[0].filename_remove_publisher, + self.config[0].filename_complicated_parser, + self.config[0].filename_remove_c2c, + self.config[0].filename_remove_fcbd, + self.config[0].filename_remove_publisher, split_words, ) if new_metadata is not None: @@ -993,8 +993,8 @@ Have fun! else: dialog.setFileMode(QtWidgets.QFileDialog.FileMode.ExistingFiles) - if self.options[0].internal_last_opened_folder is not None: - dialog.setDirectory(self.options[0].internal_last_opened_folder) + if self.config[0].internal_last_opened_folder is not None: + dialog.setDirectory(self.config[0].internal_last_opened_folder) if not folder_mode: archive_filter = "Comic archive files (*.cbz *.zip *.cbr *.rar *.cb7 *.7z)" @@ -1044,7 +1044,7 @@ Have fun! issue_count, cover_index_list, self.comic_archive, - self.options[0], + self.config[0], self.talker_api, autoselect, literal, @@ -1072,10 +1072,10 @@ Have fun! else: QtWidgets.QApplication.restoreOverrideCursor() if new_metadata is not None: - if self.options[0].cbl_apply_transform_on_import: - new_metadata = CBLTransformer(new_metadata, self.options[0]).apply() + if self.config[0].cbl_apply_transform_on_import: + new_metadata = CBLTransformer(new_metadata, self.config[0]).apply() - if self.options[0].talkers_clear_form_before_populating: + if self.config[0].talkers_clear_form_before_populating: self.clear_form() notes = ( @@ -1130,7 +1130,7 @@ Have fun! "Change Tag Read Style", "If you change read tag style now, data in the form will be lost. Are you sure?" ): self.load_data_style = self.cbLoadDataStyle.itemData(s) - self.options[0].internal_load_data_style = self.load_data_style + self.config[0].internal_load_data_style = self.load_data_style self.update_menus() if self.comic_archive is not None: self.load_archive(self.comic_archive) @@ -1141,7 +1141,7 @@ Have fun! def set_save_data_style(self, s: int) -> None: self.save_data_style = self.cbSaveDataStyle.itemData(s) - self.options[0].internal_save_data_style = self.save_data_style + self.config[0].internal_save_data_style = self.save_data_style self.update_style_tweaks() self.update_menus() @@ -1360,15 +1360,15 @@ Have fun! def show_settings(self) -> None: - settingswin = SettingsWindow(self, self.options, self.talker_api) + settingswin = SettingsWindow(self, self.config, self.talker_api) settingswin.setModal(True) settingswin.exec() settingswin.result() def set_app_position(self) -> None: - if self.options[0].internal_window_width != 0: - self.move(self.options[0].internal_window_x, self.options[0].internal_window_y) - self.resize(self.options[0].internal_window_width, self.options[0].internal_window_height) + if self.config[0].internal_window_width != 0: + self.move(self.config[0].internal_window_x, self.config[0].internal_window_y) + self.resize(self.config[0].internal_window_width, self.config[0].internal_window_height) else: screen = QtGui.QGuiApplication.primaryScreen().geometry() size = self.frameGeometry() @@ -1635,8 +1635,8 @@ Have fun! if ca.has_metadata(src_style) and ca.is_writable(): md = ca.read_metadata(src_style) - if dest_style == MetaDataStyle.CBI and self.options[0].cbl_apply_transform_on_bulk_operation: - md = CBLTransformer(md, self.options[0]).apply() + if dest_style == MetaDataStyle.CBI and self.config[0].cbl_apply_transform_on_bulk_operation: + md = CBLTransformer(md, self.config[0]).apply() if not ca.write_metadata(md, dest_style): failed_list.append(ca.path) @@ -1674,8 +1674,8 @@ Have fun! logger.exception("Save aborted.") if not ct_md.is_empty: - if self.options[0].cbl_apply_transform_on_import: - ct_md = CBLTransformer(ct_md, self.options[0]).apply() + if self.config[0].cbl_apply_transform_on_import: + ct_md = CBLTransformer(ct_md, self.config[0]).apply() QtWidgets.QApplication.restoreOverrideCursor() @@ -1694,7 +1694,7 @@ Have fun! self, ca: ComicArchive, match_results: OnlineMatchResults, dlg: AutoTagStartWindow ) -> tuple[bool, OnlineMatchResults]: success = False - ii = IssueIdentifier(ca, self.options[0], self.talker_api) + ii = IssueIdentifier(ca, self.config[0], self.talker_api) # read in metadata, and parse file name if not there try: @@ -1704,10 +1704,10 @@ Have fun! logger.error("Failed to load metadata for %s: %s", ca.path, e) if md.is_empty: md = ca.metadata_from_filename( - self.options[0].filename_complicated_parser, - self.options[0].filename_remove_c2c, - self.options[0].filename_remove_fcbd, - self.options[0].filename_remove_publisher, + self.config[0].filename_complicated_parser, + self.config[0].filename_remove_c2c, + self.config[0].filename_remove_fcbd, + self.config[0].filename_remove_publisher, dlg.split_words, ) if dlg.ignore_leading_digits_in_filename and md.series is not None: @@ -1793,7 +1793,7 @@ Have fun! ) md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger"))) - if self.options[0].talkers_auto_imprint: + if self.config[0].talkers_auto_imprint: md.fix_publisher() if not ca.write_metadata(md, self.save_data_style): @@ -1822,10 +1822,10 @@ Have fun! atstartdlg = AutoTagStartWindow( self, - self.options[0], + self.config[0], ( f"You have selected {len(ca_list)} archive(s) to automatically identify and write {MetaDataStyle.name[style]} tags to." - "\n\nPlease choose options below, and select OK to Auto-Tag." + "\n\nPlease choose config below, and select OK to Auto-Tag." ), ) @@ -1925,7 +1925,7 @@ Have fun! match_results.multiple_matches, style, self.actual_issue_data_fetch, - self.options[0], + self.config[0], self.talker_api, ) matchdlg.setModal(True) @@ -1971,17 +1971,17 @@ Have fun! f"Exit {self.appName}", "If you quit now, data in the form will be lost. Are you sure?" ): appsize = self.size() - self.options[0].internal_window_width = appsize.width() - self.options[0].internal_window_height = appsize.height() - self.options[0].internal_window_x = self.x() - self.options[0].internal_window_y = self.y() - self.options[0].internal_form_width = self.splitter.sizes()[0] - self.options[0].internal_list_width = self.splitter.sizes()[1] + self.config[0].internal_window_width = appsize.width() + self.config[0].internal_window_height = appsize.height() + self.config[0].internal_window_x = self.x() + self.config[0].internal_window_y = self.y() + self.config[0].internal_form_width = self.splitter.sizes()[0] + self.config[0].internal_list_width = self.splitter.sizes()[1] ( - self.options[0].internal_sort_column, - self.options[0].internal_sort_direction, + self.config[0].internal_sort_column, + self.config[0].internal_sort_direction, ) = self.fileSelectionList.get_sorting() - settngs.save_file(self.options, self.options[0].runtime_config.user_config_dir / "settings.json") + settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json") event.accept() else: @@ -2030,7 +2030,7 @@ Have fun! def apply_cbl_transform(self) -> None: self.form_to_metadata() - self.metadata = CBLTransformer(self.metadata, self.options[0]).apply() + self.metadata = CBLTransformer(self.metadata, self.config[0]).apply() self.metadata_to_form() def recalc_page_dimensions(self) -> None: @@ -2056,7 +2056,7 @@ Have fun! "File Rename", "If you rename files now, unsaved data in the form will be lost. Are you sure?" ): - dlg = RenameWindow(self, ca_list, self.load_data_style, self.options, self.talker_api) + dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.talker_api) dlg.setModal(True) if dlg.exec() and self.comic_archive is not None: self.fileSelectionList.update_selected_rows() @@ -2075,7 +2075,7 @@ Have fun! QtCore.QTimer.singleShot(1, self.fileSelectionList.revert_selection) return - self.options[0].internal_last_opened_folder = os.path.abspath(os.path.split(comic_archive.path)[0]) + self.config[0].internal_last_opened_folder = os.path.abspath(os.path.split(comic_archive.path)[0]) self.comic_archive = comic_archive try: self.metadata = self.comic_archive.read_metadata(self.load_data_style) @@ -2106,10 +2106,10 @@ Have fun! def check_latest_version_online(self) -> None: version_checker = VersionChecker() - self.version_check_complete(version_checker.get_latest_version(self.options[0].internal_install_id)) + self.version_check_complete(version_checker.get_latest_version(self.config[0].internal_install_id)) def version_check_complete(self, new_version: tuple[str, str]) -> None: - if new_version[0] not in (self.version, self.options[0].dialog_dont_notify_about_this_version): + if new_version[0] not in (self.version, self.config[0].dialog_dont_notify_about_this_version): website = "https://github.com/comictagger/comictagger" checked = OptionalMessageDialog.msg( self, @@ -2120,7 +2120,7 @@ Have fun! "Don't tell me about this version again", ) if checked: - self.options[0].dialog_dont_notify_about_this_version = new_version[0] + self.config[0].dialog_dont_notify_about_this_version = new_version[0] def on_incoming_socket_connection(self) -> None: # Accept connection from other instance. diff --git a/comictalker/talkerbase.py b/comictalker/talkerbase.py index c3960c3..60bbf01 100644 --- a/comictalker/talkerbase.py +++ b/comictalker/talkerbase.py @@ -37,7 +37,7 @@ class SourceDetails: self.logo = logo -class SourceStaticOptions: +class SourceStaticSettings: def __init__( self, website: str = "", @@ -143,7 +143,7 @@ class ComicTalker: def __init__(self, version: str, cache_folder: pathlib.Path) -> None: # Identity name for the information source etc. self.source_details = SourceDetails() - self.static_options = SourceStaticOptions() + self.static_config = SourceStaticSettings() self.cache_folder = cache_folder self.version = version self.api_key: str = "" diff --git a/comictalker/talkers/comicvine.py b/comictalker/talkers/comicvine.py index 820cad4..1689203 100644 --- a/comictalker/talkers/comicvine.py +++ b/comictalker/talkers/comicvine.py @@ -34,7 +34,7 @@ from comicapi.genericmetadata import GenericMetadata from comicapi.issuestring import IssueString from comictalker.comiccacher import ComicCacher from comictalker.resulttypes import ComicIssue, ComicSeries, Credit -from comictalker.talkerbase import ComicTalker, SourceDetails, SourceStaticOptions, TalkerDataError, TalkerNetworkError +from comictalker.talkerbase import ComicTalker, SourceDetails, SourceStaticSettings, TalkerDataError, TalkerNetworkError logger = logging.getLogger(__name__) @@ -165,7 +165,7 @@ class ComicVineTalker(ComicTalker): ident="comicvine", logo="https://comicvine.gamespot.com/a/bundles/comicvinesite/images/logo.png", ) - self.static_options = SourceStaticOptions( + self.static_config = SourceStaticSettings( website="https://comicvine.gamespot.com/", attribution_string="Metadata provided by Comic Vine", has_issues=True, diff --git a/tests/comicarchive_test.py b/tests/comicarchive_test.py index e0949aa..33428ae 100644 --- a/tests/comicarchive_test.py +++ b/tests/comicarchive_test.py @@ -123,7 +123,7 @@ def test_invalid_zip(tmp_comic): archivers = [ pytest.param(x.load(), marks=pytest.mark.xfail(not (x.load().enabled), reason="archiver not enabled")) - for x in entry_points(group="comicapi_archivers") + for x in entry_points(group="comicapi.archiver") ] diff --git a/tests/comiccacher_test.py b/tests/comiccacher_test.py index b98277f..18bfcf0 100644 --- a/tests/comiccacher_test.py +++ b/tests/comiccacher_test.py @@ -6,10 +6,10 @@ import comictalker.comiccacher from testing.comicdata import search_results -def test_create_cache(options, mock_version): - settings, definitions = options - comictalker.comiccacher.ComicCacher(settings.runtime_config.user_cache_dir, mock_version[0]) - assert (settings.runtime_config.user_cache_dir).exists() +def test_create_cache(config, mock_version): + config, definitions = config + comictalker.comiccacher.ComicCacher(config.runtime_config.user_cache_dir, mock_version[0]) + assert (config.runtime_config.user_cache_dir).exists() def test_search_results(comic_cache): @@ -25,9 +25,5 @@ def test_search_results(comic_cache): def test_series_info(comic_cache, series_info): comic_cache.add_series_info(series_record=series_info, source_name="test") vi = series_info.copy() - # del vi["description"] - # del vi["image_url"] cache_result = comic_cache.get_series_info(series_id=series_info.id, source_name="test") - # del cache_result["description"] - # del cache_result["image_url"] assert vi == cache_result diff --git a/tests/conftest.py b/tests/conftest.py index f8f4a96..3127f98 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,7 +14,7 @@ from PIL import Image import comicapi.comicarchive import comicapi.genericmetadata -import comictaggerlib.ctoptions +import comictaggerlib.ctsettings import comictalker.comiccacher import comictalker.comictalkerapi import comictalker.talkers.comicvine @@ -56,9 +56,7 @@ def no_requests(monkeypatch) -> None: @pytest.fixture -def comicvine_api( - monkeypatch, cbz, comic_cache, mock_version, options -) -> comictalker.talkers.comicvine.ComicVineTalker: +def comicvine_api(monkeypatch, cbz, comic_cache, mock_version, config) -> comictalker.talkers.comicvine.ComicVineTalker: # Any arguments may be passed and mock_get() will always return our # mocked object, which only has the .json() method or None for invalid urls. @@ -118,7 +116,7 @@ def comicvine_api( cv = comictalker.talkers.comicvine.ComicVineTalker( version=mock_version[0], - cache_folder=options[0].runtime_config.user_cache_dir, + cache_folder=config[0].runtime_config.user_cache_dir, ) return cv @@ -158,12 +156,12 @@ def seed_all_publishers(monkeypatch): @pytest.fixture -def options(settings_manager, tmp_path): +def config(settings_manager, tmp_path): - comictaggerlib.ctoptions.register_commandline(settings_manager) - comictaggerlib.ctoptions.register_settings(settings_manager) + comictaggerlib.ctsettings.register_commandline_settings(settings_manager) + comictaggerlib.ctsettings.register_file_settings(settings_manager) defaults = settings_manager.get_namespace(settings_manager.defaults()) - defaults[0].runtime_config = comictaggerlib.ctoptions.ComicTaggerPaths(tmp_path / "config") + defaults[0].runtime_config = comictaggerlib.ctsettings.ComicTaggerPaths(tmp_path / "config") defaults[0].runtime_config.user_data_dir.mkdir(parents=True, exist_ok=True) defaults[0].runtime_config.user_config_dir.mkdir(parents=True, exist_ok=True) defaults[0].runtime_config.user_cache_dir.mkdir(parents=True, exist_ok=True) @@ -179,5 +177,5 @@ def settings_manager(): @pytest.fixture -def comic_cache(options, mock_version) -> Generator[comictalker.comiccacher.ComicCacher, Any, None]: - yield comictalker.comiccacher.ComicCacher(options[0].runtime_config.user_cache_dir, mock_version[0]) +def comic_cache(config, mock_version) -> Generator[comictalker.comiccacher.ComicCacher, Any, None]: + yield comictalker.comiccacher.ComicCacher(config[0].runtime_config.user_cache_dir, mock_version[0]) diff --git a/tests/issueidentifier_test.py b/tests/issueidentifier_test.py index f8a8acf..6be6809 100644 --- a/tests/issueidentifier_test.py +++ b/tests/issueidentifier_test.py @@ -12,9 +12,9 @@ import testing.comicdata import testing.comicvine -def test_crop(cbz_double_cover, options, tmp_path, comicvine_api): - settings, definitions = options - ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, settings, comicvine_api) +def test_crop(cbz_double_cover, config, tmp_path, comicvine_api): + config, definitions = config + ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz_double_cover, config, comicvine_api) cropped = ii.crop_cover(cbz_double_cover.archiver.read_file("double_cover.jpg")) original_cover = cbz_double_cover.get_page(0) @@ -25,17 +25,17 @@ def test_crop(cbz_double_cover, options, tmp_path, comicvine_api): @pytest.mark.parametrize("additional_md, expected", testing.comicdata.metadata_keys) -def test_get_search_keys(cbz, options, additional_md, expected, comicvine_api): - settings, definitions = options - ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api) +def test_get_search_keys(cbz, config, additional_md, expected, comicvine_api): + config, definitions = config + ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api) ii.set_additional_metadata(additional_md) assert expected == ii.get_search_keys() -def test_get_issue_cover_match_score(cbz, options, comicvine_api): - settings, definitions = options - ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api) +def test_get_issue_cover_match_score(cbz, config, comicvine_api): + config, definitions = config + ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api) score = ii.get_issue_cover_match_score( int( comicapi.issuestring.IssueString( @@ -54,9 +54,9 @@ def test_get_issue_cover_match_score(cbz, options, comicvine_api): assert expected == score -def test_search(cbz, options, comicvine_api): - settings, definitions = options - ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api) +def test_search(cbz, config, comicvine_api): + config, definitions = config + ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api) results = ii.search() cv_expected = { "series": f"{testing.comicvine.cv_volume_result['results']['name']} ({testing.comicvine.cv_volume_result['results']['start_year']})", @@ -78,9 +78,9 @@ def test_search(cbz, options, comicvine_api): assert r == e -def test_crop_border(cbz, options, comicvine_api): - settings, definitions = options - ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, settings, comicvine_api) +def test_crop_border(cbz, config, comicvine_api): + config, definitions = config + ii = comictaggerlib.issueidentifier.IssueIdentifier(cbz, config, comicvine_api) # This creates a white square centered on a black background bg = Image.new("RGBA", (100, 100), (0, 0, 0, 255))