Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / uitest / libreoffice / connection.py
blob40c4757406abb894218453abe45a0e3da205de59
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 traceback
11 import uuid
12 import os
14 try:
15 import pyuno
16 import uno
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.xContext = None
30 def setUp(self):
31 """ Create a new connection to a LibreOffice process
33 If the connection method is path the instance will be created as a
34 new subprocess. If the connection method is connect the instance tries
35 to connect to an existing instance with the specified socket string """
36 (method, sep, rest) = self.args["--soffice"].partition(":")
37 if sep != ":":
38 raise Exception("soffice parameter does not specify method")
39 if method == "path":
40 socket = "pipe,name=pytest" + str(uuid.uuid1())
41 try:
42 userdir = self.args["--userdir"]
43 except KeyError:
44 raise Exception("'path' method requires --userdir")
45 if not(userdir.startswith("file://")):
46 raise Exception("--userdir must be file URL")
47 self.soffice = self.bootstrap(rest, userdir, socket)
48 elif method == "connect":
49 socket = rest
50 else:
51 raise Exception("unsupported connection method: " + method)
53 # connect to the soffice instance
54 success = False
55 try:
56 self.xContext = self.connect(socket)
57 success = True
58 finally:
59 if not success and self.soffice:
60 self.soffice.terminate()
61 self.soffice.wait()
62 self.soffice = None
64 def bootstrap(self, soffice, userdir, socket):
65 """ Creates a new LibreOffice process
67 @param soffice Path to the soffice installation
68 @param userdir Directory of the user profile, only one process per user
69 profile is possible
70 @param socket The socket string used for the PyUNO connection """
72 argv = [soffice, "--accept=" + socket + ";urp",
73 "-env:UserInstallation=" + userdir,
74 "--quickstart=no", "--nofirststartwizard",
75 "--norestore", "--nologo"]
76 if "--valgrind" in self.args:
77 argv.append("--valgrind")
79 if "--gdb" in self.args:
80 argv.insert(0, "gdb")
81 argv.insert(1, "-ex")
82 argv.insert(2, "run")
83 argv.insert(3, "--args")
84 argv[4] = argv[4].replace("soffice", "soffice.bin")
86 env = None
87 environ = dict(os.environ)
88 if 'LIBO_LANG' in environ:
89 env = environ
90 env['LC_ALL'] = environ['LIBO_LANG']
92 return subprocess.Popen(argv, env=env)
94 def connect(self, socket):
95 """ Tries to connect to the LibreOffice instance through the specified socket"""
96 xLocalContext = uno.getComponentContext()
97 xUnoResolver = xLocalContext.ServiceManager.createInstanceWithContext(
98 "com.sun.star.bridge.UnoUrlResolver", xLocalContext)
99 url = "uno:" + socket + ";urp;StarOffice.ComponentContext"
100 print("OfficeConnection: connecting to: " + url)
101 while True:
102 if self.soffice and self.soffice.poll() is not None:
103 raise Exception("soffice has stopped.")
105 try:
106 xContext = xUnoResolver.resolve(url)
107 return xContext
108 except pyuno.getClass("com.sun.star.connection.NoConnectException"):
109 print("NoConnectException: sleeping...")
110 time.sleep(1)
112 def tearDown(self):
113 """Terminate a LibreOffice instance created with the path connection method.
115 Tries to terminate the soffice instance through the normal
116 XDesktop::terminate method and waits indefinitely for the subprocess
117 to terminate """
119 if self.soffice:
120 if self.xContext:
121 try:
122 print("tearDown: calling terminate()...")
123 xMgr = self.xContext.ServiceManager
124 xDesktop = xMgr.createInstanceWithContext(
125 "com.sun.star.frame.Desktop", self.xContext)
126 xDesktop.terminate()
127 print("...done")
128 except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"):
129 print("caught while TearDown:\n", traceback.format_exc())
130 pass # ignore, also means disposed
131 except pyuno.getClass("com.sun.star.lang.DisposedException"):
132 print("caught while TearDown:\n", traceback.format_exc())
133 pass # ignore
134 else:
135 self.soffice.terminate()
137 ret = self.soffice.wait()
138 self.xContext = None
139 self.soffice = None
140 if ret != 0:
141 raise Exception("Exit status indicates failure: " + str(ret))
143 @classmethod
144 def getHelpText(cls):
145 message = """
146 --soffice=method:location
147 specify soffice instance to connect to
148 supported methods: 'path', 'connect'
149 --userdir=URL specify user installation directory for 'path' method
150 --valgrind pass --valgrind to soffice for 'path' method
152 'location' is a pathname, not a URL. 'userdir' is a URL.
154 return message
157 class PersistentConnection:
158 def __init__(self, args):
159 self.args = args
160 self.connection = None
162 def getContext(self):
163 """ Returns the XContext corresponding to the LibreOffice instance
165 This is the starting point for any PyUNO access to the LibreOffice
166 instance."""
167 return self.connection.xContext
169 def setUp(self):
170 # don't create two connections
171 if self.connection:
172 return
174 conn = OfficeConnection(self.args)
175 conn.setUp()
176 self.connection = conn
178 def tearDown(self):
179 if self.connection:
180 try:
181 self.connection.tearDown()
182 finally:
183 self.connection = None
185 def kill(self):
186 """ Kills the LibreOffice instance if it was created through the connection
188 Only works with the connection method path"""
189 if self.connection and self.connection.soffice:
190 self.connection.soffice.kill()
192 # vim: set shiftwidth=4 softtabstop=4 expandtab: