https://github.com/cr0hn/python-object-watchdog
Watching for runtime changes in Python objects and launch callbacks
https://github.com/cr0hn/python-object-watchdog
asyncio cache metaclasses metaprogramming monitoring python watchdog
Last synced: 6 months ago
JSON representation
Watching for runtime changes in Python objects and launch callbacks
- Host: GitHub
- URL: https://github.com/cr0hn/python-object-watchdog
- Owner: cr0hn
- License: other
- Created: 2020-05-04T07:37:22.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2024-09-07T08:02:12.000Z (about 1 year ago)
- Last Synced: 2025-03-25T17:10:05.463Z (7 months ago)
- Topics: asyncio, cache, metaclasses, metaprogramming, monitoring, python, watchdog
- Language: Python
- Homepage:
- Size: 18.6 KB
- Stars: 8
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.rst
- Changelog: CHANGELOG.rst
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
Object Watchdog
===============This library allow to monitor changes in a Python object and, when some attribute changes, then launch callbacks.
Support this project
====================Support this project (to solve issues, new features...) by applying the Github "Sponsor" button.
Install
=======.. code-block:: console
$ pip install object-watchdog
Callbacks types
===============There're 3 types of callbacks:
- Async callbacks: launch coroutines as callbacks
- Callbacks: launch functions as callbacks
- Cache callbacks: Launch methods of class to update cachesGlobal vs local callbacks
=========================- Local callbacks are called only for these classes that have set the callbacks
- Global callbacks are called for all classes that uses the Object WatchdogHow to usage
============Object Watchdog should be used as metaclass:
.. code-block:: python
from object_watchdog import ObjectWatchdog
class User(metaclass=ObjectWatchdog):
...Defining local callbacks
========================Callbacks could be defined in running time and in definition.
Definition mode
---------------At the classes you can put callbacks when any attribute changes, you can define these types of callbacks in these properties:
- `__async_callbacks__`
- `__callbacks__`
- `__cache_callbacks__`Example:
.. code-block:: python
async def async_callback(instance, klass_name, key, value):
print(f"[!] New change local callback in key '{key}'. New value '{value}'")async def async_callback2(instance, klass_name, key, value):
print(f"[0] New change local callback in key '{key}'. New value '{value}'")def callback(instance, klass_name, key, value):
print(f"[!] Sync New change local callback in key '{key}'. New value '{value}'")class User(metaclass=ObjectWatchdog):
__async_callbacks__ = [async_callback, async_callback2]
__callbacks__ = [callback]
__cache_callbacks__ = ["__build_hash__"]...
Running time
------------If you need to add some callback in run time, Metaclass add these methods:
- `add_callback`
- `add_async_callback`
- `add_cache_callback`.. code-block:: python
import asyncio
from typing import Dict
from dataclasses import dataclass, fieldfrom object_watchdog import ObjectWatchdog
@dataclass
class User(metaclass=ObjectWatchdog):
user: str
password: str@property
def hash(self):
if not self.__cached_hash:
self.__build_hash__()
return self.__cached_hashdef __build_hash__(self, key: str = None):
if key and key != "user" and key != "password":
returnh = hashlib.sha512()
h.update(
f"{self.user}#{self.password}".encode("UTF-8")
)self.__cached_hash = h.hexdigest()
async def coro_callback(instance, klass_name, key, value):
print(f"[!] New change in key '{key}'. New value '{value}'")async def main():
u = User(user="john", password="password")
u.add_async_callback(coro_callback)
u.add_cache_callback("__build_hash__")print("[*] Modifying property 'value'")
u.password = "new password!"def main():
asyncio.run(coro_main())main()
Defining global callbacks
=========================Global callback applies to all classes (or dataclasses) that uses ObjectWatchdog as a metaclass.
If you want to call any function / coroutine when some class have been modified, you also can use this method. ObjectWatchdog metaclass has these methods:
- `add_global_callback`
- `add_global_async_callback`
- `add_global_cache_callback`.. code-block:: python
import asyncio
from typing import Dict
from dataclasses import dataclass, fieldfrom object_watchdog import ObjectWatchdog
@dataclass
class MyClass(metaclass=ObjectWatchdog):
value: str
my_dict: Dict = field(default_factory=dict)@dataclass
class MyClass2(metaclass=ObjectWatchdog):
value: str
my_dict: Dict = field(default_factory=dict)async def coro_local_callback(instance, klass_name, key, value):
print(f"[!] New change local callback in key '{key}'. New value '{value}'")async def coro_global_callback(instance, klass_name, key, value):
print(f"[!] New change global callback in instance '{repr(instance)}' key '{key}'. New value '{value}'")async def coro_main():
ObjectWatchdog.add_global_callback(coro_global_callback)
u1 = MyClass(value="class 1", my_dict={"k": "v"})
u2 = MyClass2(value="class 2", my_dict={"k": "v"})print("[*] Modifying property 'value'")
u1.value = "new value!"
u2.value = "new value!"def main():
asyncio.run(coro_main())main()