Development/Extension Development/Python Extensions Development

From The Document Foundation Wiki
Jump to: navigation, search

uno package

To script LibreOffice in Python, you need the uno package. If you run the python included in LO this can be imported without problems. However, if you run you "normal" python, check if you import the libreoffice uno package since there is also a HTML-Generator named UNO. If you do pip install uno you will get that "wrong" uno package, not the Libreoffice one.

Remote Scripting

You can script LibreOffice remotely via a socket. The advantage is that you can quickly run and re-run your code and can easily debug. Open LibreOffice via your terminal:

 soffice --writer --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"

. Now there is a socket for communicating with the opened LibreOffice on port 2002. To communicate with LibreOffice, you need to start your python code with

import uno 
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")

(based on "Scripting LibreOffice with Python"; see also automate your office tasks with Python Macros)

Setting up a debugger

As far as I know, there is no build-in python debugging facility in LibreOffice. If you want to debug Python extensions, you have to connect a remote debugger. I tried several, the only one I could get working was pydevd – which is used in pydev and pycharm Pro.

Set up the debugger client

The remote debugging uses a server and a client. The client is the pydevd.py-file (preferably the one that came with your pydev/pycharm, otherwise try the link)

The pydevd file needs to be in your Pythonpath. I was unsure if the paths libreoffice uses are different then the general ones, and I modified this hello world extension to print the paths by adding an import sys and replacing text.insertString(cursor, "Hello World! \n", 0) with

 pathsstring = "paths \n"
 for i in sys.path:
     somestring = somestring + i +"\n"
 text.insertString(cursor, pathsstring+"\n", 0)

…now rebuild the extension, install and just press the world-button in the toolbar and get the pythonpaths printed. Copy the pydevd.py file to one of them.

Modify your code

In the code you want to debug, add import pydevd and, at the place where you want to start debugging, add pydevd.settrace(). The code will stop ("break") at the .settrace() call and only proceed after you commanded it to do so via your debugger.

After you changed the code, (re-)build your extension. (NOTE: If there is any way to get around rebuilding, please add this)

Debug

Now you can follow the steps at the pydev remote debugging documentation. As you can read, the server needs to be started before your code runs. Otherwise, it just gets stuck and you get an error. This is particularly important if you set a/the settrace at the codes toplevel – the code will stop there during installation and if the server does not run, it does not install the extension.