From bf2b4ab268642d776c5050846e8e5d4d42aea63f Mon Sep 17 00:00:00 2001 From: Timmy Welch Date: Wed, 6 Sep 2023 02:59:59 -0400 Subject: [PATCH] Rename check_api_key to check_status Parameter is changed to a settings dict so that a Talker can retrieve any info it needs Change issue_id type annotation to str --- comictaggerlib/ui/talkeruigenerator.py | 43 ++++++++++++-------------- comictalker/comiccacher.py | 2 +- comictalker/comictalker.py | 14 ++++++--- comictalker/talkers/comicvine.py | 12 ++++--- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/comictaggerlib/ui/talkeruigenerator.py b/comictaggerlib/ui/talkeruigenerator.py index a4d5d29..0b54c9d 100644 --- a/comictaggerlib/ui/talkeruigenerator.py +++ b/comictaggerlib/ui/talkeruigenerator.py @@ -69,17 +69,8 @@ def generate_api_widgets( layout: QtWidgets.QGridLayout, ) -> None: # *args enforces keyword arguments and allows position arguments to be ignored - def call_check_api( - *args: Any, le_url: QtWidgets.QLineEdit, le_key: QtWidgets.QLineEdit, talker: ComicTalker - ) -> None: - url = "" - key = "" - if le_key is not None: - key = le_key.text().strip() - if le_url is not None: - url = le_url.text().strip() - - check_text, check_bool = talker.check_api_key(url, key) + def call_check_api(*args: Any, tab: TalkerTab, talker: ComicTalker) -> None: + check_text, check_bool = talker.check_status(get_config_dict(tab)) if check_bool: QtWidgets.QMessageBox.information(None, "API Test Success", check_text) else: @@ -115,7 +106,7 @@ def generate_api_widgets( btn = QtWidgets.QPushButton("Test API") layout.addWidget(btn, btn_test_row, 2) # partial is used as connect will pass in event information - btn.clicked.connect(partial(call_check_api, le_url=le_url, le_key=le_key, talker=talker)) + btn.clicked.connect(partial(call_check_api, tab=TalkerTab, talker=talker)) def generate_checkbox(option: settngs.Setting, layout: QtWidgets.QGridLayout) -> QtWidgets.QCheckBox: @@ -199,6 +190,22 @@ def settings_to_talker_form(sources: Sources, config: settngs.Config[ct_ns]) -> logger.debug("Failed to set value of %s for %s(%s)", dest, talker.name, talker.id) +def get_config_dict(tab: TalkerTab) -> dict[str, Any]: + talker_options = {} + # dest is guaranteed to be unique within a talker and refer to the correct item in config.values['group name'] + for dest, widget in tab.widgets.items(): + widget_value = None + if isinstance(widget, (QtWidgets.QSpinBox, QtWidgets.QDoubleSpinBox)): + widget_value = widget.value() + elif isinstance(widget, QtWidgets.QLineEdit): + widget_value = widget.text().strip() + elif isinstance(widget, QtWidgets.QCheckBox): + widget_value = widget.isChecked() + + talker_options[dest] = widget_value + return talker_options + + def form_settings_to_config(sources: Sources, config: settngs.Config) -> settngs.Config[ct_ns]: # Update the currently selected talker config.values.Sources_source = sources.cbx_sources.currentData() @@ -207,17 +214,7 @@ def form_settings_to_config(sources: Sources, config: settngs.Config) -> settngs # Iterate over the tabs, the talker is included in the tab so no extra lookup is needed for talker, tab in sources.tabs: talker_options = cfg.values[group_for_plugin(talker)] - # dest is guaranteed to be unique within a talker and refer to the correct item in config.values['group name'] - for dest, widget in tab.widgets.items(): - widget_value = None - if isinstance(widget, (QtWidgets.QSpinBox, QtWidgets.QDoubleSpinBox)): - widget_value = widget.value() - elif isinstance(widget, QtWidgets.QLineEdit): - widget_value = widget.text().strip() - elif isinstance(widget, QtWidgets.QCheckBox): - widget_value = widget.isChecked() - - talker_options[dest] = widget_value + talker_options.update(get_config_dict(tab)) return cast(settngs.Config[ct_ns], settngs.get_namespace(cfg, True, True)) diff --git a/comictalker/comiccacher.py b/comictalker/comiccacher.py index edf5222..6a6e287 100644 --- a/comictalker/comiccacher.py +++ b/comictalker/comiccacher.py @@ -248,7 +248,7 @@ class ComicCacher: return results - def get_issue_info(self, issue_id: int, source: str, expire_stale: bool = True) -> tuple[Issue, bool] | None: + def get_issue_info(self, issue_id: str, source: str, expire_stale: bool = True) -> tuple[Issue, bool] | None: with sqlite3.connect(self.db_file) as con: con.row_factory = sqlite3.Row cur = con.cursor() diff --git a/comictalker/comictalker.py b/comictalker/comictalker.py index 14a13c3..8e10610 100644 --- a/comictalker/comictalker.py +++ b/comictalker/comictalker.py @@ -142,16 +142,20 @@ class ComicTalker: settings[f"{self.id}_url"] = None return settings - def check_api_key(self, url: str, key: str) -> tuple[str, bool]: + def check_status(self, settings: dict[str, Any]) -> tuple[str, bool]: """ - This function should return (msg, True) if the given API key and URL are valid, + This function should return (msg, True) if the given settings are valid, where msg is a message to display to the user. - This function should return (msg, False) if the given API key or URL are not valid, + This function should return (msg, False) if the given settings are not valid, where msg is a message to display to the user. - If the Talker does not use an API key it should validate that the URL works. - If the Talker does not use an API key or URL it should check that the source is available. + This function MUST NOT keep any values from the given settings, this is a test function only. + If the Talker uses the network it should ensure that it can authenticate with the given settings. + If settings provides an invalid URL, API key or other piece of information used to authenticate it MUST fail. + The only time that defaults should be used is when the value is an empty string or None + + If the Talker does not use the network it should validate that all local data has been configured correctly. Caching MUST NOT be implemented on this function. """ diff --git a/comictalker/talkers/comicvine.py b/comictalker/talkers/comicvine.py index 68eca55..cd69901 100644 --- a/comictalker/talkers/comicvine.py +++ b/comictalker/talkers/comicvine.py @@ -206,8 +206,8 @@ class ComicVineTalker(ComicTalker): return settings - def check_api_key(self, url: str, key: str) -> tuple[str, bool]: - url = talker_utils.fix_url(url) + def check_status(self, settings: dict[str, Any]) -> tuple[str, bool]: + url = talker_utils.fix_url(settings[f"{self.id}_url"]) if not url: url = self.default_api_url try: @@ -216,7 +216,11 @@ class ComicVineTalker(ComicTalker): cv_response: CVResult = requests.get( test_url, headers={"user-agent": "comictagger/" + self.version}, - params={"api_key": key or self.default_api_key, "format": "json", "field_list": "name"}, + params={ + "api_key": settings[f"{self.id}_key"] or self.default_api_key, + "format": "json", + "field_list": "name", + }, ).json() # Bogus request, but if the key is wrong, you get error 100: "Invalid API Key" @@ -583,7 +587,7 @@ class ComicVineTalker(ComicTalker): def _fetch_issue_data_by_issue_id(self, issue_id: str) -> GenericMetadata: # before we search online, look in our cache, since we might already have this info cvc = ComicCacher(self.cache_folder, self.version) - cached_issue = cvc.get_issue_info(int(issue_id), self.id) + cached_issue = cvc.get_issue_info(issue_id, self.id) if cached_issue and cached_issue[1]: return self._map_comic_issue_to_metadata(