diff --git a/oobsync.py b/oobsync.py index 311a5f9..3f3d3ef 100755 --- a/oobsync.py +++ b/oobsync.py @@ -8,82 +8,111 @@ import os import sys import time +# Finds uno.py for MS-Windows +is_found_uno = False +for p in sys.path: + if os.path.exists(os.path.join(p, "uno.py")): + is_found_uno = True + break +if not is_found_uno: + cand = sys.executable + while cand != os.path.dirname(cand): + cand = os.path.dirname(cand) + if os.path.exists(os.path.join(cand, "uno.py")): + sys.path.append(cand) + break import uno from com.sun.star.connection import NoConnectException + def main(): """ The main program. """ t_start = time.time() global args - + # Parses the arguments parse_args() - + # Connects to the OpenOffice oo = OpenOffice() - + # Synchronize the Basic macros. sync_macros(oo) - + print >> sys.stderr, "Done. %02d:%02d elapsed." % \ (int((time.time() - t_start) / 60), (time.time() - t_start) % 60) + def parse_args(): """ Parses the arguments. """ global args - - parser = argparse.ArgumentParser(description="Synchronize the local Basic scripts with OpenOffice Basic.") - parser.add_argument("projdir", metavar="dir", nargs="?", - default=os.getcwd(), - help="The project source directory (default to the current directory).") - parser.add_argument("library", metavar="Library", nargs="?", - help="The Library to upload/download the macros (default to the name of the directory).") - parser.add_argument("--get", action="store_true", + + parser = argparse.ArgumentParser( + description=("Synchronize the local Basic scripts" + " with OpenOffice Basic.")) + parser.add_argument( + "projdir", metavar="dir", nargs="?", default=os.getcwd(), + help=("The project source directory" + " (default to the current directory).")) + parser.add_argument( + "library", metavar="Library", nargs="?", + help=("The Library to upload/download the macros" + " (default to the name of the directory).")) + parser.add_argument( + "--get", action="store_true", help="Downloads the macros instead of upload.") - parser.add_argument("-r", "--run", metavar="Module.Macro", + parser.add_argument( + "-r", "--run", metavar="Module.Macro", help="The macro to run after the upload, if any.") - parser.add_argument("-v", "--version", - action="version", version="%(prog)s 0.1") + parser.add_argument( + "-v", "--version", action="version", version="%(prog)s 0.1") args = parser.parse_args() - + # Obtains the absolute path args.projdir = os.path.abspath(args.projdir) # Obtains the library name from the path - if args.library == None: + if args.library is None: args.library = os.path.basename(args.projdir) - + return + def sync_macros(oo): """ Synchronize the Basic macros. """ global args - + libraries = oo.service_manager.createInstance( "com.sun.star.script.ApplicationScriptLibraryContainer") # Downloads the macros from OpenOffice if args.get: modules = read_basic_modules(libraries, args.library) if len(modules) == 0: - print >> sys.stderr, "ERROR: Library " + args.library + " does not exist" + print >> sys.stderr, \ + "ERROR: Library " + args.library + " does not exist" return update_source_dir(args.projdir, modules) - + # Uploads the macros onto OpenOffice else: modules = read_in_source_dir(args.projdir) if len(modules) == 0: - print >> sys.stderr, "ERROR: Found no source macros in " + args.projdir + print >> sys.stderr, \ + "ERROR: Found no source macros in " + args.projdir return update_basic_modules(libraries, args.library, modules) - if args.run != None: + if args.run is not None: factory = oo.service_manager.DefaultContext.getByName( - "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") + "/singletons/com.sun.star.script.provider." + "theMasterScriptProviderFactory") provider = factory.createScriptProvider("") script = provider.getScript( - "vnd.sun.star.script:" + args.library + "." + args.run + "?language=Basic&location=application") + "vnd.sun.star.script:" + + args.library + "." + args.run + + "?language=Basic&location=application") script.invoke((), (), ()) return + def read_in_source_dir(projdir): """ Reads-in the source macros. """ modules = {} @@ -92,10 +121,11 @@ def read_in_source_dir(projdir): if os.path.isfile(path) and entry.lower().endswith(".vb"): modname = entry[0:-3] f = open(path) - modules[modname] = f.read() + modules[modname] = f.read().decode("utf-8") f.close() return modules + def update_source_dir(projdir, modules): """ Updates the source macros. """ curmods = {} @@ -105,7 +135,7 @@ def update_source_dir(projdir, modules): modname = entry[0:-3] curmods[modname] = entry for modname in sorted(modules.keys()): - if not curmods.has_key(modname): + if modname not in curmods: path = os.path.join(projdir, modname + ".vb") f = open(path, "w") f.write(modules[modname]) @@ -120,12 +150,13 @@ def update_source_dir(projdir, modules): print >> sys.stderr, curmods[modname] + " updated." f.close() for modname in sorted(curmods.keys()): - if not modules.has_key(modname): + if modname not in modules: path = os.path.join(projdir, curmods[modname]) os.remove(path) print >> sys.stderr, curmods[modname] + " removed." return + def read_basic_modules(libraries, libname): """ Reads the OpenOffice Basic macros from the macros storage. """ modules = {} @@ -137,6 +168,7 @@ def read_basic_modules(libraries, libname): modules[modname] = library.getByName(modname).encode("utf-8") return modules + def update_basic_modules(libraries, libname, modules): """ Updates the OpenOffice Basic macros storage. """ if not libraries.hasByName(libname): @@ -151,30 +183,31 @@ def update_basic_modules(libraries, libname, modules): library = libraries.getByName(libname) curmods = sorted(library.getElementNames()) for modname in sorted(modules.keys()): - if not modname in curmods: + if modname not in curmods: library.insertByName(modname, modules[modname]) print >> sys.stderr, "Module " + modname + " added." - elif modules[modname] != library.getByName(modname).encode("utf-8"): + elif modules[modname] != library.getByName(modname): library.replaceByName(modname, modules[modname]) print >> sys.stderr, "Module " + modname + " updated." for modname in curmods: - if not modules.has_key(modname): + if modname not in modules: library.removeByName(modname) print >> sys.stderr, "Module " + modname + " removed." if libraries.isModified(): libraries.storeLibraries() return + class OpenOffice: - """The OpenOffice connection.""" - + """ The OpenOffice connection. """ + def __init__(self): """Initializes the object.""" self.bootstrap_context = None self.service_manager = None self.desktop = None self.connect() - + def connect(self): """Connects to the running OpenOffice process.""" # Obtains the local context @@ -185,7 +218,8 @@ class OpenOffice: url_resolver = local_service_manager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", local_context) # Obtains the context - url = "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" + url = ("uno:socket,host=localhost,port=2002;" + "urp;StarOffice.ComponentContext") while True: try: self.bootstrap_context = url_resolver.resolve(url) @@ -198,7 +232,7 @@ class OpenOffice: # Obtains the desktop service self.desktop = self.service_manager.createInstanceWithContext( "com.sun.star.frame.Desktop", self.bootstrap_context) - + def start_oo(self): """Starts the OpenOffice in server listening mode""" # For MS-Windows, which does not have fork() @@ -207,10 +241,10 @@ class OpenOffice: ooexec = os.path.join(os.path.dirname(uno.__file__), "soffice.exe") DETACHED_PROCESS = 0x00000008 Popen([ooexec, "-accept=socket,host=localhost,port=2002;urp;"], - close_fds=True, creationflags=DETACHED_PROCESS) + close_fds=True, creationflags=DETACHED_PROCESS) time.sleep(2) return - + # For POSIX systems, including Linux try: pid = os.fork() @@ -223,11 +257,12 @@ class OpenOffice: os.setsid() ooexec = os.path.join(os.path.dirname(uno.__file__), "soffice.bin") try: - os.execl(ooexec, ooexec, + os.execl( + ooexec, ooexec, "-accept=socket,host=localhost,port=2002;urp;") except OSError: - sys.stderr.write(ooexec - + ": Failed to run the OpenOffice server.\n") + sys.stderr.write( + ooexec + ": Failed to run the OpenOffice server.\n") sys.exit(1) if __name__ == "__main__":