From f29a04ae296aaebca0c93ed7763ae6a9700092bf Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Fri, 4 Oct 2013 06:09:28 +0900 Subject: [PATCH] bump sync ver to 7 and change meta return value - /sync/meta now returns a dictionary - it includes the following extra fields - msg: if non-empty, show this message at the end of the sync - cont: if false, show above message and abort sync - uname: the user's email address, so it can be stored by the local client to show users who have forgotten which email address they used. in the future this will be saved only when logging in, so do a conditional access on it --- anki/consts.py | 2 +- anki/sync.py | 42 +++++++++++++++++++++++++++++++++------ aqt/sync.py | 15 +++++++++++++- tests/test_remote_sync.py | 10 +++++----- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/anki/consts.py b/anki/consts.py index e07184caf..682314a23 100644 --- a/anki/consts.py +++ b/anki/consts.py @@ -47,7 +47,7 @@ SCHEMA_VERSION = 11 SYNC_ZIP_SIZE = int(2.5*1024*1024) SYNC_ZIP_COUNT = 100 SYNC_URL = os.environ.get("SYNC_URL") or "https://ankiweb.net/sync/" -SYNC_VER = 6 +SYNC_VER = 7 HELP_SITE="http://ankisrs.net/docs/manual.html" diff --git a/anki/sync.py b/anki/sync.py index 80e460295..8fe47471e 100644 --- a/anki/sync.py +++ b/anki/sync.py @@ -90,17 +90,39 @@ class Syncer(object): self.server = server def sync(self): - "Returns 'noChanges', 'fullSync', or 'success'." + "Returns 'noChanges', 'fullSync', 'success', etc" + self.syncMsg = "" + self.uname = "" # if the deck has any pending changes, flush them first and bump mod # time self.col.save() # step 1: login & metadata runHook("sync", "login") - ret = self.server.meta() - if not ret: + meta = self.server.meta() + if not meta: return "badAuth" - self.rmod, rscm, self.maxUsn, rts, self.mediaUsn = ret - self.lmod, lscm, self.minUsn, lts, dummy = self.meta() + rscm = meta['scm'] + rts = meta['ts'] + self.rmod = meta['mod'] + self.maxUsn = meta['usn'] + self.mediaUsn = meta['musn'] + self.syncMsg = meta['msg'] + # this is a temporary measure to address the problem of users + # forgetting which email address they've used - it will be removed + # when enough time has passed + self.uname = meta.get("uname", "") + # server requested abort? + if not meta['cont']: + return "serverAbort" + else: + # don't abort, but ui should show message after sync finishes + # and require confirmation if it's non-empty + pass + meta = self.meta() + self.lmod = meta['mod'] + self.minUsn = meta['usn'] + lscm = meta['scm'] + lts = meta['ts'] if abs(rts - lts) > 300: return "clockOff" if self.lmod == self.rmod: @@ -154,7 +176,15 @@ class Syncer(object): return "success" def meta(self): - return (self.col.mod, self.col.scm, self.col._usn, intTime(), None) + return dict( + mod=self.col.mod, + scm=self.col.scm, + usn=self.col._usn, + ts=intTime(), + musn=0, + msg="", + cont=True + ) def changes(self): "Bundle up small objects." diff --git a/aqt/sync.py b/aqt/sync.py index 6d4a321c1..b8a29a39a 100644 --- a/aqt/sync.py +++ b/aqt/sync.py @@ -26,6 +26,7 @@ class SyncManager(QObject): auth = self._getUserPass() if not auth: return + self.pm.profile['syncUser'] = auth[0] self._sync(auth) else: self._sync() @@ -50,6 +51,10 @@ class SyncManager(QObject): self.mw.app.processEvents() self.thread.wait(100) self.mw.progress.finish() + if self.thread.syncMsg: + showText(self.thread.syncMsg) + if self.thread.uname: + self.pm.profile['syncUser'] = self.thread.uname def delayedInfo(): if self._didFullUp and not self._didError: showInfo(_("""\ @@ -270,6 +275,8 @@ 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 @@ -349,8 +356,14 @@ class SyncThread(QThread): # save and note success state if ret == "noChanges": self.fireEvent("noChanges") - else: + elif ret == "success": self.fireEvent("success") + elif ret == "serverAbort": + self.fireEvent("error", self.client.syncMsg) + else: + self.fireEvent("error", "Unknown sync return code.") + self.syncMsg = self.client.syncMsg + self.uname = self.client.uname # then move on to media sync self._syncMedia() diff --git a/tests/test_remote_sync.py b/tests/test_remote_sync.py index c4d90caed..04feaf53d 100644 --- a/tests/test_remote_sync.py +++ b/tests/test_remote_sync.py @@ -45,11 +45,11 @@ def test_meta(): print "aborting; server offline" return ts.server.hkey = TEST_HKEY - (mod, scm, usn, tstamp, mediaUSN) = ts.server.meta() - assert mod - assert scm - assert mod != ts.client.col.mod - assert abs(tstamp - time.time()) < 3 + meta = ts.server.meta() + assert meta['mod'] + assert meta['scm'] + assert meta['mod'] != ts.client.col.mod + assert abs(meta['ts'] - time.time()) < 3 @nose.with_setup(setup_remote) def test_hkey():