Developers¶
Libera Suite is a Python host around upstream editors. Most of the work is in the integration points: what the editor expects from a desktop host, how the payload is built, and how our changes to upstream are kept reviewable.
- Architecture: the pieces and how they talk.
- Build the payload: building the editors and the native binaries.
- The patch queue: how we carry changes to upstream.
- Cutting a release: which machine makes what, and in what order.
- Roadmap: what is next and what we have decided against.
Getting the source¶
On Linux, the virtualenv has to see the system's PyGObject
The window is GTK and WebKit, whose Python half is not a wheel: it is python3-gi, which your distribution installs into /usr/lib/python3/dist-packages. A plain virtualenv never has it on sys.path, so uv run libera FILE will tell you it needs GTK even on a machine that has it.
uv sync
sed -i 's/^include-system-site-packages = false/include-system-site-packages = true/' .venv/pyvenv.cfg
uv sync rewrites that file, so a fresh sync needs the line again. libera prints this exact command, with your venv's path in it, when it finds itself in a virtualenv that cannot reach GTK.
The test suite does not need this. It drives the editor through libera --serve and a headless browser, never opening a window. Only running the application does.
Point the application at a payload you have built, and run it:
Seeing what it is doing¶
libera FILE # warnings and errors only
libera -v FILE # what it is doing: opening, saving, windows
libera -vv FILE # and how: HTTP routes, x2t command lines
libera -vvv FILE # and every request, as it starts and finishes
libera -q FILE # errors only
-vv is usually the one you want when something is wrong: it prints the exact x2t command line, which you can then run by hand.
Running the checks¶
uv run pytest # everything
uv run pytest -m unit # fast and isolated
uv run pytest -m integration # the host, against a real payload
uv run pytest -m e2e # the editor, in a real browser
The suite is a pyramid, one directory per level, and the markers are applied by directory:
tests/a_unit/runs against nothing: no payload, server or browser.tests/b_integration/starts the host's HTTP server on a loopback port and talks to it the way the bridge does, and runs x2t out of the payload. It checks, among other things, that every format the Save As dialog offers is one the converter actually writes, because x2t refuses several ids that look perfectly plausible next to the ones it accepts.tests/c_e2e/runs the shipped command line.libera --servein a subprocess, headless Chromium pointed at the URL it prints, and then assertions on what came back. It also drives the keyboard through Playwright, which needs its own browser once:
The last one is the important one, and it is where the project's one hard-won lesson lives: assert on content, never on exit codes. A converter that writes an empty file exits zero. A browser that quits early exits zero. A PDF with no glyphs in it is the right size. So the e2e run photographs the editor's own canvas from inside the page, measures ink on it, and fails if the rows of text are closer together than a line of text can be. That is what a real regression looked like while every cheaper check reported success.
Both levels below a_unit skip themselves when they have nothing to run against: no installed payload, or no Chromium. Set CHROMIUM=/path/to/browser if yours is somewhere unusual.
To look at the editor by hand, with devtools, a real browser and no window toolkit in the way, run libera --serve, which prints the URL it is listening on: