{"id":20347132,"url":"https://github.com/ourway/pyworkflow","last_synced_at":"2025-11-03T15:03:40.329Z","repository":{"id":66127529,"uuid":"151015071","full_name":"ourway/pyworkflow","owner":"ourway","description":"An effort less workflow engine / server","archived":false,"fork":false,"pushed_at":"2018-09-30T23:13:09.000Z","size":12,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-14T22:43:00.994Z","etag":null,"topics":["python","workflow","workflow-automation","workflow-engine","workflow-task"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ourway.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.txt","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-30T23:11:30.000Z","updated_at":"2018-09-30T23:13:48.000Z","dependencies_parsed_at":"2023-03-10T23:38:27.763Z","dependency_job_id":null,"html_url":"https://github.com/ourway/pyworkflow","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ourway%2Fpyworkflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ourway%2Fpyworkflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ourway%2Fpyworkflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ourway%2Fpyworkflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ourway","download_url":"https://codeload.github.com/ourway/pyworkflow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241877461,"owners_count":20035404,"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":["python","workflow","workflow-automation","workflow-engine","workflow-task"],"created_at":"2024-11-14T22:15:30.817Z","updated_at":"2025-11-03T15:03:40.292Z","avatar_url":"https://github.com/ourway.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n## Basic Deploy\nrun web server:\n```\n\t./app.py\n```\n\n## Test\nTo learn better run\n```\npython tests/test_simple.py\n```\n\n------------\n\n\n## Tutorial\n\n- in the first step you should define a workflow to server \n   to define new workflow call below address using standard HTTP call:\n \n```\nhttp POST http://server_address/wf/{workflow name:string}/{workflow version:number}\n```\n\n- content must be a json which defines our workflow. for example:\n\n```\nhttp POST http://server_address/wf/my_test_workflow/1\n```\n\n- json which sends to server must have below schema:\n```\n{ \n   \t\"name\" : \"workflow name\",\n\t\"steps\":[\n\t\t\t\t{type= \"taskcall\", taskname=\"taskname to call in this step\", params = [parameters to pass to task]}\n\t\t\t\t...\n```\n\nor\n\t\t\t\t\n```\n{\n\ttype=\"eval\",\n\tparams = [ ''' string to evaluate ''']\n}\n\t\t\t\t...\t\n```\n\n### Full example:\n\n```\nhttp POST http://server_address/wf/my_test_workflow/1\n```\n\n```\n\n{\n        \"name\":\"my_test_workflow\",\n            \"steps\":[\n                        {\n                            \"type\":\"taskcall\",\n                            \"taskname\":\"test_task_add_two_number\",\n                            \"params\":[12,13,\"c\"]\n                        }\n                    ]\n}\n\n```\n\n\nthis sample defines a simple workflow that add two number. ``test_task_add_two_number`` is a task which defined in our workflow server as below:\n\n```\ndef test_task_add_two_number(a,b,\n\t\t\t\t\tresult_var_name):\n    \tdef l(obj,eng):\n        \tobj[result_var_name]=a+b\n    \treturn l\n```\n\nas you see, our function has 3 parameter that pass to it using params section of task call in our json. all tasks must defined to our workflow server\n\nTo run this workflow :\n\n```\nPOST http://server_address/run/{workflow name}/{workflow version}/{customer id}\n```\nAnd Body: \n\njson that initialize workflow variables\n\t``customer id`` is an identifcation number which specifies this ``wf(workflow)`` instance\n\nin the case of VAS service it is user mobile number that this wf runs for.\nto run pervious workflow:\n```\nhttp POST http://server_address/run/my_test_workflow/1/242233\n```\n``Content-Type``: ``application/json``\n\t\nTo get variables from workflow after its run we should defines which\nvariables we need, see below:\n\n```\nhttp POST http://server_address/run/my_test_workflow/1/123232\n```\n```\n\t{\n\t\t\"__rtn_vars__\":[\"c\"]\n\t}\n```\n\t\nabove says to workflow engine (WE) runs ``my_test_workflow`` for customer id ``123232`` and returns variable ``c``.\tas you know c must be ``25`` (12+13)\n\nto improve our understanding see this example:\n```\n{\n\t\"name\":\"simple_login\"\n   \"steps\":[\n      {\n\t  \t \"taskname\":\"IF_ELSE\",\n         \"type\":\"taskcall\",\n         \"params\":[\n\t\t\t\t{\n\t\t\t\t   \"type\":\"eval\",\n\t\t\t\t   \"params\":[\n\t\t\t\t\t  \" lambda obj,eng: obj['username']=='gholi' and obj['password']=='gholi' \"\n\t\t\t\t   ]\n\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t   \"taskname\":\"task_exec\",\n\t\t\t\t\t   \"type\":\"taskcall\"\n\t\t\t\t\t\t\"params\":[\n\t\t\t\t\t\t  \"\n\t\t\t\t\t\t  def l(obj,eng):\n\t\t\t\t\t\t  \tobj['rtn']= 'hello dear '+obj['username']\n\t\t\t\t\t\t\tobj['user_login']=True\n\t\t\t\t\t\t\t\",\n\t\t\t\t\t\t  \"l\"\n\t\t\t\t\t   \t],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t   \"taskname\":\"task_exec\",\n\t\t\t\t\t   \"type\":\"taskcall\"\n\t\t\t\t\t   \"params\":[\n\t\t\t\t\t\t  \"\n\t\t\t\t\t\t  def l(obj,eng):\n\t\t\t\t\t\t  \tobj['rtn']='failed to Login'\\n    obj['user_login']=False\n\t\t\t\t\t\t\t\",\n\t\t\t\t\t\t  \"l\"\n\t\t\t\t\t   ],\n\t\t\t\t\t}\n         ],\n         \n      }\n   ],\n   \n}\n```\n\nExplanation:\n- this example created by 1 task, it is ``IF_ELSE`` task, ``IF_ELSE`` task has 3 arguments\n- first is condition which is a lambda expression to determine ``True`` of ``False``.\n- second parameter is list of tasks if condition was ``True``.\n - Thrid parameter is list of tasks if condition was ``False``.\n\n- As you see first parameter of ``IF_ELSE`` task is:\n\n```\n {\t\n\t\"type\":\"eval\",\n\t\"params\":[\n\t\t\t\" lambda obj,eng: obj['username']=='gholi' and obj['password']=='gholi' \"\n\t\t      ]\n}\n```\nwhich defines an eval task that compiles to :\n```\nlambda obj,eng: obj['username']=='gholi' and obj['password']=='gholi'\n```\nthat compare username and password to gholi\nand if both of them are gholi returns True else returns ``False``.\n\t\n- the second parameter is (True Branch of IF_ELSE [can be list of tasks]):\n\n```\t\n{\n\t\"taskname\":\"task_exec\",\n\t\"type\":\"taskcall\",\n\t\"params\":[\n\t\t'''\n\t\tdef l(obj,eng):\n\t\t\tobj['rtn']= 'hello dear '\n\t\t\t\t+obj['username']\n\t\t\tobj['user_login']=True\n\t\t''',\n\t\t\"l\"\n\t],\n}\n```\n\nit is a task_exec which exec string in server, task_exec has two parameters:\n```\ntask_exec(code_string,function_name_string)\n```\n\ncode_string can be full Python Module but at final should define a function that has two parameter ``(obj,eng)`` that returns from it.\n\nas you see this Task sets rtn variable of WF to \"hello dear {username}\" and \n\tsets user_login variable to ```True```\n\nto run this WF we call run method using:\n```\t\nPOST http://server_address/wf/run/simple_login/1/12344\n```\n\n```\n\t{\n\t\t'__rtn_vars__':['rtn','user_login'],\n\t\t'username':'gholi',\n\t\t'password':'jafar'\n\t}\n```\n\nabove call sets username and password variable of workflow to 'gholi' and 'jafar' and \tsays to workflow returns rtn,user_login variables from workflow.\n\n----\n\nSometimes we need call external web-api and interact with them to do this we do below steps:\n\t1. define web url and its type to server using below call:\n```\nPOST http://server_address/wf/define/task\n```\n\n```\n{\n\t\"task_name\":\"task name which use in WF to specifies this web task\",\n\t\"task_type\":\"can be sync or async\"\n\t\"url\":\"url of server method\"\n}\n```\n\nsync tasks wait to get response from server and workflow waits for the result\nasync tasks halts workflow and wait to call from web server to callbacked\n\nfor example:\n```\nPOST http://server_address/wf/define/task\n```\n```\n{\n\t\t\"task_name\":\"reg_user\",\n\t\t\"task_type\":\"sync\",\n\t\t\"url\":\"http://127.0.0.1:8282/mockservice/user\"\n}\n```\n\n\t2. To use in our wf we should define a task as below:\n```\n{\n\t\"type\":\"taskcall\",\n\t\"taskname\":\"task_dynamic_task\",\n    params=[\n\t\t\t\"web task name\",\n\t\t\t\"prefix of return result\",\n\t\t\t\t{\n                   web_call_param1:{type='var or value',var_name='variable name' or value = \"direct value\"},\n\t\t\t\t\t ....\n                 }]\n}\n```\n\nFor example:\n``` \n{\n\ttype='taskcall',\n\ttaskname='task_dynamic_task',\n    params=[\n\t\t\t'reg_user',\n\t\t\t'ru',\n\t\t\t{\n               username:{type:'var',var_name:'username'},\n               password:{type:'var',var_name:'password'},\n               req_date:{type:'value',value:13931413},\n               from_service_name:{type:'value',value:'simple test to farsheed!'}\n            }\n\t\t]\n}\n```\n\nin this sample WF calls ``reg_user`` web task which defined before and add ``ru`` prefix in the head of its returns json\n\nfor example if this web call returns json as below:\n```\n{userid:12,status:'ok'}\n```\n\nthe wf add re as prefix to them and add them to wf variables,\t``re_userid=12`` and ``re_status='ok'`` added to wf variables\n\nlast parameter is a dictionary which pass as parameter to web call\n``username`` variable from workflow pass to web call as ``username`` in json body\n``password`` variable from wf pass to web-call as ``password`` in json body\n``req_date`` as direct value ``13931413`` pass to web-call as ``req_date`` \tand so on.\n\t\n\t\n\t\n\t\n   \n   \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fourway%2Fpyworkflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fourway%2Fpyworkflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fourway%2Fpyworkflow/lists"}