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 _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.hkey, self.server.con) self.client = MediaSyncer(self.col, self.server) ret = self.client.sync(self.mediaUsn) if ret == "noChanges": self.fireEvent("noMediaChanges") else: self.fireEvent("mediaSuccess")
def _sync_anki(col_path, anki_hkey): try: col = Collection(col_path) server = RemoteServer(anki_hkey) client = FullSyncer(col, anki_hkey, server.client) client.download() col = Collection(col_path) # reload collection media_server = RemoteMediaServer(col, anki_hkey, server.client) media_client = MediaSyncer(col, media_server) media_client.sync() col.close(save=True) except: return traceback.format_exc()
def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.localIsEmpty = self.col.isEmpty() self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) try: if f == "upload": if not self.client.upload(): self.fireEvent("upbad") else: ret = self.client.download() if ret == "downloadClobber": self.fireEvent(ret) return except Exception as e: if "sync cancelled" in str(e): return raise # reopen db and move on to media sync self.col.reopen() self._syncMedia()
def create_client_syncer(collection, hkey, server_test_app): mock_remote_server = MockRemoteMediaServer(col=collection, hkey=hkey, server_test_app=server_test_app) media_syncer = MediaSyncer(col=collection, server=mock_remote_server) return media_syncer
def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.localIsEmpty = self.col.isEmpty() self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) try: if f == "upload": if not self.client.upload(): self.fireEvent("upbad") else: self.client.download() except Exception as e: if "sync cancelled" in str(e): return raise # reopen db and move on to media sync self.col.reopen() self._syncMedia()
def _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.col, self.hkey, self.server.client) self.client = MediaSyncer(self.col, self.server) try: ret = self.client.sync() except Exception as e: if "sync cancelled" in str(e): return raise if ret == "noChanges": self.fireEvent("noMediaChanges") elif ret == "sanityCheckFailed" or ret == "corruptMediaDB": self.fireEvent("mediaSanity") else: self.fireEvent("mediaSuccess")
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, log=True) except: self.fireEvent("corrupt") return self.server = RemoteServer(self.hkey) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 # throttle updates; qt doesn't handle lots of posted events well self.byteUpdate = time.time() def syncEvent(type): self.fireEvent("sync", type) def syncMsg(msg): self.fireEvent("syncMsg", msg) def canPost(): if (time.time() - self.byteUpdate) > 0.1: self.byteUpdate = time.time() return True def sendEvent(bytes): self.sentTotal += bytes if canPost(): self.fireEvent("send", str(self.sentTotal)) def recvEvent(bytes): self.recvTotal += bytes if canPost(): self.fireEvent("recv", str(self.recvTotal)) addHook("sync", syncEvent) addHook("syncMsg", syncMsg) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("syncMsg", syncMsg) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent)
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, log=True) except: self.fireEvent("corrupt") return self.server = RemoteServer(self.hkey, hostNum=self.hostNum) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 def syncEvent(type): self.fireEvent("sync", type) def syncMsg(msg): self.fireEvent("syncMsg", msg) def sendEvent(bytes): if not self._abort: self.sentTotal += bytes self.fireEvent("send", str(self.sentTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") def recvEvent(bytes): if not self._abort: self.recvTotal += bytes self.fireEvent("recv", str(self.recvTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") addHook("sync", syncEvent) addHook("syncMsg", syncMsg) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("syncMsg", syncMsg) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent)
def _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.col, self.hkey, self.server.client) self.client = MediaSyncer(self.col, self.server) try: ret = self.client.sync() except Exception as e: if "sync cancelled" in str(e): return raise if ret == "noChanges": self.fireEvent("noMediaChanges") elif ret == "sanityCheckFailed": self.fireEvent("mediaSanity") else: self.fireEvent("mediaSuccess")
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, log=True) except: self.fireEvent("corrupt") return self.server = RemoteServer(self.hkey, hostNum=self.hostNum) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 def syncEvent(type): self.fireEvent("sync", type) def syncMsg(msg): self.fireEvent("syncMsg", msg) def http_progress(upload: int, download: int) -> None: if not self._abort: self.sentTotal += upload self.recvTotal += download self.progress_event.emit(self.sentTotal, self.recvTotal) # type: ignore elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") self.server.client.progress_hook = http_progress hooks.sync_stage_did_change.append(syncEvent) hooks.sync_progress_did_change.append(syncMsg) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) hooks.sync_stage_did_change.remove(syncEvent) hooks.sync_progress_did_change.remove(syncMsg)
def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.con) if f == "upload": self.client.upload() else: self.client.download() # reopen db and move on to media sync self.col.reopen() self._syncMedia()
def run(self): self.col = Collection(self.path) self.server = RemoteServer(self.hkey) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 # throttle updates; qt doesn't handle lots of posted events well self.byteUpdate = time.time() def syncEvent(type): self.fireEvent("sync", type) def canPost(): if (time.time() - self.byteUpdate) > 0.1: self.byteUpdate = time.time() return True def sendEvent(bytes): self.sentTotal += bytes if canPost(): self.fireEvent("send", self.sentTotal) def recvEvent(bytes): self.recvTotal += bytes if canPost(): self.fireEvent("recv", self.recvTotal) addHook("sync", syncEvent) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() print err self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent)
def _fullSync(self): # if the local deck is empty, assume user is trying to download if self.col.isEmpty(): f = "download" else: # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.con) if f == "upload": if not self.client.upload(): self.fireEvent("upbad") else: self.client.download() # reopen db and move on to media sync self.col.reopen() self._syncMedia()
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!')
class SyncThread(QThread): event = pyqtSignal(str, str) def __init__(self, path, hkey, auth=None, media=True, hostNum=None): QThread.__init__(self) self.path = path self.hkey = hkey self.auth = auth self.media = media self.hostNum = hostNum self._abort = 0 # 1=flagged, 2=aborting def flagAbort(self): self._abort = 1 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, log=True) except: self.fireEvent("corrupt") return self.server = RemoteServer(self.hkey, hostNum=self.hostNum) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 def syncEvent(type): self.fireEvent("sync", type) def syncMsg(msg): self.fireEvent("syncMsg", msg) def sendEvent(bytes): if not self._abort: self.sentTotal += bytes self.fireEvent("send", str(self.sentTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") def recvEvent(bytes): if not self._abort: self.recvTotal += bytes self.fireEvent("recv", str(self.recvTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") addHook("sync", syncEvent) addHook("syncMsg", syncMsg) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("syncMsg", syncMsg) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent) def _abortingSync(self): try: return self.client.sync() except Exception as e: if "sync cancelled" in str(e): self.server.abort() raise else: raise def _sync(self): if self.auth: # need to authenticate and obtain host key self.hkey = self.server.hostKey(*self.auth) if not self.hkey: # provided details were invalid return self.fireEvent("badAuth") else: # write new details and tell calling thread to save self.fireEvent("newKey", self.hkey) # run sync and check state try: ret = self._abortingSync() except Exception as e: log = traceback.format_exc() err = repr(str(e)) if ("Unable to find the server" in err or "Errno 2" in err or "getaddrinfo" in err): self.fireEvent("offline") elif "sync cancelled" in err: pass else: self.fireEvent("error", log) return if ret == "badAuth": return self.fireEvent("badAuth") elif ret == "clockOff": return self.fireEvent("clockOff") elif ret == "basicCheckFailed" or ret == "sanityCheckFailed": return self.fireEvent("checkFailed") # full sync? if ret == "fullSync": return self._fullSync() # save and note success state if ret == "noChanges": self.fireEvent("noChanges") elif ret == "success": self.fireEvent("success") elif ret == "serverAbort": pass else: self.fireEvent("error", "Unknown sync return code.") self.syncMsg = self.client.syncMsg self.uname = self.client.uname self.hostNum = self.client.hostNum # then move on to media sync self._syncMedia() def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.localIsEmpty = self.col.isEmpty() self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) try: if f == "upload": if not self.client.upload(): self.fireEvent("upbad") else: self.client.download() except Exception as e: if "sync cancelled" in str(e): return raise # reopen db and move on to media sync self.col.reopen() self._syncMedia() def _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) self.client = MediaSyncer(self.col, self.server) try: ret = self.client.sync() except Exception as e: if "sync cancelled" in str(e): return raise if ret == "noChanges": self.fireEvent("noMediaChanges") elif ret == "sanityCheckFailed" or ret == "corruptMediaDB": self.fireEvent("mediaSanity") else: self.fireEvent("mediaSuccess") def fireEvent(self, cmd, arg=""): self.event.emit(cmd, arg)
class SyncThread(QThread): event = pyqtSignal(str, str) def __init__(self, path, hkey, auth=None, media=True, hostNum=None): QThread.__init__(self) self.path = path self.hkey = hkey self.auth = auth self.media = media self.hostNum = hostNum self._abort = 0 # 1=flagged, 2=aborting def flagAbort(self): self._abort = 1 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, log=True) except: self.fireEvent("corrupt") return self.server = RemoteServer(self.hkey, hostNum=self.hostNum) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 def syncEvent(type): self.fireEvent("sync", type) def syncMsg(msg): self.fireEvent("syncMsg", msg) def sendEvent(bytes): if not self._abort: self.sentTotal += bytes self.fireEvent("send", str(self.sentTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") def recvEvent(bytes): if not self._abort: self.recvTotal += bytes self.fireEvent("recv", str(self.recvTotal)) elif self._abort == 1: self._abort = 2 raise Exception("sync cancelled") addHook("sync", syncEvent) addHook("syncMsg", syncMsg) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("syncMsg", syncMsg) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent) def _abortingSync(self): try: return self.client.sync() except Exception as e: if "sync cancelled" in str(e): self.server.abort() raise else: raise def _sync(self): if self.auth: # need to authenticate and obtain host key self.hkey = self.server.hostKey(*self.auth) if not self.hkey: # provided details were invalid return self.fireEvent("badAuth") else: # write new details and tell calling thread to save self.fireEvent("newKey", self.hkey) # run sync and check state try: ret = self._abortingSync() except Exception as e: log = traceback.format_exc() err = repr(str(e)) if ("Unable to find the server" in err or "Errno 2" in err or "getaddrinfo" in err): self.fireEvent("offline") elif "sync cancelled" in err: pass else: self.fireEvent("error", log) return if ret == "badAuth": return self.fireEvent("badAuth") elif ret == "clockOff": return self.fireEvent("clockOff") elif ret == "basicCheckFailed" or ret == "sanityCheckFailed": return self.fireEvent("checkFailed") # full sync? if ret == "fullSync": return self._fullSync() # save and note success state if ret == "noChanges": self.fireEvent("noChanges") elif ret == "success": self.fireEvent("success") elif ret == "serverAbort": self.syncMsg = self.client.syncMsg return else: self.fireEvent("error", "Unknown sync return code.") self.syncMsg = self.client.syncMsg self.uname = self.client.uname self.hostNum = self.client.hostNum # then move on to media sync self._syncMedia() def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.localIsEmpty = self.col.isEmpty() self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) try: if f == "upload": if not self.client.upload(): self.fireEvent("upbad") else: ret = self.client.download() if ret == "downloadClobber": self.fireEvent(ret) return except Exception as e: if "sync cancelled" in str(e): return raise # reopen db and move on to media sync self.col.reopen() self._syncMedia() def _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.col, self.hkey, self.server.client, hostNum=self.hostNum) self.client = MediaSyncer(self.col, self.server) try: ret = self.client.sync() except Exception as e: if "sync cancelled" in str(e): return raise if ret == "noChanges": self.fireEvent("noMediaChanges") elif ret == "sanityCheckFailed" or ret == "corruptMediaDB": self.fireEvent("mediaSanity") else: self.fireEvent("mediaSuccess") def fireEvent(self, cmd, arg=""): self.event.emit(cmd, arg)
def remove(self, fnames, minUsn): rrem = MediaSyncer.remove(self, fnames, minUsn) # increment the USN for each file removed #self.col.media.setUsn(self.col.media.usn() + len(rrem)) return rrem
def __init__(self, col): MediaSyncer.__init__(self, col)
def setup_remoteMedia(): setup_basic() con = httpCon() ts.server = RemoteMediaServer(TEST_HKEY, con) ts.server2 = RemoteServer(TEST_HKEY) ts.client = MediaSyncer(ts.deck1, ts.server)
class SyncThread(QThread): def __init__(self, path, hkey, auth=None, media=True): QThread.__init__(self) self.path = path self.hkey = hkey self.auth = auth self.media = media def run(self): self.col = Collection(self.path) self.server = RemoteServer(self.hkey) self.client = Syncer(self.col, self.server) self.sentTotal = 0 self.recvTotal = 0 # throttle updates; qt doesn't handle lots of posted events well self.byteUpdate = time.time() def syncEvent(type): self.fireEvent("sync", type) def canPost(): if (time.time() - self.byteUpdate) > 0.1: self.byteUpdate = time.time() return True def sendEvent(bytes): self.sentTotal += bytes if canPost(): self.fireEvent("send", self.sentTotal) def recvEvent(bytes): self.recvTotal += bytes if canPost(): self.fireEvent("recv", self.recvTotal) addHook("sync", syncEvent) addHook("httpSend", sendEvent) addHook("httpRecv", recvEvent) # run sync and catch any errors try: self._sync() except: err = traceback.format_exc() print err self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save self.col.close(save=False) remHook("sync", syncEvent) remHook("httpSend", sendEvent) remHook("httpRecv", recvEvent) def _sync(self): if self.auth: # need to authenticate and obtain host key self.hkey = self.server.hostKey(*self.auth) if not self.hkey: # provided details were invalid return self.fireEvent("badAuth") else: # write new details and tell calling thread to save self.fireEvent("newKey", self.hkey) # run sync and check state ret = self.client.sync() if ret == "badAuth": return self.fireEvent("badAuth") elif ret == "clockOff": return self.fireEvent("clockOff") # note mediaUSN for later self.mediaUsn = self.client.mediaUsn # full sync? if ret == "fullSync": return self._fullSync() # save and note success state self.col.save() if ret == "noChanges": self.fireEvent("noChanges") else: self.fireEvent("success") # then move on to media sync self._syncMedia() def _fullSync(self): # tell the calling thread we need a decision on sync direction, and # wait for a reply self.fullSyncChoice = False self.fireEvent("fullSync") while not self.fullSyncChoice: time.sleep(0.1) f = self.fullSyncChoice if f == "cancel": return self.client = FullSyncer(self.col, self.hkey, self.server.con) if f == "upload": self.client.upload() else: self.client.download() # reopen db and move on to media sync self.col.reopen() self._syncMedia() def _syncMedia(self): if not self.media: return self.server = RemoteMediaServer(self.hkey, self.server.con) self.client = MediaSyncer(self.col, self.server) ret = self.client.sync(self.mediaUsn) if ret == "noChanges": self.fireEvent("noMediaChanges") else: self.fireEvent("mediaSuccess") def fireEvent(self, *args): self.emit(SIGNAL("event"), *args)