{ "info": { "author": "guylapid", "author_email": "", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7" ], "description": "# Greengen\r\nGreengen is a python package that allows implementing generators without yielding items all the way up.\r\nInstead, any inner function called from a greengen generator, can yield items directly to the outer generator.\r\n## Installation\r\n```\r\npip install greengen\r\n```\r\n## Usage\r\nFor example, suppose we want to implement a function that performs some heavy business logic, and generates logs.\r\nWe want to handle the logs the moment they are created.\r\nBut our function has to call a deep stack of helper functions, which in their turn call more functions,\r\nand logs may be written anywhere inside any function.\r\nThe implementation with regular generators will be utterly annoying:\r\n```python\r\nimport time\r\n\r\n\r\ndef do_business_logic_and_yield_logs(some_input):\r\n yield from _helper_function(some_input)\r\n yield from _more_helper_function(some_input)\r\n\r\n\r\ndef _helper_function(some_input):\r\n for i in range(some_input):\r\n logs_and_result = _inner_helper_function(i)\r\n # Notice the enormous effort needed in order to retrieve the last result (using StopIteration etc.)\r\n while True:\r\n try:\r\n yield next(logs_and_result) # This is a log\r\n except StopIteration as e:\r\n result = e.value # This is the result\r\n yield log('Result for {} is {}'.format(i, result))\r\n break\r\n\r\n\r\ndef _more_helper_function(some_input):\r\n yield from _helper_function(some_input * 100)\r\n yield from _helper_function(some_input ** 2)\r\n\r\n\r\ndef _inner_helper_function(some_input):\r\n yield log('Started calculating')\r\n result = 2 ** some_input # (Or whatever other heavy calculation)\r\n yield log('Finished calculating')\r\n return result # Will be raised as StopIteration\r\n\r\n\r\ndef log(stuff):\r\n return {'message': str(stuff), 'timestamp': time.time()}\r\n\r\n\r\ndef main():\r\n for l in do_business_logic_and_yield_logs(42):\r\n # Consume the logs however we want\r\n print('{}: {}'.format(l['timestamp'], l['message']))\r\n```\r\nUsing Greengen, this example can be simplified into the following:\r\n```python\r\nimport time\r\nimport greengen\r\n\r\n@greengen.greengen\r\ndef do_business_logic_and_yield_logs(some_input):\r\n # Notice how we don't need the \"yield from\" anymore\r\n _helper_function(some_input)\r\n _more_helper_function(some_input)\r\n\r\n\r\ndef _helper_function(some_input):\r\n for i in range(some_input):\r\n # Notice how easy it is to retrieve the result now\r\n result = _inner_helper_function(i)\r\n log('Result for {} is {}'.format(i, result))\r\n\r\n\r\ndef _more_helper_function(some_input):\r\n _helper_function(some_input * 100)\r\n _helper_function(some_input ** 2)\r\n\r\n\r\ndef _inner_helper_function(some_input):\r\n log('Started calculating')\r\n result = 2 ** some_input # (Or whatever other heavy calculation)\r\n log('Finished calculating')\r\n return result\r\n\r\n\r\ndef log(stuff):\r\n # This is the only place in the entire code where we need to be aware of the fact that we are inside a generator.\r\n # This will directly yield the log as the next item in the outer generator (\"do_business_logic_and_yield_logs\")\r\n greengen.yield_({'message': str(stuff), 'timestamp': time.time()})\r\n\r\n\r\ndef main():\r\n for l in do_business_logic_and_yield_logs(42):\r\n # Consume the logs however we want\r\n print('{}: {}'.format(l['timestamp'], l['message']))\r\n```\r\n## Contributing\r\n1. Fork it!\r\n2. Create your feature branch: `git checkout -b my-new-feature`\r\n3. Commit your changes: `git commit -am 'Add some feature'`\r\n4. Push to the branch: `git push origin my-new-feature`\r\n5. Submit a pull request :D\r\n## History\r\nTODO: Write history\r\n## Credits\r\nTODO: Write credits\r\n## License\r\nTODO: Write license\r\n\r\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/guylapid/greengen", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "greengen", "package_url": "https://pypi.org/project/greengen/", "platform": "", "project_url": "https://pypi.org/project/greengen/", "project_urls": { "Homepage": "https://github.com/guylapid/greengen" }, "release_url": "https://pypi.org/project/greengen/1.0.1/", "requires_dist": [ "greenlet", "decorator" ], "requires_python": "", "summary": "Nesting generators using greenlets", "version": "1.0.1" }, "last_serial": 5656336, "releases": { "1.0.1": [ { "comment_text": "", "digests": { "md5": "eb2da490aa9e77acad0623384ea13fc7", "sha256": "d65086bb296af0458ba0732dc036d725724383e06dff9c12310e28a8e3e50cc9" }, "downloads": -1, "filename": "greengen-1.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "eb2da490aa9e77acad0623384ea13fc7", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 3829, "upload_time": "2019-08-09T15:07:51", "url": "https://files.pythonhosted.org/packages/bc/4a/63887d2337122a5791279fe4003a41288666e91e0660847ce12b6ccc3933/greengen-1.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b7328b99f9b9315745160ae21bb6f8be", "sha256": "3551339d45055d59c029bfd3ffdb3ca413d26f00834d07a1bdc3abc1e810a250" }, "downloads": -1, "filename": "greengen-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "b7328b99f9b9315745160ae21bb6f8be", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 3800, "upload_time": "2019-08-09T15:07:53", "url": "https://files.pythonhosted.org/packages/16/12/9d99c7b462c92d24d60115347a46ba3c5afbca67efb0126ae75548d3d3f6/greengen-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ca59a26550cb94d3864f1f0819340218", "sha256": "16568936a550d00025a9fd8bc5c1fc15fe4d29d8e02e37746d28b806c94c4462" }, "downloads": -1, "filename": "greengen-1.0.1.tar.gz", "has_sig": false, "md5_digest": "ca59a26550cb94d3864f1f0819340218", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3167, "upload_time": "2019-08-09T15:07:55", "url": "https://files.pythonhosted.org/packages/5f/45/919ecfbfc017d385968a457f70ebf1af3043381d950337aa12722e332697/greengen-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "eb2da490aa9e77acad0623384ea13fc7", "sha256": "d65086bb296af0458ba0732dc036d725724383e06dff9c12310e28a8e3e50cc9" }, "downloads": -1, "filename": "greengen-1.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "eb2da490aa9e77acad0623384ea13fc7", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 3829, "upload_time": "2019-08-09T15:07:51", "url": "https://files.pythonhosted.org/packages/bc/4a/63887d2337122a5791279fe4003a41288666e91e0660847ce12b6ccc3933/greengen-1.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b7328b99f9b9315745160ae21bb6f8be", "sha256": "3551339d45055d59c029bfd3ffdb3ca413d26f00834d07a1bdc3abc1e810a250" }, "downloads": -1, "filename": "greengen-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "b7328b99f9b9315745160ae21bb6f8be", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 3800, "upload_time": "2019-08-09T15:07:53", "url": "https://files.pythonhosted.org/packages/16/12/9d99c7b462c92d24d60115347a46ba3c5afbca67efb0126ae75548d3d3f6/greengen-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ca59a26550cb94d3864f1f0819340218", "sha256": "16568936a550d00025a9fd8bc5c1fc15fe4d29d8e02e37746d28b806c94c4462" }, "downloads": -1, "filename": "greengen-1.0.1.tar.gz", "has_sig": false, "md5_digest": "ca59a26550cb94d3864f1f0819340218", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3167, "upload_time": "2019-08-09T15:07:55", "url": "https://files.pythonhosted.org/packages/5f/45/919ecfbfc017d385968a457f70ebf1af3043381d950337aa12722e332697/greengen-1.0.1.tar.gz" } ] }