BOUNDARY. libpython-clj. TWO things live here, and confusing them is the whole difficulty of this integration.
It cannot import GIMP. GIMP 3 plugins run in GIMP's own embedded CPython,
linked against that process's GObject introspection typelibs and attached to
its main loop and PDB. Pointing libpython-clj at that same interpreter and
running gi.require_version('Gimp', '3.0'); from gi.repository import Gimp
SUCCEEDS, which is the trap: the module imports and is inert.
Gimp.get_images() answers for a GIMP that this process is not part of.
There is no in-process route to a running GIMP, from a JVM or from anything
else that GIMP did not itself launch.
Two useful things, and both are real.
PythonTransport drives the GIMP plugin socket FROM the embedded
interpreter. Python opens the socket, frames the request and reads the
answer; the JVM never touches a file descriptor. This is precisely the path
the reference project's own bg_remove.py takes, executed in-process instead
of as a subprocess. It satisfies IGimpTransport, so it is a drop-in
alternative to hive-gimp.transport.socket and every command works through
it unchanged.
Why have it when the native socket exists: it puts GIMP work and host-side Python work in ONE interpreter, sharing state. A workflow that exports a layer, runs rembg over it, and re-imports the result is then one Python context rather than two runtimes passing files, and the reference project's Python helpers can be imported and driven directly.
HostPython is the other half: the Python image ecosystem GIMP does not
ship (rembg, PIL, numpy, scikit-image). See hive-gimp.pixel.
Every libpython-clj var is resolved SOFTLY, at call time. The dependency
lives behind the :python alias, so a deployment without it loads this
namespace, reports :python/no-libpython, and keeps the native socket
transport and every GIMP command working.
BOUNDARY. libpython-clj. TWO things live here, and confusing them is the
whole difficulty of this integration.
## What libpython-clj CANNOT do
It cannot import GIMP. GIMP 3 plugins run in GIMP's own embedded CPython,
linked against that process's GObject introspection typelibs and attached to
its main loop and PDB. Pointing libpython-clj at that same interpreter and
running `gi.require_version('Gimp', '3.0'); from gi.repository import Gimp`
SUCCEEDS, which is the trap: the module imports and is inert.
`Gimp.get_images()` answers for a GIMP that this process is not part of.
There is no in-process route to a running GIMP, from a JVM or from anything
else that GIMP did not itself launch.
## What libpython-clj CAN do, and does here
Two useful things, and both are real.
`PythonTransport` drives the GIMP plugin socket FROM the embedded
interpreter. Python opens the socket, frames the request and reads the
answer; the JVM never touches a file descriptor. This is precisely the path
the reference project's own bg_remove.py takes, executed in-process instead
of as a subprocess. It satisfies `IGimpTransport`, so it is a drop-in
alternative to `hive-gimp.transport.socket` and every command works through
it unchanged.
Why have it when the native socket exists: it puts GIMP work and host-side
Python work in ONE interpreter, sharing state. A workflow that exports a
layer, runs rembg over it, and re-imports the result is then one Python
context rather than two runtimes passing files, and the reference project's
Python helpers can be imported and driven directly.
`HostPython` is the other half: the Python image ecosystem GIMP does not
ship (rembg, PIL, numpy, scikit-image). See `hive-gimp.pixel`.
Every libpython-clj var is resolved SOFTLY, at call time. The dependency
lives behind the `:python` alias, so a deployment without it loads this
namespace, reports `:python/no-libpython`, and keeps the native socket
transport and every GIMP command working.(ensure-embedded-modules!)Install this library's own Python modules. Idempotent.
Called on the call-python path so a caller never has to know these exist;
the port is the whole interface.
Install this library's own Python modules. Idempotent. Called on the `call-python` path so a caller never has to know these exist; the port is the whole interface.
(host-python)(host-python python-executable)An IHostPython bound to python-executable (nil to autodetect).
An `IHostPython` bound to `python-executable` (nil to autodetect).
Host-side pixel operations, as a real Python module.
Installed into sys.modules as hive_gimp_pixel so it is reachable through
the ordinary IHostPython/call-python path: hive-gimp.pixel then depends
on the PORT and never on this namespace.
Written as Python rather than driven attribute-by-attribute from Clojure because these operations pass BYTES. Reading a file into a Python bytes object, handing it to rembg and writing the result back are three steps that belong on one side of the bridge; marshalling the buffer across it twice would be slower and would convert a segmentation mask into a JVM array for no reason.
Host-side pixel operations, as a real Python module. Installed into `sys.modules` as `hive_gimp_pixel` so it is reachable through the ordinary `IHostPython/call-python` path: `hive-gimp.pixel` then depends on the PORT and never on this namespace. Written as Python rather than driven attribute-by-attribute from Clojure because these operations pass BYTES. Reading a file into a Python bytes object, handing it to rembg and writing the result back are three steps that belong on one side of the bridge; marshalling the buffer across it twice would be slower and would convert a segmentation mask into a JVM array for no reason.
(reset-cache!)Forget the cached status. For tests, and for a user who just installed the interpreter this process failed to find.
There is no compiled client to forget any more: round-trip* resolves its
modules through interop on each call, so nothing is compiled and held.
Forget the cached status. For tests, and for a user who just installed the interpreter this process failed to find. There is no compiled client to forget any more: `round-trip*` resolves its modules through interop on each call, so nothing is compiled and held.
(status python-executable)Why host-side Python is or is not usable. Never throws.
Why host-side Python is or is not usable. Never throws.
(transport endpoint)(transport endpoint connect-timeout-ms)(transport endpoint connect-timeout-ms python-executable)An IGimpTransport that reaches GIMP THROUGH the embedded Python
interpreter rather than through a JVM socket.
Interchangeable with hive-gimp.transport.socket/transport: same port, same
commands, same outcomes. Choose it when you also want host-side Python in
the same interpreter, so a GIMP export can be handed straight to rembg
without leaving the process.
An `IGimpTransport` that reaches GIMP THROUGH the embedded Python interpreter rather than through a JVM socket. Interchangeable with `hive-gimp.transport.socket/transport`: same port, same commands, same outcomes. Choose it when you also want host-side Python in the same interpreter, so a GIMP export can be handed straight to rembg without leaving the process.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |