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/.
18 print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables")
19 print("PYTHONPATH=/installation/opt/program")
20 print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc")
24 class OfficeConnection
:
25 def __init__(self
, args
):
33 """ Create a new connection to a LibreOffice process
35 If the connection method is path the instance will be created as a
36 new subprocess. If the connection method is connect the instance tries
37 to connect to an existing instance with the specified socket string """
38 (method
, sep
, rest
) = self
.args
["--soffice"].partition(":")
40 raise Exception("soffice parameter does not specify method")
42 socket
= "pipe,name=pytest" + str(uuid
.uuid1())
44 userdir
= self
.args
["--userdir"]
46 raise Exception("'path' method requires --userdir")
47 if not(userdir
.startswith("file://")):
48 raise Exception("--userdir must be file URL")
49 self
.soffice
= self
.bootstrap(rest
, userdir
, socket
)
50 elif method
== "connect":
53 raise Exception("unsupported connection method: " + method
)
55 # connect to the soffice instance
56 self
.xContext
= self
.connect(socket
)
58 def bootstrap(self
, soffice
, userdir
, socket
):
59 """ Creates a new LibreOffice process
61 @param soffice Path to the soffice installation
62 @param userdir Directory of the user profile, only one process per user
64 @param socket The socket string used for the PyUNO connection """
66 argv
= [soffice
, "--accept=" + socket
+ ";urp",
67 "-env:UserInstallation=" + userdir
,
68 "--quickstart=no", "--nofirststartwizard",
69 "--norestore", "--nologo"]
70 if "--valgrind" in self
.args
:
71 argv
.append("--valgrind")
73 if "--gdb" in self
.args
:
77 argv
.insert(3, "--args")
78 argv
[4] = argv
[4].replace("soffice", "soffice.bin")
81 environ
= dict(os
.environ
)
82 if 'LIBO_LANG' in environ
:
84 env
['LC_ALL'] = environ
['LIBO_LANG']
86 self
.pro
= subprocess
.Popen(argv
, env
=env
)
89 def connect(self
, socket
):
90 """ Tries to connect to the LibreOffice instance through the specified socket"""
91 xLocalContext
= uno
.getComponentContext()
92 xUnoResolver
= xLocalContext
.ServiceManager
.createInstanceWithContext(
93 "com.sun.star.bridge.UnoUrlResolver", xLocalContext
)
94 url
= "uno:" + socket
+ ";urp;StarOffice.ComponentContext"
95 print("OfficeConnection: connecting to: " + url
)
97 if self
.soffice
and self
.soffice
.poll() is not None:
98 raise Exception("soffice has stopped.")
101 xContext
= xUnoResolver
.resolve(url
)
103 except pyuno
.getClass("com.sun.star.connection.NoConnectException"):
104 print("NoConnectException: sleeping...")
108 """Terminate a LibreOffice instance created with the path connection method.
110 First tries to terminate the soffice instance through the normal
111 XDesktop::terminate method and waits for about 30 seconds before
112 considering this attempt failed. After the 30 seconds the subprocess
118 print("tearDown: calling terminate()...")
119 xMgr
= self
.xContext
.ServiceManager
120 xDesktop
= xMgr
.createInstanceWithContext(
121 "com.sun.star.frame.Desktop", self
.xContext
)
124 except pyuno
.getClass("com.sun.star.beans.UnknownPropertyException"):
125 print("caught UnknownPropertyException while TearDown")
126 pass # ignore, also means disposed
127 except pyuno
.getClass("com.sun.star.lang.DisposedException"):
128 print("caught DisposedException while TearDown")
131 self
.soffice
.terminate()
136 time_
+= DEFAULT_SLEEP
137 ret_attr
= self
.soffice
.poll()
138 if ret_attr
is not None:
140 time
.sleep(DEFAULT_SLEEP
)
145 self
.soffice
.terminate()
147 # ret = self.soffice.wait()
152 raise Exception("Exit status indicates failure: " + str(ret
))
155 def getHelpText(cls
):
157 --soffice=method:location
158 specify soffice instance to connect to
159 supported methods: 'path', 'connect'
160 --userdir=URL specify user installation directory for 'path' method
161 --valgrind pass --valgrind to soffice for 'path' method
163 'location' is a pathname, not a URL. 'userdir' is a URL.
168 class PersistentConnection
:
169 def __init__(self
, args
):
171 self
.connection
= None
173 def getContext(self
):
174 """ Returns the XContext corresponding to the LibreOffice instance
176 This is the starting point for any PyUNO access to the LibreOffice
178 return self
.connection
.xContext
181 # don't create two connections
185 conn
= OfficeConnection(self
.args
)
187 self
.connection
= conn
192 self
.connection
.tearDown()
194 self
.connection
= None
197 """ Kills the LibreOffice instance if it was created through the connection
199 Only works with the connection method path"""
200 if self
.connection
and self
.connection
.soffice
:
201 self
.connection
.soffice
.kill()
203 # vim: set shiftwidth=4 softtabstop=4 expandtab: