Skip to content

Instantly share code, notes, and snippets.

@secemp9
Last active November 30, 2022 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save secemp9/9654bf1d6ff91ad623fa3246525ed918 to your computer and use it in GitHub Desktop.
Save secemp9/9654bf1d6ff91ad623fa3246525ed918 to your computer and use it in GitHub Desktop.
Control OpenOffice and LibreOffice using their respective API (and python executable, which are different versions, *sigh*)
import multiprocessing
import os
import tkinter
import time
import pickle
import collections
import subprocess
import re
import sys
import tempfile
import inspect
from itertools import dropwhile
import dis
import types
import ast
def get_names(f):
ins = dis.get_instructions(f)
for x in ins:
try:
if x.opcode == 100 and '<locals>' in next(ins).argval\
and next(ins).opcode == 132:
yield next(ins).argrepr
yield from get_names(x.argval)
except Exception:
pass
def get_function_body(func): # needs recursive function listing, so can support sending nested function/etc
source_lines = inspect.getsourcelines(func)[0]
source_lines = dropwhile(lambda x: x.startswith('@'), source_lines)
line = next(source_lines).strip()
if not line.startswith('def '):
return line.rsplit(':')[-1].strip()
elif not line.endswith(':'):
for line in source_lines:
line = line.strip()
if line.endswith(':'):
break
# Handle functions that are not one-liners
first_line = next(source_lines)
# Find the indentation of the first line
indentation = len(first_line) - len(first_line.lstrip())
return ''.join([first_line[indentation:]] + [line[indentation:] for line in source_lines])
def natural_sorted(iterable, key=None, reverse=False):
"""Return a new naturally sorted list from the items in *iterable*.
The returned list is in natural sort order. The string is ordered
lexicographically (using the Unicode code point number to order individual
characters), except that multi-digit numbers are ordered as a single
character.
Has two optional arguments which must be specified as keyword arguments.
*key* specifies a function of one argument that is used to extract a
comparison key from each list element: ``key=str.lower``. The default value
is ``None`` (compare the elements directly).
*reverse* is a boolean value. If set to ``True``, then the list elements are
sorted as if each comparison were reversed.
The :func:`natural_sorted` function is guaranteed to be stable. A sort is
stable if it guarantees not to change the relative order of elements that
compare equal --- this is helpful for sorting in multiple passes (for
example, sort by department, then by salary grade).
"""
prog = re.compile(r"(\d+)")
def alphanum_key(element):
"""Split given key in list of strings and digits"""
return [int(c) if c.isdigit() else c for c in prog.split(key(element)
if key else element)]
try:
return sorted(iterable, key=alphanum_key, reverse=reverse)
except TypeError:
pass
def put_pickle_inside_file(a, filename='queue.pickle', proto=2):
with open(filename, 'wb') as handle:
pickle.dump(a, handle, protocol=proto)
def read_pickle(filename='queue.pickle'):
with open(filename, 'rb') as handle:
return pickle.load(handle)
def put_pickle(a=None, filename='queue.pickle', proto=2):
if a is None:
return
else:
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
if doit == "libre": # just for testing...will make a class later
b.append(a)
else:
b.append(get_function_body(a))
except EOFError:
pass
with open(filename, 'wb') as handle:
pickle.dump(b, handle, protocol=proto)
def get_pickle(filename='queue.pickle', proto=2):
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
wow = b.popleft()
except EOFError:
pass
with open(filename, 'wb') as handle:
pickle.dump(b, handle, protocol=proto)
if hasattr(wow, '__call__'):
return wow()
else:
return wow
def size_pickle(filename='queue.pickle'):
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
return len(b)
except EOFError:
pass
put_pickle_inside_file(collections.deque())
def testme():
import uno
return dir(uno)
def sort_selection():
oSelection = document.getCurrentSelection()
data_wow = oSelection.getDataArray()
oSelection.setDataArray(tuple(sorted(data_wow))) # had to use tuple after sorted on 2.X...works without it on 3.0
def sort_selection_reverse():
oSelection = document.getCurrentSelection()
data_wow = oSelection.getDataArray()
oSelection.setDataArray(tuple(sorted(data_wow, reverse=True)))
def sort_selection_human():
oSelection = document.getCurrentSelection()
data_wow = oSelection.getDataArray()
if natural_sorted(data_wow) is None:
pass
else:
oSelection.setDataArray(tuple(natural_sorted(data_wow)))
def add_zero():
oSelection = document.getCurrentSelection()
data_wow = oSelection.getDataArray()
ahno = tuple()
ahno2 = tuple()
for i in [row for row in data_wow]:
for g in range(len(i)):
hmm = str(i[g]).replace(".0", "")
# print(hmm)
ahno += tuple(["0" + hmm])
ahno2 += ahno, # obliged to make nested tuple...
ahno = tuple()
oSelection.setDataArray(ahno2)
def getdocs():
print(document.getTitle())
SHEETS = document.getSheets()
whole_maybe = SHEETS.getByIndex(0)
sheet = document.CurrentController.getActiveSheet()
def uno_connect():
global document # so that it works when accessed on other separate function sent
import uno
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver",
localContext)
context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
document = desktop.getCurrentComponent()
def python3_server():
# print("hello")
try:
while 1:
if size_pickle() == 0:
time.sleep(0.01)
else:
print(get_pickle())
except Exception as test:
print(test)
def tk_test():
import tkinter
def python2_pickleserver():
# coding=utf-8
import pickle
import collections
# import Queue as queue
import time
import tempfile
def f():
return "hello" # it's a test
filename = tempfile.gettempdir() + '\\queue2.pickle'
print(filename)
default_type = collections.deque()
def put_pickle_inside_file(a):
with open(filename, 'wb') as handle:
pickle.dump(a, handle, protocol=2)
def read_pickle():
with open(filename, 'rb') as handle:
wow = pickle.load(handle)
if hasattr(wow, '__call__'):
return wow()
else:
return wow
def put(a):
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
b.append(a)
except EOFError:
pass
with open(filename, 'wb') as handle:
pickle.dump(b, handle, protocol=2)
def get():
global b, wow
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
wow = b.popleft()
except EOFError:
pass
except IndexError:
pass
with open(filename, 'wb') as handle:
pickle.dump(b, handle, protocol=2)
return wow
def size():
with open(filename, 'rb') as handle:
try:
b = pickle.load(handle)
return len(b)
except EOFError:
pass
put_pickle_inside_file(default_type)
while 1:
if size() == 0:
time.sleep(0.01)
else:
exec(get())
if __name__ == '__main__':
doit = "open"
if doit == "libre":
queue_file = tempfile.gettempdir() + '\\queue.pickle'
mate2 = subprocess.Popen(
r'"C:\Program Files\LibreOffice\program\soffice.bin" --headless --invisible --nocrashreport --nodefault --nofirststartwizard --nologo --norestore --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"')
time.sleep(1)
multiprocessing.set_executable('C:/Program Files/LibreOffice/program/python.exe')
proc = multiprocessing.Process(target=python3_server, args=())
proc.start()
time.sleep(1)
put_pickle(uno_connect, filename=queue_file)
time.sleep(1)
put_pickle(getdocs, filename=queue_file)
time.sleep(1)
elif doit == "open":
queue_file = tempfile.gettempdir() + '\\queue2.pickle'
os.chdir("C:/Program Files (x86)/OpenOffice 4/program/") # have to do that for openoffice, otherwise there a dll error...
mate2 = subprocess.Popen(
'"soffice.bin" -headless -invisible -nocrashreport -nodefault -nofirststartwizard -nologo -norestore -accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"') # for openoffice, need to use one - instead of -- for libreoffice
with open("Output.py", "w") as text_file:
text_file.write(get_function_body(python2_pickleserver)) # needs to check if file content is same as result from function...so hashing
time.sleep(1)
subprocess.Popen("python.exe Output.py", shell=True) # only works if I use shell=True for whatever reasons...I want it to work like on CMD so this works for now, but later want to get separate stream and continuous/etc, either use threads for that and print/cache/write content to file/variable, but will need while loop sadly, or
time.sleep(3)
put_pickle(uno_connect, filename=queue_file)
time.sleep(1)
put_pickle(getdocs, filename=queue_file)
time.sleep(1)
tk = tkinter.Tk() # needs to automatically fetch the wanted function to make button for, camelcase their name and use that name as button, then check if it's openoffice or libreoffice, and use the method as argument
tkinter.Button(text="meow", command=lambda: put_pickle(testme, filename=queue_file)).pack()
tkinter.Button(text="add_zero", command=lambda: put_pickle(add_zero, filename=queue_file)).pack()
tkinter.Button(text="sort_normal", command=lambda: put_pickle(sort_selection, filename=queue_file)).pack()
tkinter.Button(text="sort_selection_reverse", command=lambda: put_pickle(sort_selection_reverse, filename=queue_file)).pack()
tkinter.Button(text="sort_selection_human", command=lambda: put_pickle(sort_selection_human, filename=queue_file)).pack()
tk.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment