Use new settings system for plugin
This commit is contained in:
parent
0ac5b59a1e
commit
2d8c47edca
@ -49,7 +49,7 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.options.autotag_ignore_leading_numbers_in_filename)
|
||||
self.cbxRemoveAfterSuccess.setChecked(self.options.autotag_remove_archive_after_successful_match)
|
||||
self.cbxWaitForRateLimit.setChecked(self.options.autotag_wait_and_retry_on_rate_limit)
|
||||
self.cbxAutoImprint.setChecked(self.options.comicvine_auto_imprint)
|
||||
self.cbxAutoImprint.setChecked(self.options.talkers_general_auto_imprint)
|
||||
|
||||
nlmt_tip = """<html>The <b>Name Match Ratio Threshold: Auto-Identify</b> is for eliminating automatic
|
||||
search matches that are too long compared to your series name search. The lower
|
||||
|
@ -108,7 +108,7 @@ class CLI:
|
||||
ca = match_set.ca
|
||||
md = self.create_local_metadata(ca)
|
||||
ct_md = self.actual_issue_data_fetch(match_set.matches[int(i) - 1]["issue_id"])
|
||||
if self.options.comicvine_clear_metadata_on_import:
|
||||
if self.options.talkers_general_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -117,7 +117,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options.comicvine_auto_imprint:
|
||||
if self.options.talkers_general_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
self.actual_metadata_save(ca, md)
|
||||
@ -428,7 +428,7 @@ class CLI:
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.options.comicvine_clear_metadata_on_import:
|
||||
if self.options.talkers_general_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -437,7 +437,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options.comicvine_auto_imprint:
|
||||
if self.options.talkers_general_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
# ok, done building our metadata. time to save
|
||||
|
@ -93,13 +93,9 @@ def filename(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def comicvine(parser: settngs.Manager) -> None:
|
||||
# Comic Vine settings
|
||||
parser.add_setting(
|
||||
"--series-match-search-thresh",
|
||||
default=90,
|
||||
type=int,
|
||||
)
|
||||
def talkers_general(parser: settngs.Manager) -> None:
|
||||
# General settings for all information talkers
|
||||
parser.add_setting("--source", default="comicvine", help="Use a specified source by source ID")
|
||||
parser.add_setting("--use-series-start-as-volume", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting(
|
||||
"--clear-metadata",
|
||||
@ -108,20 +104,6 @@ def comicvine(parser: settngs.Manager) -> None:
|
||||
dest="clear_metadata_on_import",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
)
|
||||
parser.add_setting(
|
||||
"--remove-html-tables",
|
||||
default=False,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Removes html tables instead of converting them to text",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--cv-api-key",
|
||||
help="Use the given Comic Vine API Key (persisted in settings).",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--cv-url",
|
||||
help="Use the given Comic Vine URL (persisted in settings).",
|
||||
)
|
||||
parser.add_setting(
|
||||
"-a",
|
||||
"--auto-imprint",
|
||||
@ -146,10 +128,10 @@ def comicvine(parser: settngs.Manager) -> None:
|
||||
help="Enables the publisher filter",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--clear-form-before-populating-from-cv",
|
||||
"--clear-form-before-populating",
|
||||
default=False,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Clears all existing metadata when applying metadata from ComicVine",
|
||||
help="Clears all existing metadata when applying metadata from comic source",
|
||||
)
|
||||
|
||||
|
||||
@ -257,13 +239,17 @@ def validate_settings(options: settngs.Config[settngs.Values], parser: settngs.M
|
||||
return options
|
||||
|
||||
|
||||
def register_settings(parser: settngs.Manager) -> None:
|
||||
def register_settings(parser: settngs.Manager, talkers: dict[str, Any]) -> None:
|
||||
parser.add_group("general", general, False)
|
||||
parser.add_group("internal", internal, False)
|
||||
parser.add_group("identifier", identifier, False)
|
||||
parser.add_group("dialog", dialog, False)
|
||||
parser.add_group("filename", filename, False)
|
||||
parser.add_group("comicvine", comicvine, False)
|
||||
parser.add_group("talkers_general", talkers_general, False)
|
||||
parser.add_group("cbl", cbl, False)
|
||||
parser.add_group("rename", rename, False)
|
||||
parser.add_group("autotag", autotag, False)
|
||||
|
||||
# Register talker plugin settings
|
||||
for talker, cls in talkers.items():
|
||||
parser.add_group(talker, cls.comic_settings, False)
|
||||
|
@ -66,8 +66,10 @@ class App:
|
||||
self.options = settngs.Config({}, {})
|
||||
self.initial_arg_parser = ctoptions.initial_cmd_line_parser()
|
||||
self.config_load_success = False
|
||||
self.talker_plugins: dict = {}
|
||||
|
||||
def run(self) -> None:
|
||||
self.talker_plugins = ct_api.get_talkers()
|
||||
opts = self.initialize()
|
||||
self.register_options()
|
||||
self.parse_options(opts.config)
|
||||
@ -87,7 +89,7 @@ class App:
|
||||
"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_settings(self.manager, self.talker_plugins)
|
||||
|
||||
def parse_options(self, config_paths: ctoptions.ComicTaggerPaths) -> None:
|
||||
self.options, self.config_load_success = self.manager.parse_config(
|
||||
@ -99,6 +101,18 @@ class App:
|
||||
self.options = ctoptions.validate_settings(self.options, self.manager)
|
||||
self.options = self.options
|
||||
|
||||
# parse talker settings
|
||||
for loaded in self.talker_plugins.values():
|
||||
parse_options = getattr(loaded, "parse_settings", None)
|
||||
if parse_options is None:
|
||||
logger.warning(f"Failed to find parse_settings in talker {loaded}")
|
||||
continue
|
||||
|
||||
try:
|
||||
parse_options(self.options)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to parse talker options for {loaded}: {e}")
|
||||
|
||||
def initialize_dirs(self) -> None:
|
||||
self.options[0].runtime_config.user_data_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.options[0].runtime_config.user_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
@ -136,28 +150,12 @@ class App:
|
||||
self.options[0].runtime_no_gui = True
|
||||
logger.warning("PyQt5 is not available. ComicTagger is limited to command-line mode.")
|
||||
|
||||
# manage the CV API key
|
||||
# None comparison is used so that the empty string can unset the value
|
||||
if self.options[0].comicvine_cv_api_key is not None or self.options[0].comicvine_cv_url is not None:
|
||||
settings_path = self.options[0].runtime_config.user_config_dir / "settings.json"
|
||||
if self.config_load_success:
|
||||
self.manager.save_file(self.options[0], settings_path)
|
||||
|
||||
if self.options[0].commands_only_set_cv_key:
|
||||
if self.config_load_success:
|
||||
print("Key set") # noqa: T201
|
||||
return
|
||||
# TODO Have option to save passed in config options and quit?
|
||||
|
||||
try:
|
||||
talker_api = ct_api.get_comic_talker("comicvine")( # type: ignore[call-arg]
|
||||
version=version,
|
||||
cache_folder=self.options[0].runtime_config.user_cache_dir,
|
||||
series_match_thresh=self.options[0].comicvine_series_match_search_thresh,
|
||||
remove_html_tables=self.options[0].comicvine_remove_html_tables,
|
||||
use_series_start_as_volume=self.options[0].comicvine_use_series_start_as_volume,
|
||||
wait_on_ratelimit=self.options[0].autotag_wait_and_retry_on_rate_limit,
|
||||
api_url=self.options[0].comicvine_cv_url,
|
||||
api_key=self.options[0].comicvine_cv_api_key,
|
||||
)
|
||||
except TalkerError as e:
|
||||
logger.exception("Unable to load talker")
|
||||
|
@ -156,7 +156,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.progdialog: QtWidgets.QProgressDialog | None = None
|
||||
self.search_thread: SearchThread | None = None
|
||||
|
||||
self.use_filter = self.options.comicvine_always_use_publisher_filter
|
||||
self.use_filter = self.options.talkers_general_always_use_publisher_filter
|
||||
|
||||
# Load to retrieve settings
|
||||
self.talker_api = talker_api
|
||||
@ -395,7 +395,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.comicvine_sort_series_by_year:
|
||||
if self.options.talkers_general_sort_series_by_year:
|
||||
try:
|
||||
self.ct_search_results = sorted(
|
||||
self.ct_search_results,
|
||||
@ -413,7 +413,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.comicvine_exact_series_matches_first:
|
||||
if self.options.talkers_general_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()
|
||||
|
@ -282,13 +282,13 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.cbxRemovePublisher.setChecked(self.options[0].filename_remove_publisher)
|
||||
self.switch_parser()
|
||||
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.options[0].comicvine_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.options[0].comicvine_clear_form_before_populating_from_cv)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.options[0].comicvine_remove_html_tables)
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.options[0].comicvine_cv_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.options[0].talkers_general_clear_form_before_populating)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.options[0].comicvine_cv_remove_html_tables)
|
||||
|
||||
self.cbxUseFilter.setChecked(self.options[0].comicvine_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.options[0].comicvine_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.options[0].comicvine_exact_series_matches_first)
|
||||
self.cbxUseFilter.setChecked(self.options[0].talkers_general_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.options[0].talkers_general_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.options[0].talkers_general_exact_series_matches_first)
|
||||
|
||||
self.leKey.setText(self.options[0].comicvine_cv_api_key)
|
||||
self.leURL.setText(self.options[0].comicvine_cv_url)
|
||||
@ -396,13 +396,13 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.options[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked()
|
||||
self.options[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked()
|
||||
|
||||
self.options[0].comicvine_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.options[0].comicvine_clear_form_before_populating_from_cv = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.options[0].comicvine_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
self.options[0].comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.options[0].talkers_general_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.options[0].comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
|
||||
self.options[0].comicvine_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.options[0].comicvine_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.options[0].comicvine_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
self.options[0].talkers_general_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.options[0].talkers_general_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.options[0].talkers_general_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
|
||||
if self.leKey.text().strip():
|
||||
self.options[0].comicvine_cv_api_key = self.leKey.text().strip()
|
||||
|
@ -1084,7 +1084,7 @@ Have fun!
|
||||
if self.options[0].cbl_apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.options[0]).apply()
|
||||
|
||||
if self.options[0].comicvine_clear_form_before_populating_from_cv:
|
||||
if self.options[0].talkers_general_clear_form_before_populating:
|
||||
self.clear_form()
|
||||
|
||||
notes = (
|
||||
@ -1802,7 +1802,7 @@ Have fun!
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.options[0].comicvine_auto_imprint:
|
||||
if self.options[0].talkers_general_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
if not ca.write_metadata(md, self.save_data_style):
|
||||
|
@ -13,10 +13,12 @@
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import pathlib
|
||||
from typing import Callable
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
import settngs
|
||||
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comictalker.resulttypes import ComicIssue, ComicSeries
|
||||
@ -148,16 +150,16 @@ class ComicTalker:
|
||||
self.cache_folder = cache_folder
|
||||
self.version = version
|
||||
|
||||
self.api_key = api_key or self.default_api_key
|
||||
self.api_url = api_url or self.default_api_url
|
||||
self.api_key = ""
|
||||
self.api_url = ""
|
||||
|
||||
tmp_url = urlsplit(self.api_url)
|
||||
@classmethod
|
||||
def comic_settings(cls, parser: settngs.Manager) -> None:
|
||||
"""Talker settings."""
|
||||
|
||||
# joinurl only works properly if there is a trailing slash
|
||||
if tmp_url.path and tmp_url.path[-1] != "/":
|
||||
tmp_url = tmp_url._replace(path=tmp_url.path + "/")
|
||||
|
||||
self.api_url = tmp_url.geturl()
|
||||
@classmethod
|
||||
def parse_settings(cls, settings: argparse.Namespace) -> None:
|
||||
"""Parse settings."""
|
||||
|
||||
def check_api_key(self, key: str, url: str) -> bool:
|
||||
"""
|
||||
|
@ -16,6 +16,7 @@ ComicVine information source
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import pathlib
|
||||
@ -24,6 +25,7 @@ from typing import Any, Callable, Generic, TypeVar
|
||||
from urllib.parse import urljoin, urlsplit
|
||||
|
||||
import requests
|
||||
import settngs
|
||||
from typing_extensions import Required, TypedDict
|
||||
|
||||
import comictalker.talker_utils as talker_utils
|
||||
@ -155,18 +157,20 @@ class ComicVineTalker(ComicTalker):
|
||||
default_api_key = "27431e6787042105bd3e47e169a624521f89f3a4"
|
||||
default_api_url = "https://comicvine.gamespot.com/api"
|
||||
|
||||
# Settings
|
||||
api_url: str = ""
|
||||
api_key: str = ""
|
||||
series_match_thresh: int = 90
|
||||
remove_html_tables: bool = False
|
||||
use_series_start_as_volume: bool = False
|
||||
wait_on_ratelimit: bool = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
version: str,
|
||||
cache_folder: pathlib.Path,
|
||||
api_url: str = "",
|
||||
api_key: str = "",
|
||||
series_match_thresh: int = 90,
|
||||
remove_html_tables: bool = False,
|
||||
use_series_start_as_volume: bool = False,
|
||||
wait_on_ratelimit: bool = False,
|
||||
):
|
||||
super().__init__(version, cache_folder, api_url, api_key)
|
||||
super().__init__(version, cache_folder)
|
||||
self.source_details = SourceDetails(name="Comic Vine", ident="comicvine")
|
||||
self.static_options = SourceStaticOptions(
|
||||
website="https://comicvine.gamespot.com/",
|
||||
@ -181,14 +185,65 @@ class ComicVineTalker(ComicTalker):
|
||||
self.source_name: str = self.source_details.id
|
||||
self.source_name_friendly: str = self.source_details.name
|
||||
|
||||
self.wait_for_rate_limit: bool = wait_on_ratelimit
|
||||
# If cls api_url or api_key is empty, use default
|
||||
self.api_url = ComicVineTalker.api_url or ComicVineTalker.default_api_url
|
||||
self.api_key = ComicVineTalker.api_key or ComicVineTalker.default_api_key
|
||||
|
||||
tmp_url = urlsplit(self.api_url)
|
||||
|
||||
# joinurl only works properly if there is a trailing slash
|
||||
if tmp_url.path and tmp_url.path[-1] != "/":
|
||||
tmp_url = tmp_url._replace(path=tmp_url.path + "/")
|
||||
|
||||
self.api_url = tmp_url.geturl()
|
||||
|
||||
self.wait_for_rate_limit: bool = ComicVineTalker.wait_on_ratelimit
|
||||
# NOTE: This was hardcoded before which is why it isn't passed in
|
||||
self.wait_for_rate_limit_time: int = 20
|
||||
|
||||
self.remove_html_tables: bool = remove_html_tables
|
||||
self.use_series_start_as_volume: bool = use_series_start_as_volume
|
||||
self.remove_html_tables: bool = ComicVineTalker.remove_html_tables
|
||||
self.use_series_start_as_volume: bool = ComicVineTalker.use_series_start_as_volume
|
||||
|
||||
self.series_match_thresh: int = series_match_thresh
|
||||
self.series_match_thresh: int = ComicVineTalker.series_match_thresh
|
||||
|
||||
@classmethod
|
||||
def comic_settings(cls, parser: settngs.Manager) -> None:
|
||||
# Might be general settings?
|
||||
parser.add_setting(
|
||||
"--series-match-search-thresh",
|
||||
default=90,
|
||||
type=int,
|
||||
)
|
||||
parser.add_setting("--cv-use-series-start-as-volume", default=False, action=argparse.BooleanOptionalAction)
|
||||
|
||||
# Comic Vine settings
|
||||
parser.add_setting("--cv-wait-on-ratelimit", default=False, action=argparse.BooleanOptionalAction)
|
||||
parser.add_setting(
|
||||
"--cv-remove-html-tables",
|
||||
default=False,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Removes html tables instead of converting them to text.",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--cv-api-key",
|
||||
help="Use the given Comic Vine API Key.",
|
||||
)
|
||||
parser.add_setting(
|
||||
"--cv-url",
|
||||
help="Use the given Comic Vine URL.",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def parse_settings(cls, settings: settngs.Config) -> None:
|
||||
"""Parse settings."""
|
||||
if settings[0].comicvine_cv_remove_html_tables:
|
||||
cls.remove_html_tables = bool(settings[0].comicvine_cv_remove_html_tables)
|
||||
if settings[0].comicvine_cv_use_series_start_as_volume:
|
||||
cls.use_series_start_as_volume = settings[0].comicvine_cv_use_series_start_as_volume
|
||||
if settings[0].comicvine_cv_api_key:
|
||||
cls.api_key = settings[0].comicvine_cv_api_key
|
||||
if settings[0].comicvine_cv_url:
|
||||
cls.api_url = settings[0].comicvine_cv_url
|
||||
|
||||
def check_api_key(self, key: str, url: str) -> bool:
|
||||
if not url:
|
||||
|
@ -118,12 +118,6 @@ def comicvine_api(
|
||||
cv = comictalker.talkers.comicvine.ComicVineTalker(
|
||||
version=mock_version[0],
|
||||
cache_folder=options[0].runtime_config.user_cache_dir,
|
||||
api_url="",
|
||||
api_key="",
|
||||
series_match_thresh=90,
|
||||
remove_html_tables=False,
|
||||
use_series_start_as_volume=False,
|
||||
wait_on_ratelimit=False,
|
||||
)
|
||||
return cv
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user