Skip to main content

NestWatch

Python

License

PyPI

NestWatch is a Python package that allows applications to react to meaningful file changes instead of raw filesystem events.

Rather than repeatedly polling files and risking cache desynchronization, NestWatch instantly notifies your application whenever a file changes and provides both its previous and new state.

Why NestWatch?

Many applications update caches using polling tasks.

@tasks.loop(minutes=1)
async def update_cache():
        ...

While this works, it introduces a delay between when data changes and when applications become aware of those changes.

This becomes problematic when multiple applications depend on the same data source.

For example:

  • Application A updates "config.json"
  • Application B continues using outdated cached data
  • Application B must wait for its polling task to run
  • Both applications become temporarily out of sync

NestWatch solves this by allowing applications to react to changes instantly.

Features

  • ⚡ Instant file change detection
  • 🧠 Returns both old and new state
  • ➕ Detects added keys
  • ➖ Detects removed keys
  • 🔄 Detects changed values
  • 📍 Dot-path support
  • 🧩 Extensible architecture
  • 📄 JSON support built in
  • 🏗️ Create custom watchers for your own file formats

Installation

pip install nestwatch

Quick Start

from nestwatch.watchers import JSONWatcher


class ConfigCache:

    def __init__(self):

        self.watcher = JSONWatcher("data/config.json")

        self.watcher.on_change(
            self.update_cache
        )

    async def update_cache(self, event):

        # Affected changes only
        print(event.added)
        print(event.removed)
        print(event.changed)

        # Reconstructed views)
        print(event.old)
        print(event.new)
        print(event.updated)

    async def startup(self):

        await self.watcher.start()

Event Object

NestWatch emits an Event object containing:

Property Description
event.added Keys that were added (dot-path → value)
event.removed Keys that were removed (dot-path → old value)
event.changed Keys that were modified (old + new)
event.old Partial reconstruction of only affected old values
event.new Partial reconstruction of only affected new values
event.updated_state Final state after applying the event to the old data

Event Examples

Suppose this file:

{
    "BOT_STATUS": {
        "presence": "online",
        "activity": {
            "type": "playing",
            "name": "Roblox"
        }
    }
}

becomes:

{
    "BOT_STATUS": {
        "presence": "idle",
        "custom": "Watching NestWatch 👀"
    },
    "API": {
        "enabled": true
    }
}

Then:

event.added

{
    "BOT_STATUS.custom": "Watching NestWatch 👀",
    "API.enabled": True
}

event.removed

{
    "BOT_STATUS.activity.type": "playing",
    "BOT_STATUS.activity.name": "Roblox"
}

event.changed

{
    "BOT_STATUS.presence": {
        "old": "online",
        "new": "idle"
    }
}

event.old

{
    "BOT_STATUS": {
        "presence": "online",
        "activity": {
            "type": "playing",
            "name": "Roblox"
        }
    }
}

event.new

{
    "BOT_STATUS": {
        "presence": "idle",
        "custom": "Watching NestWatch 👀"
    },
    
    "API": {
        "enabled": True
    }
}

event.updated_state

{
    "BOT_STATUS": {
        "presence": "idle",
        "custom": "Watching NestWatch 👀"
    },
    "API": {
        "enabled": True
    }
}

IMPORTANT NOTE: “These are partial reconstructions of only affected regions, not full file snapshots.”


Creating Custom Watchers

NestWatch is designed to be extensible.

You can support any file format by subclassing "Watcher".

from nestwatch.watchers import Watcher


class MyCustomWatcher(Watcher):

    def _serialize(self):

        return my_language.load(
            self.file_path
        )

The Watcher class supports asynchronous serializers as well.

This allows you to perform asynchronous file reads before NestWatch processes the data.

import aiofiles
from nestwatch.watchers import Watcher

class MyCustomWatcher(Watcher):

    async def _serialize(self):
        async with aiofiles.open(self.file_path) as f:
            content = await f.read()
            return my_language.load(content)

That's it.

NestWatch will automatically handle:

  • Watching the file
  • Detecting changes
  • Comparing states
  • Generating events
  • Calling your listeners

Use Cases

NestWatch works especially well for:

  • 🤖 Discord bots
  • 🌐 FastAPI applications
  • 📦 Shared caches
  • ⚙️ Configuration files
  • 🔄 Runtime reload systems
  • 🧠 Multi-application projects

Philosophy

Traditional file watchers answer:

"Did the file change?"

NestWatch answers:

"What changed inside the file?"


NestWatch's Dependency

Package Version Usage
watchdog >=6.0.0 Listens for file changes
aiofiles >=25.1.0 For reading files in async for internal asynchronous serializers.

Release files for nestwatch 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nestwatch 0.0.9
File Size Uploaded
nestwatch-0.0.9.tar.gz 9.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nestwatch 0.0.9
File Interpreter ABI Platform
nestwatch-0.0.9-py3-none-any.whl Python 3 none any Details

Total release size: 18.4 kB

Release files / nestwatch-0.0.9.tar.gz

Download URL nestwatch-0.0.9.tar.gz
Size 9.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c50895af1068661be651db5f78e8e6106aa82ba25a606092f4b480a82d11d521
BLAKE2b-256 checksum
How to use checksums
c8885ba6f3373287a3e11f7b36108a4ec5347f56120e1bb0939aab14e1d0f0cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release files / nestwatch-0.0.9-py3-none-any.whl

Download URL nestwatch-0.0.9-py3-none-any.whl
Size 9.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f6cf410f24a0436f0be05bfc524db51fa43b3246e1b06e6a68a07c0fc2b2dc3
BLAKE2b-256 checksum
How to use checksums
e8a87ea1ccadc03a365c3f5aec25edccb57797e5df132c9efed4ed98fb314109
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release history Release notifications | RSS feed

0.0.10

2 release files

This release

0.0.9 This release

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page