Is it possible to bridge connect to a flatpak installation of LibreOffice to run the API

How can I connect to a FlatPak instance of LibreOffice?

This works in command line to start LIbreOffice Flatpak. But I can’t seem to connect to it.

flatpak run org.libreoffice.LibreOffice --norestore --norestore --nofirststartwizard --nologo --accept="socket,host=localhost,port=2002,tcpNoDelay=1;urp;"

Also starts LibreOffice but I can’t seem to connect.

from subprocess import Popen

def main():
	Popen('flatpak run org.libreoffice.LibreOffice --norestore --norestore --nofirststartwizard --nologo --accept="socket,host=localhost,port=2002,tcpNoDelay=1;urp;"', shell=True)

if __name__ == "__main__":
	main()

I looked into:
$ cat /etc/apparmor.d/usr.lib.libreoffice.program.soffice.bin

Some of the comments

# This profile should enable the average LibreOffice user to get their 
# work done while blocking some advanced usage
# Namely not tested and likely not working : embedded plugins,
# Using the LibreOffice SDK and other development tasks
# Everything else should be working

Is seems the comments are saying Using the API is not possible.

Avoid subshells in context of subprocess:

from subprocess import Popen

def main():
    Popen( ['flatpak',
            'run', 
            'org.libreoffice.LibreOffice', 
            '--norestore',
            '--nofirststartwizard', 
            '--nologo', 
            '--accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;'] )

if __name__ == "__main__":
	main()

but this doesnt solve the problem, which is first to insert the required path to uno inclusive its dependencies.

$ ipython
Python 3.9.2 (default, Mar 12 2021, 04:06:34) 
Type 'copyright', 'credits' or 'license' for more information
IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sys

In [2]: sys.path.insert(0,"/var/lib/flatpak/app/org.libreoffice.LibreOffice/current/active/files/libreoffice/program/")

In [3]: sys.path
Out[3]: 
['/var/lib/flatpak/app/org.libreoffice.LibreOffice/current/active/files/libreoffice/program/',
 '/home/wertie/.local/bin',
 '/usr/lib/python39.zip',
 '/usr/lib/python3.9',
 '/usr/lib/python3.9/lib-dynload',
 '',
 '/home/wertie/.local/lib/python3.9/site-packages',
 '/usr/local/lib/python3.9/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/usr/lib/python3.9/dist-packages']

In [4]: import uno
failed to load pyuno: 'libpython3.7m.so.1.0: cannot open shared object file: No such file or directory'

at this point I dont want to do further investigations, and go to uninstall all this »flatpak garbage«

I was tired last night did figure some of this.
I put this in my notes:

When I run it on the command line I can then connect to it via python.

flatpak run org.libreoffice.LibreOffice/x86_64/stable --norestore --nofirststartwizard --nologo --accept="socket,host=localhost,port=2002,tcpNoDelay=1;urp;"

Today I could not make it work.

I spend all day trying to figure out a work around for this issue with no luck.
I keep running into import errors. Some import work like from com.sun.star.beans import XPropertySet while others fail.

I can’t see taking this any further unless new information comes to light.

BTW: I got this working for Snaps. I have been writing some guides, Will be publishing them soon.

I found that it is possible to add Python Packages to a flatpak but not how to connect via bridge in any working way.
Short Version is:
Create a virtual environment.
Use Flatseal to set environment var of PYTHONPATH

PYTHONPATH=.pyenv/versions/libreoffice/lib/python3.10/site-packages

Turns out there is a solution.

The Code to connection to LibreOffice FlatPak is something like this:

I wrote Several guides related to Python packages and LibreOffice on different systems.
The Guide for Bridging to Flapak is here.

Prerequisites

The libreoffice-script-provider-python apt package must be installed. This package allows scripts to connect to LibreOffice.

sudo apt install libreoffice-script-provider-python

Under the hood the virtual environment is linking to uno.py and unohelper.py provided by libreoffice-script-provider-python.
This solves the import errors I was having.

Connect

General Code for connecting.

# is it important to use shell=True
import os
from subprocess import Popen
Popen(f'flatpak run org.libreoffice.LibreOffice/x86_64/stable --invisible --norestore --nofirststartwizard --nologo --accept="socket,host=localhost,port=2002,tcpNoDelay=1;urp;" --display {os.getenv("DISPLAY")}', shell=True)

Notes

Connecting via pipe (Connect Socket works) does not seem to work. LibreOffice starts but python just hangs. This was the same with Snaps.

On the system I tested this on (Ubuntu 22.04), the Apt version of LibreOffice is also installed. Not sure if this has a impact on the libreoffice-script-provider-python workaround.

2 Likes

I tested this solution on an system without LibreOffice Apt version installed and it worked.

NO there is no need for shell=True and it make no sense to use --invisible together with --display {os.getenv("DISPLAY")}

#run in socket-mode:
from subprocess import Popen
Popen(['flatpak',
       'run',
       'org.libreoffice.LibreOffice',
       '--calc',
       '--accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;'])

……

# and the connection via socket:
import uno 
from pythonscript import ScriptContext

local = uno.getComponentContext()
resolver = local.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver")
ctx = resolver.resolve( "uno:socket,"
                           "host=localhost,"
                           "port=2002,"
                           "tcpNoDelay=1;"
                           "urp;"
                           "StarOffice.ComponentContext")                         

XSCRIPTCONTEXT = ScriptContext(ctx, None, None)

@karolus Here is what I can say.

While testing connecting to flatpak, without shell=True the connection was simply not possible.
I am doing some adjustments to the connection part of OooDev today, so I will be testing this again.

As far as not needing --invisible and --display together it does have some utility.
By Default OooDev always connects invisible and then after you create/open a document then the GUI sets it to visible.
See this Example Code

@karolus
Tried it again.

Popen(
    [
        "flatpak",
        "run",
        "org.libreoffice.LibreOffice",
        "--calc",
        "--accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;"
    ]
)

results in:

/app/libreoffice/program/soffice.bin X11 error: Can't open display: 
   Set DISPLAY environment variable, use -display option
   or check permissions of your X-Server
   (See "man X" resp. "man xhost" for details)

And

Popen(
    [
        "flatpak",
        "run",
        "org.libreoffice.LibreOffice",
        "--calc",
        "--accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;",
        f'--display {os.getenv("DISPLAY")}',
    ]
)

Results in

Failed to open display
LibreOffice 7.5.4.2 36ccfdc35048b057fd9854c757a8b67ec53977b6

Error in option: --display :0

Usage: soffice [argument...]
       argument - switches, switch parameters and document URIs (filenames). 
...

This below works.
I don’t know why that is the case for flatpak but that is what I get.

Popen(f'flatpak run org.libreoffice.LibreOffice --calc --accept="socket,host=localhost,port=2002,tcpNoDelay=1;urp;" --display {os.getenv("DISPLAY")}', shell=True)

Does it work this way:

import os
from subprocess import Popen
window = os.getenv("DISPLAY")
Popen(['flatpak',
       'run',
       'org.libreoffice.LibreOffice',
       '--calc',
       '--accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;'
       f'"-display{window}"'])
```</s>