{"id":37069658,"url":"https://github.com/zen747/pyscm","last_synced_at":"2026-01-14T08:01:12.038Z","repository":{"id":62583316,"uuid":"172290327","full_name":"zen747/pyscm","owner":"zen747","description":"A python state machine framework based on scxml.","archived":false,"fork":false,"pushed_at":"2021-09-13T12:45:04.000Z","size":24,"stargazers_count":15,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2024-08-08T15:03:59.299Z","etag":null,"topics":["david-harel","scxml","state-machine","statechart","statecharts"],"latest_commit_sha":null,"homepage":null,"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/zen747.png","metadata":{"files":{"readme":"README.md","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":"2019-02-24T03:13:50.000Z","updated_at":"2024-04-30T11:45:20.000Z","dependencies_parsed_at":"2022-11-03T21:37:19.851Z","dependency_job_id":null,"html_url":"https://github.com/zen747/pyscm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zen747/pyscm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen747%2Fpyscm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen747%2Fpyscm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen747%2Fpyscm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen747%2Fpyscm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zen747","download_url":"https://codeload.github.com/zen747/pyscm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen747%2Fpyscm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["david-harel","scxml","state-machine","statechart","statecharts"],"created_at":"2026-01-14T08:01:11.015Z","updated_at":"2026-01-14T08:01:11.951Z","avatar_url":"https://github.com/zen747.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyscm\nA python state machine framework based on statecharts (scxml).\n\nThis is a python library supporting statechart (in scxml format) originated by David Harel.\nFeatures like hierarchical states, parallel states, and history are ready for you to command.\nYou won't find another lib as easy and flexible to use as SCM.\n\nJust take a look and run scm_tutorial.py.\nThe code is listed here:\n```\nfrom scm import StateMachineManager\n\n\nclient_scxml = \"\"\"\\\n   \u003cscxml\u003e \n       \u003cstate id='appear'\u003e \n           \u003ctransition event='born' ontransit='say_hello' target='live'/\u003e \n       \u003c/state\u003e \n       \u003cparallel id='live'\u003e \n            \u003ctransition event='hp_zero' target='dead'/\u003e \n            \u003cstate id='eat'\u003e \n            \u003c/state\u003e \n            \u003cstate id='move'\u003e \n            \u003c/state\u003e \n       \u003c/parallel\u003e \n       \u003cfinal id='dead'/\u003e\n    \u003c/scxml\u003e \n\"\"\"\n\nclass Life:\n    def __init__(self):\n        self.mach_ = StateMachineManager.instance().getMach('the life')\n        self.mach_.set_do_exit_state_on_destroy(True)\n        self.mach_.register_state_slot(\"appear\", self.onentry_appear, self.onexit_appear)\n        self.mach_.register_state_slot(\"live\", self.onentry_live, self.onexit_live)\n        self.mach_.register_state_slot(\"eat\", self.onentry_eat, self.onexit_eat)\n        self.mach_.register_state_slot(\"move\", self.onentry_move, self.onexit_move)\n        self.mach_.register_state_slot(\"dead\", self.onentry_dead, self.onexit_dead)\n        self.mach_.register_action_slot('say_hello', self.say_hello)\n        self.mach_.StartEngine()\n        \n    def test(self):\n        self.mach_.enqueEvent(\"born\")\n        #self.mach_.frame_move(0) # state change to 'live'\n        StateMachineManager.instance().pumpMachEvents()\n        self.mach_.enqueEvent(\"hp_zero\")\n        #self.mach_.frame_move(0) # state change to 'dead'\n        StateMachineManager.instance().pumpMachEvents()\n        \n    def onentry_appear(self):\n        print(\"come to exist\")\n    \n    def onexit_appear(self):\n        print(\"we are going to...\")\n    \n    def onentry_live(self):\n        print(\"start living\")\n    \n    def onexit_live(self):\n        print(\"no longer live\")\n    \n    def onentry_eat(self):\n        print(\"start eating\")\n    \n    def onexit_eat(self):\n        print(\"stop eating\")\n    \n    def onentry_move(self):\n        print(\"start moving\")\n    \n    def onexit_move(self):\n        print(\"stop moving\")\n    \n    def onentry_dead(self):\n        print(\"end\")\n    \n    def onexit_dead(self):\n        assert (0 and \"should not exit final state\");\n        print(\"no, this won't get called.\")\n    \n    def say_hello(self):\n        print(\"\\n*** Hello, World! ***\\n\")\n        \nif __name__ == '__main__':\n    StateMachineManager.instance().set_scxml(\"the life\", client_scxml)\n    life = Life()\n    life.test()\n    StateMachineManager.instance().pumpMachEvents()\n\n```\n\nThe output you should see:\n\n\"\"\"\ncome to exist\nwe are going to...\n\n*** Hello, World! ***\n\nstart living\nstart eating\nstart moving\nstop eating\nstop moving\nno longer live\nend\n\"\"\"\n\nSimply\n1. you load the scxml from external file or from a string defined in your code.\n2. you connect these onentry_ onexit_, etc. slots\n3. you start the engine, call the framemove in main loop.\nDone.\n\nIt's that easy!\n\nRead the tutorials at\n[English] (http://zen747.blogspot.tw/2017/07/a-scm-framework-tutorial-statechart.html)\n\n[Traditional Chinese] (http://zen747.blogspot.tw/2017/07/scm-framework.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzen747%2Fpyscm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzen747%2Fpyscm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzen747%2Fpyscm/lists"}