From 2452912addcd552fb13f07850d0eda8bf1b79b2e Mon Sep 17 00:00:00 2001 From: Carl-Fredrik Pettersson Date: Thu, 6 Apr 2017 22:17:50 +0200 Subject: [PATCH 1/3] Add support for python2 and python3 --- unox.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/unox.py b/unox.py index bf2796b..4e20f71 100755 --- a/unox.py +++ b/unox.py @@ -20,13 +20,18 @@ import sys import os -import time -import urllib import traceback from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import signal +# Import depending on python version +if sys.version_info.major < 3: + from urllib import quote, unquote +else: + from urllib.parse import quote, unquote + + def sigint_handler(signal, frame): sys.exit(0) @@ -82,7 +87,7 @@ def warn(msg): def sendCmd(cmd, args): raw_cmd = cmd for arg in args: - raw_cmd += " " + urllib.quote(arg); + raw_cmd += " " + quote(arg); if _in_debug: _debug("sendCmd: " + raw_cmd) sys.stdout.write(raw_cmd + "\n") @@ -116,7 +121,7 @@ def recvCmd(): words = line.strip().split(" ") args = [] for word in words[1:]: - args.append(urllib.unquote(word)) + args.append(unquote(word)) return [words[0], args] def pathTokenize(path): From 502491c36444b3300b6f0d86377cc8ecfcd38064 Mon Sep 17 00:00:00 2001 From: Carl-Fredrik Pettersson Date: Thu, 6 Apr 2017 22:20:21 +0200 Subject: [PATCH 2/3] :art: Cleanup --- unox.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/unox.py b/unox.py index 4e20f71..be97b2a 100755 --- a/unox.py +++ b/unox.py @@ -33,7 +33,8 @@ def sigint_handler(signal, frame): - sys.exit(0) + sys.exit(0) + signal.signal(signal.SIGINT, sigint_handler) @@ -52,12 +53,13 @@ def sigint_handler(signal, frame): # Dict of pending replicas that are beeing waited on. # Replica hash mapped to True if replica is pending. -pending_reps = {} +pending_reps = {} # Dict of triggered replicas. # Replica hash mapped to recursive dict where keys are path tokens or True for pending leaf. triggered_reps = {} + def format_exception(e): # Thanks for not bundling this function in the Python library Guido. *facepalm* exception_list = traceback.format_stack() @@ -69,6 +71,7 @@ def format_exception(e): exception_str = exception_str[:-1] return exception_str + def _debug_triggers(): global pending_reps, triggered_reps if not _in_debug_plus: @@ -78,12 +81,15 @@ def _debug_triggers(): wait_info = " | wait=" + str(pending_reps) sys.stderr.write(my_log_prefix + "[DEBUG+]: trig=" + str(triggered_reps) + wait_info + "\n") + def _debug(msg): sys.stderr.write(my_log_prefix + "[DEBUG]: " + msg.strip() + "\n") + def warn(msg): sys.stderr.write(my_log_prefix + "[WARN]: " + msg.strip() + "\n") + def sendCmd(cmd, args): raw_cmd = cmd for arg in args: @@ -91,18 +97,22 @@ def sendCmd(cmd, args): if _in_debug: _debug("sendCmd: " + raw_cmd) sys.stdout.write(raw_cmd + "\n") + # Safely injects a command to send from non-receive context. def injectCmd(cmd, args): sendCmd(cmd, args) sys.stdout.flush() + def sendAck(): sendCmd("OK", []) + def sendError(msg): sendCmd("ERROR", [msg]) os._exit(1) + def recvCmd(): # We flush before stalling on read instead of # flushing every write for optimization purposes. @@ -124,6 +134,7 @@ def recvCmd(): args.append(unquote(word)) return [words[0], args] + def pathTokenize(path): path_toks = [] for path_tok in path.split("/"): @@ -131,6 +142,7 @@ def pathTokenize(path): path_toks.append(path_tok) return path_toks + def triggerReplica(replica, local_path_toks): global pending_reps, triggered_reps if replica in pending_reps: @@ -218,6 +230,7 @@ def startReplicaMon(replica, fspath, path): else: sendError("unexpected cmd in replica start: " + cmd) + def reportRecursiveChanges(local_path, cur_lvl): if (cur_lvl == True): sendCmd("RECURSIVE", [local_path]) @@ -225,6 +238,7 @@ def reportRecursiveChanges(local_path, cur_lvl): for path_tok, new_lvl in cur_lvl.items(): reportRecursiveChanges(os.path.join(local_path, path_tok), new_lvl); + def main(): global replicas, pending_reps, triggered_reps # Version handshake. @@ -292,6 +306,7 @@ def main(): else: sendError("unexpected root cmd: " + cmd) + if __name__ == '__main__': try: main() From a94501d6231a50eb501fc90ef7281f6721277c60 Mon Sep 17 00:00:00 2001 From: Carl-Fredrik Pettersson Date: Mon, 10 Apr 2017 22:29:39 +0200 Subject: [PATCH 3/3] FIX: recursive bug The observer.schedule defaults to recursive=False This resulted in that it did not pick up events in subfolders. --- unox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unox.py b/unox.py index be97b2a..c4e3c4b 100755 --- a/unox.py +++ b/unox.py @@ -211,7 +211,7 @@ def startReplicaMon(replica, fspath, path): # and compare against a snapshot. This means there's no point in us doing it, better leave it to Unison. if _in_debug: _debug("replica:[" + replica + "] watching path [" + fspath + "]") handler = Handler(fspath, replica) - watch = observer.schedule(handler, fspath) + watch = observer.schedule(handler, fspath, recursive=True) except Exception as e: sendError(str(e)) replicas[replica] = {