inotify_simple

A dependency-free ctypes wrapper that exposes Linux inotify exactly as the kernel does, in under 100 lines.

Library
PyPI
v2.0.1
135stars
BSD-2-Clause

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
41/100Fair
Development Activity0
Maintenance20
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
57/100Fair
Architecture78
Code Quality35
Innovation40
Learning Curve75

inotify_simple is a pure-Python wrapper around Linux’s inotify filesystem event API, implemented in under 100 lines using ctypes with no compiled extensions or third-party dependencies. It exposes inotify_init1(), inotify_add_watch(), and inotify_rm_watch() with almost no changes, wrapping the file descriptor in an INotify class that behaves like a standard file-like object usable directly with select or poll.

Unlike higher-level inotify wrappers that abstract away watch descriptors or impose their own event loop, inotify_simple stays close to the underlying C API: watch descriptors are plain integers the caller tracks, and events are returned as Event namedtuples decoded from the raw struct format the kernel emits. This makes it a stable foundation for building custom file-watching tools without inheriting a heavier library’s assumptions about how watches should be managed.

What You Get

  • INotify class - a file-like wrapper around the inotify file descriptor, usable directly with poll(), select(), or os.read()
  • Event namedtuples - decoded (wd, mask, cookie, name) tuples parsed from raw inotify struct data via parse_events()
  • flags and masks IntEnums - the full set of IN_* inotify constants (CREATE, DELETE, MODIFY, etc.) with a from_mask() helper to decode event bitmasks
  • Blocking and non-blocking read modes - read() accepts a timeout and an optional read_delay to let events coalesce before reading

Common Use Cases

  • Building a custom file-watching daemon that reacts to filesystem changes
  • Implementing hot-reload for development servers
  • Auditing filesystem activity in a directory tree
  • Underpinning higher-level watch libraries that need raw inotify semantics

Under The Hood

Architecture inotify_simple is a single flat module (~220 lines) with no internal layering: an INotify class subclasses io.FileIO to wrap the inotify file descriptor, lazily loading libc via ctypes.CDLL on first instantiation and registering the fd with a module-scoped poll() object to implement read()‘s timeout behavior. Event parsing is deliberately kept separate from I/O in a standalone parse_events() function, so code that reads the raw file descriptor itself (bypassing INotify.read()) can still decode events. flags and masks are IntEnum classes that mirror inotify.h’s IN_* constants directly. There is no plugin system, no configuration layer, and no abstraction beyond this thin translation between ctypes calls and Python objects - the entire attack surface for “what breaks if core abstractions change” is this one file.

Tech Stack The project has zero runtime dependencies, relying entirely on the Python 3.6+ standard library: ctypes for the libc calls, struct for unpacking inotify’s binary event format, select.poll for blocking reads, and termios/fcntl for FIONREAD-based buffer sizing. Packaging uses a pyproject.toml with setuptools as the build backend and a dynamic version sourced from the module’s own version attribute. Documentation is built with Sphinx and published to Read the Docs (docs/conf.py, readthedocs.yaml). A GitHub Actions workflow (release.yml) builds sdist/wheel artifacts and publishes to TestPyPI and PyPI on tag pushes, but runs no test suite as part of that pipeline.

Code Quality The repository contains no test files and no test job in CI - there is no automated verification of the ctypes bindings or the struct-unpacking logic in parse_events(), despite that logic being exactly the kind of low-level, binary-format code most prone to silent breakage. Error handling is minimal but correct where it exists: the internal _libc_call helper raises OSError with the appropriate strerror() message on failure and transparently retries on EINTR. There are no type hints anywhere in the codebase, and no linter or formatter configuration is present. Docstrings are thorough and Sphinx-formatted, which is the project’s main source of ongoing documentation quality, but they don’t substitute for automated tests.

What Makes It Unique inotify_simple’s distinguishing trait is deliberate restraint rather than any novel technique: it explicitly positions itself against higher-level inotify wrappers that add their own event-loop or watch-management abstractions, choosing instead to expose watch descriptors and raw event masks unchanged from the C API. Combined with having no dependencies and staying under 100 lines of implementation code by design, this makes it a stable, low-churn primitive that other file-watching tools can build on top of without inheriting an opinionated abstraction they’d have to work around.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search