This commit is contained in:
Soren I. Bjornstad 2013-10-22 07:34:46 -05:00
commit 2339f4bafc
17 changed files with 137 additions and 56 deletions

View file

@ -2,12 +2,16 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os, time import os
import time
try: try:
from pysqlite2 import dbapi2 as sqlite from pysqlite2 import dbapi2 as sqlite
except ImportError: except ImportError:
from sqlite3 import dbapi2 as sqlite from sqlite3 import dbapi2 as sqlite
Error = sqlite.Error
class DB(object): class DB(object):
def __init__(self, path, text=None, timeout=0): def __init__(self, path, text=None, timeout=0):
encpath = path encpath = path

View file

@ -3,10 +3,12 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import re import re
import sre_constants
from anki.utils import ids2str, splitFields, joinFields, intTime, fieldChecksum, stripHTMLMedia from anki.utils import ids2str, splitFields, joinFields, intTime, fieldChecksum, stripHTMLMedia
from anki.consts import * from anki.consts import *
from anki.hooks import * from anki.hooks import *
import sre_constants
# Find # Find
########################################################################## ##########################################################################
@ -257,7 +259,9 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """+preds
return "queue in (1, 3)" return "queue in (1, 3)"
return "type = %d" % n return "type = %d" % n
elif val == "suspended": elif val == "suspended":
return "c.queue in (-1, -2)" return "c.queue = -1"
elif val == "buried":
return "c.queue = -2"
elif val == "due": elif val == "due":
return """ return """
(c.queue in (2,3) and c.due <= %d) or (c.queue in (2,3) and c.due <= %d) or

View file

@ -45,7 +45,10 @@ class MediaManager(object):
except OSError: except OSError:
# cwd doesn't exist # cwd doesn't exist
self._oldcwd = None self._oldcwd = None
os.chdir(self._dir) try:
os.chdir(self._dir)
except OSError:
raise Exception("invalidTempFolder")
# change database # change database
self.connect() self.connect()

View file

@ -945,7 +945,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)"""
def _fillDyn(self, deck): def _fillDyn(self, deck):
search, limit, order = deck['terms'][0] search, limit, order = deck['terms'][0]
orderlimit = self._dynOrder(order, limit) orderlimit = self._dynOrder(order, limit)
search += " -is:suspended -deck:filtered" search += " -is:suspended -is:buried -deck:filtered"
try: try:
ids = self.col.findCards(search, order=orderlimit) ids = self.col.findCards(search, order=orderlimit)
except: except:
@ -1266,16 +1266,19 @@ To study outside of the normal schedule, click the Custom Study button below."""
"where queue = -1 and id in "+ ids2str(ids), "where queue = -1 and id in "+ ids2str(ids),
intTime(), self.col.usn()) intTime(), self.col.usn())
def buryNote(self, nid): def buryCards(self, cids):
"Bury all cards for note until next session."
cids = self.col.db.list(
"select id from cards where nid = ? and queue >= 0", nid)
self.col.log(cids) self.col.log(cids)
self.removeLrn(cids) self.removeLrn(cids)
self.col.db.execute(""" self.col.db.execute("""
update cards set queue=-2,mod=?,usn=? where id in """+ids2str(cids), update cards set queue=-2,mod=?,usn=? where id in """+ids2str(cids),
intTime(), self.col.usn()) intTime(), self.col.usn())
def buryNote(self, nid):
"Bury all cards for note until next session."
cids = self.col.db.list(
"select id from cards where nid = ? and queue >= 0", nid)
self.buryCards(cids)
# Sibling spacing # Sibling spacing
########################################################################## ##########################################################################

View file

@ -20,7 +20,7 @@ import anki
HTTP_TIMEOUT = 90 HTTP_TIMEOUT = 90
HTTP_PROXY = None HTTP_PROXY = None
# badly named; means no retries, and doesn't affect ssl connections # badly named; means no retries
httplib2.RETRIES = 1 httplib2.RETRIES = 1
try: try:

View file

@ -1,10 +1,15 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import getpass import getpass
import os
import sys
import optparse
import tempfile
import __builtin__
import locale
import gettext
import os, sys, optparse, atexit, tempfile, __builtin__
from aqt.qt import * from aqt.qt import *
import locale, gettext
import anki.lang import anki.lang
from anki.consts import HELP_SITE from anki.consts import HELP_SITE
from anki.lang import langDir from anki.lang import langDir
@ -157,6 +162,7 @@ class AnkiApp(QApplication):
sys.stderr.write(sock.errorString()) sys.stderr.write(sock.errorString())
return return
buf = sock.readAll() buf = sock.readAll()
buf = unicode(buf, sys.getfilesystemencoding(), "ignore")
self.emit(SIGNAL("appMsg"), buf) self.emit(SIGNAL("appMsg"), buf)
sock.disconnectFromServer() sock.disconnectFromServer()

View file

@ -39,7 +39,7 @@ Montague, Michael Penkov, Michal Čadil, Morteza Salehi, Nathanael Law, Nick Coo
Laxström, Nguyễn Hào Khôi, Norbert Nagold, Ole Guldberg, Laxström, Nguyễn Hào Khôi, Norbert Nagold, Ole Guldberg,
Pcsl88, Petr Michalec, Piotr Kubowicz, Richard Colley, Roland Sieker, Pcsl88, Petr Michalec, Piotr Kubowicz, Richard Colley, Roland Sieker,
Samson Melamed, Stefaan De Pooter, Silja Ijas, Snezana Lukic, Susanna Björverud, Sylvain Durand, Samson Melamed, Stefaan De Pooter, Silja Ijas, Snezana Lukic, Susanna Björverud, Sylvain Durand,
Tacutu, Timm Preetz, Timo Paulssen, Ursus, Victor Suba, Xtru %s 黃文龍 Tacutu, Timm Preetz, Timo Paulssen, Ursus, Victor Suba, Volodymyr Goncharenko, Xtru %s 黃文龍
"""% _("<!--about diag--> and")} """% _("<!--about diag--> and")}
abouttext += '<p>' + _("""\ abouttext += '<p>' + _("""\
The icons were obtained from various sources; please see the Anki source The icons were obtained from various sources; please see the Anki source

View file

@ -2,18 +2,20 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from aqt.qt import *
import re import re
from aqt.qt import *
from anki.consts import * from anki.consts import *
import aqt import aqt
from anki.sound import playFromText, clearAudioQueue from anki.sound import playFromText, clearAudioQueue
from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA,\ from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA,\
showInfo, askUser, getOnlyText, \ showInfo, askUser, getOnlyText, \
showWarning, openHelp, openLink showWarning, openHelp
from anki.utils import isMac, isWin, joinFields from anki.utils import isMac, isWin, joinFields
from aqt.webview import AnkiWebView from aqt.webview import AnkiWebView
import anki.js import anki.js
class CardLayout(QDialog): class CardLayout(QDialog):
def __init__(self, mw, note, ord=0, parent=None, addMode=False): def __init__(self, mw, note, ord=0, parent=None, addMode=False):
@ -135,7 +137,7 @@ class CardLayout(QDialog):
return showInfo(_("At least one card type is required.")) return showInfo(_("At least one card type is required."))
cards = self.mm.tmplUseCount(self.model, idx) cards = self.mm.tmplUseCount(self.model, idx)
cards = ngettext("%d card", "%d cards", cards) % cards cards = ngettext("%d card", "%d cards", cards) % cards
msg = _("Delete the '%(a)s' card type, and its %(b)s?" % msg = (_("Delete the '%(a)s' card type, and its %(b)s?") %
dict(a=self.model['tmpls'][idx]['name'], b=cards)) dict(a=self.model['tmpls'][idx]['name'], b=cards))
if not askUser(msg): if not askUser(msg):
return return

View file

@ -779,7 +779,7 @@ to a cloze type first, via Edit>Change Note Type."""))
except Exception, e: except Exception, e:
showWarning(_( showWarning(_(
"Couldn't record audio. Have you installed lame and sox?") + "Couldn't record audio. Have you installed lame and sox?") +
"\n\n" + unicode(e)) "\n\n" + repr(str(e)))
return return
self.addMedia(file) self.addMedia(file)

