项目作者: Crimson-Crow

项目描述 :
Simple event system for Python with weak reference support
高级语言: Python
项目地址: git://github.com/Crimson-Crow/pyobservable.git
创建时间: 2021-06-27T23:39:59Z
项目社区:https://github.com/Crimson-Crow/pyobservable

开源协议:MIT License

下载


pyobservable

PyPI
PyPI - Python Version
Lines of code
GitHub)

Description

pyobservable provides a simple event system for Python with weak reference support.
This ensures that the event handlers do not stay in memory when they aren’t needed anymore.

Installation

pyobservable can be installed using pip:

  1. $ pip install pyobservable

Alternatively, you can download the repository and run the following command from within the source directory:

  1. $ python setup.py install

Usage

For a quick start, a minimal example is:

  1. from pyobservable import Observable
  2. obs = Observable()
  3. obs.add_event('foo')
  4. obs.add_event('bar')
  5. # Event keys can be any object that is hashable
  6. event = object()
  7. obs.add_event(event)
  8. # Binding with decorator usage
  9. @obs.bind('foo')
  10. def foo_handler(foo_number):
  11. print('foo_handler called:', foo_number)
  12. # Binding with function usage
  13. def bar_handler(bar_list):
  14. print('bar_handler called:', bar_list)
  15. obs.bind('bar', bar_handler)
  16. obs.notify('foo', 1)
  17. obs.notify('bar', [1, 2, 3])

The rationale behind the requirement to add events before binding to them is to ensure the code is less error-prone from mistyping event names.
Also, if a duplicated event key is present, ValueError will be raised.\
However, the next example shows that event registration can be simplified using the special _events_ attribute:

  1. from pyobservable import Observable
  2. class EventEmitter(Observable):
  3. _events_ = ['foo', 2]
  4. def triggers_foo(self):
  5. self.notify('foo', 1, 2, 3)
  6. event_emitter = EventEmitter()
  7. @event_emitter.bind('foo')
  8. def foo_handler(*args):
  9. print(*args)
  10. event_emitter.triggers_foo()

Also note that _events_ can be defined multiple times in an inheritance tree.
Observable scans the MRO for this attribute and adds every event it finds.
Again, a ValueError will be raised if a duplicate event key is present.

Finally, here’s an advanced and clean example using enum:

  1. from enum import Enum, auto
  2. from pyobservable import Observable
  3. class EventType(Enum):
  4. FOO = auto()
  5. BAR = auto()
  6. class EventEmitter(Observable):
  7. _events_ = EventType # Enums are iterable
  8. def triggers_foo(self):
  9. self.notify(EventType.FOO, 'foo happened!')
  10. class EventListener:
  11. def on_foo(self, message):
  12. print("Here's a message from foo:", message)
  13. event_emitter = EventEmitter()
  14. event_listener = EventListener()
  15. event_emitter.bind(EventType.FOO, event_listener.on_foo) # pyobservable also supports bound methods
  16. event_emitter.triggers_foo()

For more information, please refer to the Observable class docstrings.

Tests

The simplest way to run tests:

  1. $ python tests.py

As a more robust alternative, you can install tox (or tox-conda if you use conda) to automatically support testing across the supported python versions, then run:

  1. $ tox

Issue tracker

Please report any bugs and enhancement ideas using the issue tracker.

License

pyobservable is licensed under the terms of the MIT License (see LICENSE.txt for more information).