Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / uitest / libreoffice / connection.py
blobcb3ae1a0128ed78868571a722054e081f2886b39
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 ret = self.soffice.wait()
134 self.xContext = None
135 self.socket = None
136 self.soffice = None
137 if ret != 0:
138 raise Exception("Exit status indicates failure: " + str(ret))
140 @classmethod
141 def getHelpText(cls):
142 message = """
143 --soffice=method:location
144 specify soffice instance to connect to
145 supported methods: 'path', 'connect'
146 --userdir=URL specify user installation directory for 'path' method
147 --valgrind pass --valgrind to soffice for 'path' method
149 'location' is a pathname, not a URL. 'userdir' is a URL.
151 return message
154 class PersistentConnection:
155 def __init__(self, args):
156 self.args = args
157 self.connection = None
159 def getContext(self):
160 """ Returns the XContext corresponding to the LibreOffice instance
162 This is the starting point for any PyUNO access to the LibreOffice
163 instance."""
164 return self.connection.xContext
166 def setUp(self):
167 # don't create two connections
168 if self.connection:
169 return
171 conn = OfficeConnection(self.args)
172 conn.setUp()
173 self.connection = conn
175 def tearDown(self):
176 if self.connection:
177 try:
178 self.connection.tearDown()
179 finally:
180 self.connection = None
182 def kill(self):
183 """ Kills the LibreOffice instance if it was created through the connection
185 Only works with the connection method path"""
186 if self.connection and self.connection.soffice:
187 self.connection.soffice.kill()
189 # vim: set shiftwidth=4 softtabstop=4 expandtab: