linuxfacts
Typed, testable library for reading Linux system state — disks, memory, systemd units, ports and packages — with no side effects.
Problem
Reading Linux system state in Python is repetitive and brittle. Every project reimplements
parsing of systemctl, reading /proc, psutil calls and permission handling. The result
is coupled to I/O and almost impossible to test without a real machine.
This library is a layer above psutil, opinionated about three things: everything is
typed, everything is injectable (so consumers test offline), and absence of
information is never confused with absence of a problem.
Features
Planned for v1.0 — implemented incrementally:
- Facts for disks, memory, CPU and load, processes, systemd units, listening ports, packages and host info
- Every result is an immutable, typed
Fact[T]with an explicitok/unknownstate - A public
FakeSourceso consumers test their own code offline and deterministically - Read-only by design: no
shell=True, subprocess with a fixed argument list, never requires elevated privilege - One runtime dependency (
psutil);py.typedso consumers get the types
Requirements
- Python 3.11, 3.12 or 3.13
- Ubuntu 22.04+ or Debian 12+
Installation
Not published yet. For local development:
uv sync
uv run pytest
Usage
import linuxfacts
fact = linuxfacts.disks()
if fact.is_ok:
for disk in fact.unwrap():
print(disk.mountpoint, disk.percent_used)
else:
print("could not read disks:", fact.reason)
Every fact returns a Fact — either ok with a value, or unknown with a reason. A
reading that could not be performed (permission denied, a missing command) is unknown,
never an exception you must catch and never a silent zero.
The headline: your code, tested offline
Because every fact reads through an injectable Source, the tool you build tests without
a real machine. The same call works in production (real system) and in tests (a
FakeSource):
# your_tool.py
import linuxfacts
from linuxfacts.sources.base import Source
def disk_warning(source: Source | None = None) -> str | None:
fact = linuxfacts.disks(source)
full = [d for d in fact.unwrap_or([]) if d.percent_used > 90]
return f"{len(full)} disk(s) over 90%" if full else None
# test_your_tool.py — offline, deterministic, no real machine
from linuxfacts.models import DiskUsage
from linuxfacts.testing import FakeSource
from your_tool import disk_warning
def test_warns_when_full():
source = FakeSource(disks=[DiskUsage("/", 100, 95, 5, 95.0)])
assert disk_warning(source) == "1 disk(s) over 90%"
Full documentation, including the testing guide and the compatibility policy, lives in
docs/ (built with MkDocs).
Testing
make check # ruff + mypy (strict) + pytest with coverage, one Python version
make matrix # nox across Python 3.11–3.13 (skips missing interpreters)
Every test runs offline. Facts are exercised through FakeSource; parsers are fed
versioned fixtures of real command output. Minimum coverage: 90% — it is a library, the bar
is higher.
Design decisions
docs/extraction-scope.md— what is extracted fromubuntu-doctorand what stays, and whydocs/compatibility.md— the SemVer and deprecation promise- Architecture decision records in
docs/adr/: Fact envelope over exceptions, protocol-based source injection, testing utilities are public API
Limitations
Stated up front:
- Debian/Ubuntu only
- Read-only — never writes to or changes the system
- Synchronous — no async API in v1.0
- No
journaldreading in v1.0
Roadmap
v1.1 adds journald reading and per-interface network facts; v1.2 an optional cache. The
public API is stable within a major version; deprecations warn for at least one minor
version before removal.
Contributing
Issues and pull requests are welcome. Please read the PR template first.
License
MIT — see LICENSE.
Contact
David Oliveira — davidoliveira.devbr@gmail.com
Metadata
Release files for linuxfacts 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| linuxfacts-1.0.0.tar.gz | 106.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| linuxfacts-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 129.2 kB
Release files / linuxfacts-1.0.0.tar.gz
| Download URL | linuxfacts-1.0.0.tar.gz |
|---|---|
| Size | 106.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef4f63744e48f899dea1a0e5a717059e6aa1b62c952b2d1f41b524ced9775f4c
|
|
BLAKE2b-256 checksum How to use checksums |
5d38a73d92eeac746d769310b775d9a197e8accf84e8d21307b017ab04ffc401
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 27, 2026.
Transparency logRelease files / linuxfacts-1.0.0-py3-none-any.whl
| Download URL | linuxfacts-1.0.0-py3-none-any.whl |
|---|---|
| Size | 23.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
30562232b346c4047c8261449077756fbe658f6bca57d5e681c15efc69ca8202
|
|
BLAKE2b-256 checksum How to use checksums |
a5b9c5dc2c515e2f5ee2463b6a1526fed0d3d49ed17f5c66e7a5957399f8be23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 27, 2026.
Transparency log