diff --git a/.github/workflows/cd-linux.yaml b/.github/workflows/cd-linux.yaml index 724f2ab0..513139ec 100644 --- a/.github/workflows/cd-linux.yaml +++ b/.github/workflows/cd-linux.yaml @@ -40,9 +40,30 @@ jobs: - name: Install required packages run: | apt update - apt install -y binutils gcc libglib2.0-dev libpcsclite-dev libusb-1.0-0 make python3-poetry swig + apt install -y binutils \ + libglib2.0-dev \ + libgl-dev \ + libegl-dev \ + libxkbcommon-x11-dev \ + libxcb-cursor-dev \ + libxcb-icccm4-dev \ + libxcb-image0-dev \ + libxcb-keysyms1-dev \ + libxcb-render-util0-dev \ + libxcb-shape0-dev \ + libxcb-xkb-dev \ + libdbus-1-dev \ + libwayland-dev \ + libgtk-3-dev \ + libatk1.0-dev \ + libpangocairo-1.0-0 \ + libpango1.0-dev \ + make \ + python3-poetry - name: Create virtual environment - run: poetry install + run: | + poetry env use python3.9 + poetry install - name: Build run: make build-pyinstaller-onefile - name: Upload artifacts diff --git a/Makefile b/Makefile index 404a829d..b7a6c118 100644 --- a/Makefile +++ b/Makefile @@ -32,14 +32,10 @@ clean: semi-clean rm -rf .mypy_cache # build -build-ui: $(UI_FILES) - $(VENV_BIN)/pyrcc5 $(UI_FILES_PATH)/resources.qrc -o $(UI_FILES_PATH)/resources_rc.py - $(foreach var,$(UI_FILES),$(VENV_BIN)/pyuic5 --from-imports $(var) -o $(subst .ui,.py,$(var));) - -build: build-ui +build: poetry build -build-pyinstaller-onefile: build-ui +build-pyinstaller-onefile: $(VENV_BIN)/pyinstaller ci-scripts/linux/pyinstaller/nitrokey-app-onefile.spec # code checks @@ -52,7 +48,7 @@ check-import-sorting: check-style: $(VENV_PYTHON) -m flake8 $(PACKAGE_NAME)/ -check-typing: build-ui +check-typing: $(VENV_PYTHON) -m mypy $(PACKAGE_NAME)/ check: check-format check-import-sorting check-style check-typing diff --git a/nitrokeyapp/__main__.py b/nitrokeyapp/__main__.py index 84a14b61..1410961a 100644 --- a/nitrokeyapp/__main__.py +++ b/nitrokeyapp/__main__.py @@ -3,7 +3,7 @@ from types import TracebackType from typing import Any, Callable, Generator, Optional, Type -from PyQt5 import QtWidgets +from PySide6 import QtWidgets from qt_material import apply_stylesheet from nitrokeyapp import get_theme_path diff --git a/nitrokeyapp/about_dialog.py b/nitrokeyapp/about_dialog.py deleted file mode 100644 index 1e464523..00000000 --- a/nitrokeyapp/about_dialog.py +++ /dev/null @@ -1,26 +0,0 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import pyqtSlot - -from nitrokeyapp import __version__ -from nitrokeyapp.logger import save_log -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.aboutdialog import Ui_AboutDialog - - -class AboutDialog(QtUtilsMixIn, QtWidgets.QDialog): - def __init__(self, log_file: str, qt_app: QtWidgets.QApplication) -> None: - QtWidgets.QDialog.__init__(self) - QtUtilsMixIn.__init__(self) - - self.log_file = log_file - - self.app = qt_app - self.ui = Ui_AboutDialog() - self.ui.setupUi(self) - self.ui.ButtonOK.clicked.connect(self.close) - self.ui.buttonSaveLog.pressed.connect(self.save_log) - self.ui.VersionLabel.setText(__version__) - - @pyqtSlot() - def save_log(self) -> None: - save_log(self.log_file, self) diff --git a/nitrokeyapp/add_secret_dialog.py b/nitrokeyapp/add_secret_dialog.py index aacfda6f..adc21b0e 100644 --- a/nitrokeyapp/add_secret_dialog.py +++ b/nitrokeyapp/add_secret_dialog.py @@ -2,11 +2,11 @@ from base64 import b32decode from typing import Optional -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QWidget +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QDialog, QDialogButtonBox, QWidget +from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn from nitrokeyapp.secrets_tab.data import Credential, OtpKind -from nitrokeyapp.ui.add_secret_dialog import Ui_AddSecretDialog # TODO: # - max length @@ -16,12 +16,13 @@ DEFAULT_OTP_KIND = OtpKind.TOTP -class AddSecretDialog(QDialog): +class AddSecretDialog(QtUtilsMixIn, QDialog): def __init__(self, parent: Optional[QWidget] = None) -> None: - super().__init__(parent) + QDialog.__init__(self, parent) + QtUtilsMixIn.__init__(self) - self.ui = Ui_AddSecretDialog() - self.ui.setupUi(self) + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("add_secret_dialog.ui", self) for kind in OtpKind: self.ui.comboBoxOtpType.addItem(str(kind)) @@ -32,7 +33,7 @@ def __init__(self, parent: Optional[QWidget] = None) -> None: self.refresh() - @pyqtSlot() + @Slot() def refresh(self) -> None: errors = [] diff --git a/nitrokeyapp/bak/change_pin_dialog.py b/nitrokeyapp/bak/change_pin_dialog.py deleted file mode 100644 index 6e7a85f3..00000000 --- a/nitrokeyapp/bak/change_pin_dialog.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Optional - -from PyQt5 import QtWidgets - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.change_pin_dialog import Ui_ChangePinDialog - - -class ChangePinDialog(QtUtilsMixIn, QtWidgets.QDialog): - def __init__(self, parent: Optional[QtWidgets.QWidget] = None) -> None: - QtWidgets.QDialog.__init__(self, parent) - QtUtilsMixIn.__init__(self) - - self.ui = Ui_ChangePinDialog() - self.ui.setupUi(self) - self.current_pin = self.ui.lineEdit_current_pin - self.current_pin.setEchoMode(QtWidgets.QLineEdit.Password) - self.new_pin = self.ui.lineEdit_new_pin - self.new_pin.setEchoMode(QtWidgets.QLineEdit.Password) - self.confirm_new_pin = self.ui.lineEdit_confirm_new_pin - self.confirm_new_pin.setEchoMode(QtWidgets.QLineEdit.Password) - # self.buttons = self.get_widget(QtWidgets.QDialogButtonBox, "buttonBox") - self.btn_ok = self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok) - self.confirm_new_pin.textChanged.connect(self.same_pin) - self.new_pin.textChanged.connect(self.same_pin) - self.btn_ok.setEnabled(False) - - def same_pin(self) -> None: - if ( - self.new_pin.text() != self.confirm_new_pin.text() - or self.new_pin.text() == "" - ): - self.btn_ok.setEnabled(False) - else: - self.btn_ok.setEnabled(True) diff --git a/nitrokeyapp/bak/clock_progressbar.py b/nitrokeyapp/bak/clock_progressbar.py deleted file mode 100644 index 8b829ac5..00000000 --- a/nitrokeyapp/bak/clock_progressbar.py +++ /dev/null @@ -1,62 +0,0 @@ -from PyQt5.QtCore import QRectF, QSize, Qt -from PyQt5.QtGui import QPainter, QPainterPath, QPen -from PyQt5.QtWidgets import QWidget - - -class ClockProgressBar(QWidget): - def __init__(self, parent=None): - super().__init__(parent) - self._value = 0 - self._max = 100 - - def setValue(self, value): - self._value = value - self.update() - - def setMaximum(self, max_value): - self._max = max_value - self.update() - - def value(self): - return self._value - - def maximum(self): - return self._max - - def paintEvent(self, event): - painter = QPainter(self) - painter.setRenderHint(QPainter.Antialiasing) - - size = min(self.width(), self.height()) - progress_radius = size / 4 - 2 - 10 - progress_x = (self.width() - 2 * progress_radius - 20) / 2 - progress_y = (self.height() - 2 * progress_radius - 20) / 2 - progress_rect = QRectF( - progress_x, progress_y, 2 * progress_radius, 2 * progress_radius - ) - progress_angle = self._value / self._max * 360 - painter.setPen(QPen(Qt.blue, 6, Qt.SolidLine)) - - path = QPainterPath() - path.arcMoveTo(progress_rect, -90) - path.arcTo(progress_rect, -90, -progress_angle) - painter.drawPath(path) - - painter.setPen(Qt.black) - painter.setFont(self.font()) - - text = str(self._value) - text_width = painter.fontMetrics().width(text) - text_height = painter.fontMetrics().height() - - text_x = int(self.width() / 2 - text_width / 2) - text_y = int((self.height() + size) / 2 + text_height / 2) - - painter.drawText(text_x, text_y, text) - - painter.end() - - def sizeHint(self): - progress_radius = min(self.width(), self.height()) / 4 - 2 - 10 - widget_size = int(progress_radius + 20) - return QSize(widget_size, widget_size) diff --git a/nitrokeyapp/bak/edit_button_widget.py b/nitrokeyapp/bak/edit_button_widget.py deleted file mode 100644 index 7b9cf9ad..00000000 --- a/nitrokeyapp/bak/edit_button_widget.py +++ /dev/null @@ -1,51 +0,0 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QTimer, pyqtSlot - - -class EditButtonsWidget(QtWidgets.QWidget): - def __init__(self, table, pop_up_copy, res, parent=None): - super().__init__(parent) - self.table_pws = table - self.pop_up_copy = pop_up_copy - - # add your buttons - layout = QtWidgets.QHBoxLayout() - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - - Copy = QtWidgets.QPushButton("Icon") - Copy.setFixedSize(65, 65) - Copy.clicked.connect(self.copy_to_clipboard_function) - layout.addWidget(Copy) - layout.addWidget(QtWidgets.QLabel(str(res))) - - self.setLayout(layout) - - @pyqtSlot() - def copy_to_clipboard_function(self): - buttons_index = self.table_pws.indexAt(self.pos()) - item = self.table_pws.item(buttons_index.row(), buttons_index.column() + 3) - QtWidgets.QApplication.clipboard().setText(item.text()) - # qtimer popup - self.time_to_wait = 5 - self.pop_up_copy.setText("Data added to clipboard.") # {0} for time display - self.pop_up_copy.setStyleSheet( - "background-color: #2B5DD1; color: #FFFFFF ; border-style: outset;" - "padding: 2px ; font: bold 20px ; border-width: 6px ; border-radius: 10px ; border-color: #2752B8;" - ) - self.pop_up_copy.show() - self.timer = QTimer(self) - self.timer.setInterval(1000) - self.timer.timeout.connect(self.changeContent) - self.timer.start() - - def changeContent(self): - self.pop_up_copy.setText("Data added to clipboard.") - self.time_to_wait -= 1 - if self.time_to_wait <= 0: - self.pop_up_copy.hide() - self.timer.stop() - - def closeEvent(self, event): - self.timer.stop() - event.accept() diff --git a/nitrokeyapp/bak/key_generation.py b/nitrokeyapp/bak/key_generation.py deleted file mode 100644 index 7b48111c..00000000 --- a/nitrokeyapp/bak/key_generation.py +++ /dev/null @@ -1,79 +0,0 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import pyqtSlot - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.key_generation import Ui_Key_generation - - -class KeyGeneration(QtUtilsMixIn, QtWidgets.QWizard): - def __init__(self, qt_app: QtWidgets.QApplication): - QtWidgets.QWizard.__init__(self) - QtUtilsMixIn.__init__(self) - - self.app = qt_app - self.ui = Ui_Key_generation() - self.ui.setupUi(self) - # dialogs - self.adsettings_button = self.ui.pushButton_wiz - self.adsettings = self.ui.adsettings_key - self.wizard_page_userinfo = self.ui.wizardPage1 - - self.placeholder_path = self.ui.lineEdit - self.placeholder_path.setPlaceholderText("Path") - - self.with_backup = self.ui.radioButton_3 - self.lastpage_keygen = self.ui.wizardPage - self.confirm_path = self.ui.lineEdit - self.confirm_path.setEnabled(False) - - self.real_name = self.ui.lineEdit_2 - self.wizard_page_userinfo.registerField("real_name*", self.real_name) - - self.email = self.ui.lineEdit_3 - self.wizard_page_userinfo.comment_line = self.ui.lineEdit_4 - self.wizard_page_userinfo.registerField("email*", self.email) - - self.comment_line = self.ui.lineEdit_4 - self.comment_line.setPlaceholderText("Optional") - - self.back_up_info = self.ui.label_2 - self.back_up_info.hide() - # insert Nitrokey - self.adsettings_button.clicked.connect(self.adsettings_func) - self.collapse(self.adsettings, self.adsettings_button) - self.with_backup.toggled.connect(self.finish_show_hide) - self.confirm_path.textChanged.connect(self.finish_show_hide_2) - # insert Nitrokey - - @pyqtSlot() - def finish_show_hide(self): - if self.with_backup.isChecked(): - self.button(QtWidgets.QWizard.FinishButton).setEnabled(False) - self.lastpage_keygen.cleanupPage() - self.confirm_path.setEnabled(True) - self.back_up_info.show() - else: - self.button(QtWidgets.QWizard.FinishButton).setEnabled(True) - self.lastpage_keygen.cleanupPage() - self.confirm_path.setEnabled(False) - self.back_up_info.hide() - - def finish_show_hide_2(self): - if self.confirm_path.text(): - self.button(QtWidgets.QWizard.FinishButton).setEnabled(True) - - def adsettings_func(self): - self.collapse(self.adsettings, self.adsettings_button) - - def loading(self): - # dialogs - self.ok_insert = self.get_widget(QtWidgets.QPushButton, "pushButton_ok_insert") - # insert Nitrokey - self.ok_insert.clicked.connect(self.ok_insert_btn) - # insert Nitrokey - - @pyqtSlot() - def ok_insert_btn(self): - self.hide() - - self.setup_wizard.show() diff --git a/nitrokeyapp/bak/loading_screen.py b/nitrokeyapp/bak/loading_screen.py deleted file mode 100644 index a6e799eb..00000000 --- a/nitrokeyapp/bak/loading_screen.py +++ /dev/null @@ -1,33 +0,0 @@ -from PyQt5 import QtWidgets - - -class LoadingScreen(QtWidgets.QWidget): - # def __init__(self): - # super().__init__() - # self.setFixedSize(128,128) #128 128 - # self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.CustomizeWindowHint) - - # self.label_animation = QLabel(self) - # self.qprogressbar = QProgressBar(self) - # self.setGeometry(QRect(650,300,0,0)) - # self.movie = QMovie(":/icons/ProgressWheel.GIF") - # self.label_animation.setMovie(self.movie) - - # timer = QTimer(self) - # self.startAnimation() - # timer.singleShot(1000, self.stopAnimation) - - # self.show() - - def startAnimation(self): - self.movie.start() - - def stopAnimation(self): - # self.movie.stop() - self.close() - # GUI.user_info( - # "success", - # "You now have a main key with the capability\n to sign and certify and a subkey for encryption. ", - # title="Key generation was successful", - # parent=self.label_animation, - # ) diff --git a/nitrokeyapp/bak/passwordsafe.py b/nitrokeyapp/bak/passwordsafe.py deleted file mode 100644 index 9ade806a..00000000 --- a/nitrokeyapp/bak/passwordsafe.py +++ /dev/null @@ -1,195 +0,0 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import pyqtSlot - -from nitrokeyapp.edit_button_widget import EditButtonsWidget - - -# pws not in use for now (was working for pro/storage) -@pyqtSlot() -def table_pws_function(self): - index = self.table_pws.currentIndex() - item = self.table_pws.item(index.row(), index.column() + 1) - item2 = self.table_pws.item(index.row(), index.column() + 2) - item3 = self.table_pws.item(index.row(), index.column() + 3) - item4 = self.table_pws.item(index.row(), index.column() + 4) - item5 = self.table_pws.item(index.row(), index.column() + 5) - - self.scrollArea.show() - self.information_label.show() - self.pws_editslotname.setText(item.text()) - self.pws_editloginname.setText(item2.text()) - self.pws_editpassword.setText(item3.text()) - self.pws_editOTP.setText(item4.text()) - self.pws_editnotes.setText(item5.text()) - self.PWS_ButtonSaveSlot.setVisible(False) - self.ButtonChangeSlot.setVisible(True) - self.PWS_ButtonDelete.setVisible(True) - # hides the otp creation stuff - self.copy_current_otp.show() - self.qr_code.hide() - self.random_otp.hide() - self.copy_otp.hide() - self.pws_editOTP.setEchoMode(QtWidgets.QLineEdit.Password) - self.show_hide_btn_2.hide() - - -def add_table_pws(self): - row = self.table_pws.rowCount() - self.table_pws.insertRow(row) - qline = self.pws_editslotname.text() - qline2 = self.pws_editloginname.text() - qline3 = self.pws_editpassword.text() - qline4 = self.pws_editOTP.text() - qline5 = self.pws_editnotes.toPlainText() - res = "{} {} {}".format(qline, "\n", qline2) - - # creates otp on key - - if not self.device.is_auth_admin: - self.ask_pin("admin") - return - - name = qline - if len(name) == 0: - self.user_err("need non-empty name") - return - - idx = row - who = "totp" - # @fixme: what are the secret allowed lengths/chars - # if len(secret) - - ret = self.device.TOTP.write(idx, name, qline4) - if not ret.ok: - self.msg(f"failed writing to {who.upper()} slot #{idx+1} err: {ret.name}") - else: - self.msg(f"wrote {who.upper()} slot #{idx+1}") - self.otp_secret.clear() - self.slot_select_otp(idx) - - self.table_pws.setCellWidget( - row, 0, (EditButtonsWidget(self.table_pws, self.pop_up_copy, res)) - ) - self.table_pws.setItem(row, 1, (QtWidgets.QTableWidgetItem(qline))) - self.table_pws.setItem(row, 2, (QtWidgets.QTableWidgetItem(qline2))) - self.table_pws.setItem(row, 3, (QtWidgets.QTableWidgetItem(qline3))) - self.table_pws.setItem(row, 4, (QtWidgets.QTableWidgetItem(qline4))) - self.table_pws.setItem(row, 5, (QtWidgets.QTableWidgetItem(qline5))) - self.pws_editslotname.setText("") - self.pws_editloginname.setText("") - self.pws_editpassword.setText("") - self.pws_editOTP.setText("") - self.pws_editnotes.setText("") - - -# adds the data existing of the key to the table -def add_table_pws_from_key(self, x): - row = self.table_pws.rowCount() - self.table_pws.insertRow(row) - # self.table_pws.setItem(row , 0, (QtWidgets.QTableWidgetItem("Name"))) - # self.table_pws.setItem(row , 1, (QtWidgets.QTableWidgetItem("Username"))) - - qline = self.device.TOTP.get_name(x) - qline2 = "" - qline3 = "" - qline4 = self.device.TOTP.get_code(x) - qline5 = "" - res = "{} {} {}".format(qline, "\n", qline2) - - self.table_pws.setCellWidget( - row, 0, (EditButtonsWidget(self.table_pws, self.pop_up_copy, res)) - ) - qlines = [qline, qline2, qline3, qline4, qline5] - for i in range(1, len(qlines) + 1): - self.table_pws.setItem(row, i, (QtWidgets.QTableWidgetItem(qlines[i - 1]))) - # self.table_pws.setItem(row , 1, (QtWidgets.QTableWidgetItem(qline))) - # self.table_pws.setItem(row , 2, (QtWidgets.QTableWidgetItem(qline2))) - # self.table_pws.setItem(row , 3, (QtWidgets.QTableWidgetItem(qline3))) - # self.table_pws.setItem(row , 4, (QtWidgets.QTableWidgetItem(qline4))) - # self.table_pws.setItem(row , 5, (QtWidgets.QTableWidgetItem(qline5))) - pws_list = [ - self.pws_editslotname, - self.pws_editloginname, - self.pws_editpassword, - self.pws_editOTP, - self.pws_editnotes, - ] - for i in pws_list: - pws_list.setText("") - # self.pws_editslotname.setText("") - # self.pws_editloginname.setText("") - # self.pws_editpassword.setText("") - # self.pws_editOTP.setText("") - # self.pws_editnotes.setText("") - - -def add_pws(self): - self.scrollArea.show() - self.information_label.show() - self.PWS_ButtonSaveSlot.setVisible(True) - self.ButtonChangeSlot.setVisible(False) - self.PWS_ButtonDelete.setVisible(False) - # self.set_visible(QtWidgets.QFrame, ["groupbox_pw"], True) - # self.set_enabled(QtWidgets.QFrame, ["groupbox_pw"], True) - # self.set_enabled(QtWidgets.QPushButton, ["PWS_ButtonSaveSlot", "PWS_ButtonClose"], True) - pws_list = [ - self.pws_editslotname, - self.pws_editloginname, - self.pws_editpassword, - self.pws_editOTP, - self.pws_editnotes, - ] - for i in pws_list: - pws_list.setText("") - # self.pws_editslotname.setText("") - # self.pws_editloginname.setText("") - # self.pws_editpassword.setText("") - # self.pws_editOTP.setText("") - # self.pws_editnotes.setText("") - # shows the otp creation stuff again - self.copy_current_otp.hide() - self.qr_code.show() - self.random_otp.show() - self.copy_otp.show() - self.pws_editOTP.setEchoMode(QtWidgets.QLineEdit.Normal) - self.show_hide_btn_2.show() - - -def delete_pws(self): - index = self.table_pws.currentIndex() - self.table_pws.removeRow(index.row()) - self.table_pws.setCurrentCell(0, 0) - - -def change_pws(self): - row = (self.table_pws.currentIndex()).row() - self.table_pws.insertRow(row) - - index = self.table_pws.currentIndex() - qline = self.pws_editslotname.text() - qline2 = self.pws_editloginname.text() - qline3 = self.pws_editpassword.text() - qline4 = self.pws_editOTP.text() - qline5 = self.pws_editnotes.toPlainText() - res = "{} {} {}".format(qline, "\n", qline2) - - self.table_pws.setCellWidget( - row, 0, (EditButtonsWidget(self.table_pws, self.pop_up_copy, res)) - ) - self.table_pws.setItem(row, 1, (QtWidgets.QTableWidgetItem(qline))) - self.table_pws.setItem(row, 2, (QtWidgets.QTableWidgetItem(qline2))) - self.table_pws.setItem(row, 3, (QtWidgets.QTableWidgetItem(qline3))) - self.table_pws.setItem(row, 4, (QtWidgets.QTableWidgetItem(qline4))) - self.table_pws.setItem(row, 5, (QtWidgets.QTableWidgetItem(qline5))) - - self.table_pws.removeRow(index.row()) - self.table_pws.setCurrentCell(index.row() - 1, 0) - - -# search function for the table -def filter_the_table(self): - # searchbox - for iterator in range(self.table_pws.rowCount()): - self.table_pws.showRow(iterator) - if self.searchbox.text() not in self.table_pws.item(iterator, 1).text(): - self.table_pws.hideRow(iterator) diff --git a/nitrokeyapp/bak/pin_dialog.py b/nitrokeyapp/bak/pin_dialog.py deleted file mode 100644 index 85021a3c..00000000 --- a/nitrokeyapp/bak/pin_dialog.py +++ /dev/null @@ -1,82 +0,0 @@ -from typing import Any - -from PyQt5 import QtWidgets -from PyQt5.QtCore import Qt, pyqtSlot - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.pindialog import Ui_PinDialog - - -# @fixme: PINDialog should be modal! -class PINDialog(QtUtilsMixIn, QtWidgets.QDialog): - def __init__(self, qt_app: QtWidgets.QApplication) -> None: - QtWidgets.QDialog.__init__(self) - QtUtilsMixIn.__init__(self) - self.app = qt_app - self.ui = Ui_PinDialog() - self.ui.setupUi(self) - self.ok_signal, self.tries_left = None, None - - self.opts: dict[str, Any] = {} - - self.checkbox = self.get_widget(QtWidgets.QCheckBox, "checkBox") - self.checkbox.stateChanged.connect(self.checkbox_toggled) - - self.ok_btn = self.get_widget(QtWidgets.QPushButton, "okButton") - self.ok_btn.clicked.connect(self.ok_clicked) - - self.line_edit = self.get_widget(QtWidgets.QLineEdit, "lineEdit") - self.status = self.get_widget(QtWidgets.QLabel, "status") - self.title = self.get_widget(QtWidgets.QLabel, "label") - - self.reset() - - @pyqtSlot() - def reset(self) -> None: - self.status.setText("") - self.title.setText("") - self.ok_signal, self.tries_left = None, None - self.line_edit.setText("") - self.checkbox.setCheckState(Qt.CheckState.Unchecked) - self.opts = {} - self.hide() - - @pyqtSlot(dict) - def invoke(self, opts: dict[str, Any]) -> None: - self.opts = dct = opts - - self.tries_left = dct.get("retries", 0) - who = dct.get("who") - if self.tries_left == 0: - self.user_warn( - f"Please reset the {who} pin counter before continuing", - "No attempts left", - ) - self.reset() - return - - self.status.setText(f"Attempts left: {self.tries_left}") - self.title.setText(dct.get("title", self.title.text())) - self.ok_signal = dct.get("sig") - self.show() - - @pyqtSlot(int) - def checkbox_toggled(self, state: int) -> None: - if state == 0: - self.line_edit.setEchoMode(QtWidgets.QLineEdit.Password) - elif state == 2: - self.line_edit.setEchoMode(QtWidgets.QLineEdit.Normal) - - @pyqtSlot() - def ok_clicked(self) -> None: - pin = self.line_edit.text() - def_pin = self.opts.get("default", "(?)") - # @fixme: get len-range from libnk.py - if len(pin) < 6 or len(pin) > 20: - self.line_edit.selectAll() - self.user_warn( - "The pin requires to be 6-20 chars in length\n" f"default: {def_pin}", - "Invalid PIN", - ) - else: - self.ok_signal.emit(self.opts, pin) diff --git a/nitrokeyapp/bak/set_pin_dialog.py b/nitrokeyapp/bak/set_pin_dialog.py deleted file mode 100644 index e403a687..00000000 --- a/nitrokeyapp/bak/set_pin_dialog.py +++ /dev/null @@ -1,30 +0,0 @@ -from PyQt5 import QtWidgets - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.set_pin_dialog import Ui_ChangePinDialog - - -class SetPinDialog(QtUtilsMixIn, QtWidgets.QDialog): - def __init__(self, parent=None): - QtWidgets.QDialog.__init__(self, parent) - QtUtilsMixIn.__init__(self) - - self.ui = Ui_ChangePinDialog() - self.ui.setupUi(self) - self.new_pin = self.ui.lineEdit_new_pin_set - self.new_pin.setEchoMode(QtWidgets.QLineEdit.Password) - self.confirm_new_pin = self.ui.lineEdit_confirm_new_pin_set - self.confirm_new_pin.setEchoMode(QtWidgets.QLineEdit.Password) - self.btn_ok = self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok) - self.confirm_new_pin.textChanged.connect(self.same_pin) - self.new_pin.textChanged.connect(self.same_pin) - self.btn_ok.setEnabled(False) - - def same_pin(self): - if ( - self.new_pin.text() != self.confirm_new_pin.text() - or self.new_pin.text() == "" - ): - self.btn_ok.setEnabled(False) - else: - self.btn_ok.setEnabled(True) diff --git a/nitrokeyapp/bak/setup_wizard.py b/nitrokeyapp/bak/setup_wizard.py deleted file mode 100644 index 939286a1..00000000 --- a/nitrokeyapp/bak/setup_wizard.py +++ /dev/null @@ -1,55 +0,0 @@ -from PyQt5 import QtWidgets - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.setup_wizard import Ui_PINSetup - - -class SetupWizard(QtUtilsMixIn, QtWidgets.QWizard): - def __init__(self, qt_app: QtWidgets.QApplication): - QtWidgets.QWizard.__init__(self) - QtUtilsMixIn.__init__(self) - self.app = qt_app - self.ui = Ui_PINSetup() - self.ui.setupUi(self) - - self.userpin_page = self.ui.wizardPage - self.userpin_1 = self.ui.lineEdit - self.userpin_2 = self.ui.lineEdit_2 - self.userpin_page.registerField("user_pin_1*", self.userpin_1) - self.userpin_page.registerField("user_pin_2*", self.userpin_2) - - self.adminpin_page = self.ui.wizardPage2 - self.adminpin_1 = self.ui.lineEdit_4 - self.adminpin_2 = self.ui.lineEdit_3 - self.adminpin_page.registerField("admin_pin_1*", self.adminpin_1) - self.adminpin_page.registerField("admin_pin_2*", self.adminpin_2) - - self.userpin_2.textChanged.connect(self.same_setup_wizard) - self.adminpin_2.textChanged.connect(self.same_setup_wizard_2) - - def same_setup_wizard(self): - if self.userpin_1.text() != self.userpin_2.text(): - self.button(QtWidgets.QWizard.NextButton).setEnabled(False) - else: - self.button(QtWidgets.QWizard.NextButton).setEnabled(True) - - def same_setup_wizard_2(self): - if self.adminpin_1.text() != self.adminpin_2.text(): - self.button(QtWidgets.QWizard.FinishButton).setEnabled(False) - else: - self.button(QtWidgets.QWizard.FinishButton).setEnabled(True) - - def closeEvent(self, event): - reply = QtWidgets.QMessageBox.question( - self, - "Message", - "Are you sure to exit?", - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No, - ) - - if reply == QtWidgets.QMessageBox.Yes: - event.accept() - - else: - event.ignore() diff --git a/nitrokeyapp/bak/storage_wizard.py b/nitrokeyapp/bak/storage_wizard.py deleted file mode 100644 index f16d7247..00000000 --- a/nitrokeyapp/bak/storage_wizard.py +++ /dev/null @@ -1,86 +0,0 @@ -# Nitrokey 2 -from PyQt5 import QtWidgets -from PyQt5.QtCore import pyqtSlot - -from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn - - -class Storage(QtUtilsMixIn, QtWidgets.QWizard): - def __init__(self, qt_app: QtWidgets.QApplication): - QtWidgets.QWizard.__init__(self) - QtUtilsMixIn.__init__(self) - self.ok_insert = None - self.app = qt_app - - def init_storage(self): - self.wizardpage_hidden_volume_pw = self.get_widget( - QtWidgets.QWizardPage, "wizardPage" - ) - self.hidden_pw_1 = self.get_widget(QtWidgets.QLineEdit, "HVPasswordEdit") - self.hidden_pw_2 = self.get_widget(QtWidgets.QLineEdit, "HVPasswordEdit_2") - self.wizardpage_hidden_volume_pw.registerField("hidden_pw_1*", self.hidden_pw_1) - self.wizardpage_hidden_volume_pw.registerField("hidden_pw_2*", self.hidden_pw_2) - self.show_hidden_pw = self.get_widget( - QtWidgets.QCheckBox, "ShowPasswordCheckBox" - ) - - self.storage_slider = self.get_widget( - QtWidgets.QSlider, "horizontalSlider_storage" - ) - self.storage_blockspin = self.get_widget( - QtWidgets.QDoubleSpinBox, "StartBlockSpin_3" - ) - - self.radio_gb = self.get_widget(QtWidgets.QRadioButton, "rd_GB_3") - self.radio_mb = self.get_widget(QtWidgets.QRadioButton, "rd_MB_3") - - self.confirm_creation = self.get_widget(QtWidgets.QCheckBox, "checkBox_confirm") - - self.lastpage = self.get_widget(QtWidgets.QWizardPage, "wizardPage_3") - - self.lastpage.registerField("confirm_creation*", self.confirm_creation) - - self.storage_blockspin.valueChanged.connect(self.change_value_2) - self.storage_slider.valueChanged.connect(self.change_value) - - self.radio_gb.toggled.connect(self.swap_to_gb) - self.radio_mb.toggled.connect(self.swap_to_mb) - self.hidden_pw_2.textChanged.connect(self.same_storage) - - def same_storage(self): - if self.hidden_pw_2.text() != self.hidden_pw_1.text(): - self.button(QtWidgets.QWizard.NextButton).setEnabled(False) - else: - self.button(QtWidgets.QWizard.NextButton).setEnabled(True) - - @pyqtSlot(int) - # storage wizard - def change_value(self, value): - self.storage_blockspin.setValue(float(value)) - - def change_value_2(self, value): - self.storage_slider.setValue(float(value)) - - @pyqtSlot() - def swap_to_mb(self): - if self.radio_mb.isChecked(): - self.storage_blockspin.setMaximum(30000) - self.storage_slider.setMaximum(30000) - self.storage_blockspin.setValue( - float(self.storage_blockspin.value()) * 1000 - ) - self.storage_slider.setValue(float(self.storage_blockspin.value())) - self.storage_slider.setSingleStep(300) - self.storage_blockspin.setSingleStep(300) - - def swap_to_gb(self): - if self.radio_gb.isChecked(): - self.storage_blockspin.setValue( - float(self.storage_blockspin.value()) / 1000 - ) - self.storage_slider.setValue(float(self.storage_blockspin.value())) - - self.storage_blockspin.setMaximum(30) - self.storage_slider.setMaximum(30) - self.storage_slider.setSingleStep(1) - self.storage_blockspin.setSingleStep(1) diff --git a/nitrokeyapp/bak/ui/change_pin_dialog.ui b/nitrokeyapp/bak/ui/change_pin_dialog.ui deleted file mode 100644 index a20eef32..00000000 --- a/nitrokeyapp/bak/ui/change_pin_dialog.ui +++ /dev/null @@ -1,111 +0,0 @@ - - - ChangePinDialog - - - Qt::WindowModal - - - - 0 - 0 - 388 - 211 - - - - - 0 - 0 - - - - Dialog - - - - - - - - - - Current PIN: - - - - - - - - - - New PIN: - - - - - - - - - - Confirm New PIN: - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - ChangePinDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ChangePinDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/bak/ui/insert_Nitrokey.ui b/nitrokeyapp/bak/ui/insert_Nitrokey.ui deleted file mode 100644 index ab77583b..00000000 --- a/nitrokeyapp/bak/ui/insert_Nitrokey.ui +++ /dev/null @@ -1,40 +0,0 @@ - - - Insert_Nitrokey - - - - 0 - 0 - 400 - 300 - - - - Dialog - - - - - - - 23 - - - - Please insert your Nitrokey - - - - - - - Ok - - - - - - - - diff --git a/nitrokeyapp/bak/ui/key_generation.ui b/nitrokeyapp/bak/ui/key_generation.ui deleted file mode 100644 index 45639cf1..00000000 --- a/nitrokeyapp/bak/ui/key_generation.ui +++ /dev/null @@ -1,379 +0,0 @@ - - - Key_generation - - - - 0 - 0 - 418 - 326 - - - - Wizard - - - QWizard::ClassicStyle - - - - - - - - 75 - true - - - - User Information - - - - - - - Qt::Horizontal - - - - - - - The following instructions guide through the generation -of OpenPGP keys directly on the Nitrokey. - - Please provide the needed information. - - - - - - - - 75 - true - - - - User ID - - - - - - Real name: - - - - - - - - - - Email address: - - - - - - - - - - Comment: - - - - - - - - - - - - - - - - - Here they can determine the expiration date. -In "Advanced Settings", the key type and size - can be changed. - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - 0 - 0 - - - - Expires in: - - - - - - - - 0 - 0 - - - - - never - - - - - 1 year - - - - - 2 years - - - - - 5 years - - - - - - - - - - - - 75 - true - - - - Key Settings - - - - - - - QPushButton { -Text-align:left; -} - - - Advanced Settings - - - - images/new/down_arrow.pngimages/new/down_arrow.png - - - true - - - - - - - - 0 - 0 - - - - - 75 - true - - - - - - - - 0 - 0 - - - - - RSA and RSA (default) - - - - - DSA - - - - - ECC - - - - - - - - Key size: - - - - - - - - 0 - 0 - - - - - 1024 Bits - - - - - 2048 Bits - - - - - 4096 Bits - - - - - - - - - 0 - 0 - - - - Key type: - - - - - - - - - - Qt::Horizontal - - - - - - - - - - - - 75 - true - - - - Backup - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - - 75 - true - - - - - - - with Backup: - - - - - - - - - - - - - - without Backup - - - true - - - - - - - - - - We recommend that you only create a backup, -if you are sure that you can keep it very secure. -It is best practice to never have this key on a -regular computer which has connection to the -internet, so that the key never gets compromised. - - - - - - - - - diff --git a/nitrokeyapp/bak/ui/keys_tab.ui b/nitrokeyapp/bak/ui/keys_tab.ui deleted file mode 100644 index 38d6f538..00000000 --- a/nitrokeyapp/bak/ui/keys_tab.ui +++ /dev/null @@ -1,195 +0,0 @@ - - - KeysTab - - - - 0 - 0 - 544 - 260 - - - - - - - - - 0 - - - - 1. Key Identity - - - - - - Import Keys - - - - - - - - 0 - 0 - - - - - 16777215 - 200 - - - - Main Key - - - - - - sec - - - - - - - rsa1024/0EFFB0704391497C - - - - - - - created: - - - - - - - 2021-07-29 - - - - - - - expires: - - - - - - - never - - - - - - - usage: SC - - - - - - - - - - Create Main Key - - - - - - - - 16777215 - 200 - - - - Subkey for Encryption - - - - - - created: - - - - - - - sec - - - - - - - never - - - - - - - expires: - - - - - - - rsa1024/AWFFB0704391458D - - - - - - - 2021-07-29 - - - - - - - usage: E - - - - - - - - - - - 2. Key Identity - - - - - - 3. Key Identity - - - - - - - - - - - diff --git a/nitrokeyapp/bak/ui/password_safe_tab.ui b/nitrokeyapp/bak/ui/password_safe_tab.ui deleted file mode 100644 index 9f7fa2b0..00000000 --- a/nitrokeyapp/bak/ui/password_safe_tab.ui +++ /dev/null @@ -1,1422 +0,0 @@ - - - tab_3 - - - - 0 - 0 - 931 - 645 - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - - 16777215 - 25 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Unlock Password Safe - - - - :/icons/icon_safe.svg:/icons/icon_safe.svg - - - - - - - - 200 - 16777215 - - - - Cancel - - - - - - - - 200 - 16777215 - - - - Save - - - true - - - true - - - - - - - Change - - - - - - - - 80 - 16777215 - - - - Delete - - - true - - - - - - - Lock Device - - - - - - - - 0 - 0 - - - - 42 - - - - - - - - - - - 0 - 0 - - - - - 250 - 450 - - - - - 240 - 350 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - - 300 - 600 - - - - QScrollBar:vertical { - border: none; - background: rgb(52, 59, 72); - width: 14px; - margin: 21px 0 21px 0; - border-radius: 0px; -} - - - Qt::ScrollBarAlwaysOff - - - QAbstractItemView::AnyKeyPressed|QAbstractItemView::EditKeyPressed - - - false - - - false - - - 0 - - - false - - - 57 - - - 250 - - - false - - - 70 - - - - - - - - - 0 - 0 - 0 - - - - - - - Name - - - - - Username - - - - - Passwort - - - - - OTP - - - - - Notizen - - - - - - - - - 0 - 0 - - - - - 270 - 16777215 - - - - Add - - - true - - - - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Information - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - 0 - 0 - - - - - 0 - 500 - - - - - 750 - 500 - - - - QFrame::Sunken - - - Qt::ScrollBarAlwaysOff - - - true - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - 0 - 0 - 721 - 1124 - - - - - - - - 0 - 0 - - - - - 703 - 0 - - - - - 703 - 16777215 - - - - - 14 - - - - QPushButton { -Text-align:left; -} - - - Password - - - - - - - - 0 - 0 - - - - - 700 - 300 - - - - - 703 - 16777215 - - - - - 9 - - - - - Hide - - - true - - - - - - - QR-Code - - - - - - - Name - - - - - - - - 0 - 0 - - - - Copy - - - false - - - - - - - Random - - - - - - - Password: - - - - - - - Secret (for OTP) - - - - - - - Username - - - - - - - - 0 - 0 - - - - Copy - - - false - - - - - - - Login name: - - - - - - - Password - - - - - - - Hide - - - true - - - - - - - Slot name: - - - - - - - - 0 - 0 - - - - - - - Copy - - - false - - - - - - - - 0 - 0 - - - - Copy - - - false - - - - - - - - - - Random - - - - - - - OTP - - - - - - - - - - - 0 - 0 - - - - - 703 - 0 - - - - - 703 - 16777215 - - - - - 14 - - - - QPushButton { -Text-align:left; -} - - - Secret - - - - ../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png - - - true - - - - - - - - 0 - 0 - - - - - 600 - 250 - - - - - 700 - 16777215 - - - - false - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - - - Example: "ZR3M5I..." - - - Secret input format: base32 - - - Base32 - - - true - - - true - - - - - - - Example: "A3911C05..." (remove any 0x prefix) - - - Secret input format: hex - - - Hex - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 11 - - - - Entered OTP 'Secret Key' string is longer than supported by this device - - - Label shown when the OTP secret key is too long - - - <html><head/><body><p><span style=" font-size:10pt; font-weight:600; color:#a40000;">Entered OTP 'Secret Key' string is longer than supported by this device</span></p></body></html> - - - - - - - - - <html><head/><body><p>The secret is provided by your service provider you may want to login or can be configured in your local application which you may want to login to.</p></body></html> - - - Secret Key: - - - - - - - - - The secret is provided by your service provider you may want to login or can be configured in your local application which you may want to login to. - - - OTP secret key - - - Note: 2nd factors aren't protected against physical attacks. Change all OTP secrets in case you loose the Nitrokey. - - - - - - - - - 200 - - - QLineEdit::PasswordEchoOnEdit - - - ******************************** - - - false - - - - - - - - 9 - 75 - true - true - - - - Secret copied to clipboard - - - - - - - - - false - - - <html><head/><body><p>Hide or show the secret.</p></body></html> - - - Hide secret - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Input format: - - - - - - - - - - - 24 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Cancel - - - - - - - Save - - - - - - - - - - - - - 0 - 0 - - - - - 703 - 0 - - - - - 703 - 16777215 - - - - - 14 - - - - QPushButton { -Text-align:left; -} - - - Notes - - - - ../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png - - - true - - - - - - - - 0 - 0 - - - - - 700 - 0 - - - - - 700 - 150 - - - - false - - - - QLayout::SetDefaultConstraint - - - - - false - - - - - - - - - - - 0 - 0 - - - - - 703 - 0 - - - - - 703 - 16777215 - - - - - 14 - - - - QPushButton { -Text-align:left; -} - - - OTP Parameter - - - - ../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png../../../../../../../nitrokey-app2/nitrokeyapp/ui/icons/down_arrow.png - - - true - - - - - - - - 0 - 0 - - - - - 0 - 240 - - - - - 700 - 200 - - - - false - - - - - - - - Select slot type: TOTP - - - (Recommendation: Use TOTP for web applications and HOTP for local applications) - - - TOTP - - - true - - - - - - - Select slot type: HOTP - - - (Recommendation: Use TOTP for web applications and HOTP for local applications) - - - HOTP - - - - - - - - 11 - true - - - - (Recommendation: Use TOTP for web applications and HOTP for local applications) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - - 0 - 80 - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - HOTP length: - - - - - - - - - OTP code length: 6 digits - - - 6 digits - - - true - - - - - - - OTP code length: 8 digits - - - 8 digits - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Moving factor seed: - - - - - - - - - - - HOTP moving factor seed - - - - - - 00000000000000000000 - - - 20 - - - - - - - Set HOTP counter to zero - - - Set to zero - - - - - - - Set HOTP counter to random value - - - Set to random - - - - - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 9 - - - 9 - - - 9 - - - 9 - - - - - TOTP interval: - - - - - - - - - TOTP interval value - - - 1 - - - 65536 - - - 30 - - - - - - - Qt::Horizontal - - - - 40 - 0 - - - - - - - - - - TOTP length: - - - - - - - - - OTP code length: 6 digits - - - 6 digits - - - true - - - - - - - OTP code length: 8 digits - - - 8 digits - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - - Generated secret target length (bytes): - - - - - - - TOTP interval value - - - 10 - - - 40 - - - 40 - - - - - - - - - - - - - - - - QFrame::Box - - - QFrame::Raised - - - 2 - - - 2 - - - - - - Qt::AlignCenter - - - - - - - - diff --git a/nitrokeyapp/bak/ui/pindialog.ui b/nitrokeyapp/bak/ui/pindialog.ui deleted file mode 100644 index c07cf0ec..00000000 --- a/nitrokeyapp/bak/ui/pindialog.ui +++ /dev/null @@ -1,213 +0,0 @@ - - - PinDialog - - - - 0 - 0 - 358 - 155 - - - - - 0 - 0 - - - - Password dialog - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - - 0 - 0 - - - - false - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - - 0 - 0 - - - - Enter card password: - - - - - - - Enter card PIN - - - 39 - - - QLineEdit::Password - - - - - - - - - - 0 - 0 - - - - Show password - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::StrongFocus - - - TextLabel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::TabFocus - - - &Cancel - - - false - - - false - - - - - - - Qt::TabFocus - - - &OK - - - true - - - true - - - - - - - - - lineEdit - checkBox - - - - - - - cancelButton - clicked() - PinDialog - reject() - - - 214 - 142 - - - 178 - 82 - - - - - diff --git a/nitrokeyapp/bak/ui/set_pin_dialog.ui b/nitrokeyapp/bak/ui/set_pin_dialog.ui deleted file mode 100644 index eff7a038..00000000 --- a/nitrokeyapp/bak/ui/set_pin_dialog.ui +++ /dev/null @@ -1,101 +0,0 @@ - - - ChangePinDialog - - - Qt::WindowModal - - - - 0 - 0 - 388 - 211 - - - - - 0 - 0 - - - - Dialog - - - - - - - - - - - - - New PIN: - - - - - - - - - - Confirm New PIN: - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - ChangePinDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ChangePinDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/bak/ui/settings_tab.ui b/nitrokeyapp/bak/ui/settings_tab.ui deleted file mode 100644 index c23c93d5..00000000 --- a/nitrokeyapp/bak/ui/settings_tab.ui +++ /dev/null @@ -1,423 +0,0 @@ - - - SettingsTab - - - - 0 - 0 - 930 - 720 - - - - - - - - 12 - - - - 0 - - - - General - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - General - - - - - - - - Show first-run message - - - - - - - Show main window on start - - - - - - - - - - - Do not quit when the main window is closed - - - true - - - - - - - Hide main window when device disconnects - - - true - - - - - - - - - Show main window when device connects - - - true - - - - - - - Show warning when no partitions could be detected on Encrypted Volume (Linux only) - - - true - - - - - - - Show message about device's connection / disconnection - - - true - - - - - - - - - <html><head/><body><p>Translation file (needs restart)</p></body></html> - - - - - - - Translation file (needs restart) - - - - - - - - - - - - Clipboard settings - - - - - - Time to store OTP secrets in clipboard (in seconds): - - - 10 - - - 600 - - - 120 - - - - - - - Time to store Password Safe secrets in clipboard (in seconds): - - - - - - - TIme to store Password Safe secrets in clipboard (in seconds): - - - 10 - - - 600 - - - 60 - - - - - - - Time to store OTP secrets in clipboard (in seconds): - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - false - - - OTP Password settings - - - - - - - 11 - 75 - true - - - - - - - - - - - - - Protect OTP by user PIN (will be requested on first use each session) - - - - - - - Forget user PIN after 10 minutes (if unchecked user PIN will remain in memory until application exits) - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 70 - - - - - - - - - - Save - - - - - - - Cancel - - - - - - - - - - 870 - 0 - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - Device - - - - - - PushButton - - - - - - - - Debug - - - - - - Debug log settings - - - - - - Path for debug log file: - - - - - - - Verbosity level: - - - 6 - - - 2 - - - - - - - Path for debug log file: - - - edit_debug_file_path - - - - - - - Verbosity level: - - - spin_debug_verbosity - - - - - - - - - - Logging enabled - - - - - - - Log to console - - - - - - - Select path - - - - - - - - - - Send Problem - - - - - - - - Firmware - - - - - - - - - diff --git a/nitrokeyapp/bak/ui/setup_wizard.ui b/nitrokeyapp/bak/ui/setup_wizard.ui deleted file mode 100644 index ef8c984b..00000000 --- a/nitrokeyapp/bak/ui/setup_wizard.ui +++ /dev/null @@ -1,253 +0,0 @@ - - - PINSetup - - - - 0 - 0 - 439 - 309 - - - - Wizard - - - - - - - This Guided Setup Wizard leads you through the process of setting up your PIN's, which are essential to use your Nitrokey device. - - - false - - - true - - - - - - - - 75 - true - - - - Nitrokey Setup - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 150 - - - - - - - - - true - - - - Your PINs can also be changed later again. - - - true - - - - - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - - - - - - - 75 - true - - - - User PIN Setup - - - - - - - new User PIN: - - - - - - - confirm new User PIN: - - - - - - - - true - - - - The Nitrokey is protected by a User PIN, -only 3 entries are possible until the device is locked. -Choose a User PIN between 6-20 characters. - - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - - - - confirm new Admin PIN: - - - - - - - Qt::Vertical - - - - 20 - 28 - - - - - - - - Qt::Horizontal - - - - - - - - - - new Admin PIN: - - - - - - - - 75 - true - - - - Admin PIN Setup - - - - - - - - true - - - - To unlock a blocked Nitrokey, you need an Admin PIN. -choose a PIN between 6-20 characters. - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - diff --git a/nitrokeyapp/bak/ui/storage.ui b/nitrokeyapp/bak/ui/storage.ui deleted file mode 100644 index af0ebaf3..00000000 --- a/nitrokeyapp/bak/ui/storage.ui +++ /dev/null @@ -1,680 +0,0 @@ - - - CreateHiddenVolume - - - - 0 - 0 - 560 - 456 - - - - Wizard - - - QWizard::ClassicStyle - - - - - - - - 75 - true - - - - Information - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - 0 - 0 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - - - images/new/icon_warning.svg - - - true - - - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - <html><head/><body><p><span style=" font-weight:600;">You should understand the properties of hidden volume before proceeding. It can destroy your encrypted data! </span></p></body></html> - - - false - - - true - - - true - - - - - - - - - - Hidden Volume Conditions - - - - - - 1. If you decide to configure hidden volume, you can not use the - encrypted storage anymore. -2. This process may damage your existing encrypted volume data. - - - - - - - - 0 - 0 - - - - - 500 - 50 - - - - - 100 - 150 - - - - - - - images/HiddenVolumes_0.png - - - true - - - - - - - - - - - - - - - 75 - true - - - - Password - - - - - - - You must set a password to open the hidden volume in the future. - - - - - - - - 100 - 0 - - - - - 100 - 0 - - - - Qt::Horizontal - - - - - - - Password settings - - - - - - Password: - - - - - - - Hidden volume password - - - Please use shift+tab key shortcut for instructions - - - - - - 20 - - - QLineEdit::Password - - - - - - - confirm Password: - - - - - - - Qt::StrongFocus - - - Hidden volume password (repeated) - - - - - - 20 - - - QLineEdit::Password - - - - - - - Show password - - - - - - - - - Password strength: - - - - - - - Password strength: - - - 42 - - - - - - - - - false - - - Qt::NoFocus - - - length - - - - - - - false - - - Qt::NoFocus - - - lower case - - - - - - - false - - - Qt::NoFocus - - - upper case - - - true - - - - - - - false - - - Qt::NoFocus - - - numbers - - - - - - - false - - - Qt::NoFocus - - - symbols - - - - - - - - - - - - - - - - - - - 75 - true - - - - Hidden Volume Settings - - - - - - - Here you can define the size of the hidden volume. - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 100 - 101 - - - - Hidden Volume Size - - - false - - - - - - - 0 - 0 - - - - Min - - - - - - - - 0 - 0 - - - - Qt::ImhNone - - - 30 - - - 1 - - - 15 - - - 15 - - - false - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 1 - - - - - - - - - Hidden Volume Size: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 - - - 30.000000000000000 - - - 15.000000000000000 - - - - - - - Unit: - - - - - - - Use this as hidden volume size unit - - - MB - - - - - - - Use this as hidden volume size unit - - - GB - - - true - - - - - - - - - - 0 - 0 - - - - Max - - - - - - - - - - - - - - - 75 - true - - - - Confirmation - - - - - - - Are you sure to create hidden volume on your Nitrokey Storage? - - - - - - - Qt::Horizontal - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - 0 - 0 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - - - images/new/icon_warning.svg - - - true - - - - - - - - 75 - true - - - - - - - Note: once you have created the hidden volume, - -you should not use the encrypted volume again, - -as you may damage data in the process! - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - Are you sure you want to set up the hidden volume? - - - - - - - Create Hidden Volume - - - - - - - - - diff --git a/nitrokeyapp/device_view.py b/nitrokeyapp/device_view.py index dcbe1251..6b46cfaf 100644 --- a/nitrokeyapp/device_view.py +++ b/nitrokeyapp/device_view.py @@ -1,6 +1,6 @@ from typing import Optional, Protocol -from PyQt5.QtWidgets import QWidget +from PySide6.QtWidgets import QWidget from nitrokeyapp.device_data import DeviceData from nitrokeyapp.worker import Worker diff --git a/nitrokeyapp/error_dialog.py b/nitrokeyapp/error_dialog.py index 37f01124..e8f9b3cc 100644 --- a/nitrokeyapp/error_dialog.py +++ b/nitrokeyapp/error_dialog.py @@ -2,21 +2,22 @@ from types import TracebackType from typing import Optional, Type -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QPushButton, QWidget +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QDialog, QDialogButtonBox, QPushButton, QWidget from nitrokeyapp.logger import save_log -from nitrokeyapp.ui.error_dialog import Ui_ErrorDialog +from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -class ErrorDialog(QDialog): +class ErrorDialog(QtUtilsMixIn, QDialog): def __init__(self, log_file: str, parent: Optional[QWidget] = None) -> None: - super().__init__(parent) + QDialog.__init__(self, parent) + QtUtilsMixIn.__init__(self) self.log_file = log_file - self.ui = Ui_ErrorDialog() - self.ui.setupUi(self) + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("error_dialog.ui", self) self.button_save_log = QPushButton("Save Log File", self) self.button_save_log.pressed.connect(self.save_log) @@ -33,7 +34,8 @@ def set_exception( ) -> None: lines = format_exception(ty, e, tb) self.ui.textEditDetails.setPlainText("".join(lines)) + self.show() - @pyqtSlot() + @Slot() def save_log(self) -> None: save_log(self.log_file, self) diff --git a/nitrokeyapp/gui.py b/nitrokeyapp/gui.py index 1c172077..6bbd452e 100644 --- a/nitrokeyapp/gui.py +++ b/nitrokeyapp/gui.py @@ -1,23 +1,20 @@ -# use "pbs" for packaging... -# pip-run -> pyqt5 -# pip-dev -> pyqt5-stubs -import functools import logging import platform -import time import webbrowser from types import TracebackType from typing import Optional, Type +if platform.system() == "Linux": + import pyudev + # Nitrokey 3 from pynitrokey.nk3 import Nitrokey3Device # pyqt5 -from PyQt5 import QtWidgets -from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot -from PyQt5.QtGui import QCursor +from PySide6 import QtWidgets +from PySide6.QtCore import Qt, Signal, Slot +from PySide6.QtGui import QCursor -# from nitrokeyapp.about_dialog import AboutDialog from nitrokeyapp.device_data import DeviceData from nitrokeyapp.device_view import DeviceView from nitrokeyapp.error_dialog import ErrorDialog @@ -30,7 +27,6 @@ from nitrokeyapp.secrets_tab import SecretsTab # import wizards and stuff -from nitrokeyapp.ui.mainwindow import Ui_MainWindow from nitrokeyapp.welcome_tab import WelcomeTab from nitrokeyapp.windows_notification import WindowsUSBNotifi @@ -45,34 +41,35 @@ def __init__(self, parent: QtWidgets.QWidget) -> None: self.setWindowTitle("Touch Confirmation") self.setText("Press the button on the Nitrokey 3 if the LED blinks.") - @pyqtSlot() + @Slot() def start(self) -> None: self.show() - @pyqtSlot() + @Slot() def stop(self) -> None: self.close() class GUI(QtUtilsMixIn, QtWidgets.QMainWindow): - trigger_handle_exception = pyqtSignal(object, BaseException, object) + trigger_handle_exception = Signal(object, BaseException, object) + sig_device_change = Signal(object) def __init__(self, qt_app: QtWidgets.QApplication, log_file: str): QtWidgets.QMainWindow.__init__(self) QtUtilsMixIn.__init__(self) + # linux if platform.system() == "Linux": - # pyudev stuff - import pyudev - from pyudev.pyqt5 import MonitorObserver - # start monitoring usb self.context = pyudev.Context() self.monitor = pyudev.Monitor.from_netlink(self.context) self.monitor.filter_by(subsystem="usb") - self.observer = MonitorObserver(self.monitor) - self.observer.deviceEvent.connect(self.device_connect) - self.monitor.start() + # pyudev.pyside6 integration doesn't work properly + self.observer = pyudev.MonitorObserver( + self.monitor, lambda action, device: self.sig_device_change.emit(action) + ) + self.observer.start() + # windows if platform.system() == "Windows": logger.info("OS:Windows") @@ -86,17 +83,20 @@ def __init__(self, qt_app: QtWidgets.QApplication, log_file: str): self.trigger_handle_exception.connect(self.handle_exception) # loads main ui - self.ui = Ui_MainWindow() - self.ui.setupUi(self) + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("mainwindow.ui", self) self.info_box = InfoBox( self.ui.information_frame, self.ui.label_information_icon, self.ui.label_information, ) - self.widgetTab = self.ui.widgetTab - self.widgetTab = WelcomeTab(self.widgetTab, self.log_file) - # self.about_dialog = AboutDialog(log_file, qt_app) + + self.welcome_widget = WelcomeTab(self, self.log_file) + + self.content_widget = self.ui.widgetTab + self.content_widget.layout().addWidget(self.welcome_widget) + self.touch_dialog = TouchDialog(self) self.overview_tab = OverviewTab(self.info_box, self) self.views: list[DeviceView] = [self.overview_tab, SecretsTab(self)] @@ -107,19 +107,16 @@ def __init__(self, qt_app: QtWidgets.QApplication, log_file: str): view.worker.start_touch.connect(self.touch_dialog.start) view.worker.stop_touch.connect(self.touch_dialog.stop) - # get widget objects - # app wide widgets - # self.status_bar = _get(_qt.QStatusBar, "statusBar") - # self.menu_bar = _get(_qt.QMenuBar, "menuBar") + # main window widgets self.tabs = self.ui.tabWidget self.home_button = self.ui.btn_home self.help_btn = self.ui.btn_dial_help # self.quit_button = self.ui.btn_dial_quit - self.settings_btn = self.ui.btn_settings - self.lock_btn = self.ui.btn_dial_lock + # self.settings_btn = self.ui.btn_settings + # self.lock_btn = self.ui.btn_dial_lock self.l_insert_nitrokey = self.ui.label_insert_Nitrokey # set some props, initial enabled/visible, finally show() - self.setAttribute(Qt.WA_DeleteOnClose) + self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) for view in self.views: self.tabs.addTab(view.widget, view.title) @@ -127,6 +124,9 @@ def __init__(self, qt_app: QtWidgets.QApplication, log_file: str): # set some spacing between Nitrokey buttons self.ui.nitrokeyButtonsLayout.setSpacing(8) + self.sig_device_change.connect(self.device_connect) + + self.sig_device_change.connect(self.device_connect) self.init_gui() self.show() @@ -135,27 +135,23 @@ def __init__(self, qt_app: QtWidgets.QApplication, log_file: str): self.help_btn.clicked.connect( lambda: webbrowser.open("https://docs.nitrokey.com/nitrokey3") ) - self.lock_btn.clicked.connect(self.slot_lock_button_pressed) + # self.lock_btn.clicked.connect(self.slot_lock_button_pressed) self.home_button.clicked.connect(self.home_button_pressed) # self.settings_btn.clicked.connect() # connections for functional signals # generic / global # overview - # experimental idea to differ between removed and added - def device_connect(self) -> None: - import pyudev + @Slot(object) + def device_connect(self, action: str) -> None: + if action == "remove": + logger.info("removed") + self.detect_removed_devices() + elif action == "bind": + logger.info("bind") + self.detect_added_devices() - dvc: pyudev.Device - for dvc in iter(functools.partial(self.monitor.poll, 3), None): - if dvc.action == "remove": - logger.info("removed") - self.detect_removed_devices() - elif dvc.action == "bind": - logger.info("BIND") - self.detect_added_devices() - - @pyqtSlot(object, BaseException, object) + @Slot(object, BaseException, object) def handle_exception( self, ty: Type[BaseException], @@ -166,7 +162,6 @@ def handle_exception( dialog = ErrorDialog(self.log_file, self) dialog.set_exception(ty, e, tb) - dialog.show() def toggle_update_btn(self) -> None: device_count = len(self.devices) @@ -202,16 +197,9 @@ def detect_added_devices(self) -> None: logger.info("no nk3 in list. no admin?") def detect_removed_devices(self) -> None: - self.tabs.setCurrentIndex(0) list_of_removed: list[DeviceData] = [] if self.devices: - try: - raw_list = Nitrokey3Device.list() - except Exception: - time.sleep(0.5) - raw_list = Nitrokey3Device.list() - - nk3_list = [str(device.uuid())[:-4] for device in raw_list] + nk3_list = [str(device.uuid())[:-4] for device in Nitrokey3Device.list()] logger.info(f"list nk3: {nk3_list}") list_of_removed = [ data @@ -257,7 +245,7 @@ def refresh(self) -> None: self.overview_tab.busy_state_changed.connect(self.set_busy) if self.selected_device: - self.widgetTab.hide() + self.welcome_widget.hide() self.views[self.tabs.currentIndex()].refresh(self.selected_device) self.tabs.show() else: @@ -268,8 +256,8 @@ def refresh(self) -> None: def init_gui(self) -> None: self.tabs.hide() self.info_box.hide() - self.lock_btn.setEnabled(False) - self.settings_btn.setEnabled(False) + # self.lock_btn.setEnabled(False) + # self.settings_btn.setEnabled(False) self.detect_added_devices() def device_selected(self, data: DeviceData) -> None: @@ -283,29 +271,29 @@ def widget_show(self) -> None: self.device_selected(data) else: self.tabs.hide() - self.widgetTab.show() + self.welcome_widget.show() - @pyqtSlot(int) + @Slot(int) def slot_tab_changed(self, idx: int) -> None: self.refresh() # main-window callbacks - @pyqtSlot() + @Slot() def home_button_pressed(self) -> None: - self.widgetTab.show() + self.welcome_widget.show() self.tabs.hide() - @pyqtSlot() + @Slot() def slot_lock_button_pressed(self) -> None: # removes side buttos for nk3 (for now) logger.info("nk3 instance removed (lock button)") for data in self.devices: self.remove_device(data) - @pyqtSlot(bool) + @Slot(bool) def set_busy(self, busy: bool) -> None: if busy: - self.setCursor(QCursor(Qt.WaitCursor)) + self.setCursor(QCursor(Qt.CursorShape.WaitCursor)) self.home_button.setEnabled(False) self.tabs.setEnabled(False) else: @@ -316,7 +304,7 @@ def set_busy(self, busy: bool) -> None: # TODO: setEnabled? # self.setEnabled(not busy) - @pyqtSlot(str) + @Slot(str) def error(self, error: str) -> None: # TODO: improve - self.user_err(error, "Error") + self.user_err(error, "Error", self) diff --git a/nitrokeyapp/information_box.py b/nitrokeyapp/information_box.py index f3f0634d..9a94213d 100644 --- a/nitrokeyapp/information_box.py +++ b/nitrokeyapp/information_box.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore, QtWidgets +from PySide6 import QtCore, QtWidgets class InfoBox: diff --git a/nitrokeyapp/logger.py b/nitrokeyapp/logger.py index e55036c8..e5d3d21e 100644 --- a/nitrokeyapp/logger.py +++ b/nitrokeyapp/logger.py @@ -1,16 +1,20 @@ import logging +import os import platform import shutil +import sys from contextlib import contextmanager from datetime import datetime from importlib.metadata import version as package_version from tempfile import NamedTemporaryFile from typing import Generator -from PyQt5.QtWidgets import QFileDialog, QWidget +from PySide6.QtWidgets import QFileDialog, QWidget logger = logging.getLogger(__name__) +log_to_console = "NKAPP_LOG" in os.environ + @contextmanager def init_logging() -> Generator[str, None, None]: @@ -21,7 +25,13 @@ def init_logging() -> Generator[str, None, None]: handler = logging.FileHandler( filename=log_file.name, delay=True, encoding="utf-8" ) - logging.basicConfig(format=log_format, level=logging.DEBUG, handlers=[handler]) + console_handler = logging.StreamHandler(sys.stdout) + + handlers = [handler] + if log_to_console: + handlers.append(console_handler) # type: ignore + + logging.basicConfig(format=log_format, level=logging.DEBUG, handlers=handlers) yield log_file.name finally: diff --git a/nitrokeyapp/nk3_button.py b/nitrokeyapp/nk3_button.py index b1b896dd..3a427311 100644 --- a/nitrokeyapp/nk3_button.py +++ b/nitrokeyapp/nk3_button.py @@ -1,8 +1,9 @@ -from PyQt5 import QtGui, QtWidgets +from PySide6 import QtWidgets from qt_material import apply_stylesheet from nitrokeyapp import get_theme_path from nitrokeyapp.device_data import DeviceData +from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn class Nk3Button(QtWidgets.QPushButton): @@ -11,7 +12,7 @@ def __init__( data: DeviceData, ) -> None: super().__init__( - QtGui.QIcon(":/icons/usb_new.png"), + QtUtilsMixIn.get_qicon("usb_new.png"), "Nitrokey 3: " f"{str(data.uuid)[:5]}", ) self.data = data diff --git a/nitrokeyapp/overview_tab.py b/nitrokeyapp/overview_tab.py index f60c9a0d..86107e6f 100644 --- a/nitrokeyapp/overview_tab.py +++ b/nitrokeyapp/overview_tab.py @@ -1,18 +1,17 @@ from typing import Optional from pynitrokey.nk3.admin_app import InitStatus -from PyQt5.QtCore import pyqtSignal, pyqtSlot -from PyQt5.QtWidgets import QFileDialog, QWidget +from PySide6.QtCore import Signal, Slot +from PySide6.QtWidgets import QFileDialog, QWidget from nitrokeyapp.device_data import DeviceData from nitrokeyapp.information_box import InfoBox from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.overview_tab import Ui_OverviewTab from nitrokeyapp.worker import Worker class OverviewTab(QtUtilsMixIn, QWidget): - busy_state_changed = pyqtSignal(bool) + busy_state_changed = Signal(bool) def __init__(self, info_box: InfoBox, parent: Optional[QWidget] = None) -> None: QWidget.__init__(self, parent) @@ -20,8 +19,9 @@ def __init__(self, info_box: InfoBox, parent: Optional[QWidget] = None) -> None: self.data: Optional[DeviceData] = None self.info_box = info_box - self.ui = Ui_OverviewTab() - self.ui.setupUi(self) + + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("overview_tab.ui", self) self.collapse(self.ui.more_options_frame, self.ui.more_options_btn) self.ui.update_with_file_btn.clicked.connect(self.update_with_file) @@ -126,16 +126,16 @@ def update_btns_during_update(self, enabled: bool) -> None: def show_more_options(self) -> None: self.collapse(self.ui.more_options_frame, self.ui.more_options_btn) - @pyqtSlot() + @Slot() def run_update(self) -> None: assert self.data self.data.update(self, self.info_box) - @pyqtSlot() + @Slot() def update_with_file(self) -> None: assert self.data fdialog = QFileDialog() - fdialog.setFileMode(QFileDialog.AnyFile) + fdialog.setFileMode(QFileDialog.FileMode.AnyFile) if fdialog.exec_(): filenames = fdialog.selectedFiles() diff --git a/nitrokeyapp/qt_utils_mix_in.py b/nitrokeyapp/qt_utils_mix_in.py index 32be52eb..01dd0151 100644 --- a/nitrokeyapp/qt_utils_mix_in.py +++ b/nitrokeyapp/qt_utils_mix_in.py @@ -1,7 +1,10 @@ -from typing import Optional, Type, TypeVar +from pathlib import Path +from typing import Any, Optional, Type, TypeVar -from PyQt5 import QtGui, QtWidgets, uic -from PyQt5.QtCore import QObject, QSize +from PySide6 import QtGui, QtWidgets +from PySide6.QtCore import QDir, QObject, QSize + +from nitrokeyapp.ui_loader import UiLoader Q = TypeVar("Q", bound=QObject) @@ -14,6 +17,22 @@ def __init__(self) -> None: # TODO: should we restrict this further to QWidget? assert isinstance(self, QObject) + @staticmethod + def load_ui( + filename: str, base_instance: Optional[QtWidgets.QWidget] = None + ) -> Any: + # returning `Any` to avoid `mypy` going crazy due to monkey-patching + loader = UiLoader(base_instance, customWidgets=None) + p_dir = (Path(__file__).parent / "ui").absolute() + loader.setWorkingDirectory(QDir(p_dir.as_posix())) + p_file = p_dir / filename + return loader.load(p_file.as_posix()) + + @staticmethod + def get_qicon(filename: str) -> QtGui.QIcon: + p = Path(__file__).parent / "ui" / "icons" / filename + return QtGui.QIcon(p.as_posix()) + def user_warn( self, msg: str, @@ -56,23 +75,19 @@ def get_widget(self, qt_cls: Type[Q], name: str = "") -> Q: self.widgets[name] = widget return widget # type: ignore - def load_ui(self, filename: str, qt_obj: Type) -> bool: - uic.loadUi(filename, qt_obj) - return True - def collapse( self, frame: QtWidgets.QWidget, expand_button: QtWidgets.QPushButton ) -> None: # Find out if the state is on or off state = expand_button.isChecked() if not state: - expand_button.setIcon(QtGui.QIcon(":/icons/right_arrow.png")) + expand_button.setIcon(self.get_qicon("right_arrow.png")) expand_button.setIconSize(QSize(12, 12)) frame.setFixedHeight(0) # Set window Height # self.setFixedHeight(self.sizeHint().height()) else: - expand_button.setIcon(QtGui.QIcon(":/icons/down_arrow.png")) + expand_button.setIcon(self.get_qicon("down_arrow.png")) oSize = frame.sizeHint() frame.setFixedHeight(oSize.height()) # Set window Height diff --git a/nitrokeyapp/secrets_tab/__init__.py b/nitrokeyapp/secrets_tab/__init__.py index 688b561b..07e12b29 100644 --- a/nitrokeyapp/secrets_tab/__init__.py +++ b/nitrokeyapp/secrets_tab/__init__.py @@ -1,13 +1,15 @@ from datetime import datetime from typing import Optional -from PyQt5.QtCore import Qt, QThread, QTimer, pyqtSignal, pyqtSlot -from PyQt5.QtGui import QGuiApplication, QIcon -from PyQt5.QtWidgets import QDialog, QListWidgetItem, QWidget +from PySide6.QtCore import Qt, QThread, QTimer, Signal, Slot +from PySide6.QtGui import QGuiApplication +from PySide6.QtWidgets import QDialog, QListWidgetItem, QWidget from nitrokeyapp.add_secret_dialog import AddSecretDialog from nitrokeyapp.device_data import DeviceData -from nitrokeyapp.ui.secrets_tab import Ui_SecretsTab +from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn + +# from nitrokeyapp.ui.secrets_tab import Ui_SecretsTab from nitrokeyapp.worker import Worker from .data import Credential, OtpData @@ -22,22 +24,23 @@ # - confirm new PIN -class SecretsTab(QWidget): +class SecretsTab(QtUtilsMixIn, QWidget): # standard UI - busy_state_changed = pyqtSignal(bool) - error = pyqtSignal(str) - start_touch = pyqtSignal() - stop_touch = pyqtSignal() + busy_state_changed = Signal(bool) + error = Signal(str) + start_touch = Signal() + stop_touch = Signal() # worker triggers - trigger_add_credential = pyqtSignal(DeviceData, Credential, bytes) - trigger_check_device = pyqtSignal(DeviceData) - trigger_delete_credential = pyqtSignal(DeviceData, Credential) - trigger_generate_otp = pyqtSignal(DeviceData, Credential) - trigger_refresh_credentials = pyqtSignal(DeviceData, bool) + trigger_add_credential = Signal(DeviceData, Credential, bytes) + trigger_check_device = Signal(DeviceData) + trigger_delete_credential = Signal(DeviceData, Credential) + trigger_generate_otp = Signal(DeviceData, Credential) + trigger_refresh_credentials = Signal(DeviceData, bool) def __init__(self, parent: Optional[QWidget] = None) -> None: - super().__init__(parent) + QWidget.__init__(self, parent) + QtUtilsMixIn.__init__(self) self.worker_thread = QThread() self._worker = SecretsWorker(self) @@ -69,8 +72,8 @@ def __init__(self, parent: Optional[QWidget] = None) -> None: self.clipboard = QGuiApplication.clipboard() self.originalText = self.clipboard.text() - self.ui = Ui_SecretsTab() - self.ui.setupUi(self) + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("secrets_tab.ui", self) labels = [ self.ui.labelName, @@ -126,13 +129,13 @@ def refresh(self, data: DeviceData) -> None: self.reset_ui() self.trigger_check_device.emit(data) - @pyqtSlot(bool) + @Slot(bool) def device_checked(self, compatible: bool) -> None: self.show_secrets(compatible) if compatible: self.refresh_credential_list() - @pyqtSlot() + @Slot() def refresh_credential_list(self) -> None: assert self.data @@ -145,7 +148,7 @@ def refresh_credential_list(self) -> None: self.trigger_refresh_credentials.emit(self.data, pin_protected) - @pyqtSlot(Credential) + @Slot(Credential) def credential_added(self, credential: Credential) -> None: self.active_credential = credential if credential.protected: @@ -153,11 +156,11 @@ def credential_added(self, credential: Credential) -> None: self.refresh_credential_list() - @pyqtSlot(Credential) + @Slot(Credential) def credential_deleted(self, credential: Credential) -> None: self.refresh_credential_list() - @pyqtSlot(list) + @Slot(list) def credentials_listed(self, credentials: list[Credential]) -> None: self.reset_ui() self.show_secrets(True) @@ -171,7 +174,7 @@ def credentials_listed(self, credentials: list[Credential]) -> None: if active_item: self.ui.secretsList.setCurrentItem(active_item) - @pyqtSlot(OtpData) + @Slot(OtpData) def otp_generated(self, data: OtpData) -> None: self.ui.lineEditOtp.setText(data.otp) self.data_otp = data.otp @@ -200,7 +203,7 @@ def add_credential(self, credential: Credential) -> QListWidgetItem: else "lock_open_FILL0_wght500_GRAD0_opsz40" ) item = QListWidgetItem(credential.name) - item.setIcon(QIcon(f":/icons/{icon}.svg")) + item.setIcon(self.get_qicon(f"{icon}.svg")) item.setData(Qt.ItemDataRole.UserRole, credential) self.ui.secretsList.addItem(item) return item @@ -236,7 +239,7 @@ def show_secrets(self, show: bool) -> None: widget = self.ui.pageCompatible if show else self.ui.pageIncompatible self.ui.stackedWidget.setCurrentWidget(widget) - @pyqtSlot() + @Slot() def hide_otp(self) -> None: self.otp_timeout = None self.otp_timer.stop() @@ -252,7 +255,7 @@ def update_otp_generation(self, credential: Optional[Credential]) -> None: visible = credential is not None and credential.otp is not None self.ui.pushButtonOtpGenerate.setVisible(visible) - @pyqtSlot() + @Slot() def update_otp_timeout(self) -> None: if not self.otp_timeout: return @@ -263,7 +266,7 @@ def update_otp_timeout(self) -> None: else: self.hide_otp() - @pyqtSlot(QListWidgetItem, QListWidgetItem) + @Slot(QListWidgetItem, QListWidgetItem) def credential_changed( self, current: Optional[QListWidgetItem], old: Optional[QListWidgetItem] ) -> None: @@ -275,7 +278,7 @@ def credential_changed( self.hide_credential() self.ui.buttonDelete.setEnabled(False) - @pyqtSlot() + @Slot() def delete_credential(self) -> None: assert self.data credential = self.get_current_credential() @@ -285,7 +288,7 @@ def delete_credential(self) -> None: self.trigger_delete_credential.emit(self.data, credential) - @pyqtSlot() + @Slot() def add_new_credential(self) -> None: if not self.data: return @@ -296,7 +299,7 @@ def add_new_credential(self) -> None: secret = dialog.secret() self.trigger_add_credential.emit(self.data, credential, secret) - @pyqtSlot() + @Slot() def generate_otp(self) -> None: assert self.data credential = self.get_current_credential() @@ -304,7 +307,7 @@ def generate_otp(self) -> None: self.trigger_generate_otp.emit(self.data, credential) - @pyqtSlot(bool) + @Slot(bool) def uncheck_checkbox(self, uncheck: bool) -> None: if uncheck: self.ui.checkBoxProtected.setChecked(False) diff --git a/nitrokeyapp/secrets_tab/ui.py b/nitrokeyapp/secrets_tab/ui.py index f098d753..8aa67293 100644 --- a/nitrokeyapp/secrets_tab/ui.py +++ b/nitrokeyapp/secrets_tab/ui.py @@ -1,21 +1,21 @@ from dataclasses import dataclass from typing import Callable, Optional -from PyQt5.QtCore import QMetaObject, QObject, pyqtSignal, pyqtSlot -from PyQt5.QtWidgets import QInputDialog, QLineEdit, QWidget +from PySide6.QtCore import QMetaObject, QObject, Signal, Slot +from PySide6.QtWidgets import QInputDialog, QLineEdit, QWidget class PinUi(QObject): - queried = pyqtSignal(str) - chosen = pyqtSignal(str) - cancelled = pyqtSignal() + queried = Signal(str) + chosen = Signal(str) + cancelled = Signal() def __init__(self, parent: QWidget) -> None: super().__init__(parent) self.parent_widget = parent - @pyqtSlot(int) + @Slot(int) def query(self, attempts: int) -> None: pin, ok = QInputDialog.getText( self.parent_widget, @@ -28,7 +28,7 @@ def query(self, attempts: int) -> None: else: self.cancelled.emit() - @pyqtSlot() + @Slot() def choose(self) -> None: # TODO: confirm pin, ok = QInputDialog.getText( @@ -42,7 +42,7 @@ def choose(self) -> None: else: self.cancelled.emit() - def connect( + def connect_actions( self, queried: Optional[Callable[[str], None]], chosen: Optional[Callable[[str], None]], diff --git a/nitrokeyapp/secrets_tab/worker.py b/nitrokeyapp/secrets_tab/worker.py index 53331d43..e4008018 100644 --- a/nitrokeyapp/secrets_tab/worker.py +++ b/nitrokeyapp/secrets_tab/worker.py @@ -4,8 +4,8 @@ from pynitrokey.nk3.secrets_app import SecretsApp, SecretsAppException from pynitrokey.nk3.utils import Uuid -from PyQt5.QtCore import pyqtSignal, pyqtSlot -from PyQt5.QtWidgets import QWidget +from PySide6.QtCore import Signal, Slot +from PySide6.QtWidgets import QWidget from nitrokeyapp.device_data import DeviceData from nitrokeyapp.worker import Job, Worker @@ -37,7 +37,7 @@ def update(self, data: DeviceData, pin: str) -> None: class CheckDeviceJob(Job): - device_checked = pyqtSignal(bool) + device_checked = Signal(bool) def __init__(self, data: DeviceData) -> None: super().__init__() @@ -60,11 +60,11 @@ def run(self) -> None: class VerifyPinJob(Job): - pin_verified = pyqtSignal(bool) + pin_verified = Signal(bool) # internal signals - query_pin = pyqtSignal(int) - choose_pin = pyqtSignal() + query_pin = Signal(int) + choose_pin = Signal() def __init__( self, @@ -84,7 +84,7 @@ def __init__( self.query_pin.connect(pin_ui.query) self.choose_pin.connect(pin_ui.choose) - self.pin_ui = pin_ui.connect( + self.pin_ui = pin_ui.connect_actions( self.pin_queried, self.pin_chosen, lambda: self.pin_verified.emit(False), @@ -109,7 +109,7 @@ def run(self) -> None: else: self.pin_verified.emit(False) - @pyqtSlot(str) + @Slot(str) def pin_queried(self, pin: str) -> None: with self.data.open() as device: secrets = SecretsApp(device) @@ -125,7 +125,7 @@ def pin_queried(self, pin: str) -> None: # TODO: improve error message self.trigger_error(f"PIN validation failed: {e}") - @pyqtSlot(str) + @Slot(str) def pin_chosen(self, pin: str) -> None: with self.data.open() as device: secrets = SecretsApp(device) @@ -138,14 +138,14 @@ def pin_chosen(self, pin: str) -> None: else: self.trigger_error("Failed to set Secrets PIN") - @pyqtSlot(str) + @Slot(str) def trigger_error(self, msg: str) -> None: self.error.emit(msg) self.pin_verified.emit(False) class AddCredentialJob(Job): - credential_added = pyqtSignal(Credential) + credential_added = Signal(Credential) def __init__( self, @@ -175,7 +175,7 @@ def run(self) -> None: list_credentials_job.credentials_listed.connect(self.check_credential) self.spawn(list_credentials_job) - @pyqtSlot(list) + @Slot(list) def check_credential(self, credentials: list[Credential]) -> None: ids = set([credential.id for credential in credentials]) if self.credential.id in ids: @@ -194,7 +194,7 @@ def check_credential(self, credentials: list[Credential]) -> None: else: self.add_credential() - @pyqtSlot(bool) + @Slot(bool) def add_credential(self, successful: bool = True) -> None: if not successful: self.finished.emit() @@ -216,7 +216,7 @@ def add_credential(self, successful: bool = True) -> None: class DeleteCredentialJob(Job): - credential_deleted = pyqtSignal(Credential) + credential_deleted = Signal(Credential) def __init__( self, @@ -243,7 +243,7 @@ def run(self) -> None: else: self.delete_credential() - @pyqtSlot() + @Slot() def delete_credential(self) -> None: with self.data.open() as device: secrets = SecretsApp(device) @@ -255,7 +255,7 @@ def delete_credential(self) -> None: class GenerateOtpJob(Job): # TODO: make period and digits configurable - otp_generated = pyqtSignal(OtpData) + otp_generated = Signal(OtpData) def __init__( self, @@ -281,7 +281,7 @@ def run(self) -> None: else: self.generate_otp() - @pyqtSlot() + @Slot() def generate_otp(self) -> None: with self.data.open() as device: secrets = SecretsApp(device) @@ -307,8 +307,8 @@ def generate_otp(self) -> None: class ListCredentialsJob(Job): - credentials_listed = pyqtSignal(list) - uncheck_checkbox = pyqtSignal(bool) + credentials_listed = Signal(list) + uncheck_checkbox = Signal(bool) def __init__( self, pin_cache: PinCache, pin_ui: PinUi, data: DeviceData, pin_protected: bool @@ -333,7 +333,7 @@ def run(self) -> None: credentials = Credential.list(secrets) self.credentials_listed.emit(credentials) - @pyqtSlot(bool) + @Slot(bool) def list_protected_credentials(self, successful: bool) -> None: credentials = [] if not successful: @@ -350,12 +350,12 @@ def list_protected_credentials(self, successful: bool) -> None: class SecretsWorker(Worker): # TODO: remove DeviceData from signatures - credential_added = pyqtSignal(Credential) - credential_deleted = pyqtSignal(Credential) - credentials_listed = pyqtSignal(list) - uncheck_checkbox = pyqtSignal(bool) - device_checked = pyqtSignal(bool) - otp_generated = pyqtSignal(OtpData) + credential_added = Signal(Credential) + credential_deleted = Signal(Credential) + credentials_listed = Signal(list) + uncheck_checkbox = Signal(bool) + device_checked = Signal(bool) + otp_generated = Signal(OtpData) def __init__(self, widget: QWidget) -> None: super().__init__() @@ -363,13 +363,13 @@ def __init__(self, widget: QWidget) -> None: self.pin_cache = PinCache() self.pin_ui = PinUi(widget) - @pyqtSlot(DeviceData) + @Slot(DeviceData) def check_device(self, data: DeviceData) -> None: job = CheckDeviceJob(data) job.device_checked.connect(self.device_checked) self.run(job) - @pyqtSlot(DeviceData, Credential, bytes) + @Slot(DeviceData, Credential, bytes) def add_credential( self, data: DeviceData, credential: Credential, secret: bytes ) -> None: @@ -377,19 +377,19 @@ def add_credential( job.credential_added.connect(self.credential_added) self.run(job) - @pyqtSlot(DeviceData, Credential) + @Slot(DeviceData, Credential) def delete_credential(self, data: DeviceData, credential: Credential) -> None: job = DeleteCredentialJob(self.pin_cache, self.pin_ui, data, credential) job.credential_deleted.connect(self.credential_deleted) self.run(job) - @pyqtSlot(DeviceData, Credential) + @Slot(DeviceData, Credential) def generate_otp(self, data: DeviceData, credential: Credential) -> None: job = GenerateOtpJob(self.pin_cache, self.pin_ui, data, credential) job.otp_generated.connect(self.otp_generated) self.run(job) - @pyqtSlot(DeviceData, bool) + @Slot(DeviceData, bool) def refresh_credentials(self, data: DeviceData, pin_protected: bool) -> None: job = ListCredentialsJob(self.pin_cache, self.pin_ui, data, pin_protected) job.credentials_listed.connect(self.credentials_listed) diff --git a/nitrokeyapp/ui/aboutdialog.ui b/nitrokeyapp/ui/aboutdialog.ui deleted file mode 100644 index b93e1a36..00000000 --- a/nitrokeyapp/ui/aboutdialog.ui +++ /dev/null @@ -1,246 +0,0 @@ - - - AboutDialog - - - - 0 - 0 - 642 - 777 - - - - - 0 - 0 - - - - Qt::NoFocus - - - About - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - false - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - - - 0 - 0 - - - - - 500 - 161 - - - - - 500 - 161 - - - - Logo - - - - - - :/icons/icon_Logo_App.svg - - - - - - - - - - - Qt::StrongFocus - - - <html><head/><body><p>This application allows you to configure your Nitrokey 3.</p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - - - Qt::StrongFocus - - - <html><head/><body><p><a href="https://www.nitrokey.com/start"><span style=" text-decoration: underline; color:#c80636;">Instructions and help</span></a></p></body></html> - - - true - - - - - - - - - - - Qt::Horizontal - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Qt::StrongFocus - - - App version: - - - - - - - - 75 - true - - - - Qt::StrongFocus - - - 1.0 - - - - - - - - - - - Qt::Horizontal - - - - - - - Qt::StrongFocus - - - <html><head/><body><p><span style=" font-size:10pt; font-style:italic;">This software is licensed under the </span><a href="http://www.apache.org/licenses/"><span style=" font-size:10pt; font-style:italic; text-decoration: underline; color:#c80636;">Apache License 2.0</span></a><span style=" font-size:10pt; font-style:italic;">.</span></p><p><a href="https://nitrokey.com"><span style=" text-decoration: underline; color:#c80636;">www.nitrokey.com</span></a></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - true - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse - - - - - - - - - - - - Save Log File - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::TabFocus - - - OK - - - true - - - - - - - - - label_7 - label_6 - label_3 - VersionLabel - AboutLabel_2 - - - - - - diff --git a/nitrokeyapp/ui/icons/home_FILL0_wght500_GRAD0_opsz40 (1).png b/nitrokeyapp/ui/icons/home_FILL0_wght500_GRAD0_opsz40.png similarity index 100% rename from nitrokeyapp/ui/icons/home_FILL0_wght500_GRAD0_opsz40 (1).png rename to nitrokeyapp/ui/icons/home_FILL0_wght500_GRAD0_opsz40.png diff --git a/nitrokeyapp/ui/mainwindow.ui b/nitrokeyapp/ui/mainwindow.ui index 165f6161..281cfe85 100644 --- a/nitrokeyapp/ui/mainwindow.ui +++ b/nitrokeyapp/ui/mainwindow.ui @@ -28,10 +28,6 @@ Nitrokey App - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - false @@ -103,7 +99,7 @@ - :/icons/info_FILL0_wght500_GRAD0_opsz40.png + nitrokeyapp/ui/icons/info_FILL0_wght500_GRAD0_opsz40.png true @@ -126,7 +122,7 @@ - + @@ -149,60 +145,36 @@ QFrame::Raised - - - + + + - + 0 0 - - - PreferDefault - - - - <html><head/><body><p>home</p></body></html> + + Qt::LeftToRight - - QPushButton { - border: none; - } + + 1 - - - :/icons/home_FILL0_wght500_GRAD0_opsz40 (1).png:/icons/home_FILL0_wght500_GRAD0_opsz40 (1).png + + icons/nitrokey-app-icon-vector.svg - - - 30 - 30 - + + true - - false + + Qt::AlignCenter - - - - Qt::Vertical - - - - 20 - 40 - - - - - + @@ -214,7 +186,6 @@ OpenSymbol 16 - 75 true @@ -230,8 +201,8 @@ - - + + border:0; @@ -254,141 +225,135 @@ - - - - - 0 - 0 - - - - <html><head/><body><p>settings</p></body></html> - - - QPushButton { - border: none; - } - - - + + + + Qt::Vertical - + - 30 - 30 + 20 + 40 - + - - - - - 0 - 0 - - - - <html><head/><body><p>lock</p></body></html> - - - QPushButton { + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + + PreferDefault + + + + Qt::NoFocus + + + <html><head/><body><p>home</p></body></html> + + + QPushButton { border: none; } - - - - - - - 30 - 30 - - - - false - - - - - - - - 0 - 0 - - - - ArrowCursor - - - false - - - <html><head/><body><p>help</p></body></html> - - - QPushButton { + + + + + + + icons/home_FILL0_wght500_GRAD0_opsz40.pngicons/home_FILL0_wght500_GRAD0_opsz40.png + + + + 30 + 30 + + + + false + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + ArrowCursor + + + false + + + Qt::NoFocus + + + <html><head/><body><p>help</p></body></html> + + + Qt::RightToLeft + + + QPushButton { border: none; } - - - - - - - :/icons/help_FILL0_wght500_GRAD0_opsz40.png:/icons/help_FILL0_wght500_GRAD0_opsz40.png - - - - 30 - 30 - - - - false - - - - - - - - 0 - 0 - - - - - 100 - 100 - - - - - 50 - 100 - - - - Qt::LeftToRight - - - 1 - - - - - - :/icons/nitrokey-app-icon-vector.svg - - - true - - - Qt::AlignJustify|Qt::AlignVCenter - + + + + + + + icons/help_FILL0_wght500_GRAD0_opsz40.pngicons/help_FILL0_wght500_GRAD0_opsz40.png + + + + 30 + 30 + + + + false + + + + @@ -430,7 +395,7 @@ true - + 0 0 diff --git a/nitrokeyapp/ui/overview_tab.ui b/nitrokeyapp/ui/overview_tab.ui index 31665880..dce85207 100644 --- a/nitrokeyapp/ui/overview_tab.ui +++ b/nitrokeyapp/ui/overview_tab.ui @@ -51,8 +51,8 @@ 0 0 - 488 - 369 + 476 + 342 @@ -315,7 +315,7 @@ Qt::AutoText - :/icons/icon_warning.svg + icons/icon_warning.svg true @@ -388,6 +388,10 @@ More Options + + + icons/right_arrow.pngicons/right_arrow.png + true diff --git a/nitrokeyapp/ui/resources.qrc b/nitrokeyapp/ui/resources.qrc deleted file mode 100644 index 59cf2027..00000000 --- a/nitrokeyapp/ui/resources.qrc +++ /dev/null @@ -1,41 +0,0 @@ - - - icons/add_circle_FILL0_wght500_GRAD0_opsz40.png - icons/delete_FILL0_wght500_GRAD0_opsz40.png - icons/down_arrow.png - icons/encrypted_FILL0_wght500_GRAD0_opsz40.png - icons/help_FILL0_wght500_GRAD0_opsz40.png - icons/home_FILL0_wght500_GRAD0_opsz40 (1).png - icons/icon_Logo_App.svg - icons/icon_NK.svg - icons/info_FILL0_wght500_GRAD0_opsz40.png - icons/lock_FILL0_wght500_GRAD0_opsz40.png - icons/lock_FILL0_wght500_GRAD0_opsz40.svg - icons/lock_open_FILL0_wght500_GRAD0_opsz40.png - icons/lock_open_FILL0_wght500_GRAD0_opsz40.svg - icons/nitrokey-app-icon-vector.svg - icons/ProgressWheel.GIF - icons/progressWheel2.gif - icons/refresh_FILL0_wght500_GRAD0_opsz40.png - icons/right_arrow.png - icons/settings_FILL0_wght500_GRAD0_opsz40.png - icons/touch_app_FILL0_wght500_GRAD0_opsz40.png - icons/usb_new.png - icons/icon_warning.svg - - - i18n/nitrokey_de_DE.qm - i18n/nitrokey_en.qm - i18n/nitrokey_arabic.qm - i18n/nitrokey_fr.qm - i18n/nitrokey_pl.qm - i18n/nitrokey_it.qm - - - 3RDPARTY.txt - LICENSES/GPLv3 - LICENSES/GPLv3 - LICENSES/LGPLv3 - LICENSES/MIT - - diff --git a/nitrokeyapp/ui/secrets_tab.ui b/nitrokeyapp/ui/secrets_tab.ui index 8eb7348a..161e66de 100644 --- a/nitrokeyapp/ui/secrets_tab.ui +++ b/nitrokeyapp/ui/secrets_tab.ui @@ -6,7 +6,7 @@ 0 0 - 500 + 655 477 @@ -73,7 +73,7 @@ - + 0 @@ -159,7 +159,7 @@ 0 0 - 218 + 373 457 diff --git a/nitrokeyapp/ui/settins_new.ui b/nitrokeyapp/ui/settins_new.ui deleted file mode 100644 index 933f59c9..00000000 --- a/nitrokeyapp/ui/settins_new.ui +++ /dev/null @@ -1,423 +0,0 @@ - - - Dialog - - - - 0 - 0 - 916 - 574 - - - - Dialog - - - - - - 0 - - - - General - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - General - - - - - - - - Show first-run message - - - - - - - Show main window on start - - - - - - - - - - - Do not quit when the main window is closed - - - true - - - - - - - Hide main window when device disconnects - - - true - - - - - - - - - Show main window when device connects - - - true - - - - - - - Show warning when no partitions could be detected on Encrypted Volume (Linux only) - - - true - - - - - - - Show message about device's connection / disconnection - - - true - - - - - - - - - <html><head/><body><p>Translation file (needs restart)</p></body></html> - - - - - - - Translation file (needs restart) - - - - - - - - - - - - - - - Clipboard settings - - - - - - Time to store OTP secrets in clipboard (in seconds): - - - 10 - - - 600 - - - 120 - - - - - - - Time to store Password Safe secrets in clipboard (in seconds): - - - - - - - TIme to store Password Safe secrets in clipboard (in seconds): - - - 10 - - - 600 - - - 60 - - - - - - - Time to store OTP secrets in clipboard (in seconds): - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - false - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - 75 - true - - - - OTP Password settings - - - - - - - - - Protect OTP by user PIN (will be requested on first use each session) - - - - - - - Forget user PIN after 10 minutes (if unchecked user PIN will remain in memory until application exits) - - - - - - - - - - - - Qt::Vertical - - - - 20 - 70 - - - - - - - - - - Save - - - - - - - Cancel - - - - - - - - - - 870 - 0 - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - Device - - - - - - PushButton - - - - - - - - Debug - - - - - - Debug log settings - - - - - - Path for debug log file: - - - - - - - Verbosity level: - - - 6 - - - 2 - - - - - - - Path for debug log file: - - - edit_debug_file_path - - - - - - - Verbosity level: - - - spin_debug_verbosity - - - - - - - - - - Logging enabled - - - - - - - Log to console - - - - - - - Select path - - - - - - - - - - Send Problem - - - - - - - - Firmware - - - - - - - - - diff --git a/nitrokeyapp/ui/stick20changepassworddialog.ui b/nitrokeyapp/ui/stick20changepassworddialog.ui deleted file mode 100644 index da3d4e14..00000000 --- a/nitrokeyapp/ui/stick20changepassworddialog.ui +++ /dev/null @@ -1,289 +0,0 @@ - - - DialogChangePassword - - - - 0 - 0 - 420 - 369 - - - - - 0 - 0 - - - - - 420 - 300 - - - - Change user PIN - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - - 0 - 0 - - - - false - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Old PIN - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Current PIN or password - - - - - - - New PIN - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - New PIN or password - - - - - - - New PIN - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - New PIN or password - - - - - - - - 0 - 0 - - - - Show PIN - - - - - - - - - - 0 - 0 - - - - true - - - Qt::StrongFocus - - - <html><head/><body><p><span style=" font-style:italic;">Nitrokey prevents against brute force password guessing attacks by allowing a maximum of 3 incorrect PIN attempts. Therefore a PIN of %1 digits is sufficient. The PIN must be between %1 and %2 characters.</span></p></body></html> - - - false - - - true - - - - - - - - - Retry count left: - - - - - - - Qt::StrongFocus - - - - - - Retry count left: - - - 3 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - lineEdit_OldPW - lineEdit_NewPW_1 - lineEdit_NewPW_2 - checkBox - label_additional_information - retryCount - - - - - - - buttonBox - accepted() - DialogChangePassword - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - DialogChangePassword - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/ui/stick20debugdialog.ui b/nitrokeyapp/ui/stick20debugdialog.ui deleted file mode 100644 index 927ff8fc..00000000 --- a/nitrokeyapp/ui/stick20debugdialog.ui +++ /dev/null @@ -1,95 +0,0 @@ - - - DebugDialog - - - - 0 - 0 - 793 - 789 - - - - Debug Log - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - - - - Courier New - - - - QPlainTextEdit::NoWrap - - - true - - - - - - Debug Log - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Ok - - - - - - - - - - - - - buttonBox - accepted() - DebugDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - DebugDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/ui/stick20hiddenvolumedialog.ui b/nitrokeyapp/ui/stick20hiddenvolumedialog.ui deleted file mode 100644 index bbc70af3..00000000 --- a/nitrokeyapp/ui/stick20hiddenvolumedialog.ui +++ /dev/null @@ -1,592 +0,0 @@ - - - stick20HiddenVolumeDialog - - - - 0 - 0 - 525 - 668 - - - - - 0 - 0 - - - - Setup hidden volume - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - - 0 - 0 - - - - false - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - - - - 0 - 0 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - 66 - 58 - - - - - - - :/icons/warning.png - - - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - <html><head/><body><p><span style=" font-weight:600;">You should understand the properties of hidden volumes before proceeding. It can destroy your encrypted data! <br/>Please read </span><a href="https://www.nitrokey.com/documentation/hidden-volumes"><span style=" font-weight:600; text-decoration: underline; color:#0000ff;">these instructions</span></a><span style=" font-weight:600;"> first.</span></p></body></html> - - - false - - - true - - - true - - - - - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - <html><head/><body><p>1. You may want to copy some innocuous files to the encrypted data.<br/>2. Configure hidden volumes in this dialogue. <br/>3. Once you configured a hidden volume you must not use/write to the encryption volume anymore. Otherwise it may destroy the data in your hidden volume.</p></body></html> - - - true - - - - - - - Password settings - - - - - - Password: - - - - - - - Hidden volume password - - - Please use shift+tab key shortcut for instructions - - - 12345678901234567890 - - - 20 - - - QLineEdit::Password - - - - - - - Password: - - - - - - - Qt::StrongFocus - - - Hidden volume password (repeated) - - - 12345678901234567890 - - - 20 - - - QLineEdit::Password - - - - - - - Show password - - - - - - - - - Password strength: - - - - - - - Password strength: - - - 42 - - - - - - - - - false - - - Qt::NoFocus - - - length - - - - - - - false - - - Qt::NoFocus - - - lower case - - - - - - - false - - - Qt::NoFocus - - - upper case - - - true - - - - - - - false - - - Qt::NoFocus - - - numbers - - - - - - - false - - - Qt::NoFocus - - - symbols - - - - - - - - - - - - - - - 0 - 0 - - - - - 100 - 101 - - - - Hidden Volume settings - - - false - - - - - - - 0 - 0 - - - - - - - Slot under which hidden volume information will be stored - - - - Hidden volume slot 1 - - - - - Hidden volume slot 2 - - - - - Hidden volume slot 3 - - - - - Hidden volume slot 4 - - - - - - - - SD card information - - - Qt::AlignCenter - - - - - - - QFrame::Box - - - - - - Qt::StrongFocus - - - Storage capacity: %1GB - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Unit: - - - - - - - - - - Use this as hidden volume size unit - - - % - - - - - - - Use this as hidden volume size unit - - - MB - - - - - - - Use this as hidden volume size unit - - - GB - - - - - - - - - - - - Start at %1 of SD size: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 999999999999999983222784.000000000000000 - - - - - - - - - - - End at %1 of SD size: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 99999999999999997748809823456034029568.000000000000000 - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Size will be rounded down to integral percent of total storage size (%1MB) - - - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - l_top_instructions - l_instructions - HVPasswordEdit - HVPasswordEdit_2 - ShowPasswordCheckBox - comboBox - l_sd_size - rd_percent - rd_MB - rd_GB - StartBlockSpin - EndBlockSpin - - - - - - diff --git a/nitrokeyapp/ui/stick20lockfirmwaredialog.ui b/nitrokeyapp/ui/stick20lockfirmwaredialog.ui deleted file mode 100644 index d5618607..00000000 --- a/nitrokeyapp/ui/stick20lockfirmwaredialog.ui +++ /dev/null @@ -1,141 +0,0 @@ - - - stick20LockFirmwareDialog - - - - 0 - 0 - 315 - 229 - - - - - 0 - 0 - - - - Lock Firmware - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - false - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - 16 - 75 - true - - - - Lock Firmware - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - <html><head/><body><p>When you select &quot;OK&quot; the stick lock the firmware and close the hardware debug port.This disables any external hardware access to the data in the device (processor).</p><p>There is no way back! </p><p>After this you can't update the firmware.</p></body></html> - - - true - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - - buttonBox - accepted() - stick20LockFirmwareDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - stick20LockFirmwareDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/ui/stick20responsedialog.ui b/nitrokeyapp/ui/stick20responsedialog.ui deleted file mode 100644 index 48c1ee85..00000000 --- a/nitrokeyapp/ui/stick20responsedialog.ui +++ /dev/null @@ -1,162 +0,0 @@ - - - Stick20ResponseDialog - - - Qt::ApplicationModal - - - - 0 - 0 - 342 - 123 - - - - - 0 - 0 - - - - Progress - - - - :/icons/icon_NK.svg - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - QLayout::SetFixedSize - - - - - - - - 11 - 50 - false - - - - HeaderLabel - - - Qt::PlainText - - - Qt::AlignCenter - - - - - - - - - LabelProgressWheel - - - Qt::AlignCenter - - - - - - - - 13 - - - - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - 24 - - - - - - - - - - Courier 10 Pitch - 10 - 50 - false - false - - - - TextLabel - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - - - HeaderText - customContextMenuRequested(QPoint) - Stick20ResponseDialog - open() - - - 195 - 29 - - - 190 - 103 - - - - - diff --git a/nitrokeyapp/ui/stick20updatedialog.ui b/nitrokeyapp/ui/stick20updatedialog.ui deleted file mode 100644 index f37800a1..00000000 --- a/nitrokeyapp/ui/stick20updatedialog.ui +++ /dev/null @@ -1,157 +0,0 @@ - - - UpdateDialog - - - - 0 - 0 - 354 - 252 - - - - Firmware update - - - - :/icons/icon_NK.svg:/icons/icon_NK.svg - - - - - - - 0 - 0 - - - - false - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - 16 - 75 - true - - - - Firmware update - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - <html><head/><body><p>When you select &quot;OK&quot; the device enters the <br/>firmware update mode. There is no way back!<br/>Please read the <a href="https://www.nitrokey.com/en/doc/firmware-update-storage"><span style=" text-decoration: underline; color:#0000ff;">documentation </span></a>how to <br/>update the firmware.</p><p>Continue entering the firmware update mode?</p><p><br/></p></body></html> - - - true - - - true - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - - buttonBox - accepted() - UpdateDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - UpdateDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/nitrokeyapp/ui/welcome_tab.ui b/nitrokeyapp/ui/welcome_tab.ui index e7eba89b..37418855 100644 --- a/nitrokeyapp/ui/welcome_tab.ui +++ b/nitrokeyapp/ui/welcome_tab.ui @@ -145,7 +145,7 @@ - icons/s_icon_Logo_App.png + icons/s_icon_Logo_App.png true diff --git a/nitrokeyapp/ui_loader.py b/nitrokeyapp/ui_loader.py new file mode 100644 index 00000000..07e286c6 --- /dev/null +++ b/nitrokeyapp/ui_loader.py @@ -0,0 +1,79 @@ +from typing import Dict, Optional + +from PySide6 import QtWidgets +from PySide6.QtUiTools import QUiLoader + + +# taken/inspired with many thanks from: https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8 +class UiLoader(QUiLoader): + """ + Subclass :class:`~PySide6.QtUiTools.QUiLoader` to create the user interface + in a base instance. + Unlike :class:`~PySide6.QtUiTools.QUiLoader` itself this class does not + create a new instance of the top-level widget, but creates the user + interface in an existing instance of the top-level class. + This mimics the behaviour of :func:`PyQt4.uic.loadUi`. + """ + + def __init__( + self, + baseinstance: Optional[QtWidgets.QWidget], + customWidgets: Optional[Dict[str, QtWidgets.QWidget]] = None, + ): + """ + Create a loader for the given ``baseinstance``. + The user interface is created in ``baseinstance``, which must be an + instance of the top-level class in the user interface to load, or a + subclass thereof. + ``customWidgets`` is a dictionary mapping from class name to class object + for widgets that you've promoted in the Qt Designer interface. Usually, + this should be done by calling registerCustomWidget on the QUiLoader. + ``parent`` is the parent object of this loader. + """ + + QUiLoader.__init__(self, baseinstance) + self.baseinstance = baseinstance + self.customWidgets = customWidgets or {} + + def createWidget( + self, + class_name: str, + parent: Optional[QtWidgets.QWidget] = None, + name: str = "", + ) -> QtWidgets.QWidget: + """ + Function that is called for each widget defined in ui file, + overridden here to populate baseinstance instead. + """ + if parent is None and self.baseinstance: + # supposed to create the top-level widget, return the base instance + # instead + return self.baseinstance + + else: + if class_name in self.availableWidgets(): + # create a new widget for child widgets + widget = QUiLoader.createWidget(self, class_name, parent, name) + else: + try: + # @fixme? in fact QWidget is callable + widget = self.customWidgets[class_name](parent) # type: ignore + + except (TypeError, KeyError): + raise Exception( + "No custom widget " + + class_name + + " found in customWidgets param of UiLoader __init__." + ) + + if self.baseinstance: + # set an attribute for the new child widget on the base + # instance, just like PyQt4.uic.loadUi does. + + setattr(self.baseinstance, name, widget) + + # this outputs the various widget names, e.g. + # sampleGraphicsView, dockWidget, samplesTableView etc. + # print(name) + + return widget diff --git a/nitrokeyapp/update.py b/nitrokeyapp/update.py index c2502890..235f4e06 100644 --- a/nitrokeyapp/update.py +++ b/nitrokeyapp/update.py @@ -21,8 +21,8 @@ from pynitrokey.nk3.device import Nitrokey3Device from pynitrokey.nk3.updates import Updater, UpdateUi from pynitrokey.nk3.utils import Version -from PyQt5 import QtWidgets -from PyQt5.QtCore import QCoreApplication +from PySide6 import QtWidgets +from PySide6.QtCore import QCoreApplication from nitrokeyapp.information_box import InfoBox @@ -94,16 +94,17 @@ def abort_downgrade(self, current: Version, image: Version) -> Exception: def confirm_download(self, current: Optional[Version], new: Version) -> None: confirm_download_msgBox = QtWidgets.QMessageBox(self.overview_tab) - confirm_download_msgBox.setIcon(QtWidgets.QMessageBox.Information) + confirm_download_msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information) confirm_download_msgBox.setText( f"Do you want to download the firmware version {new}?" ) confirm_download_msgBox.setWindowTitle("Nitrokey 3 Firmware Update") confirm_download_msgBox.setStandardButtons( - QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel + QtWidgets.QMessageBox.StandardButton.Ok + | QtWidgets.QMessageBox.StandardButton.Cancel ) returnValue = confirm_download_msgBox.exec() - if returnValue == QtWidgets.QMessageBox.Cancel: + if returnValue == QtWidgets.QMessageBox.StandardButton.Cancel: logger.info("Cancel clicked (confirm download)") logger.info( "Firmware Download cancelled by user in the (confirm download) dialog" @@ -111,25 +112,26 @@ def confirm_download(self, current: Optional[Version], new: Version) -> None: raise self.abort( "Update cancelled by user in the (confirm download) dialog" ) - elif returnValue == QtWidgets.QMessageBox.Ok: + elif returnValue == QtWidgets.QMessageBox.StandardButton.Ok: logger.info("OK clicked (confirm download)") def confirm_update(self, current: Optional[Version], new: Version) -> None: confirm_update_msgBox = QtWidgets.QMessageBox(self.overview_tab) - confirm_update_msgBox.setIcon(QtWidgets.QMessageBox.Information) + confirm_update_msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information) confirm_update_msgBox.setText( "Please do not remove the Nitrokey 3 or insert any other Nitrokey 3 devices during the update. Doing so may damage the Nitrokey 3. Do you want to perform the firmware update now?" ) confirm_update_msgBox.setWindowTitle("Nitrokey 3 Firmware Update") confirm_update_msgBox.setStandardButtons( - QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel + QtWidgets.QMessageBox.StandardButton.Ok + | QtWidgets.QMessageBox.StandardButton.Cancel ) returnValue = confirm_update_msgBox.exec() - if returnValue == QtWidgets.QMessageBox.Cancel: + if returnValue == QtWidgets.QMessageBox.StandardButton.Cancel: logger.info("Cancel clicked (confirm update)") logger.info("Update cancelled by user in the (confirm update) dialog") raise self.abort("Update cancelled by user in the (confirm update) dialog") - elif returnValue == QtWidgets.QMessageBox.Ok: + elif returnValue == QtWidgets.QMessageBox.StandardButton.Ok: logger.info("OK clicked (confirm update)") self.info_frame.set_text( "Please touch the Nitrokey 3 until it stops flashing/glowing and then wait a few seconds.." @@ -138,44 +140,47 @@ def confirm_update(self, current: Optional[Version], new: Version) -> None: def confirm_update_same_version(self, version: Version) -> None: confirm_update_same_version_msgBox = QtWidgets.QMessageBox(self.overview_tab) - confirm_update_same_version_msgBox.setIcon(QtWidgets.QMessageBox.Information) + confirm_update_same_version_msgBox.setIcon( + QtWidgets.QMessageBox.Icon.Information + ) confirm_update_same_version_msgBox.setText( "The version of the firmware image is the same as on the device. Do you want to continue anyway?" ) confirm_update_same_version_msgBox.setWindowTitle("Nitrokey 3 Firmware Update") confirm_update_same_version_msgBox.setStandardButtons( - QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel + QtWidgets.QMessageBox.StandardButton.Ok + | QtWidgets.QMessageBox.StandardButton.Cancel ) returnValue = confirm_update_same_version_msgBox.exec() - if returnValue == QtWidgets.QMessageBox.Cancel: + if returnValue == QtWidgets.QMessageBox.StandardButton.Cancel: logger.info("Cancel clicked (confirm same version)") logger.info("Update cancelled by user in the (confirm same version) dialog") # raise Abort() raise self.abort( "Update cancelled by user in the (confirm same version) dialog" ) - elif returnValue == QtWidgets.QMessageBox.Ok: + elif returnValue == QtWidgets.QMessageBox.StandardButton.Ok: logger.info("OK clicked (confirm same version)") def confirm_extra_information(self, txt: List[str]) -> None: # if txt: # logger.info("\n".join(txt)) # confirm_extra_information_msgBox QMessageBox(= QtWidgets.QMessageBox() - # confirm_extra_information_msgBox.setIcon(QtWidgets.QMessageBox.Information) + # confirm_extra_information_msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information) # confirm_extra_information_msgBox.setText( # "Have you read these information? Do you want to continue?" # ) # confirm_extra_information_msgBox.setWindowTitle("Nitrokey 3 Firmware Update") # confirm_extra_information_msgBox.setStandardButtons( - # QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel + # QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel # ) # returnValue = confirm_extra_information_msgBox.exec() - # if returnValue == QtWidgets.QMessageBox.Cancel: + # if returnValue == QtWidgets.QMessageBox.StandardButton.Cancel: # logger.info("Cancel clicked (confirm extra information)") # logger.info("Update cancelled by user in the (confirm extra information) dialog") # # raise Abort() # raise self.abort("Update cancelled by user in the (confirm extra information) dialog") - # elif returnValue == QtWidgets.QMessageBox.Ok: + # elif returnValue == QtWidgets.QMessageBox.StandardButton.Ok: # logger.info("OK clicked (confirm extra information)") # TODO: implement pass diff --git a/nitrokeyapp/welcome_tab.py b/nitrokeyapp/welcome_tab.py index c5c30d7d..fdaa51ae 100644 --- a/nitrokeyapp/welcome_tab.py +++ b/nitrokeyapp/welcome_tab.py @@ -3,13 +3,12 @@ from urllib.request import urlopen from pynitrokey.nk3.utils import Version -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QWidget +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QWidget from nitrokeyapp import __version__ from nitrokeyapp.logger import save_log from nitrokeyapp.qt_utils_mix_in import QtUtilsMixIn -from nitrokeyapp.ui.welcome_tab import Ui_WelcomeTab class WelcomeTab(QtUtilsMixIn, QWidget): @@ -19,8 +18,8 @@ def __init__(self, parent: Optional[QWidget], log_file: str) -> None: self.log_file = log_file - self.ui = Ui_WelcomeTab() - self.ui.setupUi(self) + # self.ui === self -> this tricks mypy due to monkey-patching self + self.ui = self.load_ui("welcome_tab.ui", self) self.ui.buttonSaveLog.pressed.connect(self.save_log) self.ui.VersionNr.setText(__version__) self.ui.CheckUpdate.pressed.connect(self.check_update) @@ -46,6 +45,6 @@ def check_update(self) -> None: else: self.ui.CheckUpdate.setText("App is up to date") - @pyqtSlot() + @Slot() def save_log(self) -> None: save_log(self.log_file, self) diff --git a/nitrokeyapp/worker.py b/nitrokeyapp/worker.py index b2e47435..fda12023 100644 --- a/nitrokeyapp/worker.py +++ b/nitrokeyapp/worker.py @@ -1,7 +1,7 @@ from contextlib import contextmanager from typing import Generator -from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot +from PySide6.QtCore import QObject, Signal, Slot # TODO: DeviceJob # - connection management @@ -9,12 +9,12 @@ class Job(QObject): - finished = pyqtSignal() + finished = Signal() # standard UI - error = pyqtSignal(str) - start_touch = pyqtSignal() - stop_touch = pyqtSignal() + error = Signal(str) + start_touch = Signal() + stop_touch = Signal() def __init__(self) -> None: super().__init__() @@ -24,11 +24,11 @@ def __init__(self) -> None: def run(self) -> None: pass - @pyqtSlot() + @Slot() def cleanup(self) -> None: pass - @pyqtSlot(str) + @Slot(str) def trigger_error(self, msg: str) -> None: self.error.emit(msg) self.finished.emit() @@ -50,10 +50,10 @@ def touch_prompt(self) -> Generator[None, None, None]: class Worker(QObject): # standard UI - busy_state_changed = pyqtSignal(bool) - error = pyqtSignal(str) - start_touch = pyqtSignal() - stop_touch = pyqtSignal() + busy_state_changed = Signal(bool) + error = Signal(str) + start_touch = Signal() + stop_touch = Signal() def run(self, job: Job) -> None: self.busy_state_changed.emit(True) diff --git a/poetry.lock b/poetry.lock index c54cf0ab..59cd18b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -436,34 +436,34 @@ files = [ [[package]] name = "cryptography" -version = "39.0.2" +version = "41.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "cryptography-39.0.2-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:2725672bb53bb92dc7b4150d233cd4b8c59615cd8288d495eaa86db00d4e5c06"}, - {file = "cryptography-39.0.2-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:23df8ca3f24699167daf3e23e51f7ba7334d504af63a94af468f468b975b7dd7"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:eb40fe69cfc6f5cdab9a5ebd022131ba21453cf7b8a7fd3631f45bbf52bed612"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc0521cce2c1d541634b19f3ac661d7a64f9555135e9d8af3980965be717fd4a"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffd394c7896ed7821a6d13b24657c6a34b6e2650bd84ae063cf11ccffa4f1a97"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:e8a0772016feeb106efd28d4a328e77dc2edae84dfbac06061319fdb669ff828"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8f35c17bd4faed2bc7797d2a66cbb4f986242ce2e30340ab832e5d99ae60e011"}, - {file = "cryptography-39.0.2-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b49a88ff802e1993b7f749b1eeb31134f03c8d5c956e3c125c75558955cda536"}, - {file = "cryptography-39.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c682e736513db7d04349b4f6693690170f95aac449c56f97415c6980edef5"}, - {file = "cryptography-39.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:d7d84a512a59f4412ca8549b01f94be4161c94efc598bf09d027d67826beddc0"}, - {file = "cryptography-39.0.2-cp36-abi3-win32.whl", hash = "sha256:c43ac224aabcbf83a947eeb8b17eaf1547bce3767ee2d70093b461f31729a480"}, - {file = "cryptography-39.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:788b3921d763ee35dfdb04248d0e3de11e3ca8eb22e2e48fef880c42e1f3c8f9"}, - {file = "cryptography-39.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d15809e0dbdad486f4ad0979753518f47980020b7a34e9fc56e8be4f60702fac"}, - {file = "cryptography-39.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:50cadb9b2f961757e712a9737ef33d89b8190c3ea34d0fb6675e00edbe35d074"}, - {file = "cryptography-39.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:103e8f7155f3ce2ffa0049fe60169878d47a4364b277906386f8de21c9234aa1"}, - {file = "cryptography-39.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6236a9610c912b129610eb1a274bdc1350b5df834d124fa84729ebeaf7da42c3"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e944fe07b6f229f4c1a06a7ef906a19652bdd9fd54c761b0ff87e83ae7a30354"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:35d658536b0a4117c885728d1a7032bdc9a5974722ae298d6c533755a6ee3915"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:30b1d1bfd00f6fc80d11300a29f1d8ab2b8d9febb6ed4a38a76880ec564fae84"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e029b844c21116564b8b61216befabca4b500e6816fa9f0ba49527653cae2108"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fa507318e427169ade4e9eccef39e9011cdc19534f55ca2f36ec3f388c1f70f3"}, - {file = "cryptography-39.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8bc0008ef798231fac03fe7d26e82d601d15bd16f3afaad1c6113771566570f3"}, - {file = "cryptography-39.0.2.tar.gz", hash = "sha256:bc5b871e977c8ee5a1bbc42fa8d19bcc08baf0c51cbf1586b0e87a2694dde42f"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, + {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, + {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, + {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, ] [package.dependencies] @@ -472,12 +472,12 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "check-manifest", "mypy", "ruff", "types-pytz", "types-requests"] -sdist = ["setuptools-rust (>=0.11.4)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist", "pytz"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] -tox = ["tox"] [[package]] name = "deepmerge" @@ -510,13 +510,13 @@ gmpy2 = ["gmpy2"] [[package]] name = "fastjsonschema" -version = "2.16.3" +version = "2.17.1" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.16.3-py3-none-any.whl", hash = "sha256:04fbecc94300436f628517b05741b7ea009506ce8f946d40996567c669318490"}, - {file = "fastjsonschema-2.16.3.tar.gz", hash = "sha256:4a30d6315a68c253cfa8f963b9697246315aa3db89f98b97235e345dedfb0b8e"}, + {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"}, + {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"}, ] [package.extras] @@ -569,62 +569,6 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.11.0,<2.12.0" pyflakes = ">=3.1.0,<3.2.0" -[[package]] -name = "frozendict" -version = "2.3.9" -description = "A simple immutable dictionary" -optional = false -python-versions = ">=3.6" -files = [ - {file = "frozendict-2.3.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb949eaf12d53b1e4034865516c6a1945d6d6f1cb102fa7417c017d7cefcc7a7"}, - {file = "frozendict-2.3.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b57205e9ca00733064e9abfc5b2ced46d65370e5451502a17162d42a7d527d0"}, - {file = "frozendict-2.3.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1262df1e9bea434d5859398522e8d8e393721ea6a3a1ccb0e36a27022a52fa5e"}, - {file = "frozendict-2.3.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:561ddd000da66360142a81996f0ae5b806c267868e77bae2f5ab459334bf6b89"}, - {file = "frozendict-2.3.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a82ffff413d70eab71b9cfcf6f9fb9ad7a1d414a1d664470a214771c332d3c8"}, - {file = "frozendict-2.3.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c04aa367a21bd3af396b64b2021ea13325faa11b832be77791a987dda3fa543c"}, - {file = "frozendict-2.3.9-cp310-cp310-win_amd64.whl", hash = "sha256:48e9a94e4beba7dbb880dab9d33b656ef3a608da3d43105335225b06cb6ae139"}, - {file = "frozendict-2.3.9-cp310-cp310-win_arm64.whl", hash = "sha256:a9331ddde2cdf4fc7d5ad09c6078643517663a3028346cc765fc4145be9d8dd2"}, - {file = "frozendict-2.3.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:38f2f43b44d7d3ac4924116017578ec81812ba385c8f710abda58617eae20afe"}, - {file = "frozendict-2.3.9-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45d517af1aaede930a7b22b21ff80c09f22bd296a902f681ca58fd5acb5dd33b"}, - {file = "frozendict-2.3.9-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d0dc4c36c0342c5748aab2fcca0c07f33876e41caf62fbdfeac951c2a3bcb5"}, - {file = "frozendict-2.3.9-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9c63147ce90b2b7e45d3f0923063d624892ed0c7a13fa95787e57dbb27b376a7"}, - {file = "frozendict-2.3.9-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9286378eecfe993b803842e2c14c65efd1b12e99e3ac5c25d05661630cedff6d"}, - {file = "frozendict-2.3.9-cp36-cp36m-win_amd64.whl", hash = "sha256:7e89b56f3c13749fd1bf8d20325a572063b5ad8dbf880e7881b8eb8cf41e1743"}, - {file = "frozendict-2.3.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:56117a0104ce68445d6856b5585133f667ae04098f0dcecd7786a510dc121818"}, - {file = "frozendict-2.3.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45071ad048ca6feb4b7a90383aa64377d130b5245bffdd8204debb4f5e9ccf0a"}, - {file = "frozendict-2.3.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75b02cb3473b0da9003b3d71ef8fc76bb97092543035a47000a63352cab2c125"}, - {file = "frozendict-2.3.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ff2e07b94abed60ef233117d5ffc6cac6353c6856fbba898b12a556e5698e440"}, - {file = "frozendict-2.3.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e135a2dd22cf668ce45cb697522497ba2e2bd9cf6c239d06856b69eeae0a557b"}, - {file = "frozendict-2.3.9-cp37-cp37m-win_amd64.whl", hash = "sha256:d3de16b88214874ac1caa1c9527441bdfa0c20bce809d2efbffb307a05f5fafd"}, - {file = "frozendict-2.3.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fa04e7561d10c2feef423963818e43bc24a0fb65f5ea21ffb00f11ae8e6129e3"}, - {file = "frozendict-2.3.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8ce979138e0d5f04e879c9f732a7deba5bf3d55708e1f02533b8301326e1ffda"}, - {file = "frozendict-2.3.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:525da194ad0407c97d23339c19200fa0b464ff16ca2624f7adfc95ec1da17a42"}, - {file = "frozendict-2.3.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bff7ff522ee2a53103a4ae848826d9212a0d61a025562eaac245e93a6aa6285"}, - {file = "frozendict-2.3.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094d43bff2f65371734832385d1a457c5da10399e638e01f85dd71a9e12b9408"}, - {file = "frozendict-2.3.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9c69650ed54670d73652b0880229c8356defbdc4663cf3cb5f844169c7c71666"}, - {file = "frozendict-2.3.9-cp38-cp38-win_amd64.whl", hash = "sha256:21af4b67c1bb7075b5a2e5c1d128f69331ee405bd34028416d9106a0ef6c84eb"}, - {file = "frozendict-2.3.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06b586394d8e654558fcf2e79ac8511a47d484de8e55a20ecdc6667d87ec1730"}, - {file = "frozendict-2.3.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0196d6f50db96b26aa4144782930caf019aabf68c368b66c79490552128e3472"}, - {file = "frozendict-2.3.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53fb48e8929309a62f1402f0feb2db76a80faa45b69d9cf23bd1e42de8730c62"}, - {file = "frozendict-2.3.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac297f91e101b89514e0dbe8a70c3f6a6185107d8306c3b800440bcdab1bd853"}, - {file = "frozendict-2.3.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bd12f907e378a9796d449aa292607672ba59e6ba3153d7bfa1d891c0b0a1160b"}, - {file = "frozendict-2.3.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95f2f6def297eaa00e8aff4e72cc251b91c7c318507f15643c8f4b0647248da2"}, - {file = "frozendict-2.3.9-cp39-cp39-win_amd64.whl", hash = "sha256:f2d2146ae474e3478263932d363128b1bab6e7ddd9cd79fd142247a15c710f76"}, - {file = "frozendict-2.3.9-cp39-cp39-win_arm64.whl", hash = "sha256:87f6cf5513d0920836df067ae79296e3d52be88abcee1629b7010ed2af1ee121"}, - {file = "frozendict-2.3.9-py3-none-any.whl", hash = "sha256:ecabff354ec0ea070770f6556e6e23deaca2053e18322163fce76cdd93a3845f"}, - {file = "frozendict-2.3.9.tar.gz", hash = "sha256:8c4771eec34a8a47a62d3520465e7ac2d8f583d8ed99fea8dbba4218756e9360"}, -] - -[[package]] -name = "future" -version = "0.18.3" -description = "Clean single-source support for Python 3 and 2" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, -] - [[package]] name = "hexdump" version = "3.3" @@ -720,6 +664,25 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] +[[package]] +name = "importlib-metadata" +version = "7.0.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + [[package]] name = "importlib-resources" version = "6.1.1" @@ -764,20 +727,17 @@ sortedcontainers = ">=2.0,<3.0" [[package]] name = "isort" -version = "5.12.0" +version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "jinja2" @@ -796,6 +756,23 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "lark" +version = "1.1.8" +description = "a modern parsing library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "lark-1.1.8-py3-none-any.whl", hash = "sha256:7d2c221a66a8165f3f81aacb958d26033d40d972fdb70213ab0a2e0627e29c86"}, + {file = "lark-1.1.8.tar.gz", hash = "sha256:7ef424db57f59c1ffd6f0d4c2b705119927f566b68c0fe1942dddcc0e44391a5"}, +] + +[package.extras] +atomic-cache = ["atomicwrites"] +interegular = ["interegular (>=0.3.1,<0.4.0)"] +nearley = ["js2py"] +regex = ["regex"] + [[package]] name = "lark-parser" version = "0.7.8" @@ -1072,6 +1049,27 @@ files = [ fast = ["fastnumbers (>=2.0.0)"] icu = ["PyICU (>=1.0.0)"] +[[package]] +name = "nethsm" +version = "1.0.0" +description = "Python Library to manage NetHSM(s)." +optional = false +python-versions = ">=3.9" +files = [ + {file = "nethsm-1.0.0-py3-none-any.whl", hash = "sha256:bc55a7619c15c5a148a0e9050930e5f1d8e027df846f6136b90fc27a754aecc4"}, + {file = "nethsm-1.0.0.tar.gz", hash = "sha256:b0436e49d038a58b7cbf6c3646f0e47102d808ff55d2f64e7563a590d062dffa"}, +] + +[package.dependencies] +certifi = "*" +cryptography = ">=41.0" +python-dateutil = "*" +typing_extensions = ">=4.3.0,<4.4.0" +urllib3 = ">=2.0,<2.1" + +[package.extras] +dev = ["black (>=22.1.0,<23)", "cryptography", "docker", "flake8", "flit (>=3.2,<4)", "ipython", "isort", "mypy (>=1.4,<1.5)", "pycryptodome", "pyinstaller (==5.9.0)", "pyinstaller-versionfile (==2.1.1)", "pytest", "pytest-cov", "pytest-reporter-html1", "pyyaml", "requests", "types-python-dateutil", "types-requests"] + [[package]] name = "nkdfu" version = "0.2" @@ -1116,13 +1114,13 @@ files = [ [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] @@ -1138,13 +1136,13 @@ files = [ [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, - {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -1201,27 +1199,27 @@ files = [ [[package]] name = "psutil" -version = "5.9.6" +version = "5.9.7" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, - {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, - {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, - {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, - {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, - {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, - {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, - {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, - {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, - {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, + {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"}, + {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"}, + {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"}, + {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"}, + {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"}, + {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"}, + {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"}, + {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"}, + {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"}, + {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"}, ] [package.extras] @@ -1251,44 +1249,43 @@ files = [ [[package]] name = "pycryptodome" -version = "3.17" +version = "3.18.0" description = "Cryptographic library for Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "pycryptodome-3.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:2c5631204ebcc7ae33d11c43037b2dafe25e2ab9c1de6448eb6502ac69c19a56"}, - {file = "pycryptodome-3.17-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:04779cc588ad8f13c80a060b0b1c9d1c203d051d8a43879117fe6b8aaf1cd3fa"}, - {file = "pycryptodome-3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f812d58c5af06d939b2baccdda614a3ffd80531a26e5faca2c9f8b1770b2b7af"}, - {file = "pycryptodome-3.17-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:9453b4e21e752df8737fdffac619e93c9f0ec55ead9a45df782055eb95ef37d9"}, - {file = "pycryptodome-3.17-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:121d61663267f73692e8bde5ec0d23c9146465a0d75cad75c34f75c752527b01"}, - {file = "pycryptodome-3.17-cp27-cp27m-win32.whl", hash = "sha256:ba2d4fcb844c6ba5df4bbfee9352ad5352c5ae939ac450e06cdceff653280450"}, - {file = "pycryptodome-3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:87e2ca3aa557781447428c4b6c8c937f10ff215202ab40ece5c13a82555c10d6"}, - {file = "pycryptodome-3.17-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f44c0d28716d950135ff21505f2c764498eda9d8806b7c78764165848aa419bc"}, - {file = "pycryptodome-3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5a790bc045003d89d42e3b9cb3cc938c8561a57a88aaa5691512e8540d1ae79c"}, - {file = "pycryptodome-3.17-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:d086d46774e27b280e4cece8ab3d87299cf0d39063f00f1e9290d096adc5662a"}, - {file = "pycryptodome-3.17-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:5587803d5b66dfd99e7caa31ed91fba0fdee3661c5d93684028ad6653fce725f"}, - {file = "pycryptodome-3.17-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:e7debd9c439e7b84f53be3cf4ba8b75b3d0b6e6015212355d6daf44ac672e210"}, - {file = "pycryptodome-3.17-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ca1ceb6303be1282148f04ac21cebeebdb4152590842159877778f9cf1634f09"}, - {file = "pycryptodome-3.17-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:dc22cc00f804485a3c2a7e2010d9f14a705555f67020eb083e833cabd5bd82e4"}, - {file = "pycryptodome-3.17-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80ea8333b6a5f2d9e856ff2293dba2e3e661197f90bf0f4d5a82a0a6bc83a626"}, - {file = "pycryptodome-3.17-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c133f6721fba313722a018392a91e3c69d3706ae723484841752559e71d69dc6"}, - {file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:333306eaea01fde50a73c4619e25631e56c4c61bd0fb0a2346479e67e3d3a820"}, - {file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:1a30f51b990994491cec2d7d237924e5b6bd0d445da9337d77de384ad7f254f9"}, - {file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:909e36a43fe4a8a3163e9c7fc103867825d14a2ecb852a63d3905250b308a4e5"}, - {file = "pycryptodome-3.17-cp35-abi3-win32.whl", hash = "sha256:a3228728a3808bc9f18c1797ec1179a0efb5068c817b2ffcf6bcd012494dffb2"}, - {file = "pycryptodome-3.17-cp35-abi3-win_amd64.whl", hash = "sha256:9ec565e89a6b400eca814f28d78a9ef3f15aea1df74d95b28b7720739b28f37f"}, - {file = "pycryptodome-3.17-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:e1819b67bcf6ca48341e9b03c2e45b1c891fa8eb1a8458482d14c2805c9616f2"}, - {file = "pycryptodome-3.17-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:f8e550caf52472ae9126953415e4fc554ab53049a5691c45b8816895c632e4d7"}, - {file = "pycryptodome-3.17-pp27-pypy_73-win32.whl", hash = "sha256:afbcdb0eda20a0e1d44e3a1ad6d4ec3c959210f4b48cabc0e387a282f4c7deb8"}, - {file = "pycryptodome-3.17-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a74f45aee8c5cc4d533e585e0e596e9f78521e1543a302870a27b0ae2106381e"}, - {file = "pycryptodome-3.17-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38bbd6717eac084408b4094174c0805bdbaba1f57fc250fd0309ae5ec9ed7e09"}, - {file = "pycryptodome-3.17-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f68d6c8ea2974a571cacb7014dbaada21063a0375318d88ac1f9300bc81e93c3"}, - {file = "pycryptodome-3.17-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8198f2b04c39d817b206ebe0db25a6653bb5f463c2319d6f6d9a80d012ac1e37"}, - {file = "pycryptodome-3.17-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a232474cd89d3f51e4295abe248a8b95d0332d153bf46444e415409070aae1e"}, - {file = "pycryptodome-3.17-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4992ec965606054e8326e83db1c8654f0549cdb26fce1898dc1a20bc7684ec1c"}, - {file = "pycryptodome-3.17-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53068e33c74f3b93a8158dacaa5d0f82d254a81b1002e0cd342be89fcb3433eb"}, - {file = "pycryptodome-3.17-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:74794a2e2896cd0cf56fdc9db61ef755fa812b4a4900fa46c49045663a92b8d0"}, - {file = "pycryptodome-3.17.tar.gz", hash = "sha256:bce2e2d8e82fcf972005652371a3e8731956a0c1fbb719cc897943b3695ad91b"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:d1497a8cd4728db0e0da3c304856cb37c0c4e3d0b36fcbabcc1600f18504fc54"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:928078c530da78ff08e10eb6cada6e0dff386bf3d9fa9871b4bbc9fbc1efe024"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:157c9b5ba5e21b375f052ca78152dd309a09ed04703fd3721dce3ff8ecced148"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:d20082bdac9218649f6abe0b885927be25a917e29ae0502eaf2b53f1233ce0c2"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:e8ad74044e5f5d2456c11ed4cfd3e34b8d4898c0cb201c4038fe41458a82ea27"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-win32.whl", hash = "sha256:62a1e8847fabb5213ccde38915563140a5b338f0d0a0d363f996b51e4a6165cf"}, + {file = "pycryptodome-3.18.0-cp27-cp27m-win_amd64.whl", hash = "sha256:16bfd98dbe472c263ed2821284118d899c76968db1a6665ade0c46805e6b29a4"}, + {file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7a3d22c8ee63de22336679e021c7f2386f7fc465477d59675caa0e5706387944"}, + {file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:78d863476e6bad2a592645072cc489bb90320972115d8995bcfbee2f8b209918"}, + {file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:b6a610f8bfe67eab980d6236fdc73bfcdae23c9ed5548192bb2d530e8a92780e"}, + {file = "pycryptodome-3.18.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:422c89fd8df8a3bee09fb8d52aaa1e996120eafa565437392b781abec2a56e14"}, + {file = "pycryptodome-3.18.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:9ad6f09f670c466aac94a40798e0e8d1ef2aa04589c29faa5b9b97566611d1d1"}, + {file = "pycryptodome-3.18.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:53aee6be8b9b6da25ccd9028caf17dcdce3604f2c7862f5167777b707fbfb6cb"}, + {file = "pycryptodome-3.18.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:10da29526a2a927c7d64b8f34592f461d92ae55fc97981aab5bbcde8cb465bb6"}, + {file = "pycryptodome-3.18.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f21efb8438971aa16924790e1c3dba3a33164eb4000106a55baaed522c261acf"}, + {file = "pycryptodome-3.18.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4944defabe2ace4803f99543445c27dd1edbe86d7d4edb87b256476a91e9ffa4"}, + {file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:51eae079ddb9c5f10376b4131be9589a6554f6fd84f7f655180937f611cd99a2"}, + {file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:83c75952dcf4a4cebaa850fa257d7a860644c70a7cd54262c237c9f2be26f76e"}, + {file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:957b221d062d5752716923d14e0926f47670e95fead9d240fa4d4862214b9b2f"}, + {file = "pycryptodome-3.18.0-cp35-abi3-win32.whl", hash = "sha256:795bd1e4258a2c689c0b1f13ce9684fa0dd4c0e08680dcf597cf9516ed6bc0f3"}, + {file = "pycryptodome-3.18.0-cp35-abi3-win_amd64.whl", hash = "sha256:b1d9701d10303eec8d0bd33fa54d44e67b8be74ab449052a8372f12a66f93fb9"}, + {file = "pycryptodome-3.18.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:cb1be4d5af7f355e7d41d36d8eec156ef1382a88638e8032215c215b82a4b8ec"}, + {file = "pycryptodome-3.18.0-pp27-pypy_73-win32.whl", hash = "sha256:fc0a73f4db1e31d4a6d71b672a48f3af458f548059aa05e83022d5f61aac9c08"}, + {file = "pycryptodome-3.18.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f022a4fd2a5263a5c483a2bb165f9cb27f2be06f2f477113783efe3fe2ad887b"}, + {file = "pycryptodome-3.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:363dd6f21f848301c2dcdeb3c8ae5f0dee2286a5e952a0f04954b82076f23825"}, + {file = "pycryptodome-3.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12600268763e6fec3cefe4c2dcdf79bde08d0b6dc1813887e789e495cb9f3403"}, + {file = "pycryptodome-3.18.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4604816adebd4faf8810782f137f8426bf45fee97d8427fa8e1e49ea78a52e2c"}, + {file = "pycryptodome-3.18.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:01489bbdf709d993f3058e2996f8f40fee3f0ea4d995002e5968965fa2fe89fb"}, + {file = "pycryptodome-3.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3811e31e1ac3069988f7a1c9ee7331b942e605dfc0f27330a9ea5997e965efb2"}, + {file = "pycryptodome-3.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4b967bb11baea9128ec88c3d02f55a3e338361f5e4934f5240afcb667fdaec"}, + {file = "pycryptodome-3.18.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:9c8eda4f260072f7dbe42f473906c659dcbadd5ae6159dfb49af4da1293ae380"}, + {file = "pycryptodome-3.18.0.tar.gz", hash = "sha256:c9adee653fc882d98956e33ca2c1fb582e23a8af7ac82fee75bd6113c55a0413"}, ] [[package]] @@ -1375,29 +1372,28 @@ PyYAML = "*" [[package]] name = "pylink-square" -version = "0.14.3" +version = "1.1.0" description = "Python interface for SEGGER J-Link." optional = false python-versions = "*" files = [ - {file = "pylink-square-0.14.3.tar.gz", hash = "sha256:1c403c00b15d60e28721370fcbfeb9a558f4971daff0a707ae6ccc5d2acb2e2f"}, - {file = "pylink_square-0.14.3-py2.py3-none-any.whl", hash = "sha256:ef0007be93209f0c4bac53c1252ffe01a2e1a848919e236c94c2b7f426f9acf3"}, + {file = "pylink-square-1.1.0.tar.gz", hash = "sha256:12d6b03f39a2a70beb1d4df08cc7b464bc7518a9131e498f1e4055236044d4ac"}, + {file = "pylink_square-1.1.0-py2.py3-none-any.whl", hash = "sha256:d212d486dc221e856fcb8fa86f88722ce9baeab030c3c9807ad1dcfcbed699d0"}, ] [package.dependencies] -future = "*" psutil = ">=5.2.2" six = "*" [[package]] name = "pynitrokey" -version = "0.4.40" +version = "0.4.43" description = "Python Library for Nitrokey devices." optional = false python-versions = ">=3.9" files = [ - {file = "pynitrokey-0.4.40-py3-none-any.whl", hash = "sha256:4ce46d66e5f3e299fddf3ec6b16eb8a4d65e8b7dc49104a5da94513544061dda"}, - {file = "pynitrokey-0.4.40.tar.gz", hash = "sha256:1eefbc528a03cefe068645add2c09c9104321e35a7e15ff3b760039550a81e69"}, + {file = "pynitrokey-0.4.43-py3-none-any.whl", hash = "sha256:3cb6cae19d5ed6ff52fb100037e3852371e072e1f8ce36507c3dbbf5829b030b"}, + {file = "pynitrokey-0.4.43.tar.gz", hash = "sha256:75839da24a802c38385e7ecde98774b2433fb62b7e8f9fb163bdec9bd93bea11"}, ] [package.dependencies] @@ -1405,11 +1401,11 @@ certifi = ">=14.5.14" cffi = "*" click = ">=8.0,<=8.1.3" click-aliases = "*" -cryptography = ">=39.0.1,<39.1" +cryptography = ">=41.0.4,<44" ecdsa = "*" -fido2 = ">=1.1.0,<2" -frozendict = ">=2.3.4,<2.4.0" +fido2 = ">=1.1.2,<2" intelhex = "*" +nethsm = ">=1.0.0,<2" nkdfu = "*" protobuf = ">=3.17.3,<4.0.0" pyserial = "*" @@ -1417,11 +1413,10 @@ python-dateutil = ">=2.7.0,<2.8.0" pyusb = "*" requests = "*" semver = "*" -spsdk = ">=1.10.1,<1.11.0" +spsdk = ">=1.11.0,<1.12.0" tlv8 = "*" tqdm = "*" typing_extensions = ">=4.3.0,<4.4.0" -urllib3 = ">=2.0,<2.1" [package.extras] dev = ["black (>=22.1.0,<23)", "flake8", "flit (>=3.2,<4)", "ipython", "isort", "mypy (>=1.4,<1.5)", "oath", "pyinstaller (==5.9.0)", "pyinstaller-versionfile (==2.1.1)", "pytest", "pytest-reporter-html1", "types-requests", "types-tqdm"] @@ -1429,27 +1424,30 @@ pcsc = ["pyscard (>=2.0.0,<3)"] [[package]] name = "pyocd" -version = "0.34.3" +version = "0.35.1" description = "Cortex-M debugger for Python" optional = false -python-versions = ">=3.6.0" +python-versions = ">=3.7.0" files = [ - {file = "pyocd-0.34.3-py3-none-any.whl", hash = "sha256:2f8dae50a2b0531ea79c4cd41ff62e2ebdbfd18d3a06bcbe3fc1f74d3af2ed10"}, - {file = "pyocd-0.34.3.tar.gz", hash = "sha256:db30ebe9f9c0d8c0934ff84d56f93bbb782e80ca3e9d417613656c38f8495c7e"}, + {file = "pyocd-0.35.1-py3-none-any.whl", hash = "sha256:b1e0ee1951a2f3b098ef830a02c4046d76295b9d8834df785b63109f46977da4"}, + {file = "pyocd-0.35.1.tar.gz", hash = "sha256:02e8084f4d3b26d4d7c7470bb470fd4edc6c2bf2ba781e3dd94da4f84571c975"}, ] [package.dependencies] capstone = ">=4.0,<5.0" -cmsis-pack-manager = ">=0.4.0,<1.0" +cmsis-pack-manager = ">=0.5.2,<1.0" colorama = "<1.0" hidapi = {version = ">=0.10.1,<1.0", markers = "platform_system != \"Linux\""} +importlib-metadata = ">=3.6" +importlib-resources = "*" intelhex = ">=2.0,<3.0" intervaltree = ">=3.0.2,<4.0" +lark = ">=1.1.5,<2.0" libusb-package = ">=1.0,<2.0" natsort = ">=8.0.0,<9.0" prettytable = ">=2.0,<4.0" pyelftools = "<1.0" -pylink-square = ">=0.11.1,<1.0" +pylink-square = ">=1.0,<2.0" pyusb = ">=1.2.1,<2.0" pyyaml = ">=6.0,<7.0" six = ">=1.15.0,<2.0" @@ -1485,105 +1483,98 @@ files = [ ] [[package]] -name = "pyqt5" -version = "5.15.10" -description = "Python bindings for the Qt cross platform application toolkit" +name = "pyreadline3" +version = "3.4.1" +description = "A python implementation of GNU readline." optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "PyQt5-5.15.10-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:93288d62ebd47b1933d80c27f5d43c7c435307b84d480af689cef2474e87e4c8"}, - {file = "PyQt5-5.15.10-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:862cea3be95b4b0a2b9678003b3a18edf7bd5eafd673860f58820f246d4bf616"}, - {file = "PyQt5-5.15.10-cp37-abi3-manylinux_2_17_x86_64.whl", hash = "sha256:b89478d16d4118664ff58ed609e0a804d002703c9420118de7e4e70fa1cb5486"}, - {file = "PyQt5-5.15.10-cp37-abi3-win32.whl", hash = "sha256:ff99b4f91aa8eb60510d5889faad07116d3340041916e46c07d519f7cad344e1"}, - {file = "PyQt5-5.15.10-cp37-abi3-win_amd64.whl", hash = "sha256:501355f327e9a2c38db0428e1a236d25ebcb99304cd6e668c05d1188d514adec"}, - {file = "PyQt5-5.15.10.tar.gz", hash = "sha256:d46b7804b1b10a4ff91753f8113e5b5580d2b4462f3226288e2d84497334898a"}, + {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, + {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, ] -[package.dependencies] -PyQt5-Qt5 = ">=5.15.2" -PyQt5-sip = ">=12.13,<13" - [[package]] -name = "pyqt5-qt5" -version = "5.15.2" -description = "The subset of a Qt installation needed by PyQt5." +name = "pyserial" +version = "3.5" +description = "Python Serial Port Extension" optional = false python-versions = "*" files = [ - {file = "PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962"}, + {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, + {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, ] +[package.extras] +cp2110 = ["hidapi"] + [[package]] -name = "pyqt5-sip" -version = "12.13.0" -description = "The sip module support for PyQt5" +name = "pyside6" +version = "6.6.1" +description = "Python bindings for the Qt cross-platform application and UI framework" optional = false -python-versions = ">=3.7" +python-versions = "<3.13,>=3.8" files = [ - {file = "PyQt5_sip-12.13.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a7e3623b2c743753625c4650ec7696362a37fb36433b61824cf257f6d3d43cca"}, - {file = "PyQt5_sip-12.13.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6e4ac714252370ca037c7d609da92388057165edd4f94e63354f6d65c3ed9d53"}, - {file = "PyQt5_sip-12.13.0-cp310-cp310-win32.whl", hash = "sha256:d5032da3fff62da055104926ffe76fd6044c1221f8ad35bb60804bcb422fe866"}, - {file = "PyQt5_sip-12.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:9a8cdd6cb66adcbe5c941723ed1544eba05cf19b6c961851b58ccdae1c894afb"}, - {file = "PyQt5_sip-12.13.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f85fb633a522f04e48008de49dce1ff1d947011b48885b8428838973fbca412"}, - {file = "PyQt5_sip-12.13.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec60162e034c42fb99859206d62b83b74f987d58937b3a82bdc07b5c3d190dec"}, - {file = "PyQt5_sip-12.13.0-cp311-cp311-win32.whl", hash = "sha256:205cd449d08a2b024a468fb6100cd7ed03e946b4f49706f508944006f955ae1a"}, - {file = "PyQt5_sip-12.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:1c8371682f77852256f1f2d38c41e2e684029f43330f0635870895ab01c02f6c"}, - {file = "PyQt5_sip-12.13.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7fe3375b508c5bc657d73b9896bba8a768791f1f426c68053311b046bcebdddf"}, - {file = "PyQt5_sip-12.13.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:773731b1b5ab1a7cf5621249f2379c95e3d2905e9bd96ff3611b119586daa876"}, - {file = "PyQt5_sip-12.13.0-cp312-cp312-win32.whl", hash = "sha256:fb4a5271fa3f6bc2feb303269a837a95a6d8dd16be553aa40e530de7fb81bfdf"}, - {file = "PyQt5_sip-12.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4498f3b1b15f43f5d12963accdce0fd652b0bcaae6baf8008663365827444c"}, - {file = "PyQt5_sip-12.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b984c2620a7a7eaf049221b09ae50a345317add2624c706c7d2e9e6632a9587"}, - {file = "PyQt5_sip-12.13.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3188a06956aef86f604fb0d14421a110fad70d2a9e943dbacbfc3303f651dade"}, - {file = "PyQt5_sip-12.13.0-cp38-cp38-win32.whl", hash = "sha256:108a15f603e1886988c4b0d9d41cb74c9f9815bf05cefc843d559e8c298a10ce"}, - {file = "PyQt5_sip-12.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:db228cd737f5cbfc66a3c3e50042140cb80b30b52edc5756dbbaa2346ec73137"}, - {file = "PyQt5_sip-12.13.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5338773bbaedaa4f16a73c142fb23cc18c327be6c338813af70260b756c7bc92"}, - {file = "PyQt5_sip-12.13.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:29fa9cc964517c9fc3f94f072b9a2aeef4e7a2eda1879cb835d9e06971161cdf"}, - {file = "PyQt5_sip-12.13.0-cp39-cp39-win32.whl", hash = "sha256:96414c93f3d33963887cf562d50d88b955121fbfd73f937c8eca46643e77bf61"}, - {file = "PyQt5_sip-12.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:bbc7cd498bf19e0862097be1ad2243e824dea56726f00c11cff1b547c2d31d01"}, - {file = "PyQt5_sip-12.13.0.tar.gz", hash = "sha256:7f321daf84b9c9dbca61b80e1ef37bdaffc0e93312edae2cd7da25b953971d91"}, + {file = "PySide6-6.6.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:3c348948fe3957b18164c9c7b8942fe065bdb39648b326f212bc114326679fa9"}, + {file = "PySide6-6.6.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0a67587c088cb80e90d4ce3023b02466ea858c93a6dc9c4e062b13314e03d464"}, + {file = "PySide6-6.6.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:ed3822150f0d7a06b68bf4ceebe287515b5e8309bb256e9b49ae405afd062b18"}, + {file = "PySide6-6.6.1-cp38-abi3-win_amd64.whl", hash = "sha256:3593d605175e83e6952cf3b428ecc9c146af97effb36de921ecf3da2752de082"}, ] +[package.dependencies] +PySide6-Addons = "6.6.1" +PySide6-Essentials = "6.6.1" +shiboken6 = "6.6.1" + [[package]] -name = "pyqt5-stubs" -version = "5.15.6.0" -description = "PEP561 stub files for the PyQt5 framework" +name = "pyside6-addons" +version = "6.6.1" +description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" optional = false -python-versions = ">= 3.5" +python-versions = "<3.13,>=3.8" files = [ - {file = "PyQt5-stubs-5.15.6.0.tar.gz", hash = "sha256:91270ac23ebf38a1dc04cd97aa852cd08af82dc839100e5395af1447e3e99707"}, - {file = "PyQt5_stubs-5.15.6.0-py3-none-any.whl", hash = "sha256:7fb8177c72489a8911f021b7bd7c33f12c87f6dba92dcef3fdcdb5d9400f0f3f"}, + {file = "PySide6_Addons-6.6.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:7cb7af1b050c40f7ac891b0e61c758c1923863173932f5b92dc47bdfb4158b42"}, + {file = "PySide6_Addons-6.6.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a0982da4033319667f9df5ed6fa8eff300a88216aec103a1fff6751a172b19a0"}, + {file = "PySide6_Addons-6.6.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:5a63a8a943724ce5acd2df72e5ab04982b6906963278cbabb216656b9a26ee18"}, + {file = "PySide6_Addons-6.6.1-cp38-abi3-win_amd64.whl", hash = "sha256:a223575c81e9a13173136c044c3447e25f6d656b462b4d71fc3c6bd9c935a709"}, ] -[package.extras] -dev = ["mypy (==0.930)", "pytest", "pytest-xvfb"] +[package.dependencies] +PySide6-Essentials = "6.6.1" +shiboken6 = "6.6.1" [[package]] -name = "pyreadline3" -version = "3.4.1" -description = "A python implementation of GNU readline." +name = "pyside6-essentials" +version = "6.6.1" +description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" optional = false -python-versions = "*" +python-versions = "<3.13,>=3.8" files = [ - {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, - {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, + {file = "PySide6_Essentials-6.6.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:0c8917b15236956957178a8c9854641b12b11dad79ba0caf26147119164c30cf"}, + {file = "PySide6_Essentials-6.6.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c7185616083eab6f42eaed598d97d49fac4f60ae2e7415194140d54f58c2b42c"}, + {file = "PySide6_Essentials-6.6.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:a383c3d60298392cfb621ec1a0cf24b4799321e6c5bbafc021d4cc8076ea1315"}, + {file = "PySide6_Essentials-6.6.1-cp38-abi3-win_amd64.whl", hash = "sha256:13da926e9e9ee3e26e3f66883a9d5e43726ddee70cdabddca02a07aa1ccf9484"}, ] +[package.dependencies] +shiboken6 = "6.6.1" + [[package]] -name = "pyserial" -version = "3.5" -description = "Python Serial Port Extension" +name = "pyside6-stubs" +version = "6.4.2.0" +description = "PEP561 stub files for the *Qt for Python/PySide6* framework" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, - {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, + {file = "PySide6-stubs-6.4.2.0.tar.gz", hash = "sha256:d5578eb1597d1c07831c899b35636410b08915a4695ce6e41cceb6707c400fcf"}, + {file = "PySide6_stubs-6.4.2.0-py3-none-any.whl", hash = "sha256:e825ded4b3555d540f297f405e3a9dc0943c032a96c53184cf644a8e4c4a6b0b"}, ] +[package.dependencies] +mypy = ">=1.0" +PySide6 = ">=6.0" + [package.extras] -cp2110 = ["hidapi"] +dev = ["pytest"] [[package]] name = "python-dateutil" @@ -1853,6 +1844,19 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "shiboken6" +version = "6.6.1" +description = "Python/C++ bindings helper module" +optional = false +python-versions = "<3.13,>=3.8" +files = [ + {file = "shiboken6-6.6.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:d756fd1fa945b787e8eef142f2eb571da0b4c4dc2f2eec1a7c12a474a2cf84e4"}, + {file = "shiboken6-6.6.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:fb102e4bc210006f0cdd0ce38e1aaaaf792bd871f02a2b3f01d07922c5cf4c59"}, + {file = "shiboken6-6.6.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:a605960e72af5eef915991cee7eef4cc72f5cabe63b9ae1a955ceb3d3b0a00b9"}, + {file = "shiboken6-6.6.1-cp38-abi3-win_amd64.whl", hash = "sha256:072c35c4fe46ec13b364d9dc47b055bb2277ee3aeaab18c23650280ec362f62a"}, +] + [[package]] name = "six" version = "1.16.0" @@ -1888,13 +1892,13 @@ files = [ [[package]] name = "spsdk" -version = "1.10.1" +version = "1.11.0" description = "Open Source Secure Provisioning SDK for NXP MCU/MPU" optional = false python-versions = ">=3.8" files = [ - {file = "spsdk-1.10.1-py3-none-any.whl", hash = "sha256:640a012d6028e27164be81256655a0e3a0df53133fe6a1797313b403c6b4abaf"}, - {file = "spsdk-1.10.1.tar.gz", hash = "sha256:c4523c7d51eb79238bad7450844fa6a63ebe835558004b4e3265193a6170819c"}, + {file = "spsdk-1.11.0-py3-none-any.whl", hash = "sha256:79d956ee528b42e6bc8e6636a853773658ce526754906d457f545fd0783aee31"}, + {file = "spsdk-1.11.0.tar.gz", hash = "sha256:03d8821ad05a0149a107b9ddfc01371f6894d02ada36e1065b0efd9301526854"}, ] [package.dependencies] @@ -1908,35 +1912,38 @@ click-option-group = ">=0.3.0,<0.6" colorama = ">=0.4.6,<0.5" commentjson = ">=0.9,<0.10" crcmod = "<1.8" -cryptography = ">=3.4.4,<40.1" +cryptography = ">=3.4.4,<41.1" deepmerge = "<1.2" -fastjsonschema = ">=2.15.1,<2.17" +fastjsonschema = ">=2.15.1,<2.18" hexdump = "<3.4" jinja2 = ">=3.0,<3.2" libusbsio = ">=2.1.11,<2.2" oscrypto = "<1.4" -pycryptodome = ">=3.9.3,<3.18" -pylink-square = ">=0.8.2,<0.15" -pyocd = ">=0.33.0,<0.35" +pycryptodome = ">=3.9.3,<3.19" +pylink-square = ">=1.0,<1.2" +pyocd = ">=0.35.1,<0.36" pyocd-pemicro = ">=1.1.5,<1.2" pypemicro = ">=0.1.11,<0.2" pyserial = ">=3.1,<3.6" "ruamel.yaml" = ">=0.17,<0.18" sly = "<0.6" -typing-extensions = "<4.6" +typing-extensions = "<4.7" [package.extras] +all = ["flask", "ftd2xx", "ipython", "notebook", "pyftdi", "pylibftdi", "pyscard (==2.0.2)", "requests"] +dk6 = ["ftd2xx", "pyftdi", "pylibftdi"] +examples = ["flask", "ipython", "notebook", "requests"] tp = ["pyscard (==2.0.2)"] [[package]] name = "termcolor" -version = "2.3.0" +version = "2.4.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, - {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, + {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, + {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, ] [package.extras] @@ -2054,4 +2061,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "a49e2f58cc5206e3457874f9241c5cb9155776f77cd52c1a3a6573022d14eeb4" +content-hash = "f9c6ca107f4156b4de12e07666fd4a7c37c3633d6e423bca3f61ecbc4ed83c59" diff --git a/pyproject.toml b/pyproject.toml index 740ff8b7..6e5166d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,22 +25,20 @@ classifiers=[ packages = [ {include = "nitrokeyapp"} ] -include=["nitrokeyapp/ui/*.py"] [tool.poetry.scripts] nitrokeyapp = "nitrokeyapp.__main__:main" [tool.poetry.dependencies] python = ">=3.9,<3.12" -pyqt5 = "^5.15.10" -pyqt5-qt5 = "<=5.15.2" +pySide6 = ">=6.6.0" pyudev = "^0.24.1" -pynitrokey = "0.4.40" +pynitrokey = "0.4.43" pywin32 = { version = "305", markers = "sys_platform =='win32'" } qt_material = "^2.14" [tool.poetry.group.dev.dependencies] -pyqt5-stubs = "^5.15.6.0" +PySide6-stubs = "^6.4.2" black = ">=22.1.0,<23" flake8 = "^6.1.0" isort = "^5.12.0"