Revert "tdf#127471 Remove font width scaling hack"
[LibreOffice.git] / uitest / libreoffice / connection.py
blob2b0e9c2274790bf2fa5c2aed550fdf562642d929
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 import unohelper
18 except ImportError:
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")
22 raise
25 class OfficeConnection:
26 def __init__(self, args):
27 self.args = args
28 self.soffice = None
29 self.xContext = None
31 def setUp(self):
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(":")
38 if sep != ":":
39 raise Exception("soffice parameter does not specify method")
40 if method == "path":
41 socket = "pipe,name=pytest" + str(uuid.uuid1())
42 try:
43 userdir = self.args["--userdir"]
44 except KeyError:
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":
50 socket = rest
51 else:
52 raise Exception("unsupported connection method: " + method)
54 # connect to the soffice instance
55 success = False
56 try:
57 self.xContext = self.connect(socket)
58 success = True
59 finally:
60 if not success and self.soffice:
61 self.soffice.terminate()
62 self.soffice.wait()
63 self.soffice = None
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
70 profile is possible
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:
81 argv.insert(0, "gdb")
82 argv.insert(1, "-ex")
83 argv.insert(2, "run")
84 argv.insert(3, "--args")
85 argv[4] = argv[4].replace("soffice", "soffice.bin")
87 env = None
88 environ = dict(os.environ)
89 if 'LIBO_LANG' in environ:
90 env = 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)
102 while True:
103 if self.soffice and self.soffice.poll() is not None:
104 raise Exception("soffice has stopped.")
106 try:
107 xContext = xUnoResolver.resolve(url)
108 return xContext
109 except pyuno.getClass("com.sun.star.connection.NoConnectException"):
110 print("NoConnectException: sleeping...")
111 time.sleep(1)
113 def tearDown(self):
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
118 to terminate """
120 if self.soffice:
121 if self.xContext:
122 try:
123 print("tearDown: calling terminate()...")
124 xMgr = self.xContext.ServiceManager
125 xDesktop = xMgr.createInstanceWithContext(
126 "com.sun.star.frame.Desktop", self.xContext)
127 xDesktop.terminate()
128 print("...done")
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())
134 pass # ignore
135 else:
136 self.soffice.terminate()
138 ret = self.soffice.wait()
139 self.xContext = None
140 self.soffice = None
141 if ret != 0:
142 raise Exception("Exit status indicates failure: " + str(ret))
144 @classmethod
145 def getHelpText(cls):
146 message = """
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.
155 return message
158 class PersistentConnection:
159 def __init__(self, args):
160 self.args = 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
167 instance."""
168 return self.connection.xContext
170 def setUp(self):
171 # don't create two connections
172 if self.connection:
173 return
175 conn = OfficeConnection(self.args)
176 conn.setUp()
177 self.connection = conn
179 def tearDown(self):
180 if self.connection:
181 try:
182 self.connection.tearDown()
183 finally:
184 self.connection = None
186 def kill(self):
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: