Change source term to metadata

Generate API text field in their own function
API tests return string message of result
Add help to text field lables
This commit is contained in:
Mizaki 2023-02-23 00:42:48 +00:00
parent 5b5a483e25
commit 118429f84c
4 changed files with 75 additions and 82 deletions

View File

@ -338,7 +338,7 @@
</widget>
<widget class="QWidget" name="tComicTalkers">
<attribute name="title">
<string>Comic Sources</string>
<string>Metadata Sources</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4"/>
</widget>

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import argparse
import logging
from functools import partial
import settngs
from PyQt5 import QtCore, QtWidgets
@ -11,56 +12,53 @@ from comictalker.comictalker import ComicTalker
logger = logging.getLogger(__name__)
def call_check_api_key(
def generate_api_widgets(
talker_id: str,
sources_info: dict[str, QtWidgets.QWidget],
sources: dict[str, QtWidgets.QWidget],
config: settngs.Config[settngs.Namespace],
layout: QtWidgets.QGridLayout,
talkers: dict[str, ComicTalker],
):
key = ""
# Find the correct widget to get the API key
for name, widget in sources_info[talker_id]["widgets"].items():
if name.startswith("talker_" + talker_id) and name.endswith("api_key"):
key = widget.text().strip()
# *args enforces keyword arguments and allows position arguments to be ignored
def call_check_api(*args, le_url: QtWidgets.QLineEdit, le_key: QtWidgets.QLineEdit, talker_id: str):
url = ""
key = ""
if le_key is not None:
key = le_key.text().strip()
if le_url is not None:
url = le_url.text().strip()
QtWidgets.QMessageBox.information(None, "API Test", talkers[talker_id].check_api_key(url, key))
if talkers[talker_id].check_api_key(key):
QtWidgets.QMessageBox.information(None, "API Key Test", "Key is valid!")
else:
QtWidgets.QMessageBox.warning(None, "API Key Test", "Key is NOT valid!")
# get the actual config objects in case they have overwritten the default
talker_key = config[1][f"talker_{talker_id}"][1][f"{talker_id}_key"]
talker_url = config[1][f"talker_{talker_id}"][1][f"{talker_id}_url"]
btn_test_row = None
le_key = None
le_url = None
# only file settings are saved
if talker_key.file:
# record the current row so we know where to add the button
btn_test_row = layout.rowCount()
le_key = generate_textbox(talker_key, layout)
# To enable setting and getting
sources["tabs"][talker_id]["widgets"][f"talker_{talker_id}_{talker_id}_key"] = le_key
def call_check_api_url(
talker_id: str,
sources_info: dict[str, QtWidgets.QWidget],
talkers: dict[str, ComicTalker],
):
url = ""
# Find the correct widget to get the URL key
for name, widget in sources_info[talker_id]["widgets"].items():
if name.startswith("talker_" + talker_id) and name.endswith("url"):
url = widget.text().strip()
# only file settings are saved
if talker_url.file:
# record the current row so we know where to add the button
# We overwrite so that the default will be next to the url text box
btn_test_row = layout.rowCount()
le_url = generate_textbox(talker_url, layout)
# To enable setting and getting
sources["tabs"][talker_id]["widgets"][f"talker_{talker_id}_{talker_id}_url"] = le_url
if talkers[talker_id].check_api_url(url):
QtWidgets.QMessageBox.information(None, "API Key Test", "URL is valid!")
else:
QtWidgets.QMessageBox.warning(None, "API Key Test", "URL is NOT valid!")
def api_key_btn_connect(
btn: QtWidgets.QPushButton,
talker_id: str,
sources_info: dict[str, QtWidgets.QWidget],
talkers: dict[str, ComicTalker],
) -> None:
btn.clicked.connect(lambda: call_check_api_key(talker_id, sources_info, talkers))
def api_url_btn_connect(
btn: QtWidgets.QPushButton,
talker_id: str,
sources_info: dict[str, QtWidgets.QWidget],
talkers: dict[str, ComicTalker],
) -> None:
btn.clicked.connect(lambda: call_check_api_url(talker_id, sources_info, talkers))
# The button row was recorded so we add it
if btn_test_row is not None:
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_id=talker_id))
def generate_checkbox(option: settngs.Setting, layout: QtWidgets.QGridLayout) -> QtWidgets.QCheckBox:
@ -95,33 +93,21 @@ def generate_doublespinbox(option: settngs.Setting, layout: QtWidgets.QGridLayou
return widget
def generate_textbox(
option: settngs.Setting, layout: QtWidgets.QGridLayout
) -> tuple[QtWidgets.QLineEdit, QtWidgets.QPushButton]:
btn = None
def generate_textbox(option: settngs.Setting, layout: QtWidgets.QGridLayout) -> QtWidgets.QLineEdit:
row = layout.rowCount()
lbl = QtWidgets.QLabel(option.display_name)
layout.addWidget(lbl, row, 0)
widget = QtWidgets.QLineEdit()
widget.setObjectName(option.internal_name)
lbl.setToolTip(option.help)
widget.setToolTip(option.help)
layout.addWidget(widget, row, 1)
# Special case for api_key, make a test button
if option.internal_name.endswith("key"):
btn = QtWidgets.QPushButton("Test Key")
layout.addWidget(btn, row, 2)
if option.internal_name.endswith("url"):
btn = QtWidgets.QPushButton("Test URL")
layout.addWidget(btn, row, 2)
return widget, btn
return widget
def settings_to_talker_form(sources: dict[str, QtWidgets.QWidget], config: settngs.Config[settngs.Namespace]) -> None:
# Set the active talker in sources combo box
sources["talker_source"].setCurrentIndex(sources["talker_source"].findData(config[0].talker_source))
# Set the active talker via id in sources combo box
sources["cbx_select_talker"].setCurrentIndex(sources["cbx_select_talker"].findData(config[0].talker_source))
for talker in sources["tabs"].items():
for name, widget in talker[1]["widgets"].items():
@ -140,7 +126,7 @@ def settings_to_talker_form(sources: dict[str, QtWidgets.QWidget], config: settn
def form_settings_to_config(sources: dict[str, QtWidgets.QWidget], config: settngs.Config[settngs.Namespace]) -> None:
# Source combo box value
config[0].talker_source = sources["talker_source"].currentData()
config[0].talker_source = sources["cbx_select_talker"].currentData()
for tab in sources["tabs"].items():
for name, widget in tab[1]["widgets"].items():
@ -171,33 +157,37 @@ def generate_source_option_tabs(
comic_talker_tab_layout = comic_talker_tab.layout()
talker_layout = QtWidgets.QGridLayout()
lbl_info = QtWidgets.QLabel("Information Source:")
cbx_info = QtWidgets.QComboBox()
lbl_select_talker = QtWidgets.QLabel("Metadata Sources:")
cbx_select_talker = QtWidgets.QComboBox()
line = QtWidgets.QFrame()
line.setFrameShape(QtWidgets.QFrame.HLine)
line.setFrameShadow(QtWidgets.QFrame.Sunken)
talker_tabs = QtWidgets.QTabWidget()
talker_layout.addWidget(lbl_info, 0, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
talker_layout.addWidget(cbx_info, 0, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
talker_layout.addWidget(lbl_select_talker, 0, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
talker_layout.addWidget(cbx_select_talker, 0, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
talker_layout.addWidget(line, 1, 0, 1, -1)
talker_layout.addWidget(talker_tabs, 2, 0, 1, -1)
comic_talker_tab_layout.addLayout(talker_layout)
# Add cbx_info combobox to sources for getting and setting talker
sources["talker_source"] = cbx_info
# Add combobox to sources for getting and setting talker
sources["cbx_select_talker"] = cbx_select_talker
# Add source sub tabs to Comic Sources tab
for talker_id, talker_obj in talkers.items():
# Add source to general tab dropdown list
cbx_info.addItem(talker_obj.name, talker_id)
cbx_select_talker.addItem(talker_obj.name, talker_id)
tab_name = talker_id
sources["tabs"][tab_name] = {"tab": QtWidgets.QWidget(), "widgets": {}}
layout_grid = QtWidgets.QGridLayout()
for option in config[1][f"talker_{talker_id}"][1].values():
if not option.file:
continue
if option.dest in (f"{talker_id}_url", f"{talker_id}_key"):
continue
current_widget = None
if option.action is not None and (
option.action is argparse.BooleanOptionalAction
@ -215,18 +205,14 @@ def generate_source_option_tabs(
sources["tabs"][tab_name]["widgets"][option.internal_name] = current_widget
# option.type of None should be string
elif (option.type is None and option.action is None) or option.type is str:
current_widget, btn = generate_textbox(option, layout_grid)
current_widget = generate_textbox(option, layout_grid)
sources["tabs"][tab_name]["widgets"][option.internal_name] = current_widget
if option.internal_name.endswith("key"):
# Attach test api function to button. A better way?
api_key_btn_connect(btn, talker_id, sources, talkers)
if option.internal_name.endswith("url"):
# Attach test api function to button. A better way?
api_url_btn_connect(btn, talker_id, sources, talkers)
else:
logger.debug(f"Unsupported talker option found. Name: {option.internal_name} Type: {option.type}")
# Add talker URL and API key fields
generate_api_widgets(talker_id, sources, config, layout_grid, talkers)
# Add vertical spacer
vspacer = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
layout_grid.addItem(vspacer, layout_grid.rowCount() + 1, 0)

View File

@ -141,9 +141,9 @@ class ComicTalker:
self.api_url = self.default_api_url
return settings
def check_api_key(self, key: str) -> bool:
def check_api_key(self, url: str, key: str) -> str:
"""
This function should return true if the given api key is valid.
This function should return a string with the test outcome for display to user.
"""
raise NotImplementedError

View File

@ -216,7 +216,11 @@ class ComicVineTalker(ComicTalker):
self.remove_html_tables = settings["cv_remove_html_tables"]
return settings
def check_api_key(self, key: str, url: str) -> bool:
def check_api_key(
self,
url: str,
key: str,
) -> str:
url = talker_utils.fix_url(url)
if not url:
url = self.default_api_url
@ -230,9 +234,12 @@ class ComicVineTalker(ComicTalker):
).json()
# Bogus request, but if the key is wrong, you get error 100: "Invalid API Key"
return cv_response["status_code"] != 100
if cv_response["status_code"] != 100:
return "API key is valid"
else:
return "API key is INVALID!"
except Exception:
return False
return "Failed to connect to the URL!"
def search_for_series(
self,