Skip to main content

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 explicit ok/unknown state
  • A public FakeSource so 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.typed so 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

Limitations

Stated up front:

  • Debian/Ubuntu only
  • Read-only — never writes to or changes the system
  • Synchronous — no async API in v1.0
  • No journald reading 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linuxfacts-1.0.0.tar.gz (106.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linuxfacts-1.0.0-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

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

Hashes for linuxfacts-1.0.0.tar.gz
Algorithm Hash digest
SHA256 ef4f63744e48f899dea1a0e5a717059e6aa1b62c952b2d1f41b524ced9775f4c
MD5 b7b9110872a1da2ee50d4165bed3fedb
BLAKE2b-256 5d38a73d92eeac746d769310b775d9a197e8accf84e8d21307b017ab04ffc401

See more details on using hashes here.

Provenance

The following attestation bundles were made for linuxfacts-1.0.0.tar.gz:

Publisher: release.yml on david-oliveira-dev/linuxfacts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for linuxfacts-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 30562232b346c4047c8261449077756fbe658f6bca57d5e681c15efc69ca8202
MD5 7e17f9cc3e7d70c504ac4d7d87d8138d
BLAKE2b-256 a5b9c5dc2c515e2f5ee2463b6a1526fed0d3d49ed17f5c66e7a5957399f8be23

See more details on using hashes here.

Provenance

The following attestation bundles were made for linuxfacts-1.0.0-py3-none-any.whl:

Publisher: release.yml on david-oliveira-dev/linuxfacts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page