{ "info": { "author": "Nenad Radulovic", "author_email": "nenad.b.radulovic@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Programming Language :: Python :: 3.4", "Topic :: Software Development" ], "description": ".. image:: https://travis-ci.org/nradulovic/pyeds.svg?branch=master\n :target: https://travis-ci.org/nradulovic/pyeds\n.. image:: https://coveralls.io/repos/github/nradulovic/pyeds/badge.svg?branch=master\n :target: https://coveralls.io/github/nradulovic/pyeds?branch=master\n\n\n**Python Event Driven System**\n\n.. contents:: Table of contents\n :backlinks: top\n :local:\n\nIntroduction\n============\n\nThis package provides a means to efficiently write finite state machines (FSM) \nby hand. The focus was to make the API as simplest as possible since no GUI \ntools are included to define a FSM.\n\nInstallation\n============\n\nUsing PIP\n---------\n\nPyEDS can be installed using the standard Python tool ``pip`` with\n\n.. code:: console\n\n pip install pyeds\n\nInstalling from source\n----------------------\n\nThe easiest way to install PyEDS from source is to use ``setup.py`` script \nwhich uses setuptools. For complete documentation about this script please\nrefer to setuptools manual.\n\nTo install from source issue the following command:\n\n.. code:: console\n\n python setup.py install\n \nCode documentation\n------------------\n\nCode documentation is bundled together with the source. The documentation\nscripts use Sphinx to generate documents. \n\nTo generate HTML documentation:\n\n.. code:: console\n\n cd doc\n make html\n \nThis will create HTML documents in ``doc/_build/html`` directory.\n\nThe documentation can be accessed via Python interpreter, too.\n\n.. code:: python\n\n >>> import pyeds\n >>> help(pyeds.fsm)\n\nHow to use it\n=============\n\nThe basic routine to create a state machine is the following:\n\n1) Declare a FSM class \n2) Declare all state classes\n3) Instantiate FSM class\n \nDeclaring a FSM class\n---------------------\n\nFSM class is the entry point of a FSM which is used to receive events (see \nbelow) and do the transitions between states. Each FSM must declare it's own \nclass which is a subclass of ``StateMachine``. The simplest way is to just\ndeclare an empty class which inherits the class ``StateMachine``:\n\n.. code:: python\n\n from pyeds import fsm\n \n class MyFsm(fsm.StateMachine):\n pass\n \nDeclaring a state class\n-----------------------\n\nEach state is represented by different class. Every method in that class may \nhandle one particular event. To declare the state, a class must be decorated \nwith ``DeclareState`` decorator which require state machine as an argument. \nThis decorator binds the state class to the specific FSM class. Also, the new \nstate class must be a subclass of ``State`` class:\n\n.. code:: python\n\n @fsm.DeclareState(MyFsm)\n class MyState(fsm.State):\n pass\n \nDeclare a new class per state.\n \nInstantiating the FSM\n---------------------\n\nTo instantiate the FSM class do the following:\n\n.. code:: python\n\n my_fsm = MyFsm()\n \nAfter object initialization the FSM is put into running state.\n\nBlinky example\n==============\n\nThe following is an example of FSM which is called Blinky. The FSM will print \n'on' text and 'off' text on console with 0.5 seconds of delay between the \nmessages. \n\nThe Blinky FSM has 2 states:\n\n- State On\n- State Off\n \n::\n\n o----+\n |\n On v Off\n +----+----+ blink +---------+\n | +--------->+ |\n | | | |\n | +<---------+ |\n +---------+ blink +---------+\n\n\nThe event ``blink`` is used to trigger transitions between the states.\n\n.. code:: python\n\n from pyeds import fsm\n\n\n # The first step is to declare a class which represent custom FSM.\n \n class BlinkyFsm(fsm.StateMachine):\n pass\n\n\n # The second step is to start writing the states of new state machine:\n\n\n @fsm.DeclareState(BlinkyFsm)\n class Initialization(fsm.State):\n def on_init(self):\n fsm.Every(0.5, 'blink')\n return StateOn\n \n \n @fsm.DeclareState(BlinkFsm)\n class StateOn(fsm.State):\n def on_entry(self):\n print('on')\n \n def on_blink(self, event):\n return StateOff\n \n \n @fsm.DeclareState(BlinkFsm)\n class StateOff(fsm.State):\n def on_entry(self):\n print('off')\n \n def on_blink(self, event):\n return StateOn\n\n\n # The final step is to instantiate the FSM class defined in the first step.\n\n blinky_fsm = BlinkyFsm()\n\nAfter creation the FSM is automatically put into a running state.\n\nEvent\n=====\n\nAn event is a notable occurrence at a particular point in time. Events can, but\ndo not necessarily, cause state transitions from one state to another in state \nmachines.\n\nAn event can have associated parameters, allowing the event to convey not only \nthe occurrence but also quantitative information about the occurrence. \n\nAn event is the only means of communication between state machines. Each event \ncarries name. Based on the event name a handler will be called from current \nstate class which has the same name.\n \nAn event in PyEDS is instanced using class ``Event``. \n\nThe associated parameters with an event are:\n\n- Name of the event: this is a string containing event name.\n- Owner of event: specifies which state machine has generated this event.\n \nGenerate an event\n-----------------\n\nTo generate a new event just instantiate ``Event`` class with event name as\nparameter:\n\n.. code:: python\n\n new_event = fsm.Event('my_special_event')\n\nAlternative way is to first declare a new event class and instantiate this\nderived class:\n\n.. code:: python\n\n class MySpecialEvent(fsm.Event):\n pass\n \n new_event = MySpecialEvent() # This event is implicitly\n # called 'my_special_event'\n\nIn this case base ``Event`` class will implicitly take the name of the class as \nown name. This can be overridden by calling the super constructor:\n\n.. code:: python\n\n # This event has the exact same name as the above one\n class DerivedEvent(fsm.Event):\n def __init__(self):\n super().__init__('my_special_event')\n\nRules about event naming\n------------------------\n\nWhen an event is created and sent to a state machine it's name is used to decide\nwhich method in current state instance should be invoked. The state machine \ntakes the name of the event, it prepends text ``on_`` to the name string and \nthen it looks up to event handler method.\n\nExample: If an event named ``toggle`` is created and sent to a state machine, \nthe target state machine will lookup for a method named ``on_toggle`` in the \ncurrent state instance. \n\nSince the event name directly impacts which state instance method will be called\nthe name of events must follow the Python identifier naming rules; please refer\nto https://docs.python.org/3.3/reference/lexical_analysis.html#identifiers for\nmore details.\n\n.. code:: python\n\n ok_event = fsm.Event('some_event_with_long_name')\n bad_event = fsm.Event('you cannot use spaces, @, $ and % here')\n\nTimers\n======\n\nTimers are used to generate time events:\n\n- After: Means an event will be generated after elapsed time.\n- Every: Means an event will be generated every period of time.\n \nTo generate the events use ``After`` and ``Every`` objects:\n\n.. code:: python\n\n blinking = fsm.Every(1.0, 'blink')\n \nThis line will generate an event named `blink` every 1.0 seconds. To stop the \ngeneration use:\n\n.. code:: python\n\n blinking.cancel()\n \nWhen a timer generates an event it will add new attribute to event called \n``timer``. With this attribute you can access the originating timer through\nevent. This means that you can also stop the timer through an event:\n\n.. code:: python\n\n def on_blink(self, event):\n event.timer.cancel() # Stop the originating timer\n\nState\n=====\n\nA state is a description of the status of a system that is waiting to execute \na transition.\n\nState machine\n=============\n\nA finite-state machine (FSM) is a mathematical model of computation. It is an \nabstract machine that can be in exactly one of a finite number of states at any\ngiven time. The FSM can change from one state to another in response to some\nexternal events; the change from one state to another is called a state\ntransition. An FSM is defined by a list of its states, its initial state, and\nthe conditions for each transition.\n\nState transition\n================\n\nSwitching from one state to another is called state transition. A transition is \na set of actions to be executed when a condition is fulfilled or when an event \nis received.\n\nTransitions are started by returning target state class in an event handler.\n\n.. code:: python\n \n def on_some_event(self, event):\n do_some_stuff()\n return SomeOtherState # Note: return a class object, not instance object\n\nHierarchical Finite State Machines (HFSM)\n=========================================\n\nPlease, refer to Wikipedia article for further explanation:\n\n- https://en.wikipedia.org/wiki/UML_state_machine#Hierarchically_nested_states \n\nSource\n======\n\nSource is available at github:\n\n- https://github.com/nradulovic/pyeds\n\nOther links\n===========\n\nThe following is a list of links to tools used by the project:\n\n- *Sphinx* (used to build documentation): http://www.sphinx-doc.org/en/stable/\n- *setuptools* (used for installing from source): \n https://setuptools.readthedocs.io/en/latest/\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/nradulovic", "keywords": "fsm hsm state finite event machine", "license": "LGPL", "maintainer": "", "maintainer_email": "", "name": "pyeds", "package_url": "https://pypi.org/project/pyeds/", "platform": "", "project_url": "https://pypi.org/project/pyeds/", "project_urls": { "Homepage": "https://github.com/nradulovic" }, "release_url": "https://pypi.org/project/pyeds/17.12.0/", "requires_dist": null, "requires_python": "", "summary": "Python Event Driven System", "version": "17.12.0" }, "last_serial": 3419349, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "775265b01793144328c1bd93a2c66ee5", "sha256": "0757633de9975e7bd1750213e344ef707868e9eeb29488c57453c68609db5e24" }, "downloads": -1, "filename": "pyeds-0.2.tar.gz", "has_sig": false, "md5_digest": "775265b01793144328c1bd93a2c66ee5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6285, "upload_time": "2017-07-11T12:50:35", "url": "https://files.pythonhosted.org/packages/c9/4d/297849f643a7b43f554e9e82c43d13de6a21cf083dee9dad3454be6c9d3e/pyeds-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "fda6bf65ffc1cc221c05d02a98266cec", "sha256": "3a4ea94313114cff492cd3c0daa4b6a1023b248225c5a370de96a2cbc8f21d3c" }, "downloads": -1, "filename": "pyeds-0.3.tar.gz", "has_sig": false, "md5_digest": "fda6bf65ffc1cc221c05d02a98266cec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6366, "upload_time": "2017-07-11T12:56:32", "url": "https://files.pythonhosted.org/packages/02/0d/fbfd4a348fa0f860123ae33f9fa8964d6f89a229731bce014653707c41be/pyeds-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "f7988d44af81fdac60e25a8057ed7cb1", "sha256": "712d02d9b07f34f30e3d6ad7053c06519ae16c27b2a38c8ecd092c24568d72c2" }, "downloads": -1, "filename": "pyeds-0.4-py3.4.egg", "has_sig": false, "md5_digest": "f7988d44af81fdac60e25a8057ed7cb1", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 10525, "upload_time": "2017-07-17T18:39:09", "url": "https://files.pythonhosted.org/packages/17/d5/a6a6282c64094f03920d3f6b7920bb367926762fc9c1e556437cf6693fc2/pyeds-0.4-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "2ae70ca6ac173136c376cc32ede717f2", "sha256": "e8195af2b183e150aa95aa69624a74174d0929df27e40e7587c5fa7e846eff20" }, "downloads": -1, "filename": "pyeds-0.4.tar.gz", "has_sig": false, "md5_digest": "2ae70ca6ac173136c376cc32ede717f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6050, "upload_time": "2017-07-17T18:38:52", "url": "https://files.pythonhosted.org/packages/97/17/2459abf116fa231291fcd7ce78d47c96602d65a0220bd5c9c07189787d46/pyeds-0.4.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "a103837b058da8fe304f6df66aa4dc75", "sha256": "1b7ee0ed3a922cbddb487e142149924b03e34e30be663840b96c0dda34c54a13" }, "downloads": -1, "filename": "pyeds-0.7-py3.4.egg", "has_sig": false, "md5_digest": "a103837b058da8fe304f6df66aa4dc75", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 20194, "upload_time": "2017-07-27T14:10:12", "url": "https://files.pythonhosted.org/packages/f8/85/b8b535e2c30b6dd0080ed4062a4372dba55f28f6e29e701f53ebf41203dd/pyeds-0.7-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "df8a676f1734ac837b3b66b0feb8befd", "sha256": "b1e81876dbe718ad72d63948a52415eb07ab4172c0b2e9a9e6bb4b5e1a9b0ae6" }, "downloads": -1, "filename": "pyeds-0.7.tar.gz", "has_sig": false, "md5_digest": "df8a676f1734ac837b3b66b0feb8befd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13679, "upload_time": "2017-07-27T14:10:23", "url": "https://files.pythonhosted.org/packages/be/87/d6d12b62518605cb644bf35aa1f1b44fff790b188a223fcf47201fd996b9/pyeds-0.7.tar.gz" } ], "0.7.1": [ { "comment_text": "", "digests": { "md5": "c568d837551f69c461ce6ff6df388bb1", "sha256": "8dceb2001340ca0806684da8057185c8e74f4c7fd911437279f20c150bc7af15" }, "downloads": -1, "filename": "pyeds-0.7.1.tar.gz", "has_sig": false, "md5_digest": "c568d837551f69c461ce6ff6df388bb1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13734, "upload_time": "2017-07-27T14:13:23", "url": "https://files.pythonhosted.org/packages/e6/90/18b864a6500ae01d823d3a7a52ec499892028c03d82e34c60f0107182204/pyeds-0.7.1.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "356a1b79ef0ea42916994712d9153a3f", "sha256": "637e09a0d8f6300b792a9f39d7867bd4007a00a1e74cd9e9f63ba2f30719e489" }, "downloads": -1, "filename": "pyeds-0.7.2-py3.4.egg", "has_sig": false, "md5_digest": "356a1b79ef0ea42916994712d9153a3f", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 19855, "upload_time": "2017-07-27T14:16:32", "url": "https://files.pythonhosted.org/packages/b0/cb/7256ce72baba3354d0c63476a14361d63b18d73fb7e694869f1ca2e0c57f/pyeds-0.7.2-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "65cbebff461b7f4d235e61dbf1fdc5f7", "sha256": "e21952c3d3fbecd56b9ca0c67ac9303fec9a1d5c9b78ca01beecc9e3eb3ceb94" }, "downloads": -1, "filename": "pyeds-0.7.2.tar.gz", "has_sig": false, "md5_digest": "65cbebff461b7f4d235e61dbf1fdc5f7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13187, "upload_time": "2017-07-27T14:14:56", "url": "https://files.pythonhosted.org/packages/cf/9b/bc3a15438b6c270b62897099ef16d36798236f4f53ad0348b287baacd3a1/pyeds-0.7.2.tar.gz" } ], "0.7.3": [ { "comment_text": "", "digests": { "md5": "e1b36a376005803f1cda627e51107c4f", "sha256": "0b7c306572a0306d465570fd18a986089c05eec4a9e273db089acbf1f31bf434" }, "downloads": -1, "filename": "pyeds-0.7.3-py3.4.egg", "has_sig": false, "md5_digest": "e1b36a376005803f1cda627e51107c4f", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 19891, "upload_time": "2017-07-27T14:20:16", "url": "https://files.pythonhosted.org/packages/b9/ca/cca73383fdd521f9f7801d1f13c2608f680c450cbbd23b8a2be00a29b8ca/pyeds-0.7.3-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "e7d4a095c39d555b47955b2e9c200dfc", "sha256": "2c47402b19979f4d9b3b4a7c32728d4ed5ac01b704abdf5b6ea594dfd6a6ee8e" }, "downloads": -1, "filename": "pyeds-0.7.3.tar.gz", "has_sig": false, "md5_digest": "e7d4a095c39d555b47955b2e9c200dfc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13260, "upload_time": "2017-07-27T14:20:27", "url": "https://files.pythonhosted.org/packages/f7/f0/7e4b475e5c9d2968ff51ebdb4fdc13dc114fde68e305ec489b2cd752f826/pyeds-0.7.3.tar.gz" } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "4308c20d73259928a127f9244e25ba97", "sha256": "81c0dc3933a64ce2e6f8b4de0f18d01ee24e3975f212fee177fd2a590fdee62d" }, "downloads": -1, "filename": "pyeds-0.7.5-py3.4.egg", "has_sig": false, "md5_digest": "4308c20d73259928a127f9244e25ba97", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 19128, "upload_time": "2017-08-12T22:30:53", "url": "https://files.pythonhosted.org/packages/a5/a6/9ac3e56f26ee93f94fba61a77a3df209c8fef45de5c6f718e7f4b1ff865f/pyeds-0.7.5-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "f2b52929fa30da5c73f1b1658a7204ab", "sha256": "781fe0724ba45763f84b3beb3ade2c06f0f6f24dbc8845320d91a034c094b237" }, "downloads": -1, "filename": "pyeds-0.7.5.tar.gz", "has_sig": false, "md5_digest": "f2b52929fa30da5c73f1b1658a7204ab", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11158, "upload_time": "2017-08-12T22:31:33", "url": "https://files.pythonhosted.org/packages/43/95/3c521d1d999ae148d7c9727bc5c76a540477fd57943c5d54e5b9754563af/pyeds-0.7.5.tar.gz" } ], "0.7.6": [ { "comment_text": "", "digests": { "md5": "aaec514cd4cf87a9474df131d0ed5666", "sha256": "2e2d62b7456bd396c06d65c562a29b4bab5fb7e0b31a44d3ebcc234284fda12f" }, "downloads": -1, "filename": "pyeds-0.7.6-py3.4.egg", "has_sig": false, "md5_digest": "aaec514cd4cf87a9474df131d0ed5666", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 30433, "upload_time": "2017-09-07T20:39:46", "url": "https://files.pythonhosted.org/packages/93/0f/a093820e121e7fa5ed940b7adc53d86f8bf02caee0b037db24ef825ca549/pyeds-0.7.6-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "4f20ef0f64cb15a1a5e722fbffa123cd", "sha256": "5ff5c99dfcda96c92090b78bc24f42019eb2528362c6371d79d832d6850acbe3" }, "downloads": -1, "filename": "pyeds-0.7.6.tar.gz", "has_sig": false, "md5_digest": "4f20ef0f64cb15a1a5e722fbffa123cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30132, "upload_time": "2017-09-07T20:37:02", "url": "https://files.pythonhosted.org/packages/d0/2b/b7d6cf57f79fb6b8c4f09f60e9a8a42d1788ae8635598074bacdf39f8830/pyeds-0.7.6.tar.gz" } ], "17.12.0": [ { "comment_text": "", "digests": { "md5": "306e0cd60d7ebb36785ca0a36e33612f", "sha256": "5ea5272c591f94c6d903570907885cf20251ed8ea077b2ec5bd4c605b1d675ab" }, "downloads": -1, "filename": "pyeds-17.12.0-py3-none-any.whl", "has_sig": false, "md5_digest": "306e0cd60d7ebb36785ca0a36e33612f", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 19239, "upload_time": "2017-12-15T09:28:31", "url": "https://files.pythonhosted.org/packages/bf/39/53bfd199d105de82df858aa871be7971d52e29567fac76dcf3acde30ad84/pyeds-17.12.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2db1ab0f9f346afd85d15ff1b93f61c3", "sha256": "188b5fc4b20269741a9a2ebe243efe8bf74008c1233366753cb1d0f8c8a64b62" }, "downloads": -1, "filename": "pyeds-17.12.0.tar.gz", "has_sig": false, "md5_digest": "2db1ab0f9f346afd85d15ff1b93f61c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32263, "upload_time": "2017-12-15T09:25:24", "url": "https://files.pythonhosted.org/packages/89/bf/51736c5bfa0310b5c88dc292a56c298d083b9af60eff4f27415e21a0964e/pyeds-17.12.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "306e0cd60d7ebb36785ca0a36e33612f", "sha256": "5ea5272c591f94c6d903570907885cf20251ed8ea077b2ec5bd4c605b1d675ab" }, "downloads": -1, "filename": "pyeds-17.12.0-py3-none-any.whl", "has_sig": false, "md5_digest": "306e0cd60d7ebb36785ca0a36e33612f", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 19239, "upload_time": "2017-12-15T09:28:31", "url": "https://files.pythonhosted.org/packages/bf/39/53bfd199d105de82df858aa871be7971d52e29567fac76dcf3acde30ad84/pyeds-17.12.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2db1ab0f9f346afd85d15ff1b93f61c3", "sha256": "188b5fc4b20269741a9a2ebe243efe8bf74008c1233366753cb1d0f8c8a64b62" }, "downloads": -1, "filename": "pyeds-17.12.0.tar.gz", "has_sig": false, "md5_digest": "2db1ab0f9f346afd85d15ff1b93f61c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32263, "upload_time": "2017-12-15T09:25:24", "url": "https://files.pythonhosted.org/packages/89/bf/51736c5bfa0310b5c88dc292a56c298d083b9af60eff4f27415e21a0964e/pyeds-17.12.0.tar.gz" } ] }