View file

@ -1,10 +1,11 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from aqt.qt import *
import sys import sys
import cgi import cgi
from anki.lang import _
from aqt.qt import *
from aqt.utils import showText, showWarning from aqt.utils import showText, showWarning
class ErrorHandler(QObject): class ErrorHandler(QObject):
@ -43,6 +44,12 @@ class ErrorHandler(QObject):
self.timer.setSingleShot(True) self.timer.setSingleShot(True)
self.timer.start() 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): def onTimeout(self):
error = cgi.escape(self.pool) error = cgi.escape(self.pool)
self.pool = "" self.pool = ""
@ -56,6 +63,8 @@ class ErrorHandler(QObject):
if "no default output" in error: if "no default output" in error:
return showWarning(_("Please connect a microphone, and ensure " return showWarning(_("Please connect a microphone, and ensure "
"other programs are not using the audio device.")) "other programs are not using the audio device."))
if "invalidTempFolder" in error:
return showWarning(self.tempFolderMsg())
stdText = _("""\ stdText = _("""\
An error occurred. It may have been caused by a harmless bug, <br> An error occurred. It may have been caused by a harmless bug, <br>
or your deck may have a problem. or your deck may have a problem.

View file

@ -1,13 +1,22 @@
# coding=utf-8
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os, re, traceback, zipfile, json import os
import re
import traceback
import zipfile
import json
from aqt.qt import * from aqt.qt import *
import anki.importing as importing import anki.importing as importing
from aqt.utils import getOnlyText, getFile, showText, showWarning, openHelp,\ from aqt.utils import getOnlyText, getFile, showText, showWarning, openHelp,\
askUser, tooltip askUser, tooltip
from anki.hooks import addHook, remHook from anki.hooks import addHook, remHook
import aqt.forms, aqt.modelchooser, aqt.deckchooser import aqt.forms
import aqt.modelchooser
import aqt.deckchooser
class ChangeMap(QDialog): class ChangeMap(QDialog):
def __init__(self, mw, model, current): def __init__(self, mw, model, current):
@ -155,7 +164,7 @@ you can enter it here. Use \\t to represent tab."""),
return return
except Exception, e: except Exception, e:
msg = _("Import failed.\n") msg = _("Import failed.\n")
err = unicode(e) err = repr(str(e))
if "1-character string" in err: if "1-character string" in err:
msg += err msg += err
else: else:
@ -283,7 +292,7 @@ def importFile(mw, file):
showUnicodeWarning() showUnicodeWarning()
return return
except Exception, e: except Exception, e:
msg = unicode(e) msg = repr(str(e))
if msg == "unknownFormat": if msg == "unknownFormat":
if file.endswith(".anki2"): if file.endswith(".anki2"):
showWarning(_("""\ showWarning(_("""\
@ -322,11 +331,12 @@ failed. Please try again, and if the problem persists, please try again \
with a different browser.""") with a different browser.""")
showWarning(msg) showWarning(msg)
except Exception, e: except Exception, e:
if "invalidFile" in unicode(e): err = repr(str(e))
if "invalidFile" in err:
msg = _("""\ msg = _("""\
Invalid file. Please restore from backup.""") Invalid file. Please restore from backup.""")
showWarning(msg) showWarning(msg)
elif "readonly" in unicode(e): elif "readonly" in err:
showWarning(_("""\ showWarning(_("""\
Unable to import from a read-only file.""")) Unable to import from a read-only file."""))
else: else:

View file

@ -24,7 +24,7 @@ import aqt.stats
from aqt.utils import restoreGeom, showInfo, showWarning,\ from aqt.utils import restoreGeom, showInfo, showWarning,\
restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \ restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \
openHelp, openLink, checkInvalidFilename openHelp, openLink, checkInvalidFilename
import anki.db
class AnkiQt(QMainWindow): class AnkiQt(QMainWindow):
def __init__(self, app, profileManager, args): def __init__(self, app, profileManager, args):
@ -64,7 +64,7 @@ class AnkiQt(QMainWindow):
"syncing and add-on loading.")) "syncing and add-on loading."))
# were we given a file to import? # were we given a file to import?
if args and args[0]: if args and args[0]:
self.onAppMsg(unicode(args[0], "utf8", "ignore")) self.onAppMsg(unicode(args[0], sys.getfilesystemencoding(), "ignore"))
# Load profile in a timer so we can let the window finish init and not # Load profile in a timer so we can let the window finish init and not
# close on profile load error. # close on profile load error.
self.progress.timer(10, self.setupProfile, False) self.progress.timer(10, self.setupProfile, False)
@ -229,7 +229,12 @@ Are you sure?""")):
self.activateWindow() self.activateWindow()
self.raise_() self.raise_()
# maybe sync (will load DB) # maybe sync (will load DB)
self.onSync(auto=True) if self.pendingImport and os.path.basename(
self.pendingImport).startswith("backup-"):
# skip sync when importing a backup
self.loadCollection()
else:
self.onSync(auto=True)
# import pending? # import pending?
if self.pendingImport: if self.pendingImport:
if self.pm.profile['key']: if self.pm.profile['key']:
@ -265,13 +270,22 @@ To import into a password protected profile, please open the profile before atte
self.hideSchemaMsg = True self.hideSchemaMsg = True
try: try:
self.col = Collection(self.pm.collectionPath()) self.col = Collection(self.pm.collectionPath())
except: except anki.db.Error:
# move back to profile manager # move back to profile manager
showWarning("""\ showWarning("""\
Your collection is corrupt. Please see the manual for \ Your collection is corrupt. Please see the manual for \
how to restore from a backup.""") how to restore from a backup.""")
self.unloadProfile() self.unloadProfile()
raise 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.hideSchemaMsg = False
self.progress.setupDB(self.col.db) self.progress.setupDB(self.col.db)
self.maybeEnableUndo() self.maybeEnableUndo()
@ -290,7 +304,10 @@ how to restore from a backup.""")
return return
self.maybeOptimize() self.maybeOptimize()
self.progress.start(immediate=True) self.progress.start(immediate=True)
corrupt = self.col.db.scalar("pragma integrity_check") != "ok" if os.getenv("ANKIDEV", 0):
corrupt = False
else:
corrupt = self.col.db.scalar("pragma integrity_check") != "ok"
if corrupt: if corrupt:
showWarning(_("Your collection file appears to be corrupt. \ showWarning(_("Your collection file appears to be corrupt. \
This can happen when the file is copied or moved while Anki is open, or \ This can happen when the file is copied or moved while Anki is open, or \
@ -309,7 +326,7 @@ the manual for information on how to restore from an automatic backup."))
def backup(self): def backup(self):
nbacks = self.pm.profile['numBackups'] nbacks = self.pm.profile['numBackups']
if not nbacks: if not nbacks or os.getenv("ANKIDEV", 0):
return return
dir = self.pm.backupFolder() dir = self.pm.backupFolder()
path = self.pm.collectionPath() path = self.pm.collectionPath()
@ -808,16 +825,24 @@ title="%s">%s</button>''' % (
def newMsg(self, data): def newMsg(self, data):
aqt.update.showMessages(self, data) aqt.update.showMessages(self, data)
def clockIsOff(self): def clockIsOff(self, diff):
showWarning("""\ diffText = ngettext("%s second", "%s seconds", diff)
warn = _("""\
In order to ensure your collection works correctly when moved between \ In order to ensure your collection works correctly when moved between \
devices, Anki requires the system clock to be set correctly. Your system \ devices, Anki requires your computer's internal clock to be set correctly. \
clock appears to be wrong by more than 5 minutes. The internal clock can be wrong even if your system is showing the correct \
local time.
This can be because the \ Please go to the time settings on your computer and check the following:
clock is slow or fast, because the date is set incorrectly, or because \
the timezone or daylight savings information is incorrect. Please correct \ - AM/PM
the problem and restart Anki.""") - Clock drift
- Day, month and year
- Timezone
- Daylight savings
Difference to correct time: %s.""") % diffText
showWarning(warn)
self.app.closeAllWindows() self.app.closeAllWindows()
# Count refreshing # Count refreshing
@ -1106,10 +1131,6 @@ will be lost. Continue?"""))
self.connect(self.app, SIGNAL("appMsg"), self.onAppMsg) self.connect(self.app, SIGNAL("appMsg"), self.onAppMsg)
def onAppMsg(self, buf): def onAppMsg(self, buf):
if not isinstance(buf, unicode):
# even though we're sending this as unicode up above,
# a bug report still came in that we were receiving a qbytearray
buf = unicode(buf, "utf8", "ignore")
if self.state == "startup": if self.state == "startup":
# try again in a second # try again in a second
return self.progress.timer(1000, lambda: self.onAppMsg(buf), False) return self.progress.timer(1000, lambda: self.onAppMsg(buf), False)

