معرفی شرکت ها


event-signal-1.8.0


Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر

توضیحات

Library to help notify when something has changed.
ویژگی مقدار
سیستم عامل -
نام فایل event-signal-1.8.0
نام event-signal
نسخه کتابخانه 1.8.0
نگهدارنده []
ایمیل نگهدارنده []
نویسنده Justin Engel
ایمیل نویسنده jtengel08@gmail.com
آدرس صفحه اصلی https://github.com/justengel/event_signal
آدرس اینترنتی https://pypi.org/project/event-signal/
مجوز MIT
# Event Signal This library was created to help maintain when variables are changed and when functions are called. There are 5 main utilities provided * signaler - Function decorator to help observe functions * signaler_property - Custom property that helps observe when a property value is changed or deleted. * MethodObserver - class mixin to make all function observable * Signal - Similar to Qt's signal without requiring PyQT or PySide * bind - Make two object share the same value ## Use There are 5 main functions to use the signals. * get_signal - returns a list of connected function callbacks * on - connect a callback function to a signal * off - disconnect a callback funciton from a signal * fire - Call all callback functions that are associated with a signal * block - Temporarily block a signal from calling callback functions Two basic signals are provided `'before_change'` and `'change'`. The signaler_property also has delete signals. * 'before_change' - This signal automatically fires before a function is called. * 'change' - This signal automatically fires after a function is called. * 'before_delete' - signaler_property fired before `del obj.property` is called. * 'delete' - signaler_property fired after `del obj.property` is called. ## Basics A signaler is a custom class that decorates a function. It acts just like a function (it is callable). A signaler can have other functions attached to it with a name. When the signaler fire is called it will call all of the attached functions. ```python from event_signal import signaler def my_function(a, b, c): print(a, b, c) my_function = signaler(my_function) # Call the signaler like a normal function my_function(1, 2, 3) # print = 1, 2, 3 print('=====\n') def print_signal(value1, value2): print('print_signal called', value1, value2) my_function.on('my_signal', print_signal) my_function.fire('my_signal', 1, 2) # print = print_signal called 1 2 print('=====\n') def another_signal(value1, value2): print('another_signal called', value1, value2, value1 == value2) my_function.on('my_signal', another_signal) my_function.fire('my_signal', 2, 2) # print = print_signal called 2 2 # print = another_signal called 2 2 True print('=====\n') my_function.off('my_signal', print_signal) my_function.fire('my_signal', 3, 2) # print = another_signal called 3 2 False print('=====\n') print(my_function.get_signal('my_signal')) # print = [<function ...another_signal at 0x056076F0>] print('=====\n') my_function.block('my_signal') my_function.fire('my_signal', 4, 5) # No print! my_function.block('my_signal', False) my_function.fire('my_signal', 5, 6) # print = another_signal called 5 6 False print('=====\n') ``` ## Example - signaler Javascript like events for functions and objects. The signaler automatically creates and fires signals `'before_change'` and `'change'`. ```python from event_signal import signaler class XTest(object): def __init__(self, x=0): self._x = x def get_x(self): return self._x @signaler def set_x(self, x): self._x = x @set_x.on("before_change") def x_changing(self, x): print("x is changing") @set_x.on("change") def x_changed(self, x): print("x changed", x) t = XTest() t.set_x(1) # x is changing # x changed 1 t.set_x.on("change", lambda x: print("new signal")) t.set_x(2) # x is changing # x changed 2 # new signal t.set_x.off("before_change", t.x_changing) t.set_x(3) # x changed 3 # new signal t.set_x.block() t.set_x(4) t.set_x.block(block=False) t.set_x(5) # x changed 3 # new signal t.set_x.block('change', True) t.set_x(6) ``` Change the value that is passed to the change callback functions. ```python from event_signal import signaler class XTest(object): def __init__(self, x=0): self._x = x def get_x(self): return self._x @signaler(getter=get_x) def set_x(self, x): """Set x and force the value to be between 1 and 100.""" if x < 0: x = 0 elif x > 100: x = 100 self._x = x @set_x.on("before_change") def x_changing(self, x): print("x is changing", x) @set_x.on("change") def x_changed(self, x): print("x changed", x) t = XTest() t.set_x(1) # x is changing 1 # x changed 1 # Normally (without the getter) the change callback functions receive # the x value that was passed into set_x t.set_x(-1) # x is changing -1 # x changed 0 t.set_x(102) # x is changing 102 # x changed 100 # In this case the value passed into the change callback functions # is the value returned from the signaler getter (t.get_x) # which is how the signaler_property works. ``` ## Example - signaler_property A property with signaler capabilities. The signaler_property automatically creates and fires signals `'before_change'`, `'change'`, `'before_delete'`, and `'delete'`. ```python from event_signal import signaler_property class XTest(object): def __init__(self, x=0): self._x = x @signaler_property # or signaler.property def x(self): return self._x @x.setter def x(self, x): self._x = x @x.on("before_change") def x_changing(self, x): print("x is changing") @x.on("change") def x_changed(self, x): print("x changed", x) t = XTest() t.x = 1 # x is changing # x changed 1 XTest.x.on(t, "change", lambda x: print("new signal")) t.x = 2 # x is changing # x changed 2 # new signal XTest.x.off(t, "before_change", t.x_changing) t.x = 3 # x changed 3 # new signal XTest.x.block(t, 'change') t.x = 4 XTest.x.block(t, 'change', False) t.x = 5 # x changed # new signal ``` ## Example - MethodObserver Inheritable class or metaclass that makes every function/method in a class a signaler. ```python from event_signal import MethodObserver class XTest(MethodObserver): def __init__(self, x=0): self._x = x def get_x(self): return self._x def set_x(self, x): self._x = x def x_changing(self, x): print("x is changing") def x_changed(self, x): print("x changed", x) t = XTest() t.set_x(1) t.set_x.on("change", t.x_changed) t.set_x(2) # x changed 2 t.set_x.on("before_change", t.x_changing) t.set_x(3) # x is changing # x changed 3 t.set_x.off("before_change", t.x_changing) t.set_x(4) # x changed 4 ``` ## Example - Signal Qt like signal. **Warning:** Qt's signals are thread safe (depending on how you connect them). They call the callback functions in the main thread. Many Qt widgets error and do not update when a value is set from a separate thread. So Qt's Signal is a good way to update a QWidget's value display, but can be slow. The event_signal.Signal works like a Qt Signal with a direct connection. The callback functions are called in the same thread that originally called the function. If you are using Qt and use this Signal from a separate thread to udate a QWidget it may not work properly and throw errors or warnings. For more information on how to make a QWidget thread safe go to <https://tasks.justengel.com/project/justengel-event-signal/wiki/signal-qt-thread-safe> Also this signal does not do any kind of type checking. Passing types into the Signal constructor ```Signal(int, str)``` is just for looks and maybe code readability. ```python from event_signal import Signal class XTest(object): x_changed = Signal(int) def __init__(self, x=0): self._x = x def get_x(self): return self._x def set_x(self, x): self._x = x self.x_changed.emit(self._x) def notify_x_changed(self, x): print("x changed", x) t = XTest() t.set_x(1) t.x_changed.connect(t.notify_x_changed) t.set_x(2) # x changed 2 t.x_changed.emit(3) # x changed 3 print(t.get_x()) # 2 t.x_changed.disconnect(t.notify_x_changed) # or t.x_changed.disconnect() t.set_x(4) print(t.get_x()) # 4 ``` ## Example - bind bind the value of two objects together. This will automatically use properties or find setter methods ("set_" + property_name or "set" + property_name). The binder will change a property to a signaler_property or if a property is not found and a setter function is used it will change that setter function to a signaler if it is not already a signaler. The main goal is to help two objects keep the same value for a variable. When using Qt I found this very annoying. I wanted a regular python object to store data and a GUI Widget to display the value and let the user change value. I wanted the two items decoupled. Occasionally, I wanted to programmatically set the data object value and wanted the GUI Widget to display this change automatically. The signals became annoying to deal with since I do a lot of work with threading. After several overly complex solutions, I made this bind function to make the GUI and data objects match values. ```python from event_signal import bind, bind_signals # bind_signals is only for directly giving signalers. class XTest(object): def __init__(self, x=0, y=0): self._x = x self._y = y def get_x(self): return self._x def set_x(self, x): self._x = x @property def y(self): return self._y @y.setter def y(self, y): self._y = y t = XTest() t2 = XTest() bind(t, "x", t2) t.set_x(1) print(t.get_x()) # 1 assert t.get_x() == t2.get_x() bind(t, "y", t2, "y") t2.y = 2 print(t2.y) # 2 assert t.y == t2.y ``` You can manually bind the signalers as well. ```python from event_signal import signaler, bind_signals # bind_signals is only for directly giving signalers. class Test2(object): def __init__(self, x=0, y=0): self._x = x self._y = y def get_x(self): return self._x @signaler(getter=get_x) def set_x(self, x): self._x = x t1 = Test2() t2 = Test2() bind_signals(t1.set_x, t2.set_x) t1.set_x(2) assert t1.get_x() == t2.get_x() t2.set_x(5) assert t1.get_x() == t2.get_x() ``` An unbind option is also available and works just like the examples above accept you can choose to unbind a single object at a time ```python from event_signal import bind, unbind, unbind_signals # unbind_signals is only for directly giving one or more signalers. class XTest(object): def __init__(self, x=0): self._x = x def get_x(self): return self._x def set_x(self, x): self._x = x t = XTest() t2 = XTest() bind(t, "x", t2) t.set_x(1) print(t.get_x()) # 1 assert t.get_x() == t2.get_x() unbind(t, "x") t.set_x(2) print(t.get_x()) # 2 assert t.get_x() != t2.get_x() t2.set_x(3) print(t2.get_x()) # 3 assert t.get_x() == t2.get_x() unbind(t2.set_x) t2.set_x(4) print(t2.get_x()) # 4 assert t.get_x() != t2.get_x() bind(t, "x", t2) t.set_x(1) print(t.get_x()) # 1 assert t.get_x() == t2.get_x() unbind(t, "x", t2) t.set_x(2) print(t.get_x()) # 2 assert t.get_x() != t2.get_x() t2.set_x(3) print(t2.get_x()) # 3 assert t.get_x() != t2.get_x() ``` ### bind Qt I now provide a `bind_qt` and `unbind_qt` functions. ```python from event_signal import signaler, bind_qt, unbind_qt from qtpy import QtWidgets class MyData(object): def __init__(self, name='hello'): self._name = name def get_name(self): return self._name @signaler(getter=get_name) def set_name(self, name): self._name = str(name) app = QtWidgets.QApplication([]) widg = QtWidgets.QWidget() lay = QtWidgets.QVBoxLayout() widg.setLayout(lay) widg.show() data = MyData() data.set_name.on('change', lambda name: print('data name changed to', name)) inp = QtWidgets.QLineEdit('Hello World!') lay.addWidget(inp) bind_qt(data, 'set_name', inp, 'setText') # qt_signal='editingFinished' btn = QtWidgets.QPushButton('Set Hello') def set_hello(): data.set_name('Hello') btn.clicked.connect(set_hello) lay.addWidget(btn) unbind_btn = QtWidgets.QPushButton('unbind') def unbind_call(): unbind_qt(data, 'set_name', inp, 'setText') unbind_btn.clicked.connect(unbind_call) lay.addWidget(unbind_btn) app.exec_() ``` To edit what widget value is used. ```python from event_signal import qt_binder def get_widget_value(widget): if isinstance(widget, CustomWidget): return widget.my_value() return qt_binder.get_widget_value(widget) qt_binder.get_widget_value = get_widget_value() ``` One thing to watch out for is if functions are called multiple times or are infinitely recursive.


نحوه نصب


نصب پکیج whl event-signal-1.8.0:

    pip install event-signal-1.8.0.whl


نصب پکیج tar.gz event-signal-1.8.0:

    pip install event-signal-1.8.0.tar.gz