Last active
November 30, 2022 14:24
-
-
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*)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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