View file

@ -3,9 +3,12 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import division from __future__ import division
import difflib, re, cgi import difflib
import re
import cgi
import unicodedata as ucd import unicodedata as ucd
import HTMLParser import HTMLParser
from anki.lang import _, ngettext from anki.lang import _, ngettext
from aqt.qt import * from aqt.qt import *
from anki.utils import stripHTML, isMac, json from anki.utils import stripHTML, isMac, json
@ -15,6 +18,7 @@ from aqt.utils import mungeQA, getBase, openLink, tooltip, askUserDialog
from aqt.sound import getAudio from aqt.sound import getAudio
import aqt import aqt
class Reviewer(object): class Reviewer(object):
"Manage reviews. Maintains a separate state." "Manage reviews. Maintains a separate state."
@ -285,8 +289,10 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
self.replayAudio() self.replayAudio()
elif key == "*": elif key == "*":
self.onMark() self.onMark()
elif key == "-": elif key == "=":
self.onBuryNote() self.onBuryNote()
elif key == "-":
self.onBuryCard()
elif key == "!": elif key == "!":
self.onSuspend() self.onSuspend()
elif key == "@": elif key == "@":
@ -678,7 +684,8 @@ function showAnswer(txt) {
def showContextMenu(self): def showContextMenu(self):
opts = [ opts = [
[_("Mark Note"), "*", self.onMark], [_("Mark Note"), "*", self.onMark],
[_("Bury Note"), "-", self.onBuryNote], [_("Bury Card"), "-", self.onBuryCard],
[_("Bury Note"), "=", self.onBuryNote],
[_("Suspend Card"), "@", self.onSuspendCard], [_("Suspend Card"), "@", self.onSuspendCard],
[_("Suspend Note"), "!", self.onSuspend], [_("Suspend Note"), "!", self.onSuspend],
[_("Delete Note"), "Delete", self.onDelete], [_("Delete Note"), "Delete", self.onDelete],
@ -740,6 +747,12 @@ function showAnswer(txt) {
"Note and its %d cards deleted.", "Note and its %d cards deleted.",
cnt) % cnt) cnt) % cnt)
def onBuryCard(self):
self.mw.checkpoint(_("Bury"))
self.mw.col.sched.buryCards([self.card.id])
self.mw.reset()
tooltip(_("Card buried."))
def onBuryNote(self): def onBuryNote(self):
self.mw.checkpoint(_("Bury")) self.mw.checkpoint(_("Bury"))
self.mw.col.sched.buryNote(self.card.nid) self.mw.col.sched.buryNote(self.card.nid)

View file

@ -275,6 +275,10 @@ class SyncThread(QThread):
self.media = media self.media = media
def run(self): def run(self):
# init this first so an early crash doesn't cause an error
# in the main thread
self.syncMsg = ""
self.uname = ""
try: try:
self.col = Collection(self.path) self.col = Collection(self.path)
except: except:
@ -282,8 +286,6 @@ class SyncThread(QThread):
return return
self.server = RemoteServer(self.hkey) self.server = RemoteServer(self.hkey)
self.client = Syncer(self.col, self.server) self.client = Syncer(self.col, self.server)
self.syncMsg = ""
self.uname = ""
self.sentTotal = 0 self.sentTotal = 0
self.recvTotal = 0 self.recvTotal = 0
# throttle updates; qt doesn't handle lots of posted events well # throttle updates; qt doesn't handle lots of posted events well
@ -447,7 +449,7 @@ httplib.HTTPConnection.send = _incrementalSend
# receiving in httplib2 # receiving in httplib2
def _conn_request(self, conn, request_uri, method, body, headers): def _conn_request(self, conn, request_uri, method, body, headers):
for i in range(2): for i in range(httplib2.RETRIES):
try: try:
if conn.sock is None: if conn.sock is None:
conn.connect() conn.connect()

View file

@ -1,14 +1,17 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import urllib
import urllib2
import time
from aqt.qt import * from aqt.qt import *
import urllib, urllib2, time
import aqt import aqt
import platform
from aqt.utils import openLink from aqt.utils import openLink
from anki.utils import json, isWin, isMac, platDesc from anki.utils import json, platDesc
from aqt.utils import showText from aqt.utils import showText
class LatestVersionFinder(QThread): class LatestVersionFinder(QThread):
def __init__(self, main): def __init__(self, main):
@ -45,7 +48,7 @@ class LatestVersionFinder(QThread):
self.emit(SIGNAL("newVerAvail"), resp['ver']) self.emit(SIGNAL("newVerAvail"), resp['ver'])
diff = resp['time'] - time.time() diff = resp['time'] - time.time()
if abs(diff) > 300: if abs(diff) > 300:
self.emit(SIGNAL("clockIsOff")) self.emit(SIGNAL("clockIsOff"), diff)
def askAndUpdate(mw, ver): def askAndUpdate(mw, ver):
baseStr = ( baseStr = (

View file

@ -259,16 +259,16 @@ class UpgradeThread(QThread):
try: try:
self.maybeCopyFromCustomFolder(path) self.maybeCopyFromCustomFolder(path)
except Exception, e: except Exception, e:
imp.log.append(unicode(e)) imp.log.append(repr(str(e)))
# then run the import # then run the import
try: try:
imp.run() imp.run()
except Exception, e: except Exception, e:
if unicode(e) == "invalidFile": if repr(str(e)) == "invalidFile":
# already logged # already logged
pass pass
else: else:
imp.log.append(unicode(e)) imp.log.append(repr(str(e)))
self.col.save() self.col.save()
return imp.log return imp.log

View file

@ -6,6 +6,7 @@
from ctypes import windll, Structure, byref, c_uint from ctypes import windll, Structure, byref, c_uint
from ctypes.wintypes import HWND, UINT, LPCWSTR, BOOL from ctypes.wintypes import HWND, UINT, LPCWSTR, BOOL
import os
import os.path as op import os.path as op
shell32 = windll.shell32 shell32 = windll.shell32