Skip to main content

Observable managed attributes (aka, observable properties)

Project description

Observable managed attributes (also known as "observable properties")

In summary:

  • Declare observable properties using the @observable decorator instead of @property.
  • Subscribe/unsubscribe any number of callback functions to observable properties.
  • If the value of an observable property changes, all subscribed callbacks are executed.

How to use

Declare observable properties in your class

Use the @observable decorator as you do with @property:

from observable_properties import observable

class Test():
    def __init__(self):
        self._value = 0
    @observable
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        self._value = value

Needless to say, observable properties are also regular properties and they work just the same:

t = Test()
t.value = 1000
print(t.value)

Subscribe to property changes

In the context of this library, an observer is a callback function to be executed just before a property is written in a given object. For example:

def observer(instance,property_name,new_value):
    old_value = getattr(instance,property_name)
    print(f"{instance.__class__.__name__}.{property_name} changes from {old_value} to {new_value}")

To start observing a property, call subscribe() passing the instance and property name to observe along with the callback function:

from observable_properties import subscribe

subscribe(observer,t,"value")

Which means "subscribe observer to t.value". Now, the observer is executed whenever the value of the observed property changes at the observed object:

t.value = 2000

prints:

Test.value changes from 1000 to 2000

Note that:

  • Observers are not allowed to change the value of the observed property. ObservablePropertyError is raised in such a case.
  • The same observer can subscribe to many objects and properties.
  • Any number of observers can subscribe to the same object and property. All of them will run. The execution order depends on subscription order.

Unsubscribe

To stop observing a property, call unsubscribe() with the same parameters that were given to subscribe():

from observable_properties import unsubscribe

unsubscribe(observer,t,"value")

Syntactic sugar

To speed things up, derive your class from the Observable class (note the capital letter). The declaration itself does not differ too much from the previous example:

from observable_properties import Observable

class ObservableTest(Observable):
    def __init__(self):
        self._value = 0
    @observable
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        self._value = value

Observable classes offers another decorator for easier subscription to a single property in a single object:

ot = ObservableTest()
@ot.subscribe("value")
def on_change(instance, property_name, new_value):
    old_value = ot.value
    print(f"ot.value changes from {old_value} to {new_value}")

And the unsubscribe() method:

ot.unsubscribe("value",on_change)

An already-defined observer may subscribe to a property in this way:

def another_observer(new_value):
  ...

ot.subscribe("value")(another_observer)

Other notes

  • Both subscribe() and unsubscribe() raise ObservablePropertyError on non-observable or non-existing properties.
  • Subscribing twice to the same object and property has no effect.
  • Unsubscribing to non-subscribed properties has no effect, but unsubscribe() returns False.
  • Objects hold strong references to observers. Deleting an observer does not prevent it from running. Unsubscribe first.
  • Coroutines are accepted as observers. They are executed by the means of asyncio.run()

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

observable-properties-2.0.0.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

observable_properties-2.0.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file observable-properties-2.0.0.tar.gz.

File metadata

  • Download URL: observable-properties-2.0.0.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for observable-properties-2.0.0.tar.gz
Algorithm Hash digest
SHA256 a59d6f042688e311b33b16e2b6feda3f04701946202557ef86a220269e7c5849
MD5 4f19a572fbd598e0ed39e9167f0589fb
BLAKE2b-256 060625ca50c7e87454e26d20551dd6618cb96d4ea3e97385923904532146563a

See more details on using hashes here.

File details

Details for the file observable_properties-2.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for observable_properties-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 81a77ec42d88b6c96bbdb3217fbe0aabf4e7ad6c10f4147d4d78d1c807698c2e
MD5 501ff20723f96dad5bdcbefd0c965404
BLAKE2b-256 85c9d20b5d2c0d6cde31dc7c44e35e5f43b5a40d46ac29e783e82dcb9b2a31a4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page