Unbill Python bindings
After CI publishes a release, install it with python -m pip install unbill. Wheels
target Linux x86_64 (glibc 2.28 or newer), macOS ARM64, and Windows x86_64.
Use an in-process console directly, or connect to a separately installed daemon.
The Python package reuses the Rust console interface. Build it from the repository with Cargo and Python 3.9 or newer:
python3 bindings/python/build.py
python3 -m pip install ./target/python/debug
For an optimized build, add --release and install ./target/python/release.
The output follows Cargo's target directory if you override it. Generated
bindings and the native library stay under that directory and are not committed.
The generator is built from the same pinned workspace dependencies as the library.
The script fetches locked dependency sources before compilation so the embedded
license catalog can include dependencies across all platforms.
The package includes a native shared library for the build host. Wheels are
platform-specific (py3-none-<platform>), and require no Rust toolchain at runtime.
To build a wheel for distribution:
python3 -m pip wheel --no-deps ./target/python/release -w ./target/python/wheels
Build separately for each supported operating system and architecture. Linux distribution may additionally require wheel repair with auditwheel; macOS may require delocate when the build links external shared libraries. The script builds for the Rust host target even if a cross-compilation target is configured.
Open an in-process console to run the Rust device service and SQLite storage inside Python, with no separate daemon:
import unbill
console = unbill.Console.open_in_process("./household-data")
ledger = console.create_ledger("Household", "USD")
detail = console.ledger_detail(ledger.ledger_id)
print(detail)
Alternatively, start unbill-daemon and connect to it:
console = unbill.Console.open_rpc(unbill.default_data_directory())
Both constructors provide the same operations. RPC uses the existing desktop
data-directory configuration and UNBILL_SOCKET override. In-process mode uses
the supplied directory directly and ignores UNBILL_SOCKET. A data directory
can have only one storage owner: an in-process console or the daemon. Competing
in-process opens raise unbill.ConsoleError.DataDirectoryInUse.
Keep the in-process console alive while using it; releasing it stops its runtime
and releases its storage ownership.
Records, enums, errors, and methods are generated from the same Rust exports
used by Swift. Rust errors raise unbill.ConsoleError. Most methods are synchronous
and block; use asyncio.to_thread when calling them from an asyncio application.
sync_once is async and can be awaited directly.
Observers subclass unbill.ConsoleObserver and implement on_event(self, event).
Keep the subscription returned by console.observe(observer) alive, then call
subscription.cancel() when finished. Callbacks run on Rust worker threads:
enqueue events or use loop.call_soon_threadsafe to forward them to the owning
event loop before calling console methods.
Verify the generated package without installing it:
PYTHONPATH=target/python/debug python3 bindings/python/test_bindings.py
The default tests cover in-process operations, persistence, directory ownership,
and observer delivery. For additional RPC verification, start a daemon with an isolated
UNBILL_DATA_DIR, then set UNBILL_PYTHON_TEST_DIR to that same directory when
running the tests. Use a temporary directory because this test creates a ledger.
CI and PyPI publishing
.github/workflows/python.yml builds, repairs, and tests wheels on relevant pull
requests, pushes to main, and manual runs. Pushing a v* tag also publishes to
PyPI after every platform passes. The tag must exactly match v followed by the
Cargo workspace version. Package versions come from the workspace; nightly tags
and manual runs do not publish. Rerunning a release skips files already on PyPI.
Linux wheels are built in manylinux_2_28 and repaired with auditwheel. macOS wheels use delocate, and Windows wheels use delvewheel to bundle external dependencies. CI installs the repaired wheels on Python 3.9 and 3.14 before uploading artifacts; Linux also tests Python 3.11. PyPI receives wheels only, so unsupported platforms use the repository build instructions above.
Publishing uses PyPI Trusted Publishing. Configure it once before pushing the first release tag:
-
Create a GitHub Actions environment named
pypiinunbill-project/unbill. Restrict its deployment tags tov*. -
In your PyPI account, open Publishing and add a pending GitHub publisher with these values:
Field Value PyPI project name unbillOwner unbill-projectRepository unbillWorkflow filename python.ymlEnvironment pypiIf the PyPI project already belongs to you, add the publisher under that project's Publishing settings instead. A pending publisher creates the project on its first successful upload; it does not reserve the name.
-
Push a version tag through the existing
cargo releaseprocess. The Python workflow publishes alongside the existing application releases.
No PyPI API token or GitHub repository secret is required. Only the publishing
job receives id-token: write; build and pull-request jobs have read permissions.
Metadata
Release files for unbill 0.0.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unbill-0.0.8-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| unbill-0.0.8-py3-none-manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64 | Details |
| unbill-0.0.8-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 32.9 MB
Release files / unbill-0.0.8-py3-none-win_amd64.whl
| Download URL | unbill-0.0.8-py3-none-win_amd64.whl |
|---|---|
| Size | 8.9 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
f2c7adb809e33fd2b14ec0a52590e0869bb9334f30295f05e50c9f58b409a593
|
|
BLAKE2b-256 checksum How to use checksums |
cef7b3b2af31a9ee4c746b003747828b532877a74097be13c6c05574cc6048ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / unbill-0.0.8-py3-none-manylinux_2_28_x86_64.whl
| Download URL | unbill-0.0.8-py3-none-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 13.8 MB |
| Tags | Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
72586fa56a31b96b2812707cb2164d021354bd8583c4ea2532da733e7b53952e
|
|
BLAKE2b-256 checksum How to use checksums |
6a3993c2292b0c3d1249e3a8fa53016ccebab19663c3416ee1d95eb61aad00ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / unbill-0.0.8-py3-none-macosx_11_0_arm64.whl
| Download URL | unbill-0.0.8-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
cda6e844d8f5dbc2c8fb270c99d28266a8e0c8744528c6960fd44d50d248cd83
|
|
BLAKE2b-256 checksum How to use checksums |
d455e3674f1767305c1113021b66d662ac80361e0d791593e65a1668b42b3af2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for unbill 0.0.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 3 files in this release have been uploaded with provenance metadata.
Attestation for unbill-0.0.8-py3-none-win_amd64.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.