{ "info": { "author": "Justin Engel", "author_email": "jtengel08@gmail.com", "bugtrack_url": null, "classifiers": [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3" ], "description": "# Event Signal\n\nThis library was created to help maintain when variables are changed and when functions are called.\n\nThere are 5 main utilities provided\n\n * signaler - Function decorator to help observe functions\n * signaler_property - Custom property that helps observe when a property value is changed or deleted.\n * MethodObserver - class mixin to make all function observable\n * Signal - Similar to Qt's signal without requiring PyQT or PySide\n * bind - Make two object share the same value\n \n## Use\n\nThere are 5 main functions to use the signals.\n\n * get_signal - returns a list of connected function callbacks\n * on - connect a callback function to a signal\n * off - disconnect a callback funciton from a signal\n * fire - Call all callback functions that are associated with a signal\n * block - Temporarily block a signal from calling callback functions\n \nTwo basic signals are provided `'before_change'` and `'change'`. The signaler_property also has delete signals.\n\n * 'before_change' - This signal automatically fires before a function is called.\n * 'change' - This signal automatically fires after a function is called.\n * 'before_delete' - signaler_property fired before `del obj.property` is called.\n * 'delete' - signaler_property fired after `del obj.property` is called.\n\n## Basics\n\nA signaler is a custom class that decorates a function. It acts just like a function (it is callable). A signaler can \nhave other functions attached to it with a name. When the signaler fire is called it will call all of the attached \nfunctions.\n\n```python\nfrom event_signal import signaler\n\ndef my_function(a, b, c):\n print(a, b, c)\n\nmy_function = signaler(my_function)\n\n# Call the signaler like a normal function\nmy_function(1, 2, 3)\n# print = 1, 2, 3\nprint('=====\\n')\n\ndef print_signal(value1, value2):\n print('print_signal called', value1, value2)\n\nmy_function.on('my_signal', print_signal)\nmy_function.fire('my_signal', 1, 2)\n# print = print_signal called 1 2\nprint('=====\\n')\n\ndef another_signal(value1, value2):\n print('another_signal called', value1, value2, value1 == value2)\n\nmy_function.on('my_signal', another_signal)\nmy_function.fire('my_signal', 2, 2)\n# print = print_signal called 2 2\n# print = another_signal called 2 2 True\nprint('=====\\n')\n\nmy_function.off('my_signal', print_signal)\nmy_function.fire('my_signal', 3, 2)\n# print = another_signal called 3 2 False\nprint('=====\\n')\n\nprint(my_function.get_signal('my_signal'))\n# print = []\nprint('=====\\n')\n\nmy_function.block('my_signal')\nmy_function.fire('my_signal', 4, 5)\n# No print!\nmy_function.block('my_signal', False)\nmy_function.fire('my_signal', 5, 6)\n# print = another_signal called 5 6 False\nprint('=====\\n')\n``` \n\n \n## Example - signaler\nJavascript like events for functions and objects. \nThe signaler automatically creates and fires signals `'before_change'` and `'change'`.\n\n\n```python\nfrom event_signal import signaler\n\n\nclass XTest(object):\n def __init__(self, x=0):\n self._x = x\n\n def get_x(self):\n return self._x\n\n @signaler\n def set_x(self, x):\n self._x = x\n \n @set_x.on(\"before_change\")\n def x_changing(self, x):\n print(\"x is changing\")\n \n @set_x.on(\"change\")\n def x_changed(self, x):\n print(\"x changed\", x)\n \nt = XTest()\nt.set_x(1)\n# x is changing\n# x changed 1\nt.set_x.on(\"change\", lambda x: print(\"new signal\"))\nt.set_x(2)\n# x is changing\n# x changed 2\n# new signal\nt.set_x.off(\"before_change\", t.x_changing)\nt.set_x(3)\n# x changed 3\n# new signal\n\nt.set_x.block()\nt.set_x(4)\n\nt.set_x.block(block=False)\nt.set_x(5)\n# x changed 3\n# new signal\n\nt.set_x.block('change', True)\nt.set_x(6)\n```\n\n\nChange the value that is passed to the change callback functions.\n```python\nfrom event_signal import signaler\n\nclass XTest(object):\n def __init__(self, x=0):\n self._x = x\n\n def get_x(self):\n return self._x\n\n @signaler(getter=get_x)\n def set_x(self, x):\n \"\"\"Set x and force the value to be between 1 and 100.\"\"\"\n if x < 0:\n x = 0\n elif x > 100:\n x = 100\n self._x = x\n \n @set_x.on(\"before_change\")\n def x_changing(self, x):\n print(\"x is changing\", x)\n \n @set_x.on(\"change\")\n def x_changed(self, x):\n print(\"x changed\", x)\n \nt = XTest()\n\nt.set_x(1)\n# x is changing 1\n# x changed 1\n\n# Normally (without the getter) the change callback functions receive \n# the x value that was passed into set_x\nt.set_x(-1)\n# x is changing -1\n# x changed 0\n\nt.set_x(102)\n# x is changing 102\n# x changed 100\n\n# In this case the value passed into the change callback functions\n# is the value returned from the signaler getter (t.get_x) \n# which is how the signaler_property works.\n```\n\n## Example - signaler_property\nA property with signaler capabilities.\nThe signaler_property automatically creates and fires signals `'before_change'`, `'change'`, `'before_delete'`, and `'delete'`.\n\n```python\nfrom event_signal import signaler_property\n\n\nclass XTest(object):\n def __init__(self, x=0):\n self._x = x\n\n @signaler_property # or signaler.property\n def x(self):\n return self._x\n\n @x.setter\n def x(self, x):\n self._x = x\n \n @x.on(\"before_change\")\n def x_changing(self, x):\n print(\"x is changing\")\n \n @x.on(\"change\")\n def x_changed(self, x):\n print(\"x changed\", x)\n \nt = XTest()\nt.x = 1\n# x is changing\n# x changed 1\nXTest.x.on(t, \"change\", lambda x: print(\"new signal\"))\nt.x = 2\n# x is changing\n# x changed 2\n# new signal\nXTest.x.off(t, \"before_change\", t.x_changing)\nt.x = 3\n# x changed 3\n# new signal\n\nXTest.x.block(t, 'change')\nt.x = 4\n\nXTest.x.block(t, 'change', False)\nt.x = 5\n# x changed \n# new signal\n```\n\n## Example - MethodObserver\nInheritable class or metaclass that makes every function/method in a class a signaler.\n\n```python\nfrom event_signal import MethodObserver\n\n\nclass XTest(MethodObserver):\n def __init__(self, x=0):\n self._x = x\n\n def get_x(self):\n return self._x\n\n def set_x(self, x):\n self._x = x\n \n def x_changing(self, x):\n print(\"x is changing\")\n \n def x_changed(self, x):\n print(\"x changed\", x)\n \nt = XTest()\nt.set_x(1)\nt.set_x.on(\"change\", t.x_changed)\nt.set_x(2)\n# x changed 2\nt.set_x.on(\"before_change\", t.x_changing)\nt.set_x(3)\n# x is changing\n# x changed 3\nt.set_x.off(\"before_change\", t.x_changing)\nt.set_x(4)\n# x changed 4\n```\n\n## Example - Signal\nQt like signal.\n\n\n**Warning:**\n\nQt's signals are thread safe (depending on how you connect them). They call the callback functions in the main thread.\nMany 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 \nupdate a QWidget's value display, but can be slow. \n\nThe event_signal.Signal works like a Qt Signal with a direct connection. \nThe callback functions are called in the same thread that originally called the function. If you are using Qt and use \nthis Signal from a separate thread to udate a QWidget it may not work properly and throw errors or warnings.\n\nFor more information on how to make a QWidget thread safe go to \n\nAlso this signal does not do any kind of type checking. Passing types into the Signal constructor ```Signal(int, str)``` \nis just for looks and maybe code readability.\n\n```python\nfrom event_signal import Signal\n\n\nclass XTest(object):\n x_changed = Signal(int)\n\n def __init__(self, x=0):\n self._x = x\n\n def get_x(self):\n return self._x\n\n def set_x(self, x):\n self._x = x\n self.x_changed.emit(self._x)\n \n def notify_x_changed(self, x):\n print(\"x changed\", x)\n \nt = XTest()\nt.set_x(1)\nt.x_changed.connect(t.notify_x_changed)\nt.set_x(2)\n# x changed 2\nt.x_changed.emit(3)\n# x changed 3\nprint(t.get_x())\n# 2\nt.x_changed.disconnect(t.notify_x_changed) # or t.x_changed.disconnect()\nt.set_x(4)\nprint(t.get_x())\n# 4\n```\n\n## Example - bind\nbind the value of two objects together. This will automatically use properties or find setter methods \n(\"set_\" + property_name or \"set\" + property_name). The binder will change a property to a signaler_property or if a \nproperty is not found and a setter function is used it will change that setter function to a signaler if it is not \nalready a signaler.\n\nThe main goal is to help two objects keep the same value for a variable.\n\nWhen using Qt I found this very annoying. I wanted a regular python object to store data and a GUI Widget to display \nthe value and let the user change value. I wanted the two items decoupled. Occasionally, I wanted to programmatically \nset the data object value and wanted the GUI Widget to display this change automatically. The signals became annoying \nto deal with since I do a lot of work with threading. After several overly complex solutions, I made this bind function \nto make the GUI and data objects match values.\n\n```python\nfrom event_signal import bind, bind_signals # bind_signals is only for directly giving signalers.\n\n\nclass XTest(object):\n def __init__(self, x=0, y=0):\n self._x = x\n self._y = y\n\n def get_x(self):\n return self._x\n\n def set_x(self, x):\n self._x = x\n \n @property \n def y(self):\n return self._y\n \n @y.setter\n def y(self, y):\n self._y = y\n \n \nt = XTest()\nt2 = XTest()\nbind(t, \"x\", t2)\nt.set_x(1)\nprint(t.get_x())\n# 1\nassert t.get_x() == t2.get_x()\n\nbind(t, \"y\", t2, \"y\")\nt2.y = 2\nprint(t2.y)\n# 2\nassert t.y == t2.y\n```\n\nYou can manually bind the signalers as well.\n```python\nfrom event_signal import signaler, bind_signals # bind_signals is only for directly giving signalers.\n\n\nclass Test2(object):\n def __init__(self, x=0, y=0):\n self._x = x\n self._y = y\n\n def get_x(self):\n return self._x\n\n @signaler(getter=get_x)\n def set_x(self, x):\n self._x = x\n \nt1 = Test2()\nt2 = Test2()\nbind_signals(t1.set_x, t2.set_x)\n\nt1.set_x(2)\nassert t1.get_x() == t2.get_x()\n\nt2.set_x(5)\nassert t1.get_x() == t2.get_x()\n```\n\nAn unbind option is also available and works just like the examples above accept you can choose to unbind a single object at a time\n```python\nfrom event_signal import bind, unbind, unbind_signals # unbind_signals is only for directly giving one or more signalers.\n\n\nclass XTest(object):\n def __init__(self, x=0):\n self._x = x\n\n def get_x(self):\n return self._x\n\n def set_x(self, x):\n self._x = x\n \nt = XTest()\nt2 = XTest()\nbind(t, \"x\", t2)\n\nt.set_x(1)\nprint(t.get_x())\n# 1\nassert t.get_x() == t2.get_x()\n\nunbind(t, \"x\")\nt.set_x(2)\nprint(t.get_x())\n# 2\nassert t.get_x() != t2.get_x()\n\nt2.set_x(3)\nprint(t2.get_x())\n# 3\nassert t.get_x() == t2.get_x()\n\n\nunbind(t2.set_x)\nt2.set_x(4)\nprint(t2.get_x())\n# 4\nassert t.get_x() != t2.get_x()\n\n\nbind(t, \"x\", t2)\nt.set_x(1)\nprint(t.get_x())\n# 1\nassert t.get_x() == t2.get_x()\n\nunbind(t, \"x\", t2)\nt.set_x(2)\nprint(t.get_x())\n# 2\nassert t.get_x() != t2.get_x()\n\nt2.set_x(3)\nprint(t2.get_x())\n# 3\nassert t.get_x() != t2.get_x()\n```\n\n### bind Qt\n\nI now provide a `bind_qt` and `unbind_qt` functions. \n\n```python\nfrom event_signal import signaler, bind_qt, unbind_qt\nfrom qtpy import QtWidgets\n\nclass MyData(object):\n def __init__(self, name='hello'):\n self._name = name\n\n def get_name(self):\n return self._name\n\n @signaler(getter=get_name)\n def set_name(self, name):\n self._name = str(name)\n\napp = QtWidgets.QApplication([])\n\nwidg = QtWidgets.QWidget()\nlay = QtWidgets.QVBoxLayout()\nwidg.setLayout(lay)\nwidg.show()\n\ndata = MyData()\ndata.set_name.on('change', lambda name: print('data name changed to', name))\n\ninp = QtWidgets.QLineEdit('Hello World!')\nlay.addWidget(inp)\n\nbind_qt(data, 'set_name', inp, 'setText') # qt_signal='editingFinished'\n\nbtn = QtWidgets.QPushButton('Set Hello')\ndef set_hello():\n data.set_name('Hello')\nbtn.clicked.connect(set_hello)\nlay.addWidget(btn)\n\nunbind_btn = QtWidgets.QPushButton('unbind')\ndef unbind_call():\n unbind_qt(data, 'set_name', inp, 'setText')\nunbind_btn.clicked.connect(unbind_call)\nlay.addWidget(unbind_btn)\n\napp.exec_()\n```\n\nTo edit what widget value is used.\n\n```python\nfrom event_signal import qt_binder\n\ndef get_widget_value(widget):\n if isinstance(widget, CustomWidget):\n return widget.my_value()\n \n return qt_binder.get_widget_value(widget)\n \nqt_binder.get_widget_value = get_widget_value()\n```\n\nOne thing to watch out for is if functions are called multiple times or are infinitely recursive.", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/justengel/event_signal/archive/v1.8.0.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/justengel/event_signal", "keywords": "signal observer signaler event javascript events bind", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "event-signal", "package_url": "https://pypi.org/project/event-signal/", "platform": "any", "project_url": "https://pypi.org/project/event-signal/", "project_urls": { "Download": "https://github.com/justengel/event_signal/archive/v1.8.0.tar.gz", "Homepage": "https://github.com/justengel/event_signal" }, "release_url": "https://pypi.org/project/event-signal/1.8.0/", "requires_dist": null, "requires_python": "", "summary": "Library to help notify when something has changed.", "version": "1.8.0" }, "last_serial": 5130207, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "7dc52229c8f4925554a9b1b0a532c67f", "sha256": "b566fb87f51d8cf83a9033f61fa0e0aa53d02260320a185dc9635cb735eda3ad" }, "downloads": -1, "filename": "event_signal-1.0.0.tar.gz", "has_sig": false, "md5_digest": "7dc52229c8f4925554a9b1b0a532c67f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11282, "upload_time": "2018-03-02T15:21:06", "url": "https://files.pythonhosted.org/packages/1b/e5/ed699967e7f7d23a7a65166373c513bf418d62dcc6d093b56a027fc19258/event_signal-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "c8f540bf6671d64128a32c034bf80d35", "sha256": "5191affd5af2b7848acc24f9d06eaf7592a5bca5adca4a27bc18e209db07152c" }, "downloads": -1, "filename": "event_signal-1.1.0.tar.gz", "has_sig": false, "md5_digest": "c8f540bf6671d64128a32c034bf80d35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11285, "upload_time": "2018-03-02T21:59:57", "url": "https://files.pythonhosted.org/packages/cd/c3/13174048dc2f1eab39b49567d867874481462e7dfbc2a612b93f5f55caba/event_signal-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "f2adbaf84d84a732bb90898c43befec2", "sha256": "22db9c4d52bc07d644950bfb99ae12b57f839ad029051a4f4f123628dbec99b5" }, "downloads": -1, "filename": "event_signal-1.1.1.tar.gz", "has_sig": false, "md5_digest": "f2adbaf84d84a732bb90898c43befec2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14086, "upload_time": "2018-03-08T18:29:58", "url": "https://files.pythonhosted.org/packages/e6/68/10d00f34f10074fb50b260a7403c0bcd9cb1009a23f65116aab9b9fd1926/event_signal-1.1.1.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "f894792d7520f7a46f76c2353e13c374", "sha256": "8fd81a0d1ea7ae1fd634a6af694c5bffcae500f0995fee581b4c8de99e8af1f1" }, "downloads": -1, "filename": "event_signal-1.2.0.tar.gz", "has_sig": false, "md5_digest": "f894792d7520f7a46f76c2353e13c374", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11458, "upload_time": "2018-03-15T20:10:32", "url": "https://files.pythonhosted.org/packages/ea/3c/aa64eccd60dc830c2d20bb42c1bc4fc0f7ebd66f3df3fbe83f45916297d9/event_signal-1.2.0.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "8cc10584c7c9ce4884b021bd77fe1977", "sha256": "9ab868e1a3252683cd2432cd455a5e367d79a5a591c057223698bece6718c1aa" }, "downloads": -1, "filename": "event_signal-1.2.1.tar.gz", "has_sig": false, "md5_digest": "8cc10584c7c9ce4884b021bd77fe1977", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11901, "upload_time": "2018-03-19T16:28:30", "url": "https://files.pythonhosted.org/packages/55/9c/e2761e4eb9a71fd92de27c0ac0545316bc1cb7fac6828753669cb7822879/event_signal-1.2.1.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "f8c7c514e58bf2a5d2c23d55f674e624", "sha256": "de1e1311cb389bc9db56cb37c2d99e422724328e2eca45ae69a15d7bfaa59b16" }, "downloads": -1, "filename": "event_signal-1.3.0.tar.gz", "has_sig": false, "md5_digest": "f8c7c514e58bf2a5d2c23d55f674e624", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13158, "upload_time": "2018-03-20T14:36:51", "url": "https://files.pythonhosted.org/packages/e8/92/c8360454827eaa12d15d318bd7578e07793b0990852172e6efbac08f0cd3/event_signal-1.3.0.tar.gz" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "9ae36ba6c531a3cfc89acc168d51d8a9", "sha256": "3130c2d8579b5781a8ced05efab6d8746ceb67f35bb28615f62a34e280169521" }, "downloads": -1, "filename": "event_signal-1.4.0.tar.gz", "has_sig": false, "md5_digest": "9ae36ba6c531a3cfc89acc168d51d8a9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15459, "upload_time": "2018-03-21T20:50:00", "url": "https://files.pythonhosted.org/packages/4f/43/ae371c26947d541e1eba171cd1f7321acbf4673e051939fc3f40c988ea3c/event_signal-1.4.0.tar.gz" } ], "1.5.0": [ { "comment_text": "", "digests": { "md5": "ad1b0d4f35b11bbcecc97c01c26b5ae3", "sha256": "33bbd79fda50f1c139041aee10a812179d645f00ad84bd6f4ae1aba2fbc4ceed" }, "downloads": -1, "filename": "event_signal-1.5.0.tar.gz", "has_sig": false, "md5_digest": "ad1b0d4f35b11bbcecc97c01c26b5ae3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16334, "upload_time": "2018-03-23T15:48:40", "url": "https://files.pythonhosted.org/packages/b0/02/7cbc6d5a982a20ff311bd9553e04b05261224dc120ca74215ec154f64714/event_signal-1.5.0.tar.gz" } ], "1.5.1": [ { "comment_text": "", "digests": { "md5": "941900b6b6ae2cbb5ad098421b85a5f6", "sha256": "3fee42212e9c776397f743d71f722744a8b80eb67406bdb0cf2f297dd7bc42f1" }, "downloads": -1, "filename": "event_signal-1.5.1.tar.gz", "has_sig": false, "md5_digest": "941900b6b6ae2cbb5ad098421b85a5f6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16455, "upload_time": "2018-05-04T21:41:53", "url": "https://files.pythonhosted.org/packages/e5/2c/16b691b534cb953be00d43e5ca9bd3e31701ba77b3fca225387268ce64eb/event_signal-1.5.1.tar.gz" } ], "1.5.2": [ { "comment_text": "", "digests": { "md5": "f9293016f1aa48bc8d53405cbb09c2e7", "sha256": "6e580d05378d0b93c3ecdf8e8edee91d0ee2b61f5700bfc68a7f88f5b6a3a195" }, "downloads": -1, "filename": "event_signal-1.5.2.tar.gz", "has_sig": false, "md5_digest": "f9293016f1aa48bc8d53405cbb09c2e7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16355, "upload_time": "2018-05-04T22:36:05", "url": "https://files.pythonhosted.org/packages/e8/84/25dd5a38e02d2c4f49e6e54ac96c35a14b9539affd796bb154f56731ed9b/event_signal-1.5.2.tar.gz" } ], "1.5.3": [ { "comment_text": "", "digests": { "md5": "9fe314fff5bcf8ff952eb1ddf4ae0cff", "sha256": "1d15bb32ec0d50e1e01ae86b1fdec68019684ee04b6c533b86c35fd122d32859" }, "downloads": -1, "filename": "event_signal-1.5.3.tar.gz", "has_sig": false, "md5_digest": "9fe314fff5bcf8ff952eb1ddf4ae0cff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16483, "upload_time": "2018-05-12T12:28:05", "url": "https://files.pythonhosted.org/packages/2b/f1/f0a7a5cef6660ae062141772a5cd27d7ec40a6590f063b579a4c21538433/event_signal-1.5.3.tar.gz" } ], "1.5.4": [ { "comment_text": "", "digests": { "md5": "fbbdea4817ca8b29cc959e94be2a8595", "sha256": "4c7ce30a30449479a26089b3b8791ef461c78d69d28ad52ad1037725c4e05364" }, "downloads": -1, "filename": "event_signal-1.5.4.tar.gz", "has_sig": false, "md5_digest": "fbbdea4817ca8b29cc959e94be2a8595", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19193, "upload_time": "2018-08-14T20:30:16", "url": "https://files.pythonhosted.org/packages/42/cc/e0293823967b9b0e44344334adfa95fb67260a03338dbde452e76c7eced2/event_signal-1.5.4.tar.gz" } ], "1.6.0": [ { "comment_text": "", "digests": { "md5": "148c4db5989fdc2a4449ab9a58e9169d", "sha256": "d7d628e3363cf6ec4fa146f976f2aed41e0c1ea674cadcc77211dbf0d97d235f" }, "downloads": -1, "filename": "event_signal-1.6.0.tar.gz", "has_sig": false, "md5_digest": "148c4db5989fdc2a4449ab9a58e9169d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21718, "upload_time": "2018-08-30T20:00:38", "url": "https://files.pythonhosted.org/packages/1c/93/b0a7b19789a282bd9e3c96630849ac0cbd68187a25e3ee69f2b0c8906317/event_signal-1.6.0.tar.gz" } ], "1.6.1": [ { "comment_text": "", "digests": { "md5": "5504d9d810cfc14fb4ca00a037e9d9b3", "sha256": "63a36ca3efaea545e5d653168443d6fbaffdfb5c1d9c45cf2478863aaf76805c" }, "downloads": -1, "filename": "event_signal-1.6.1.tar.gz", "has_sig": false, "md5_digest": "5504d9d810cfc14fb4ca00a037e9d9b3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21728, "upload_time": "2018-08-30T21:32:56", "url": "https://files.pythonhosted.org/packages/60/2a/9b50c65cd23bbcc0d8f59d55be338b0b5234d193c6f4ba7ada1f3618ee5c/event_signal-1.6.1.tar.gz" } ], "1.6.2": [ { "comment_text": "", "digests": { "md5": "6d4daa3a4e1e032e30130c3786952bb6", "sha256": "ab936533a396bd6de209e4b67167a5125e4869e73c40b9a34933b8c05183d36f" }, "downloads": -1, "filename": "event_signal-1.6.2.tar.gz", "has_sig": false, "md5_digest": "6d4daa3a4e1e032e30130c3786952bb6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21967, "upload_time": "2018-08-31T15:34:10", "url": "https://files.pythonhosted.org/packages/4b/10/c97c8ad32f9bdde8b798204fc042db7ad55724ca909d0bfae17b5357e611/event_signal-1.6.2.tar.gz" } ], "1.6.3": [ { "comment_text": "", "digests": { "md5": "b6641c85d76d4d94ea9a75e631baa81c", "sha256": "98f3a19cda1745d145580be80989956d5efd25368d75889868cf4d8b37a810fe" }, "downloads": -1, "filename": "event_signal-1.6.3.tar.gz", "has_sig": false, "md5_digest": "b6641c85d76d4d94ea9a75e631baa81c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22324, "upload_time": "2018-09-04T12:05:20", "url": "https://files.pythonhosted.org/packages/90/7b/8ebb438cd8b50999fe3445c8418a35aed12304ff82cef04446c99249ca96/event_signal-1.6.3.tar.gz" } ], "1.6.4": [ { "comment_text": "", "digests": { "md5": "f50396336b7876305e0a58681ed87b1b", "sha256": "a76d9fda99e3b563970be30594f7da7a3cda8421e0f5f2279ffd1a8260edd76a" }, "downloads": -1, "filename": "event_signal-1.6.4.tar.gz", "has_sig": false, "md5_digest": "f50396336b7876305e0a58681ed87b1b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22352, "upload_time": "2018-09-04T13:23:04", "url": "https://files.pythonhosted.org/packages/3d/67/b4344cd038581a5e34fccd76258ddbd3c3a52cf9b4cc9316b0030fa2eaef/event_signal-1.6.4.tar.gz" } ], "1.6.5": [ { "comment_text": "", "digests": { "md5": "770e4ce3bbeeec2b470abb0c81d9b4d5", "sha256": "fa5ac99b1c9041f003d99388f0abf437aea0aa642bd1a7a1831befaf1197243e" }, "downloads": -1, "filename": "event_signal-1.6.5.tar.gz", "has_sig": false, "md5_digest": "770e4ce3bbeeec2b470abb0c81d9b4d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22442, "upload_time": "2018-10-03T17:12:53", "url": "https://files.pythonhosted.org/packages/a8/89/71214ea19e5fac9e52bd9aebe7fba2f90514d47f80679c0ec87a81bc7131/event_signal-1.6.5.tar.gz" } ], "1.6.6": [ { "comment_text": "", "digests": { "md5": "9a607df6947a76a736f8989c77c6a84a", "sha256": "2309ccd0f6e720380e75be039d02129027fbfecc3fdf99c454de6c13653c00ff" }, "downloads": -1, "filename": "event_signal-1.6.6.tar.gz", "has_sig": false, "md5_digest": "9a607df6947a76a736f8989c77c6a84a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22451, "upload_time": "2018-10-24T21:36:04", "url": "https://files.pythonhosted.org/packages/39/1e/919a60ee4cf8793e26ab88ca881b99097a062548cd5e7895dba0f0c691d9/event_signal-1.6.6.tar.gz" } ], "1.6.7": [ { "comment_text": "", "digests": { "md5": "40adffdbccfadb56bb451c31ff54294e", "sha256": "d419b9ada154e433494ee19338781d30201406969103b1f2c9bd54f386f9b024" }, "downloads": -1, "filename": "event_signal-1.6.7.tar.gz", "has_sig": false, "md5_digest": "40adffdbccfadb56bb451c31ff54294e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22564, "upload_time": "2018-11-28T22:43:44", "url": "https://files.pythonhosted.org/packages/8d/8e/4af91ca721886f88ee4b8105ac6af21fa6941e3cc758e80838dba50baa01/event_signal-1.6.7.tar.gz" } ], "1.6.8": [ { "comment_text": "", "digests": { "md5": "fabfc17de3e76b93401cfab2e763d9cd", "sha256": "8f2917eafe46635924c11e2bea90ac423d53b1f6e1b1ce4a67ffcd1eccbf6a75" }, "downloads": -1, "filename": "event_signal-1.6.8.tar.gz", "has_sig": false, "md5_digest": "fabfc17de3e76b93401cfab2e763d9cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22697, "upload_time": "2018-11-28T22:56:48", "url": "https://files.pythonhosted.org/packages/63/29/8f0208f7cc6820df693c1aa06a0bf33bbb8d298f2014b071bcd4e24f0367/event_signal-1.6.8.tar.gz" } ], "1.6.9": [ { "comment_text": "", "digests": { "md5": "6c85d2f89ca8027a3d0c9d044b903f4a", "sha256": "ba3a3065ce43ac8e0ff2fab418297d77c4b4f17d8730cc4463733de723b267b0" }, "downloads": -1, "filename": "event_signal-1.6.9.tar.gz", "has_sig": false, "md5_digest": "6c85d2f89ca8027a3d0c9d044b903f4a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22832, "upload_time": "2018-12-08T14:39:22", "url": "https://files.pythonhosted.org/packages/fc/b9/816b2bd663cab3b526b49d298a2bb82ad995e548a38a891fd941e4776201/event_signal-1.6.9.tar.gz" } ], "1.7.0": [ { "comment_text": "", "digests": { "md5": "c10710a9c648a2df79dc4f3427a76da1", "sha256": "1820c473701498de79b5151804936e7e23b7fb3aa0a1fb2bec07716b20add93b" }, "downloads": -1, "filename": "event_signal-1.7.0.tar.gz", "has_sig": false, "md5_digest": "c10710a9c648a2df79dc4f3427a76da1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23541, "upload_time": "2018-12-10T18:10:50", "url": "https://files.pythonhosted.org/packages/9b/ea/8cc7d8f2d671dc15253a44c284d258999268bc749672d344e1c010d557dc/event_signal-1.7.0.tar.gz" } ], "1.7.1": [ { "comment_text": "", "digests": { "md5": "8a83b8f3221257f2a643ed45ade9f66b", "sha256": "0224b21c54e286e9878092d236d9b14d5812fbf2d7f495060e4d4fa2d7348bbc" }, "downloads": -1, "filename": "event_signal-1.7.1.tar.gz", "has_sig": false, "md5_digest": "8a83b8f3221257f2a643ed45ade9f66b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23826, "upload_time": "2019-01-02T18:08:30", "url": "https://files.pythonhosted.org/packages/1d/6b/fec92dbda6a6ccefd21cfd688d9d7da4116b5a706f10d2753cc278ffa49e/event_signal-1.7.1.tar.gz" } ], "1.8.0": [ { "comment_text": "", "digests": { "md5": "582a3fd64ef27c58c0b7a2eda789d9ee", "sha256": "8a2865573c53507da66cde2eb119a79fcf704835c6dbc87a20126e8d30fad013" }, "downloads": -1, "filename": "event_signal-1.8.0.tar.gz", "has_sig": false, "md5_digest": "582a3fd64ef27c58c0b7a2eda789d9ee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19809, "upload_time": "2019-04-11T18:03:28", "url": "https://files.pythonhosted.org/packages/94/de/ccbe6b572c3303a02eba9c1b9f5465afd113abe84f0ee95b2febcd6300ee/event_signal-1.8.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "582a3fd64ef27c58c0b7a2eda789d9ee", "sha256": "8a2865573c53507da66cde2eb119a79fcf704835c6dbc87a20126e8d30fad013" }, "downloads": -1, "filename": "event_signal-1.8.0.tar.gz", "has_sig": false, "md5_digest": "582a3fd64ef27c58c0b7a2eda789d9ee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19809, "upload_time": "2019-04-11T18:03:28", "url": "https://files.pythonhosted.org/packages/94/de/ccbe6b572c3303a02eba9c1b9f5465afd113abe84f0ee95b2febcd6300ee/event_signal-1.8.0.tar.gz" } ] }