1 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
19 print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
20 print("PYTHONPATH=/installation/opt/program")
21 print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
25 class OfficeConnection
:
26 def __init__(self
, args
):
32 """ Create a new connection to a LibreOffice process
34 If the connection method is path the instance will be created as a
35 new subprocess. If the connection method is connect the instance tries
36 to connect to an existing instance with the specified socket string """
37 (method
, sep
, rest
) = self
.args
["--soffice"].partition(":")
39 raise Exception("soffice parameter does not specify method")
41 socket
= "pipe,name=pytest" + str(uuid
.uuid1())
43 userdir
= self
.args
["--userdir"]
45 raise Exception("'path' method requires --userdir")
46 if not(userdir
.startswith("file://")):
47 raise Exception("--userdir must be file URL")
48 self
.soffice
= self
.bootstrap(rest
, userdir
, socket
)
49 elif method
== "connect":
52 raise Exception("unsupported connection method: " + method
)
54 # connect to the soffice instance
57 self
.xContext
= self
.connect(socket
)
60 if not success
and self
.soffice
:
61 self
.soffice
.terminate()
65 def bootstrap(self
, soffice
, userdir
, socket
):
66 """ Creates a new LibreOffice process
68 @param soffice Path to the soffice installation
69 @param userdir Directory of the user profile, only one process per user
71 @param socket The socket string used for the PyUNO connection """
73 argv
= [soffice
, "--accept=" + socket
+ ";urp",
74 "-env:UserInstallation=" + userdir
,
75 "--quickstart=no", "--nofirststartwizard",
76 "--norestore", "--nologo"]
77 if "--valgrind" in self
.args
:
78 argv
.append("--valgrind")
80 if "--gdb" in self
.args
:
84 argv
.insert(3, "--args")
85 argv
[4] = argv
[4].replace("soffice", "soffice.bin")
88 environ
= dict(os
.environ
)
89 if 'LIBO_LANG' in environ
:
91 env
['LC_ALL'] = environ
['LIBO_LANG']
93 return subprocess
.Popen(argv
, env
=env
)
95 def connect(self
, socket
):
96 """ Tries to connect to the LibreOffice instance through the specified socket"""
97 xLocalContext
= uno
.getComponentContext()
98 xUnoResolver
= xLocalContext
.ServiceManager
.createInstanceWithContext(
99 "com.sun.star.bridge.UnoUrlResolver", xLocalContext
)
100 url
= "uno:" + socket
+ ";urp;StarOffice.ComponentContext"
101 print("OfficeConnection: connecting to: " + url
)
103 if self
.soffice
and self
.soffice
.poll() is not None:
104 raise Exception("soffice has stopped.")
107 xContext
= xUnoResolver
.resolve(url
)
109 except pyuno
.getClass("com.sun.star.connection.NoConnectException"):
110 print("NoConnectException: sleeping...")
114 """Terminate a LibreOffice instance created with the path connection method.
116 Tries to terminate the soffice instance through the normal
117 XDesktop::terminate method and waits indefinitely for the subprocess
123 print("tearDown: calling terminate()...")
124 xMgr
= self
.xContext
.ServiceManager
125 xDesktop
= xMgr
.createInstanceWithContext(
126 "com.sun.star.frame.Desktop", self
.xContext
)
129 except pyuno
.getClass("com.sun.star.beans.UnknownPropertyException"):
130 print("caught while TearDown:\n", traceback
.format_exc())
131 pass # ignore, also means disposed
132 except pyuno
.getClass("com.sun.star.lang.DisposedException"):
133 print("caught while TearDown:\n", traceback
.format_exc())
136 self
.soffice
.terminate()
138 ret
= self
.soffice
.wait()
142 raise Exception("Exit status indicates failure: " + str(ret
))
145 def getHelpText(cls
):
147 --soffice=method:location
148 specify soffice instance to connect to
149 supported methods: 'path', 'connect'
150 --userdir=URL specify user installation directory for 'path' method
151 --valgrind pass --valgrind to soffice for 'path' method
153 'location' is a pathname, not a URL. 'userdir' is a URL.
158 class PersistentConnection
:
159 def __init__(self
, args
):
161 self
.connection
= None
163 def getContext(self
):
164 """ Returns the XContext corresponding to the LibreOffice instance
166 This is the starting point for any PyUNO access to the LibreOffice
168 return self
.connection
.xContext
171 # don't create two connections
175 conn
= OfficeConnection(self
.args
)
177 self
.connection
= conn
182 self
.connection
.tearDown()
184 self
.connection
= None
187 """ Kills the LibreOffice instance if it was created through the connection
189 Only works with the connection method path"""
190 if self
.connection
and self
.connection
.soffice
:
191 self
.connection
.soffice
.kill()
193 # vim: set shiftwidth=4 softtabstop=4 expandtab: