So, it turns out the answer was really kind of complex. Burried deep within pythonscript.py you find (with some variation depending on pythonscript.py version):
Code: Select all
code = None
if url.startswith("file:"):
code = compile(src, encfile(
uno.fileUrlToSystemPath(url)), "exec")
else:
code = compile(src, url, "exec")
exec code in entry.module.__dict__
entry.module.__file__ = url
self.modules[url] = entryAfter a lot of mind melting process tracing and debugging though I was finally able to figure out what was going on. To work around the issue as a proof of concept I found a change that can be made to pythonscript.py that can catch any writes to stderr or stdout. Enter my IO Context Manager:
Code: Select all
import sys
import contextlib
from StringIO import StringIO
@contextlib.contextmanager
def outputIO():
"""
Context manager that replaces standard out and standard error with a single
file like object. This is useful for running applications where in some
circumstances no buffer is allocated for stdout or stderr. Our common use
case here is for executing python scripts in OpenOffice/LibreOffice from
inside of the thick client app.
"""
old_out = sys.stdout
old_err = sys.stderr
# Create a file-like object to catch output
out_flo = StringIO()
# Map standard out and standard error to this file like object
sys.stdout = out_flo
sys.stderr = out_flo
yield out_flo
# Reset standard out and stanard error to original settings
sys.stdout = old_out
sys.stderr = old_errOnce this has been added to pythonscript.py the only other change necessary is in that exec call:
Code: Select all
with outputIO() as f:
exec code in entry.module.__dict__
log.isDebugLevel() and log.debug("Exec %s" % f.getvalue())
WHEW! All that said, just to give a little context for a simple question:
I'd like to know if it is possible to ship/use a custom version of pythonscript.py for a specific addon. Specifically, if possible, I'd like to ship our addon with my updated version if possible.
Thoughts or ideas?