Added setuptools and published to PyPI, so that it can be installed with pip.
This commit is contained in:
297
bin/obasync
Normal file
297
bin/obasync
Normal file
@ -0,0 +1,297 @@
|
||||
#! /opt/openoffice4/program/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Office Basic macro source synchronizer.
|
||||
# by imacat <imacat@mail.imacat.idv.tw>, 2016-08-31
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def append_uno_path():
|
||||
""" Appends the path of the uno module to the import path. """
|
||||
|
||||
is_found_uno = False
|
||||
for p in sys.path:
|
||||
if os.path.exists(os.path.join(p, "uno.py")):
|
||||
return
|
||||
# For uno.py on MacOS
|
||||
cand = "/Applications/OpenOffice.app/Contents/MacOS"
|
||||
if os.path.exists(os.path.join(cand, "uno.py")):
|
||||
sys.path.append(cand)
|
||||
return
|
||||
# Finds uno.py for MS-Windows
|
||||
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)
|
||||
return
|
||||
|
||||
append_uno_path()
|
||||
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",
|
||||
help="Downloads the macros instead of upload.")
|
||||
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")
|
||||
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 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"
|
||||
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
|
||||
return
|
||||
update_basic_modules(libraries, args.library, modules, oo)
|
||||
if args.run is not None:
|
||||
factory = oo.service_manager.DefaultContext.getByName(
|
||||
"/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")
|
||||
script.invoke((), (), ())
|
||||
return
|
||||
|
||||
|
||||
def read_in_source_dir(projdir):
|
||||
""" Reads-in the source macros. """
|
||||
modules = {}
|
||||
for entry in os.listdir(projdir):
|
||||
path = os.path.join(projdir, entry)
|
||||
if os.path.isfile(path) and entry.lower().endswith(".vb"):
|
||||
modname = entry[0:-3]
|
||||
f = open(path)
|
||||
modules[modname] = f.read().decode("utf-8").replace(
|
||||
"\r\n", "\n")
|
||||
f.close()
|
||||
return modules
|
||||
|
||||
|
||||
def update_source_dir(projdir, modules):
|
||||
""" Updates the source macros. """
|
||||
curmods = {}
|
||||
is_in_sync = True
|
||||
for entry in os.listdir(projdir):
|
||||
path = os.path.join(projdir, entry)
|
||||
if os.path.isfile(path) and entry.lower().endswith(".vb"):
|
||||
modname = entry[0:-3]
|
||||
curmods[modname] = entry
|
||||
for modname in sorted(modules.keys()):
|
||||
if modname not in curmods:
|
||||
path = os.path.join(projdir, modname + ".vb")
|
||||
f = open(path, "w")
|
||||
f.write(modules[modname])
|
||||
f.close()
|
||||
print >> sys.stderr, modname + ".vb added."
|
||||
is_in_sync = False
|
||||
else:
|
||||
path = os.path.join(projdir, curmods[modname])
|
||||
f = open(path, "r+")
|
||||
if modules[modname] != f.read().replace("\r\n", "\n"):
|
||||
f.seek(0)
|
||||
f.write(modules[modname])
|
||||
print >> sys.stderr, curmods[modname] + " updated."
|
||||
is_in_sync = False
|
||||
f.close()
|
||||
for modname in sorted(curmods.keys()):
|
||||
if modname not in modules:
|
||||
path = os.path.join(projdir, curmods[modname])
|
||||
os.remove(path)
|
||||
print >> sys.stderr, curmods[modname] + " removed."
|
||||
is_in_sync = False
|
||||
if is_in_sync:
|
||||
print >> sys.stderr, "Everything is in sync."
|
||||
return
|
||||
|
||||
|
||||
def read_basic_modules(libraries, libname):
|
||||
""" Reads the OpenOffice Basic macros from the macros storage. """
|
||||
modules = {}
|
||||
if not libraries.hasByName(libname):
|
||||
return modules
|
||||
libraries.loadLibrary(libname)
|
||||
library = libraries.getByName(libname)
|
||||
for modname in library.getElementNames():
|
||||
modules[modname] = library.getByName(modname).encode("utf-8")
|
||||
return modules
|
||||
|
||||
|
||||
def update_basic_modules(libraries, libname, modules, oo):
|
||||
""" Updates the OpenOffice Basic macros storage. """
|
||||
if not libraries.hasByName(libname):
|
||||
libraries.createLibrary(libname)
|
||||
print >> sys.stderr, "Script library " + libname + " created."
|
||||
create_dialog_library(oo, libname)
|
||||
library = libraries.getByName(libname)
|
||||
for modname in sorted(modules.keys()):
|
||||
library.insertByName(modname, modules[modname])
|
||||
print >> sys.stderr, "Module " + modname + " added."
|
||||
else:
|
||||
libraries.loadLibrary(libname)
|
||||
library = libraries.getByName(libname)
|
||||
curmods = sorted(library.getElementNames())
|
||||
for modname in sorted(modules.keys()):
|
||||
if modname not in curmods:
|
||||
library.insertByName(modname, modules[modname])
|
||||
print >> sys.stderr, "Module " + modname + " added."
|
||||
elif modules[modname] != library.getByName(modname):
|
||||
library.replaceByName(modname, modules[modname])
|
||||
print >> sys.stderr, "Module " + modname + " updated."
|
||||
for modname in curmods:
|
||||
if modname not in modules:
|
||||
library.removeByName(modname)
|
||||
print >> sys.stderr, "Module " + modname + " removed."
|
||||
if libraries.isModified():
|
||||
libraries.storeLibraries()
|
||||
else:
|
||||
print >> sys.stderr, "Everything is in sync."
|
||||
return
|
||||
|
||||
|
||||
def create_dialog_library(oo, libname):
|
||||
""" Creates the dialog library. """
|
||||
libraries = oo.service_manager.createInstance(
|
||||
"com.sun.star.script.ApplicationDialogLibraryContainer")
|
||||
libraries.createLibrary(libname)
|
||||
print >> sys.stderr, "Dialog library " + libname + " created."
|
||||
libraries.storeLibraries()
|
||||
|
||||
|
||||
class OpenOffice:
|
||||
""" 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
|
||||
local_context = uno.getComponentContext()
|
||||
# Obtains the local service manager
|
||||
local_service_manager = local_context.getServiceManager()
|
||||
# Obtains the URL resolver
|
||||
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")
|
||||
while True:
|
||||
try:
|
||||
self.bootstrap_context = url_resolver.resolve(url)
|
||||
except NoConnectException:
|
||||
self.start_oo()
|
||||
else:
|
||||
break
|
||||
# Obtains the service manager
|
||||
self.service_manager = self.bootstrap_context.getServiceManager()
|
||||
# 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()
|
||||
if os.name == "nt":
|
||||
from subprocess import Popen
|
||||
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)
|
||||
time.sleep(2)
|
||||
return
|
||||
|
||||
# For POSIX systems, including Linux
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError:
|
||||
sys.stderr.write("failed to fork().\n")
|
||||
sys.exit(1)
|
||||
if pid != 0:
|
||||
time.sleep(2)
|
||||
return
|
||||
os.setsid()
|
||||
ooexec = os.path.join(os.path.dirname(uno.__file__), "soffice")
|
||||
try:
|
||||
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.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user