From ecdefe79f587e7b85c1e125129126e3133f0b974 Mon Sep 17 00:00:00 2001 From: JoeGruffins <34998433+JoeGruffins@users.noreply.github.com> Date: Fri, 1 May 2020 21:06:51 +0900 Subject: [PATCH] screens: Continue on open file cancel. (#183) Rather than throwing an exception when restoring a wallet from file, just return, allowing the user to do something else. Create a logging helper for errors that logs to stdErr and the main ui window. Do not move a user's wallet file without warning. Copy it instead. Check that the file is a sqlite database, otherwise you get stuck in a loop until you delete or move the file manually. --- decred/decred/util/database.py | 19 +++++++++++++++++++ tinywallet/tinywallet/screens.py | 32 ++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/decred/decred/util/database.py b/decred/decred/util/database.py index 9844b932..83a6e54e 100644 --- a/decred/decred/util/database.py +++ b/decred/decred/util/database.py @@ -60,6 +60,25 @@ class NoValueError(DecredError): KVFirst = "SELECT k, v FROM {tablename} ORDER BY k LIMIT 1;" +def isSqlite3DB(filepath): + """ + Returns whether file at filepath is a sqlite3 database. + + Args: + filepath (str): The file to check. + + Returns: + bool: Whether the database could be opened and queried. + """ + try: + conn = sqlite3.connect(filepath) + conn.execute("pragma schema_version;") + except Exception: + return False + conn.close() + return True + + class KeyValueDatabase: """ A KeyValueDatabase is a sqlite3 database specialized for two-column tables diff --git a/tinywallet/tinywallet/screens.py b/tinywallet/tinywallet/screens.py index b84b4daa..93b4c61c 100644 --- a/tinywallet/tinywallet/screens.py +++ b/tinywallet/tinywallet/screens.py @@ -39,6 +39,17 @@ app = None +def logError(err): + """ + Log an error to stderr and to the ui main window. + + Args: + err (str): The error to log and display. + """ + log.error(err) + app.appWindow.showError(err) + + def openInBrowser(url): """ Open a URL in the user's browser. @@ -971,26 +982,31 @@ def loadClicked(self): fd.setViewMode(QtWidgets.QFileDialog.Detail) qdir = QtCore.QDir fd.setFilter(qdir.Dirs | qdir.Files | qdir.NoDotAndDotDot | qdir.Hidden) + noFileMsg = "no file selected" if fd.exec_(): fileNames = fd.selectedFiles() if len(fileNames) != 1: msg = "more than one file selected for importing" - log.error(msg) - raise Exception(msg) + logError(msg) + return else: - raise Exception("no file selected") + log.info(noFileMsg) + return walletPath = fileNames[0] - log.debug("loading wallet from %r" % walletPath) + log.debug(f"loading wallet from {walletPath}") if walletPath == "": - app.appWindow.showError("no file selected") + logError(noFileMsg) return elif not os.path.isfile(walletPath): - log.error("no file found at %s" % walletPath) - app.showMessaage("file error. try again") + msg = f"no file found at {walletPath}" + logError(msg) + return + elif not database.isSqlite3DB(walletPath): + logError(f"{walletPath} is not a sqlite3 database") return destination = app.walletFilename() - shutil.move(walletPath, destination) + shutil.copy(walletPath, destination) app.initialize() def restoreClicked(self):