{ "info": { "author": "Farhan Ahmed", "author_email": "farhan@themacronaut.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# Flux: A State Machine\n\n[![pipeline status](https://gitlab.com/insha/Flux/badges/dev/pipeline.svg)](https://gitlab.com/insha/Flux/commits/dev) [![coverage report](https://gitlab.com/insha/Flux/badges/dev/coverage.svg)](https://gitlab.com/insha/Flux/commits/dev)\n\nFlux is a lightweight library that provides an API for implementing a state machine in \nPython. It is a work-in-progress, but has some really cool features (see below) and unit tested.\n\nState machines are a great way to manage complexity in your application and Flux provides \nyou with an elegant API for implementing state machines in your project.\n\n## Features\n- Supports an arbitrary number of States and Events.\n- States and Events support callbacks for responding to state transitions.\n- Transitions support the inclusion of arbitrary user data, making it easy to broadcast metadata across callbacks.\n- No dependencies for normal usage.\n\n## Installation\n\nFrom the cheese shop:\n\n pip install Flux\n\nFrom source:\n\n pip install -e .\n\n## Usage\n\nA simple definition of a state machine is that any *machine* that has a set of *states* and *events* (also referred to as *transitions*) defined between them. The state machine pattern **enforces** only events that are allowed in the particular state can be triggered. However, this requires us to spend a bit of time upfront figuring out what are our states and which events can be triggered from these states.\n\nHere, we are going to create a simple water bottle filling machine. There are three states, Waiting, Filling, Done. There are three events that lets us transition from one state to the next. A diagram of this state machine looks like:\n\n```mermaid\ngraph TD;\n Waiting --> Filling;\n Filling --> Done;\n Done --> Waiting;\n```\n\nWe start by importing in the main components of Flux:\n\n```python\nfrom flux.machine import StateMachine\nfrom flux.state import State, StateInfo\nfrom flux.event import Event, EventCallback\nfrom flux.errors import StateMachineError, StateMachineEventError, StateMachineStateError\n```\n\n```python\n# Callbacks for states\ndef did_enter_state(transition):\n print(f'==> FSM::Did enter {transition.destination_state}')\n\ndef did_exit_state(transition):\n print(f'<== FSM::Did exit {transition.source_state}')\n\ndef will_enter_state(transition):\n print(f'--> FSM::Will enter {transition.destination_state} from {transition.source_state}')\n\ndef will_exit_state(transition):\n print(f'<-- FSM::Will exit {transition.source_state}')\n\n# Callbacks for events\ndef did_fire_event(transition):\n print(f'=> FSM::Did fire {transition.event} in state {transition.source_state}')\n\ndef will_fire_event(transition):\n print(f'=> FSM::Will fire {transition.event} in state {transition.source_state}')\n\n# State configuration\nwaiting = State(name='waiting', info=StateInfo(did_enter_state=did_enter_state, \n did_exit_state=did_exit_state,\n will_enter_state=will_enter_state,\n will_exit_state=will_exit_state))\n\nfilling = State(name='filling', info=StateInfo(did_enter_state=did_enter_state, \n did_exit_state=did_exit_state,\n will_enter_state=will_enter_state,\n will_exit_state=will_exit_state))\n\ndone = State(name='done', info=StateInfo(did_enter_state=did_enter_state, \n did_exit_state=did_exit_state,\n will_enter_state=will_enter_state,\n will_exit_state=will_exit_state))\n\n# Event configuration\nstart_filling = Event(name='start_filling', info=EventInfo(source_states=[waiting], \n destination_state=filling,\n will_fire_event=will_fire_event,\n did_fire_event=did_fire_event))\n\nbottle_full = Event(name='bottle_full', info=EventInfo(source_states=[filling], \n destination_state=done,\n will_fire_event=will_fire_event,\n did_fire_event=did_fire_event))\n\nremove_bottle = Event(name='remove_bottle', info=EventInfo(source_states=[done], \n destination_state=waiting,\n will_fire_event=will_fire_event,\n did_fire_event=did_fire_event))\n\n# Let build and use our water bottle filling state machine!\ntry:\n fsm = StateMachine(states=[waiting, filling, done], \n events=[start_filling, bottle_full, remove_bottle], \n initial_state=waiting)\n\n print('Adding a bottle to fill.')\n fsm.activate()\n\n time.sleep(1.0)\n print('')\n fsm.fire_event(start_filling)\n time.sleep(1.0)\n print('')\n fsm.fire_event(bottle_full)\n print('')\n fsm.fire_event(remove_bottle)\n print('\u2728 \ud83c\udf70 \u2728')\nexcept StateMachineEventError as e:\n print(e.message)\nexcept StateMachineError as e:\n print(e.message)\n```\n\n## Running Tests\n\nIn order to run all of unit tests, you will need `pytest` and `pytest-cov` installed. These can be\ninstalled using:\n\n pip install -r flux/requirements.txt\n\nOnce installed you can run all unit tests using:\n\n pytest --cov-report term-missing --cov=flux tests/\n\n## Contributing\n\nPlease see the `CONTRIBUTING.md` file for more information.\n\n## Code of Conduct\n\nOur contributor code of conduct can be found in the `code-of-conduct.md` file.\n\n## License\n\nFlux is licensed under a three clause BSD License. It basically means: do whatever you want with it as long as the copyright in Salah sticks around, the conditions are not modified and the disclaimer is present. Furthermore you must not use the names of the authors to promote derivatives of the software without written consent.\n\nThe full license text can be found in the `LICENSE` file.\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/insha/Flux", "keywords": "", "license": "BSD-3-Clause", "maintainer": "", "maintainer_email": "", "name": "flux-insha", "package_url": "https://pypi.org/project/flux-insha/", "platform": "any", "project_url": "https://pypi.org/project/flux-insha/", "project_urls": { "Code": "https://github.com/insha/Flux", "Homepage": "https://github.com/insha/Flux", "Issue tracker": "https://github.com/insha/Flux/issues" }, "release_url": "https://pypi.org/project/flux-insha/0.1.4/", "requires_dist": null, "requires_python": ">=3.6", "summary": "A lightweight finite state machine", "version": "0.1.4" }, "last_serial": 4836268, "releases": { "0.1.4": [ { "comment_text": "", "digests": { "md5": "dde8b3a0ddb95f8d6a274b38a8a8e54c", "sha256": "52a9f2721def33bea629235e82794b8a87ce794d3ca111c369ec50b6e53a7f79" }, "downloads": -1, "filename": "flux_insha-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "dde8b3a0ddb95f8d6a274b38a8a8e54c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 17729, "upload_time": "2019-02-18T17:43:33", "url": "https://files.pythonhosted.org/packages/6e/c8/69cac95f41ccb53940d68770f74bcd758b209191b81550cf75221d11dd8e/flux_insha-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "28c2e8cde9a15ec06c10a7e8a4625992", "sha256": "b129d30dda3bdf4e2e0b283350f335427c6a5496d4ef22c1ab319d131f49aeb8" }, "downloads": -1, "filename": "flux-insha-0.1.4.tar.gz", "has_sig": false, "md5_digest": "28c2e8cde9a15ec06c10a7e8a4625992", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12938, "upload_time": "2019-02-18T17:43:35", "url": "https://files.pythonhosted.org/packages/db/21/a7607ee01c3894cea40ed98adab309619d1f6dc00ca2c1b721d80fb7c4a3/flux-insha-0.1.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "dde8b3a0ddb95f8d6a274b38a8a8e54c", "sha256": "52a9f2721def33bea629235e82794b8a87ce794d3ca111c369ec50b6e53a7f79" }, "downloads": -1, "filename": "flux_insha-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "dde8b3a0ddb95f8d6a274b38a8a8e54c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 17729, "upload_time": "2019-02-18T17:43:33", "url": "https://files.pythonhosted.org/packages/6e/c8/69cac95f41ccb53940d68770f74bcd758b209191b81550cf75221d11dd8e/flux_insha-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "28c2e8cde9a15ec06c10a7e8a4625992", "sha256": "b129d30dda3bdf4e2e0b283350f335427c6a5496d4ef22c1ab319d131f49aeb8" }, "downloads": -1, "filename": "flux-insha-0.1.4.tar.gz", "has_sig": false, "md5_digest": "28c2e8cde9a15ec06c10a7e8a4625992", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12938, "upload_time": "2019-02-18T17:43:35", "url": "https://files.pythonhosted.org/packages/db/21/a7607ee01c3894cea40ed98adab309619d1f6dc00ca2c1b721d80fb7c4a3/flux-insha-0.1.4.tar.gz" } ] }