Skip to main content

Object Observability for Python โ€” automatically track every attribute change.

Project description

๐Ÿ“œ Bijoy

Object Observability for Python
Automatically track every attribute change โ€” built for debugging & auditing.

Python 3.8+ Zero Dependencies Thread Safe MIT License


โœจ What is Bijoy?

Bijoy is a lightweight Python library that gives your objects memory. By inheriting from the Chronicle base class, every attribute change is automatically recorded with:

  • ๐Ÿ• High-precision UTC timestamp
  • ๐Ÿ“ Exact source location (file, line number, function name)
  • ๐Ÿ”’ Thread-safe logging via threading.Lock
  • ๐Ÿ“ฆ Zero external dependencies โ€” uses only the Python Standard Library

Perfect for debugging state mutations, auditing workflows, and understanding when and where your objects changed.


๐Ÿš€ Quick Start

Installation

pip install bijoy

Or install from source:

git clone https://github.com/bijoy/bijoy.git
cd bijoy
pip install -e .

Basic Usage

from bijoy import Chronicle


class Server(Chronicle):
    def __init__(self, name: str):
        super().__init__(max_history=50)
        self.name = name
        self.status = "booting"


srv = Server("web-prod-01")
srv.status = "deploying"
srv.status = "running"

# View the full history of an attribute
for entry in srv.get_history("status"):
    print(entry)

# Undo the last change
srv.undo("status")
print(srv.status)  # "deploying"

# Print a formatted audit report
srv.audit()

Output:

========================================================================
  CHRONICLE AUDIT โ€” Server (id=0x...)
========================================================================

  Attribute: 'name'
  โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
    [1] value = 'web-prod-01'
        time  = 2026-03-21 17:00:00.123456 UTC
        where = example.py:8 in __init__()

  Attribute: 'status'
  โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”
    [1] value = 'booting'
        time  = 2026-03-21 17:00:00.123457 UTC
        where = example.py:9 in __init__()
    [2] value = 'deploying'
        time  = 2026-03-21 17:00:00.123458 UTC
        where = example.py:13 in <module>()

========================================================================

๐Ÿ“– API Reference

Chronicle(max_history: int = 100)

Base class. Inherit from it to enable automatic attribute tracking.

Parameter Type Default Description
max_history int 100 Maximum entries kept per attribute (FIFO)

get_history(attr_name: str) โ†’ List[HistoryEntry]

Returns a chronological list of all recorded changes for the given attribute.

entries = obj.get_history("status")
for e in entries:
    print(f"{e.value} at {e.timestamp} โ€” {e.filename}:{e.lineno}")

undo(attr_name: str) โ†’ Any

Reverts an attribute to its previous value and removes the latest history entry.

obj.status = "crashed"
prev = obj.undo("status")  # restores previous value
  • Returns the restored value, or None if the attribute had only one entry (gets deleted).
  • Raises KeyError if no history exists.

audit() โ†’ str

Prints and returns a human-readable, formatted report of all recorded attribute changes.

report = obj.audit()  # prints to stdout and returns the string

toggle_recording(enable: bool) โ†’ None

Pause or resume history tracking. Useful to skip noisy updates.

obj.toggle_recording(False)
obj.cpu_load = 99.9  # NOT recorded
obj.toggle_recording(True)
obj.cpu_load = 42.0  # recorded

clear_history(attr_name: str | None = None) โ†’ None

Erase recorded history. Pass an attribute name to clear only that attribute, or None to clear everything.


HistoryEntry

Each recorded change is stored as a HistoryEntry with these fields:

Field Type Description
value Any The new value assigned
timestamp datetime UTC time of the change
filename str Source file path
lineno int Line number in the source file
function str Function/method name

๐Ÿงช Running Tests

python -m unittest test_chronicle -v
test_initial_assignment_creates_history ........................ ok
test_subsequent_changes_are_appended ........................... ok
test_history_entry_has_caller_metadata ......................... ok
test_private_attrs_not_logged .................................. ok
test_undo_restores_previous_value .............................. ok
test_undo_removes_latest_entry ................................. ok
test_undo_single_entry_deletes_attribute ....................... ok
test_undo_no_history_raises .................................... ok
test_oldest_entries_discarded .................................. ok
test_max_history_of_one ........................................ ok
test_paused_changes_not_logged ................................. ok
test_resume_recording .......................................... ok
test_concurrent_writes ......................................... ok

----------------------------------------------------------------------
Ran 13 tests in 0.XXXs

OK

๐Ÿ—๏ธ Project Structure

bijoy/
โ”œโ”€โ”€ bijoy/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ chronicle.py
โ”œโ”€โ”€ example_chronicle.py
โ”œโ”€โ”€ test_chronicle.py
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ LICENSE
โ”œโ”€โ”€ .gitignore
โ””โ”€โ”€ README.md

๐ŸŽฏ Design Highlights

Feature How
No recursion loops __init__ writes internals via self.__dict__ directly
No meta-logging Attributes starting with _ are silently skipped
O(1) eviction Uses collections.deque(maxlen=โ€ฆ) for FIFO pruning
Thread safety All history reads/writes are guarded by threading.Lock
Zero dependencies Only inspect, threading, datetime, collections

๐Ÿ“„ License

MIT License โ€” free for personal and commercial use.


Made with โค๏ธ by Bijoy

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

bijoy-1.0.0.tar.gz (6.8 kB view details)

Uploaded Source

Built Distribution

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

bijoy-1.0.0-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file bijoy-1.0.0.tar.gz.

File metadata

  • Download URL: bijoy-1.0.0.tar.gz
  • Upload date:
  • Size: 6.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for bijoy-1.0.0.tar.gz
Algorithm Hash digest
SHA256 34d0cb73102901107196e44c0e121e842eefc943ca0dae74725262a7ea396366
MD5 50aed953c10519def919234557fafe02
BLAKE2b-256 8d20161755a37dc8591da876d3e9df99b53ecf334c5ce8c1313f98b417c8697d

See more details on using hashes here.

File details

Details for the file bijoy-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: bijoy-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 6.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for bijoy-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 940ca693177d9245703fdeeb9abbd2284f61a2c08bf875fad5895688a666d1ab
MD5 c06c52ef4328182f2fe7babcc8069e30
BLAKE2b-256 60d4186b52afcc04507602f408250b185541f193a65337a71d79a695cbbd9765

See more details on using hashes here.

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