{"id":20108005,"url":"https://github.com/nazavode/automaton","last_synced_at":"2025-07-07T21:32:52.688Z","repository":{"id":52704820,"uuid":"43289916","full_name":"nazavode/automaton","owner":"nazavode","description":"A minimal Python finite-state machine.","archived":false,"fork":false,"pushed_at":"2021-10-21T17:57:43.000Z","size":158,"stargazers_count":23,"open_issues_count":7,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-09T13:40:49.481Z","etag":null,"topics":["automata","automaton","finite-state-machine","pythonic"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nazavode.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-28T08:46:48.000Z","updated_at":"2024-10-07T09:28:25.000Z","dependencies_parsed_at":"2022-08-21T19:20:10.185Z","dependency_job_id":null,"html_url":"https://github.com/nazavode/automaton","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/nazavode/automaton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nazavode%2Fautomaton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nazavode%2Fautomaton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nazavode%2Fautomaton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nazavode%2Fautomaton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nazavode","download_url":"https://codeload.github.com/nazavode/automaton/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nazavode%2Fautomaton/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261304113,"owners_count":23138281,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automata","automaton","finite-state-machine","pythonic"],"created_at":"2024-11-13T17:59:19.050Z","updated_at":"2025-07-07T21:32:52.646Z","avatar_url":"https://github.com/nazavode.png","language":"Python","funding_links":[],"categories":["Libraries"],"sub_categories":["Python"],"readme":"=========\nAutomaton\n=========\n\nPythonic finite-state machines.\n\n|build-status| |coverage-status| |documentation-status| |codeqa| |pypi| |license-status|\n\nAutomaton is an easy to use, *pythonic* `finite-state machine`_ module for Python 3.4 or greater.\nThe goal here is to have something to define finite-state machines in a minimal, straightforward\nand elegant way that enforces **clarity** and **correctness**.\n\nInstallation\n============\nAutomaton is available on `pypi \u003chttps://pypi.python.org/pypi/python-automaton\u003e`_,\nso to install it just use:\n\n.. code::\n\n    $ pip3 install python-automaton\n\n\nDependencies\n============\n\n* `Python \u003e= 3.4`\n* `networkx \u003chttps://github.com/networkx/networkx\u003e`_\n* `tabulate \u003chttps://pypi.python.org/pypi/tabulate\u003e`_\n\n\nGetting started\n===============\n\nIn order to define an automaton, just subclass a provided base:\n\n.. code-block:: python\n\n    from automaton import *\n\n    class TrafficLight(Automaton):\n\n        go = Event(\"red\", \"green\")\n        slowdown = Event(\"green\", \"yellow\")\n        stop = Event(\"yellow\", \"red\")\n\nYou're done: you now have a new *automaton* definition that can be instantiated to an **initial state**:\n\n.. code-block:: python\n\n    crossroads = TrafficLight(initial_state=\"red\")\n    assert crossroads.state == \"red\"\n\nEach **event** (also known as **transition**) is a class attribute defined by its **source state** and\n**destination state**. When an *event fires*, the automaton changes its state from the *source* to the *destination*:\nyou can *fire* an event by calling it:\n\n.. code-block:: python\n\n    crossroads.go()\n    assert crossroads.state == \"green\"\n    crossroads.slowdown()\n    assert crossroads.state == \"yellow\"\n\nAn alternative way, more convenient if triggering events progammatically, is to call the ``event()`` method:\n\n.. code-block:: python\n\n    crossroads.event(\"stop\")\n    assert crossroads.state == \"red\"\n\nCorrectness\n-----------\n\nAutomaton enforces correctness in two ways:\n\n1. checking that the requested event is *valid*, that is a transition from the current state to the destination\n   state exists in the state machine definition;\n#. checking whether the *state graph* representing the automaton is *connected* or not (that is it must have only\n    one `connected component`_).\n\nSo, if you try to trigger an invalid event...\n\n.. code-block:: python\n\n    crossroads = TrafficLight(initial_state=\"red\")\n    crossroads.stop()\n\n...you will end up with an error:\n\n.. code::\n\n    automaton.InvalidTransitionError: The specified event 'Event(source_states=('yellow',), dest_state='red')'\n                                      is invalid in current state 'red'.\n\n\nAgain, trying to define a class like this...\n\n.. code-block:: python\n\n    class BrokenTrafficLight(Automaton):\n\n       go = Event(\"red\", \"green\")\n       slowdown = Event(\"green\", \"yellow\")\n       # broken!\n       stop = Event(\"black\", \"purple\")\n\n...will trigger an error:\n\n.. code::\n\n    automaton.DefinitionError: The state graph contains 2 connected components:\n                               ['green', 'yellow', 'red'], ['purple', 'black']\n\n\nHow to visualize an automaton?\n------------------------------\n\nWhen things are getting complex and it seems that our automata are becoming autonomous life forms grasping to escape\nour control, it could be useful to have a *human friendly* representation of their behaviour.\n\nYou can ask for the *transition table*...\n\n.. code-block:: python\n\n    transitiontable(TrafficLight, fmt='rst')\n\n...and you will be presented with a nice ``reStructuredText`` snippet:\n\n.. code::\n\n    ========  ======  ========\n    Source    Dest    Event\n    ========  ======  ========\n    green     yellow  slowdown\n    yellow    red     stop\n    red       green   go\n    ========  ======  ========\n\nYou can ask for the *state graph* as well...\n\n.. code-block:: python\n\n    stategraph(TrafficLight, fmt='plantuml')\n\n...and you'll end up with a proper `PlantUML \u003chttp://plantuml.com/\u003e`_ representation...\n\n.. code::\n\n    @startuml\n        [*] --\u003e red\n        green --\u003e yellow : slowdown\n        red --\u003e green : go\n        yellow --\u003e red : stop\n    @enduml\n\n...that can of course be rendered through ``plantuml``:\n\n.. image:: https://github.com/nazavode/automaton/raw/master/docs/source/_static/trafficlight.png\n   :alt: Traffic Light Graph\n\n\nKeep your docstrings tidy!\n--------------------------\n\nSince *automata are classes* here, it would be great to have a textual representation of the automaton's behaviour\nin our docstrings. What about having one that updates itself in order to stay up-to-date with the\nactual code?\n\nHere you have it:\n\n.. code-block:: python\n\n    class TrafficLight(Automaton):\n        \"\"\" This is a pretty standard traffic light.\n\n        This automaton follows the behaviour defined by\n        the following transition table:\n\n        {automaton:rst}\n\n        \"\"\"\n\n        go = Event(\"red\", \"green\")\n        slowdown = Event(\"green\", \"yellow\")\n        stop = Event(\"yellow\", \"red\")\n\nUsing a standard format specifier with the ``automaton`` keyword and the proper output format (e.g.: ``rst``), the\nautomaton representation will be inserted in the docstring during the class definition, **just where it should be**:\n\n.. code-block:: python\n\n    \u003e\u003e\u003e print(TrafficLight.__doc__)\n    \"\"\" This is a pretty standard traffic light.\n\n    This automaton follows the behaviour defined by\n    the following transition table:\n\n    ========  ======  ========\n    Source    Dest    Event\n    ========  ======  ========\n    green     yellow  slowdown\n    yellow    red     stop\n    red       green   go\n    ========  ======  ========\n\n    \"\"\"\n\n*Easy!*\n\n\nDocumentation\n=============\n\nYou can find the full documentation at http://automaton.readthedocs.org.\n\n\nChanges\n=======\n\n1.3.1 *(2017-02-05)*\n--------------------\n\nChanged\n```````\n- Fixed ``README.rst`` rendering on pypi.\n\n\n1.3.0 *(2017-02-05)*\n--------------------\n\nAdded\n`````\n- Enabled access to all event's attributes from automaton instances.\n- New constructor parameter to initialize an automaton given an initial\n  *startup* event.\n\nChanged\n```````\n- Misc bugs fixed.\n- Tests cleanup.\n- Improved reference and documentation.\n\n\n1.2.1 *(2017-01-30)*\n--------------------\n\nFixed\n`````\n- Severe distribution issue: package was missing some files.\n- Tox testing: ``py.test`` was running against *source files*,\n  not against the package installed in ``tox`` virtualenv.\n\n\n1.2.0 *(2017-01-29)*\n--------------------\n\nAdded\n`````\n- Custom format specifiers for ``Automaton`` definitions (classes and instances).\n- Auto-docstring completion: if requested, the automaton textual representation\n  is automatically added to the ``__doc__`` class attribute.\n\nChanged\n```````\n- Refactored formatting functions to more streamlined and coherent interfaces.\n- Removed package, now the whole library lives in one module file.\n\n\n1.1.0 *(2017-01-28)*\n--------------------\n\nAdded\n`````\n- Automaton representation as transition table or state-transition graph.\n\n\n1.0.0 *(2017-01-25)*\n--------------------\n\nAdded\n`````\n- Functions to retrieve incoming and outgoing events from a state or a set of states.\n\n\n.. _finite-state machine:\n    https://en.wikipedia.org/wiki/Finite-state_machine\n\n.. _connected component:\n    https://en.wikipedia.org/wiki/Connected_component_(graph_theory)\n\n.. |build-status| image:: https://travis-ci.org/nazavode/automaton.svg?branch=master\n    :target: https://travis-ci.org/nazavode/automaton\n    :alt: Build status\n\n.. |documentation-status| image:: https://readthedocs.org/projects/automaton/badge/?version=latest\n    :target: http://automaton.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n\n.. |coverage-status| image:: https://codecov.io/gh/nazavode/automaton/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/nazavode/automaton\n    :alt: Coverage report\n\n.. |license-status| image:: https://img.shields.io/badge/license-Apache2.0-blue.svg\n    :target: http://opensource.org/licenses/Apache2.0\n    :alt: License\n\n.. |codeqa| image:: https://api.codacy.com/project/badge/Grade/0eb6d3a1a1b04030852e153b13f7cbc9\n   :target: https://www.codacy.com/app/federico-ficarelli/automaton?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=nazavode/automaton\u0026utm_campaign=badger\n   :alt: Codacy Badge\n\n.. |pypi| image:: https://badge.fury.io/py/python-automaton.svg\n    :target: https://badge.fury.io/py/python-automaton\n    :alt: PyPI\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnazavode%2Fautomaton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnazavode%2Fautomaton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnazavode%2Fautomaton/lists"}