def handle_wrap(self, msg, args): if msg in ("Call", "Doc"): path = args["Macro"].rsplit(".", 1) if len(path)==1: path.insert(0, DEF_MODULE) if path[0] in macro_tree and path[1] in macro_tree[path[0]]: macro = getattr(modules[path[0]], path[1], None) else: macro = None if not macro: return "SERVER_NO_MACRO" elif msg == "Doc": print("Help on '%s' requested"%args["Macro"]) return macro.__doc__ or "" else: #Caller must 'Test' if server is 'OK' before this print("Macro '%s' called "%path[1]) invoker.invoke(app().form.startMacro, macro, args["Workbook"]) return "OK" elif msg == "Request": print("Macro list requested") return "|".join(getMacroList(args["Application"])) elif msg == "Test": print("Connection checked") with run_lock: return "Busy" if not run_lock._value else "OK" elif msg == "Interrupt": print("Request to interrupt macro") with run_lock: #FIXME: It's possible to make several requests before macro is interrupted. Is it ok? if not run_lock._value: _thread.interrupt_main() else: return "Not busy" return "OK" else: print("Unknown message") return "Unknown"
def __init__(self): initModuleLoader() self.server = TCPServer((SHARED_SERVER_ADDR, SHARED_SERVER_PORT), Handler) threading.Thread(target=self.server.serve_forever).start() self.tray.addMenuItem("Exit", self.btnExit_clicked) self.terminated.connect(self.btnExit_clicked) self.twModules.header().close() for i in self.office_icons: self.office_icons[i] = QtGui.QIcon(str(app().path.joinpath(self.office_icons[i])))
def initModuleLoader(): watch, loader_lock = {}, threading.RLock() src_path = str(app().path.joinpath("source")) def watcher(): def readChanges(h, flags): return win32file.ReadDirectoryChangesW(h, 1024, True, flags, None, None) actions = {1: "add", 2: "del", 3: "add", 4: "del", 5: "add"} #3 - update; 4, 5 - rename hDir = win32file.CreateFile(src_path, winnt.FILE_LIST_DIRECTORY, win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE, None, win32con.OPEN_EXISTING, win32con.FILE_FLAG_BACKUP_SEMANTICS, None) while True: for action, file in readChanges(hDir, win32con.FILE_NOTIFY_CHANGE_FILE_NAME| win32con.FILE_NOTIFY_CHANGE_LAST_WRITE): filename = pathlib.Path(file) if filename.suffix == ".py" and not filename.stem.startswith("__"): with loader_lock: watch[filename.stem] = actions[action] def unload(mod_name): if mod_name in modules: # m = modules[mod_name] del modules[mod_name], macro_tree[mod_name], sys.modules[SOURCEDIR+"."+mod_name] # print(sys.getrefcount(m)) def import_mod(mod_name): try: macro_tree[mod_name] = {} modules[mod_name] = importlib.import_module(SOURCEDIR+"."+mod_name) print("Module '%s' updated"%mod_name) except Exception as e: print("Failed to update '%s' module: %s: %s"%(mod_name, type(e).__name__, e)) del macro_tree[mod_name] def reloader(): while True: with loader_lock: if len(watch): #if update needed for i in watch: if watch[i] == "add": if i in modules: unload(i) import_mod(i) elif watch[i] == "del": unload(i) print("Module '%s' unloaded"%i) invoker.wait(app().form.updateMacroTree) watch.clear() time.sleep(1) for i in [f for f in pathlib.Path(src_path).iterdir() if f.is_file() and f.suffix == ".py" and not f.stem.startswith("__")]: watch[i.stem] = "add" for i in threading.Thread(target=watcher), \ threading.Thread(target=reloader): i.daemon = True i.start()
def reloader(): while True: with loader_lock: if len(watch): #if update needed for i in watch: if watch[i] == "add": if i in modules: unload(i) import_mod(i) elif watch[i] == "del": unload(i) print("Module '%s' unloaded"%i) invoker.wait(app().form.updateMacroTree) watch.clear() time.sleep(1)
def showConsole(): app().form.showWindow(console=True)