Skip to main content

A Python decorator for logging attribute changes in classes

Project description

Selv

A Python decorator for logging attribute changes in class. Track every modification to your object's attributes with automatic logging and changelog.

Motivation

Tracking attribute changes helps me understand how a complex class behaves and speeds up debugging when issues occur. Having said this, I need a simple way to log all attribute changes without writing boilerplate code for each attribute.

Features

  • Automatic attribute change tracking: Decorated class automatically log all attribute changes

  • Container support: Tracks value modifications inside built-in containers (dict, list, set, tuple)

  • Flexible logging: Use good ol print statement or any custom logger function

  • View changelog: Query complete change history for any attribute

  • Exclude specific attributes: Optionally exclude specific attributes from tracking

  • Custom actions: Execute custom functions when specific attributes change

Installation

pip install selv

Or using mighty uv:

uv add selv

Usage

Tracking changes

from selv import selv

@selv
class Counter:
    def __init__(self):
        self.value = 0

    def increment(self):
        self.value += 1

    def decrement(self):
        self.value -= 1

# Create counter and use it
counter = Counter()
counter.increment()
counter.decrement()

# Changes are automatically logged:
# [Counter] value: 0 -> 1
# [Counter] value: 1 -> 0

View changelog

# View all changes
all_changes = counter.view_changelog()
print(all_changes)
# [
#   {'time': datetime, 'attr': 'value', 'from': None, 'to': 0},
#   {'time': datetime, 'attr': 'value', 'from': 0, 'to': 1},
#   {'time': datetime, 'attr': 'value', 'from': 1, 'to': 0}
# ]

# View changes for specific attribute
value_changes = counter.view_changelog("value")
print(value_changes)
# [
#   {'time': datetime, 'from': None, 'to': 0},
#   {'time': datetime, 'from': 0, 'to': 1},
#   {'time': datetime, 'from': 1, 'to': 0}
# ]

# View changes grouped by attribute
grouped = counter.view_changelog(format="attr")
print(grouped)
# {
#   'value': [
#     {'time': datetime, 'from': None, 'to': 0},
#     {'time': datetime, 'from': 0, 'to': 1},
#     {'time': datetime, 'from': 1, 'to': 0}
#   ]
# }

Set custom action

from selv import selv


def log_inventory_change(inventory):
    total = sum(inventory.values())
    print(f"Total items in inventory: {total}")

@selv(actions={"inventory": log_inventory_change})
class Store:
    def __init__(self):
        self.inventory = {"apples": 10, "bananas": 5}

store = Store()
store.inventory["oranges"] = 8
# [Store] inventory = {'apples': 10, 'bananas': 5} (initialized)
# Total items in inventory: 15
# [Store] inventory: {'apples': 10, 'bananas': 5} -> {'apples': 10, 'bananas': 5, 'oranges': 8}
# Total items in inventory: 23

Parameters

The @selv decorator has a few parameters to customize its behavior.

  1. track_private (bool, default: True)

    • When True: Tracks all attributes including those starting with _ (private attributes)
    • When False: Only tracks public attributes (those not starting with _)
  2. logger (Callable[[str], None], default: print)

    • Function to use for logging change messages (e.g., logging.info, logging.debug)
    • Can be any function that accepts a string argument
  3. exclude (List[str], default: None)

    • List of attribute names to exclude from tracking
    • Useful for exclude sensitive data or unimportant attributes
  4. actions (Dict[str, Callable[[Any], None]], default: None)

    • Dictionary mapping attribute names to functions that are called when the attribute changes
    • Each function receives the new value of the attribute as its argument

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

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

selv-1.2.0.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

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

selv-1.2.0-py3-none-any.whl (7.5 kB view details)

Uploaded Python 3

File details

Details for the file selv-1.2.0.tar.gz.

File metadata

  • Download URL: selv-1.2.0.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for selv-1.2.0.tar.gz
Algorithm Hash digest
SHA256 4a8c3f8cbcd6492488c6ddb14ad5947fb02449c9926bb6b13b3bd2863e693eb9
MD5 93e342d29142e7fd3596dde076386454
BLAKE2b-256 a9ae5a6b7291ca49f7d82369af86ffe15e730e758efb93c521160e0523d6cdc3

See more details on using hashes here.

File details

Details for the file selv-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: selv-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 7.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for selv-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3166bea1b631168caf4045d57de72bed079d7cda107356238c6f090d99fffea1
MD5 b0555406d91e854be0276ef5a14ef4d4
BLAKE2b-256 1e9e1223523ce703fa2196fdd8b4386546bd2324d29e65129bccbe8e7beaf6ed

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