def test_threeway(): test_sync() deck1.close(save=False) d3path = deck1.path.replace(".anki", "2.anki") shutil.copy2(deck1.path, d3path) deck1.reopen() deck3 = aopen(d3path) client2 = Syncer(deck3, server) assert client2.sync() == "noChanges" # client 1 adds a card at time 1 time.sleep(1) f = deck1.newNote() f['Front'] = "1" deck1.addNote(f) deck1.save() # at time 2, client 2 syncs to server time.sleep(1) deck3.setMod() deck3.save() assert client2.sync() == "success" # at time 3, client 1 syncs, adding the older note time.sleep(1) assert client.sync() == "success" assert deck1.noteCount() == deck2.noteCount() # syncing client2 should pick it up assert client2.sync() == "success" assert deck1.noteCount() == deck2.noteCount() == deck3.noteCount()
def test_threeway(): test_sync() deck1.close(save=False) d3path = deck1.path.replace(".anki", "2.anki") shutil.copy2(deck1.path, d3path) deck1.reopen() deck3 = aopen(d3path) client2 = Syncer(deck3, server) assert client2.sync() == "noChanges" # client 1 adds a card at time 1 time.sleep(1) f = deck1.newNote() f['Front'] = u"1"; deck1.addNote(f) deck1.save() # at time 2, client 2 syncs to server time.sleep(1) deck3.setMod() deck3.save() assert client2.sync() == "success" # at time 3, client 1 syncs, adding the older note time.sleep(1) assert client.sync() == "success" assert deck1.noteCount() == deck2.noteCount() # syncing client2 should pick it up assert client2.sync() == "success" assert deck1.noteCount() == deck2.noteCount() == deck3.noteCount()
def sync(self): """Sync collection to AnkiWeb""" if self.pm is None: return hkey = self.pm.sync_key() hostNum = self.pm.sync_shard() if not hkey: click.echo('No sync auth registered in profile') return # Initialize servers and sync clients server = RemoteServer(hkey, hostNum=hostNum) main_client = Syncer(self.col, server) # Perform main sync try: click.echo('Syncing deck ... ', nl=False) ret = main_client.sync() except Exception as e: if 'sync cancelled' in str(e): server.abort() click.secho('Error during sync!', fg='red') click.echo(e) raise click.Abort() # Parse return value if ret == "noChanges": click.echo('done (no changes)!') elif ret == "success": click.echo('done!') elif ret == "serverAbort": click.echo('aborted!') return elif ret == "fullSync": click.echo('aborted!') click.secho('Full sync required!', fg='red') return else: click.echo('failed!') click.echo(f'Message: {ret}') return # Perform media sync try: debug_output = 'media=debug' in os.environ.get('RUST_LOG', '') with cd(self.col.media.dir()): if debug_output: click.echo('Syncing media:') else: click.echo('Syncing media ... ', nl=False) self.col.backend.sync_media( hkey, f"https://sync{hostNum}.ankiweb.net/msync/") if not debug_output: click.echo('done!') except Exception as e: if "sync cancelled" in str(e): return raise
def sync_collection(username, password, full_sync="upload"): from anki.sync import Syncer, RemoteServer, FullSyncer, MediaSyncer, RemoteMediaServer collection = open_or_create_collection(username) server = RemoteServer(None) app.logger.info("u: %s,pass: %s" % (username, password)) hkey = server.hostKey(username, password) syncer = Syncer(collection, server) ret = syncer.sync() app.logger.info("syncer return: %s" % ret) if (ret == "fullSync"): # app.logger.info("trying to do fullSync - upload - Not tested") client = FullSyncer(collection, hkey, server.client) if full_sync == "download": client.download() else: client.upload() if ret not in ("noChanges", "fullSync", "success"): collection.close() return False mediaserver = RemoteMediaServer(collection, hkey, server.client) mediaclient = MediaSyncer(collection, mediaserver) mediaret = mediaclient.sync() app.logger.info("mediasync returned: %s" % mediaret) collection.save() collection.close() return True
def sync(self): server= RemoteServer(self.pm.profile['syncKey']) client = Syncer(self.collection, server) ret = None try: print client.sync() except Exception, e: log = traceback.format_exc() try: err = unicode(e[0], "utf8", "ignore") except: # number, exception with no args, etc err = "" if "Unable to find the server" in err: print "offline" return else: if not isinstance(log, unicode): err = unicode(log, "utf8", "replace") print "error", log return
def sync_server(self): server = RemoteServer(self.profile['syncKey'], self.profile['hostNum']) client = Syncer(self.col, server) res = client.sync() if res in ['success', 'noChanges']: pass elif res == 'fullSync': print('FULL SYNC') client = FullSyncer(self.col, self.profile['syncKey'], server.client, self.profile['hostNum']) client.download() self.col.reopen()
def _test_speed(): t = time.time() deck1 = aopen(os.path.expanduser("~/rapid.anki")) for tbl in "revlog", "cards", "notes", "graves": deck1.db.execute("update %s set usn = -1 where usn != -1"%tbl) for m in deck1.models.all(): m['usn'] = -1 for tx in deck1.tags.all(): deck1.tags.tags[tx] = -1 deck1._usn = -1 deck1.save() deck2 = getEmptyDeck(server=True) deck1.scm = deck2.scm = 0 server = LocalServer(deck2) client = Syncer(deck1, server) print "load %d" % ((time.time() - t)*1000); t = time.time() assert client.sync() == "success" print "sync %d" % ((time.time() - t)*1000); t = time.time()
def test_threeway2(): # for this test we want ms precision of notes so we don't have to # sleep a lot import anki.notes intTime = anki.notes.intTime anki.notes.intTime = lambda x=1: intTime(1000) def setup(): # create collection 1 with a single note c1 = getEmptyCol() f = c1.newNote() f['Front'] = "startingpoint" nid = f.id c1.addNote(f) cid = f.cards()[0].id c1.beforeUpload() # start both clients and server off in this state s1path = c1.path.replace(".anki2", "-s1.anki2") c2path = c1.path.replace(".anki2", "-c2.anki2") shutil.copy2(c1.path, s1path) shutil.copy2(c1.path, c2path) # open them c1 = Collection(c1.path) c2 = Collection(c2path) s1 = Collection(s1path, server=True) return c1, c2, s1, nid, cid c1, c2, s1, nid, cid = setup() # modify c1 then sync c1->s1 n = c1.getNote(nid) t = "firstmod" n['Front'] = t n.flush() c1.db.execute("update cards set mod=1, usn=-1") srv = LocalServer(s1) clnt1 = Syncer(c1, srv) clnt1.sync() n.load() assert n['Front'] == t assert s1.getNote(nid)['Front'] == t assert s1.db.scalar("select mod from cards") == 1 # sync s1->c2 clnt2 = Syncer(c2, srv) clnt2.sync() assert c2.getNote(nid)['Front'] == t assert c2.db.scalar("select mod from cards") == 1 # modify c1 and sync time.sleep(0.001) t = "secondmod" n = c1.getNote(nid) n['Front'] = t n.flush() c1.db.execute("update cards set mod=2, usn=-1") clnt1.sync() # modify c2 and sync - both c2 and server should be the same time.sleep(0.001) t2 = "thirdmod" n = c2.getNote(nid) n['Front'] = t2 n.flush() c2.db.execute("update cards set mod=3, usn=-1") clnt2.sync() n.load() assert n['Front'] == t2 assert c2.db.scalar("select mod from cards") == 3 n = s1.getNote(nid) assert n['Front'] == t2 assert s1.db.scalar("select mod from cards") == 3 # and syncing c1 again should yield the updated note as well clnt1.sync() n = s1.getNote(nid) assert n['Front'] == t2 assert s1.db.scalar("select mod from cards") == 3 n = c1.getNote(nid) assert n['Front'] == t2 assert c1.db.scalar("select mod from cards") == 3
def test_threeway2(): # for this test we want ms precision of notes so we don't have to # sleep a lot import anki.notes intTime = anki.notes.intTime anki.notes.intTime = lambda x=1: intTime(1000) def setup(): # create collection 1 with a single note c1 = getEmptyCol() f = c1.newNote() f['Front'] = u"startingpoint" nid = f.id c1.addNote(f) cid = f.cards()[0].id c1.beforeUpload() # start both clients and server off in this state s1path = c1.path.replace(".anki2", "-s1.anki2") c2path = c1.path.replace(".anki2", "-c2.anki2") shutil.copy2(c1.path, s1path) shutil.copy2(c1.path, c2path) # open them c1 = Collection(c1.path) c2 = Collection(c2path) s1 = Collection(s1path, server=True) return c1, c2, s1, nid, cid c1, c2, s1, nid, cid = setup() # modify c1 then sync c1->s1 n = c1.getNote(nid) t = "firstmod" n['Front'] = t n.flush() c1.db.execute("update cards set mod=1, usn=-1") srv = LocalServer(s1) clnt1 = Syncer(c1, srv) clnt1.sync() n.load() assert n['Front'] == t assert s1.getNote(nid)['Front'] == t assert s1.db.scalar("select mod from cards") == 1 # sync s1->c2 clnt2 = Syncer(c2, srv) clnt2.sync() assert c2.getNote(nid)['Front'] == t assert c2.db.scalar("select mod from cards") == 1 # modify c1 and sync time.sleep(0.001) t = "secondmod" n = c1.getNote(nid) n['Front'] = t n.flush() c1.db.execute("update cards set mod=2, usn=-1") clnt1.sync() # modify c2 and sync - both c2 and server should be the same time.sleep(0.001) t2 = "thirdmod" n = c2.getNote(nid) n['Front'] = t2 n.flush() c2.db.execute("update cards set mod=3, usn=-1") clnt2.sync() n.load() assert n['Front'] == t2 assert c2.db.scalar("select mod from cards") == 3 n = s1.getNote(nid) assert n['Front'] == t2 assert s1.db.scalar("select mod from cards") == 3 # and syncing c1 again should yield the updated note as well clnt1.sync() n = s1.getNote(nid) assert n['Front'] == t2 assert s1.db.scalar("select mod from cards") == 3 n = c1.getNote(nid) assert n['Front'] == t2 assert c1.db.scalar("select mod from cards") == 3
def sync(self): """Sync collection to AnkiWeb""" if self.pm is None: return import click if not self.pm.profile['syncKey']: click.echo('No sync auth registered in profile') return from anki.sync import (Syncer, MediaSyncer, RemoteServer, RemoteMediaServer) # Initialize servers and sync clients hkey = self.pm.profile['syncKey'] hostNum = self.pm.profile.get('hostNum') server = RemoteServer(hkey, hostNum=hostNum) main_client = Syncer(self.col, server) media_client = MediaSyncer( self.col, RemoteMediaServer(self.col, hkey, server.client, hostNum=hostNum)) # Perform main sync try: click.echo('Syncing deck ... ', nl=False) ret = main_client.sync() except Exception as e: if 'sync cancelled' in str(e): server.abort() click.secho('Error during sync!', fg='red') click.echo(e) raise click.Abort() # Parse return value if ret == "noChanges": click.echo('done (no changes)!') elif ret == "success": click.echo('done!') elif ret == "serverAbort": click.echo('aborted!') return elif ret == "fullSync": click.echo('aborted!') click.secho('Full sync required!', fg='red') return else: click.echo('failed!') click.echo(f'Message: {ret}') return # Perform media sync try: click.echo('Syncing media ... ', nl=False) save_cwd = os.getcwd() os.chdir(self.col.media.dir()) ret = media_client.sync() os.chdir(save_cwd) except Exception as e: if "sync cancelled" in str(e): return raise if ret == "noChanges": click.echo('done (no changes)!') elif ret in ("sanityCheckFailed", "corruptMediaDB"): click.echo('failed!') else: click.echo('done!')