{ "info": { "author": "Tianhong Chu", "author_email": "cthesky13@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Customer Service", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "## gtui\n\nTask scheduler & executor with text-based user interface, able to:\n\n* declare task & dependency as a graph\n* execute task graph\n* show task status, stdout & log \n* provide a nice user interface\n\nTo install:\n\n```\n$ pip install gtui\n```\n\n## Quickstart\n\nLet's say we have some helloworld tasks & their dependencies like this:\n\n![task_graph_demo.png](https://github.com/CtheSky/gtui/blob/master/img/task_graph_demo.png)\n\nWe need to create `Task` and add them to `TaskGraph`:\n\n```python\nimport time\nimport logging\nfrom gtui import Task, TaskGraph\n\ndef foo(n):\n logging.info('foo(%s) is called', n)\n print('Start to sleep %s seconds.' % n)\n time.sleep(n)\n print('Hello World!')\n\nt1 = Task('t1', func=foo, args=[0.1])\nt2 = Task('t2', func=foo, args=[1])\nt3 = Task('t3', func=foo, args=[1])\nt4 = Task('t4', func=foo, args=[0.5])\n\ng = TaskGraph()\ng.add_task(t1)\ng.add_task(t2, waiting_for=t1)\ng.add_task(t3, waiting_for=t1)\ng.add_task(t4, waiting_for=[t2, t3])\n\ng.run()\n```\n\n`TaskGraph.run` starts the text user interface, and you can navigate through tasks, see their status, output and logs:\n![tui_demo.gif](https://github.com/CtheSky/gtui/blob/master/img/tui_demo.gif)\n\nKeybindings:\n* t : toggle tail -f mode, will follow text when enabled\n* tab : switch between output & log\n* j/k : select previous/next task\n* h/l : page up/down\n* \u2191/\u2193 : scroll up/down one line\n* y : copy text\n* q : exit\n\n## Task & TaskGraph\n\n`Task` defines what to do and has an unique name:\n\n```python\n# foo(*args, **kwargs) will be called\nt = Task(name='foo', func=foo, args=[1, 2], kwargs={'foo': 'bar'})\n```\n\n`TaskGraph` defines execution order of a set of tasks, it provides method to declare task & dependency:\n```python\ng = TaskGraph()\ng.add_task(t1) # added task t1\ng.add_task(t2, waiting_for=t1) # added task t2, t2 runs after t1 finishes\ng.add_tasks([t3, t4]) # added task t3, t4\ng.add_dependency(t3, waiting_for=[t1, t2]) # declare t3 to run after t1 & t2 finish\n```\n\nWhen `TaskGraph` contains a cycle denpendency, `run` method will throw a `ValueError`. You can also use `has_cycle` to \ncheck:\n\n```python\n> g = TaskGraph()\n> g.add_tasks([t1, t2])\n> g.add_dependency(t1, waiting_for=t2)\n> g.add_dependency(t2, waiting_for=t1)\n> g.has_cycle()\n[t1, t2, t1]\n```\n\n## Run Options\n\n`TaskGraph.run` provides some options:\n\n```python\ng.run(\n title='Demo', # Text shown at the left bottom corner\n callback=None, # A function called when execution fail or succeed\n log_formatter=None, # An instance of logging.Formatter, to specify the log format\n exit_on_success=False # whether exit tui when execution succeed\n)\n```\n\n`callback` can be used to notify the execution result, it will be called with an boolean indicating whether execution succeed. `gtui.callback` has some common callbacks:\n\n```python\n# emit a desktop notification, use osascript on mac and notify-send on linux\nfrom gtui import callback\ng.run(callback.desktop_nofity(title='Plz See Here!', success_msg='Success', fail_msg='Fail'))\n```\n\n## Possible Problem with Stdout\n\nWriting to stdout will break the TUI display. `gtui` runs each task in a new thread with `sys.stdout` replaced so functions like `print` will just work fine. When creating a new thread inside a task, `gtui.IORedirectedThread` can be used to achieve the same result:\n\n```python\nfrom gtui import IORedirectedThread\n\nt = IORedirectedThread(target=print, args=['hello world'])\nt.start()\nt.join()\n\ncontent = t.get_stdout_content()\n```\n\nHowever, `gtui` doesn't try to deal with other cases so you should take care of it by yourself.\n\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/CtheSky/gtui", "keywords": "TUI,Command Line Tool,Scheduler", "license": "", "maintainer": "", "maintainer_email": "", "name": "gtui", "package_url": "https://pypi.org/project/gtui/", "platform": "any", "project_url": "https://pypi.org/project/gtui/", "project_urls": { "Homepage": "https://github.com/CtheSky/gtui" }, "release_url": "https://pypi.org/project/gtui/0.1.1/", "requires_dist": [ "urwid (>=2.0.0)", "additional-urwid-widgets (==0.4.1)", "pyperclip (>=1.7.0)" ], "requires_python": ">= 3.4", "summary": "Simple Task Scheduler & Executor with Friendly Text User Interface", "version": "0.1.1", "yanked": false, "yanked_reason": null }, "last_serial": 6122547, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "dc27f640f723d0148d1ecfa83c97f3cc", "sha256": "331fa40823bc95b754ef87491159690dfeb4e981f8a0d9079be981d1b5fa26cd" }, "downloads": -1, "filename": "gtui-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dc27f640f723d0148d1ecfa83c97f3cc", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*", "size": 3544, "upload_time": "2019-07-16T07:48:49", "upload_time_iso_8601": "2019-07-16T07:48:49.163193Z", "url": "https://files.pythonhosted.org/packages/a0/67/ce3f781bf582ee4d0480d8319944ff273775670d0c4755de398029f53359/gtui-0.0.1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "debb5ad0d156c6ef6bba8298a4c4faec", "sha256": "83ce79ef083e50c5d678502f8f34345b073b3ce46d2b3618b01efc6f5e1e155b" }, "downloads": -1, "filename": "gtui-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "debb5ad0d156c6ef6bba8298a4c4faec", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">= 3.4", "size": 29880, "upload_time": "2019-10-23T12:44:37", "upload_time_iso_8601": "2019-10-23T12:44:37.498908Z", "url": "https://files.pythonhosted.org/packages/f1/a9/b27b61de77d172be77e17c1a213668d90bdff1ad1e0d233b78455cdb7488/gtui-0.1.0-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "081f10e0a0b6eeb93022f845f7550c87", "sha256": "38322bbfa0eb38b563f6059ff7a3ee8730d875a83bda18c6c3730ec58d81e482" }, "downloads": -1, "filename": "gtui-0.1.0.tar.gz", "has_sig": false, "md5_digest": "081f10e0a0b6eeb93022f845f7550c87", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.4", "size": 17196, "upload_time": "2019-10-23T12:44:39", "upload_time_iso_8601": "2019-10-23T12:44:39.007803Z", "url": "https://files.pythonhosted.org/packages/77/fd/80eaf2b152d24ee0caacfb59e2ea473d24124d209feb53b2be5570f2d5b1/gtui-0.1.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "87b6fadb97bb19fb92b6497412979d99", "sha256": "1a1b0998dd1944dd5a89faee8475a48e80905fe740b7b270f1e66f6804a25c21" }, "downloads": -1, "filename": "gtui-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "87b6fadb97bb19fb92b6497412979d99", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">= 3.4", "size": 29886, "upload_time": "2019-11-12T09:48:55", "upload_time_iso_8601": "2019-11-12T09:48:55.218670Z", "url": "https://files.pythonhosted.org/packages/11/77/a8960565042eac79f5901944682cc104d3776a57e0bd0a5a754367ab5a52/gtui-0.1.1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "95ac5afdc2a50518a099280fb9c1bb42", "sha256": "63eff172e1c9560576c32b611bc2dd8ef3111b90485b5cd9608a5bf91aa2af70" }, "downloads": -1, "filename": "gtui-0.1.1.tar.gz", "has_sig": false, "md5_digest": "95ac5afdc2a50518a099280fb9c1bb42", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.4", "size": 17211, "upload_time": "2019-11-12T09:48:57", "upload_time_iso_8601": "2019-11-12T09:48:57.094855Z", "url": "https://files.pythonhosted.org/packages/48/63/8f087eda220c8289e68937f7284eaf1a2799d1554f27c69a65297599b749/gtui-0.1.1.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "87b6fadb97bb19fb92b6497412979d99", "sha256": "1a1b0998dd1944dd5a89faee8475a48e80905fe740b7b270f1e66f6804a25c21" }, "downloads": -1, "filename": "gtui-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "87b6fadb97bb19fb92b6497412979d99", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">= 3.4", "size": 29886, "upload_time": "2019-11-12T09:48:55", "upload_time_iso_8601": "2019-11-12T09:48:55.218670Z", "url": "https://files.pythonhosted.org/packages/11/77/a8960565042eac79f5901944682cc104d3776a57e0bd0a5a754367ab5a52/gtui-0.1.1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "95ac5afdc2a50518a099280fb9c1bb42", "sha256": "63eff172e1c9560576c32b611bc2dd8ef3111b90485b5cd9608a5bf91aa2af70" }, "downloads": -1, "filename": "gtui-0.1.1.tar.gz", "has_sig": false, "md5_digest": "95ac5afdc2a50518a099280fb9c1bb42", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.4", "size": 17211, "upload_time": "2019-11-12T09:48:57", "upload_time_iso_8601": "2019-11-12T09:48:57.094855Z", "url": "https://files.pythonhosted.org/packages/48/63/8f087eda220c8289e68937f7284eaf1a2799d1554f27c69a65297599b749/gtui-0.1.1.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }