From 82a54c780ff64292a8fe743b9ec17fa4c1e4fbde Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 22 Oct 2013 15:30:46 +0900 Subject: [PATCH] catch invalid temp folder and other tweaks - tweak sync code so that a failure in loading the collection won't leave the app with an unopen collection - don't show corrupt collection message when the error is not a db error - catch the temp folder issue when loading the collection. i suspect this was the issue that was causing some people to end up with an open anki instance with no collection loaded --- anki/db.py | 6 +++++- anki/media.py | 5 ++++- aqt/errors.py | 13 +++++++++++-- aqt/main.py | 13 +++++++++++-- aqt/sync.py | 6 ++++-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/anki/db.py b/anki/db.py index 045bafd35..c66813c24 100644 --- a/anki/db.py +++ b/anki/db.py @@ -2,12 +2,16 @@ # Copyright: Damien Elmes # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -import os, time +import os +import time + try: from pysqlite2 import dbapi2 as sqlite except ImportError: from sqlite3 import dbapi2 as sqlite +Error = sqlite.Error + class DB(object): def __init__(self, path, text=None, timeout=0): encpath = path diff --git a/anki/media.py b/anki/media.py index 5818770d4..3560278a2 100644 --- a/anki/media.py +++ b/anki/media.py @@ -45,7 +45,10 @@ class MediaManager(object): except OSError: # cwd doesn't exist self._oldcwd = None - os.chdir(self._dir) + try: + os.chdir(self._dir) + except OSError: + raise Exception("invalidTempFolder") # change database self.connect() diff --git a/aqt/errors.py b/aqt/errors.py index 77724cd82..5c2a37330 100644 --- a/aqt/errors.py +++ b/aqt/errors.py @@ -1,10 +1,11 @@ # Copyright: Damien Elmes # -*- coding: utf-8 -*- # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html - -from aqt.qt import * import sys import cgi + +from anki.lang import _ +from aqt.qt import * from aqt.utils import showText, showWarning class ErrorHandler(QObject): @@ -43,6 +44,12 @@ class ErrorHandler(QObject): self.timer.setSingleShot(True) self.timer.start() + def tempFolderMsg(self): + return _("""\ +The permissions on your system's temporary folder are incorrect, and Anki is \ +not able to correct them automatically. Please search for 'temp folder' in the \ +Anki manual for more information.""") + def onTimeout(self): error = cgi.escape(self.pool) self.pool = "" @@ -56,6 +63,8 @@ class ErrorHandler(QObject): if "no default output" in error: return showWarning(_("Please connect a microphone, and ensure " "other programs are not using the audio device.")) + if "invalidTempFolder" in error: + return showWarning(self.tempFolderMsg()) stdText = _("""\ An error occurred. It may have been caused by a harmless bug,
or your deck may have a problem. diff --git a/aqt/main.py b/aqt/main.py index 0184ae292..425080987 100644 --- a/aqt/main.py +++ b/aqt/main.py @@ -24,7 +24,7 @@ import aqt.stats from aqt.utils import restoreGeom, showInfo, showWarning,\ restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \ openHelp, openLink, checkInvalidFilename - +import anki.db class AnkiQt(QMainWindow): def __init__(self, app, profileManager, args): @@ -270,13 +270,22 @@ To import into a password protected profile, please open the profile before atte self.hideSchemaMsg = True try: self.col = Collection(self.pm.collectionPath()) - except: + except anki.db.Error: # move back to profile manager showWarning("""\ Your collection is corrupt. Please see the manual for \ how to restore from a backup.""") self.unloadProfile() raise + except Exception, e: + # the custom exception handler won't catch this if we immediately + # unload, so we have to manually handle it + if "invalidTempFolder" in repr(str(e)): + showWarning(self.errorHandler.tempFolderMsg()) + self.unloadProfile() + return + self.unloadProfile() + raise self.hideSchemaMsg = False self.progress.setupDB(self.col.db) self.maybeEnableUndo() diff --git a/aqt/sync.py b/aqt/sync.py index 0ef164322..ce749f2e9 100644 --- a/aqt/sync.py +++ b/aqt/sync.py @@ -275,6 +275,10 @@ class SyncThread(QThread): self.media = media def run(self): + # init this first so an early crash doesn't cause an error + # in the main thread + self.syncMsg = "" + self.uname = "" try: self.col = Collection(self.path) except: @@ -282,8 +286,6 @@ class SyncThread(QThread): return self.server = RemoteServer(self.hkey) self.client = Syncer(self.col, self.server) - self.syncMsg = "" - self.uname = "" self.sentTotal = 0 self.recvTotal = 0 # throttle updates; qt doesn't handle lots of posted events well