Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / uitest / libreoffice / connection.py
blob50fdda33fd34487fb63ebd1f3fe2748a93648696
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/.
8 import subprocess
9 import time
10 import uuid
11 import os
13 try:
14 import pyuno
15 import uno
16 import unohelper
17 except ImportError:
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")
21 raise
24 class OfficeConnection:
25 def __init__(self, args):
26 self.args = args
27 self.soffice = None
28 self.socket = None
29 self.xContext = None
30 self.pro = None
32 def setUp(self):
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(":")
39 if sep != ":":
40 raise Exception("soffice parameter does not specify method")
41 if method == "path":
42 socket = "pipe,name=pytest" + str(uuid.uuid1())
43 try:
44 userdir = self.args["--userdir"]
45 except KeyError:
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":
51 socket = rest
52 else:
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
63 profile is possible
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:
74 argv.insert(0, "gdb")
75 argv.insert(1, "-ex")
76 argv.insert(2, "run")
77 argv.insert(3, "--args")
78 argv[4] = argv[4].replace("soffice", "soffice.bin")
80 env = None
81 environ = dict(os.environ)
82 if 'LIBO_LANG' in environ:
83 env = environ
84 env['LC_ALL'] = environ['LIBO_LANG']
86 self.pro = subprocess.Popen(argv, env=env)
87 return self.pro
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)
96 while True:
97 if self.soffice and self.soffice.poll() is not None:
98 raise Exception("soffice has stopped.")
100 try:
101 xContext = xUnoResolver.resolve(url)
102 return xContext
103 except pyuno.getClass("com.sun.star.connection.NoConnectException"):
104 print("NoConnectException: sleeping...")
105 time.sleep(1)
107 def tearDown(self):
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
113 is terminated """
115 if self.soffice:
116 if self.xContext:
117 try:
118 print("tearDown: calling terminate()...")
119 xMgr = self.xContext.ServiceManager
120 xDesktop = xMgr.createInstanceWithContext(
121 "com.sun.star.frame.Desktop", self.xContext)
122 xDesktop.terminate()
123 print("...done")
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")
129 pass # ignore
130 else:
131 self.soffice.terminate()
133 DEFAULT_SLEEP = 0.1
134 time_ = 0
135 while time_ < 30:
136 time_ += DEFAULT_SLEEP
137 ret_attr = self.soffice.poll()
138 if ret_attr is not None:
139 break
140 time.sleep(DEFAULT_SLEEP)
142 ret = 0
143 if ret_attr is None:
144 ret = 1
145 self.soffice.terminate()
147 # ret = self.soffice.wait()
148 self.xContext = None
149 self.socket = None
150 self.soffice = None
151 if ret != 0:
152 raise Exception("Exit status indicates failure: " + str(ret))
154 @classmethod
155 def getHelpText(cls):
156 message = """
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.
165 return message
168 class PersistentConnection:
169 def __init__(self, args):
170 self.args = 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
177 instance."""
178 return self.connection.xContext
180 def setUp(self):
181 # don't create two connections
182 if self.connection:
183 return
185 conn = OfficeConnection(self.args)
186 conn.setUp()
187 self.connection = conn
189 def tearDown(self):
190 if self.connection:
191 try:
192 self.connection.tearDown()
193 finally:
194 self.connection = None
196 def kill(self):
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: