From c0ea23c30748845ea1009b9a908a340958e1f3a2 Mon Sep 17 00:00:00 2001 From: flan Date: Mon, 6 Nov 2017 22:50:44 +0100 Subject: [PATCH] Monkey patch anki at runtime The server should work fine with /usr/share/anki now, as long as external Anki version >= 2.1. --- README.md | 10 +++------ ankisyncd/__init__.py | 30 +++++++++++++++++++++++++++ libanki.patch | 48 ------------------------------------------- 3 files changed, 33 insertions(+), 55 deletions(-) delete mode 100644 libanki.patch diff --git a/README.md b/README.md index 69bc0e9..7b0125f 100644 --- a/README.md +++ b/README.md @@ -21,17 +21,13 @@ Installing $ pip install webob -2. Patch the bundled libanki: +2. Modify ankisyncd.conf according to your needs - $ (cd anki-bundled && git apply ../libanki.patch) - -3. Modify ankisyncd.conf according to your needs - -4. Create user: +3. Create user: $ ./ankisyncctl.py adduser -5. Run ankisyncd: +4. Run ankisyncd: $ python ./ankisyncd/sync_app.py ankisyncd.conf diff --git a/ankisyncd/__init__.py b/ankisyncd/__init__.py index 629db46..5cc6251 100644 --- a/ankisyncd/__init__.py +++ b/ankisyncd/__init__.py @@ -1,2 +1,32 @@ +import functools import sys + +def __mediapatch(): + """ + Monkey-patch Anki's MediaManager to ignore the "server" attribute. + + It's needed because MediaManager's __init__(), connect() and close() are + close to no-ops when self.col.server is True. If self.col.server is False, + Syncer.usnLim() doesn't match entities that are supposed to be sent to the + client, thus breaking server→client deck sync. + """ + + def noserver(f): + @functools.wraps(f) + def wrapped(self, *args, **kwargs): + orig = self.col.server + self.col.server = False + ret = f(self, *args, **kwargs) + self.col.server = orig + return ret + return wrapped + + from anki.media import MediaManager + orig_init = MediaManager.__init__ + + MediaManager.__init__ = functools.wraps(MediaManager.__init__)(lambda self, col, _: orig_init(self, col, False)) + MediaManager.connect = noserver(MediaManager.connect) + MediaManager.close = noserver(MediaManager.close) + sys.path.insert(0, "/usr/share/anki") +__mediapatch() diff --git a/libanki.patch b/libanki.patch deleted file mode 100644 index 7d48e44..0000000 --- a/libanki.patch +++ /dev/null @@ -1,48 +0,0 @@ -diff --git a/anki/collection.py b/anki/collection.py -index 6cec228..189c706 100644 ---- a/anki/collection.py -+++ b/anki/collection.py -@@ -60,7 +60,7 @@ class _Collection: - self.server = server - self._lastSave = time.time() - self.clearUndo() -- self.media = MediaManager(self, server) -+ self.media = MediaManager(self) - self.models = ModelManager(self) - self.decks = DeckManager(self) - self.tags = TagManager(self) -diff --git a/anki/media.py b/anki/media.py -index 4e3ccf3..3bfdc81 100644 ---- a/anki/media.py -+++ b/anki/media.py -@@ -26,11 +26,8 @@ class MediaManager: - ] - regexps = soundRegexps + imgRegexps - -- def __init__(self, col, server): -+ def __init__(self, col): - self.col = col -- if server: -- self._dir = None -- return - # media directory - self._dir = re.sub("(?i)\.(anki2)$", ".media", self.col.path) - if not os.path.exists(self._dir): -@@ -48,8 +45,6 @@ class MediaManager: - self.connect() - - def connect(self): -- if self.col.server: -- return - path = self.dir()+".db2" - create = not os.path.exists(path) - os.chdir(self._dir) -@@ -100,8 +95,6 @@ create table meta (dirMod int, lastUsn int); insert into meta values (0, 0); - os.rename("../collection.media.db", npath) - - def close(self): -- if self.col.server: -- return - self.db.close() - self.db = None - # change cwd back to old location