Typed, testable library for reading Linux system state — disks, memory, systemd units, ports and packages — with no side effects.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file linuxfacts-1.0.0.tar.gz.
File metadata
- Download URL: linuxfacts-1.0.0.tar.gz
- Upload date:
- Size: 106.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef4f63744e48f899dea1a0e5a717059e6aa1b62c952b2d1f41b524ced9775f4c
|
|
| MD5 |
b7b9110872a1da2ee50d4165bed3fedb
|
|
| BLAKE2b-256 |
5d38a73d92eeac746d769310b775d9a197e8accf84e8d21307b017ab04ffc401
|
Provenance
The following attestation bundles were made for linuxfacts-1.0.0.tar.gz:
Publisher:
release.yml on david-oliveira-dev/linuxfacts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
linuxfacts-1.0.0.tar.gz -
Subject digest:
ef4f63744e48f899dea1a0e5a717059e6aa1b62c952b2d1f41b524ced9775f4c - Sigstore transparency entry: 2259121433
- Sigstore integration time:
-
Permalink:
david-oliveira-dev/linuxfacts@af0456152130cb74cf661d0435cd0f8707867f14 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/david-oliveira-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af0456152130cb74cf661d0435cd0f8707867f14 -
Trigger Event:
push
-
Statement type:
File details
Details for the file linuxfacts-1.0.0-py3-none-any.whl.
File metadata
- Download URL: linuxfacts-1.0.0-py3-none-any.whl
- Upload date:
- Size: 23.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30562232b346c4047c8261449077756fbe658f6bca57d5e681c15efc69ca8202
|
|
| MD5 |
7e17f9cc3e7d70c504ac4d7d87d8138d
|
|
| BLAKE2b-256 |
a5b9c5dc2c515e2f5ee2463b6a1526fed0d3d49ed17f5c66e7a5957399f8be23
|
Provenance
The following attestation bundles were made for linuxfacts-1.0.0-py3-none-any.whl:
Publisher:
release.yml on david-oliveira-dev/linuxfacts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
linuxfacts-1.0.0-py3-none-any.whl -
Subject digest:
30562232b346c4047c8261449077756fbe658f6bca57d5e681c15efc69ca8202 - Sigstore transparency entry: 2259121447
- Sigstore integration time:
-
Permalink:
david-oliveira-dev/linuxfacts@af0456152130cb74cf661d0435cd0f8707867f14 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/david-oliveira-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@af0456152130cb74cf661d0435cd0f8707867f14 -
Trigger Event:
push
-
Statement type: