{ "info": { "author": "John-Paul Jorissen", "author_email": "jjorissen52@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: Microsoft :: Windows :: Windows 10", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3.6", "Topic :: Office/Business" ], "description": "# python-pipeline\n\nThis library allows users to easily wrap functions with a series of decorators to form \nan execution pipeline. \nThis is useful in scenarios where input needs to be cleaned and output needs to be processed in a systematic way.\n\n## Installation\n pip install execution-pipeline\n\n\n## Usage\nA pipeline consists of four optional segments\n### Pre\nThe `pre` execution segment allows you to modify any input parameters passed to the decorated function. Any functions \npassed to the `pre` segment will always be executed first.\n\n from pipeline import execution_pipeline\n\n def do_thing_before(params):\n params['arg1'] = 'okay'\n return params\n\n\n @execution_pipeline(pre=[do_thing_before])\n def do_thing(arg1=5):\n return arg1*10\n \n \n \n do_thing()\n # okayokayokayokayokayokayokayokayokayokay\n\n\n### Post\nThe `post` execution segment allows you to modify or handle the result after the decorated function has already run.\n\n def do_thing_after(response):\n response['added'] = 'yup'\n return response\n \n \n @execution_pipeline(post=[do_thing_after])\n def do_thing(**kwargs):\n return {**kwargs} # just make a new dictionary using the passed keyword arguments\n \n \n do_thing(apples=2, oranges=3, bananas=0)\n # {'apples': 2, 'oranges': 3, 'bananas': 0, 'added': 'yup'}\n \nJust like the other segments, you can use as many post processing functions as you need; they will be executed in the order\nthat they are passed.\n\n\n def do_another_thing_after(response):\n assert response['added'] == 'yup' # the one that is first in the pipeline happens first.\n response['also_added'] = 'also yup'\n return response\n \n \n @execution_pipeline(post=[do_thing_after, do_another_thing_after])\n def do_thing(**kwargs):\n return {**kwargs}\n \n \n do_thing()\n # {'apples': 2, 'oranges': 3, 'bananas': 0, 'added': 'yup', 'also_added': 'also yup'}\n \n### Error\nThe `error` execution segment allows you to pass error handling to log, modify, absorb, etc. any exceptions that are \nraised by the wrapped function.\n\n\n class MyException(BaseException):\n pass\n \n \n def handle_this_error(e, response=None):\n print(f\"oh no, Bob! {e}\")\n return \"Don't worry, we handled a TypeError.\"\n \n \n def handle_that_error(e, response=None):\n print(f\"oh no, Bob! {e}\")\n return \"Don't worry, we handled MyException.\"\n \n def handle_other_errors(e, response=None):\n print(f\"? {e}\")\n return \"Other errors?\"\n \n error_handlers = [\n {\"exception_class\": TypeError, \"handler\": handle_this_error},\n {\"exception_class\": MyException, \"handler\": handle_that_error},\n {\"exception_classes\": (Exception, BaseException), \"handler\": handle_other_errors},\n ]\n \n \n @execution_pipeline(pre=[do_thing_before], post=[do_thing_after], error=error_handlers)\n def fun_boys(arg1, arg4, arg2, arg3, thing=None):\n raise MyException('Something went wrong!')\n \n \n result = fun_boys(1, 2, 3, 4, 5)\n # oh no, Bob! Something went wrong!\n \n print(result) \n # Don't worry, we handled MyException.\n \nYou can also use class instances instead of dictionaries to define your error handlers if you prefer.\n\n```\nclass ErrorHandler:\n def __init__(self, exception_class, handler):\n self.exception_class = exception_class\n self.handler = handler\n \n\nerror_handlers = [\n ErrorHandler(TypeError, handle_this_error),\n ErrorHandler(MyException, handle_that_error),\n ]\n```\n \n### Cache\nThe `cache` execution segment will record all arguments (before and after the `pre` segment) and store the result \n(after the `post` and `error` segments). \n\n from pipeline.cache.mock import MockCache\n # MockCache is basically just a dict() with some expiration convenience methods.\n mock_cache = MockCache()\n \n changing_value = 0\n \n @execution_pipeline(cache=mock_cache)\n def fun_boys(arg1, arg4, arg2, arg3, thing=None):\n return changing_value\n \n \n \n fun_boys(1, 2, 3, 4, 5)\n # 0\n \n changing_value = 100\n \n \n fun_boys(1, 2, 3, 4, 5)\n # 0 # ignores the changes ( \u00af\\_(\u30c4)_/\u00af that's caching! ) \n \n#### Supported Cache Backends\nNote: if the appropriate backend is not installed, they will be replaced with a `MockCache` instance at runtime. This \nis intended to improve portability of pipeline code. \n\n##### Redis\n```\npip install redis\n```\nAnd then same as above except with\n\n from pipeline.cache.redis import RedisCache\n redis = RedisCache(host='localhost', port=6379) # defaults\n \n \n##### MemCached\n```\npip install memcached\n```\nAnd then the same as above except with\n\n from pipeline.cache.mem_cache import MemCache \n mem_cache = MemCache(host='localhost', port=11211) # defaults\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/jjorissen/python-pipeline", "keywords": "python decorators execution pipeline execution_pipeline caching error handling", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "execution-pipeline", "package_url": "https://pypi.org/project/execution-pipeline/", "platform": "", "project_url": "https://pypi.org/project/execution-pipeline/", "project_urls": { "Homepage": "https://bitbucket.org/jjorissen/python-pipeline" }, "release_url": "https://pypi.org/project/execution-pipeline/0.4.0/", "requires_dist": null, "requires_python": "", "summary": "This library allows users to easily wrap functions with a series of decorators.", "version": "0.4.0" }, "last_serial": 4823102, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "e727a9eeb121e8688cf780276b57b05c", "sha256": "5593556fa7542287fd81f14bf47743c0c1a2ddb630b7ebd21b084e7e2ff95992" }, "downloads": -1, "filename": "execution-pipeline-0.1.0.tar.gz", "has_sig": false, "md5_digest": "e727a9eeb121e8688cf780276b57b05c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6428, "upload_time": "2018-10-24T01:33:41", "url": "https://files.pythonhosted.org/packages/06/1c/87ba56fbe51cdc752a78c93d98481f98c4a2f06a6d7f4606f9d3e97ef151/execution-pipeline-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "df55ad8416a0aecfb10a0f9db5c22aa5", "sha256": "6c2c2997c6ba2f8f3ebe80c98b4a80a73ca334f657968a57162c547985c7511c" }, "downloads": -1, "filename": "execution-pipeline-0.2.0.tar.gz", "has_sig": false, "md5_digest": "df55ad8416a0aecfb10a0f9db5c22aa5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6664, "upload_time": "2019-01-04T18:20:42", "url": "https://files.pythonhosted.org/packages/2c/ae/04c2b59b5c6d500933d26934a45a8c2785ca386b2124fb4c787eeea40f0a/execution-pipeline-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "8466432e10bd0abd005f93aa514cf27e", "sha256": "0b75465415b286982f93ab1d9b79e5d00d626a8aa43956a8cb1a9b543e073069" }, "downloads": -1, "filename": "execution-pipeline-0.2.1.tar.gz", "has_sig": false, "md5_digest": "8466432e10bd0abd005f93aa514cf27e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7179, "upload_time": "2019-01-08T20:35:46", "url": "https://files.pythonhosted.org/packages/e5/7f/a8c000b255c6766ad282e8ad72b0cfe579d8d51326734d8c5f5def2ef871/execution-pipeline-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "a21b7e2bfcf6277a01979f4b4d746584", "sha256": "1b31710959b569148d29cee8b15b504e79bea4d2e33b0abbb4b16807b25da371" }, "downloads": -1, "filename": "execution-pipeline-0.3.0.tar.gz", "has_sig": false, "md5_digest": "a21b7e2bfcf6277a01979f4b4d746584", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10058, "upload_time": "2019-01-20T23:35:20", "url": "https://files.pythonhosted.org/packages/5b/fa/74b50b8e6dce34028c12a3a8e81f4ba7bcfc32ab768e4349a74d21af7e39/execution-pipeline-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "d09be3dd69b6a31a49dbc115339efd73", "sha256": "7e27b3efdb175ab3dfc2b36aa9a13520e9e072372dfbefc5bc5b198f4f939a37" }, "downloads": -1, "filename": "execution-pipeline-0.4.0.tar.gz", "has_sig": false, "md5_digest": "d09be3dd69b6a31a49dbc115339efd73", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10762, "upload_time": "2019-02-15T04:13:31", "url": "https://files.pythonhosted.org/packages/d0/ba/c3b544a616c96dd63452a713495586966abe5fa7594fabf6381a9ee5f885/execution-pipeline-0.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d09be3dd69b6a31a49dbc115339efd73", "sha256": "7e27b3efdb175ab3dfc2b36aa9a13520e9e072372dfbefc5bc5b198f4f939a37" }, "downloads": -1, "filename": "execution-pipeline-0.4.0.tar.gz", "has_sig": false, "md5_digest": "d09be3dd69b6a31a49dbc115339efd73", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10762, "upload_time": "2019-02-15T04:13:31", "url": "https://files.pythonhosted.org/packages/d0/ba/c3b544a616c96dd63452a713495586966abe5fa7594fabf6381a9ee5f885/execution-pipeline-0.4.0.tar.gz" } ] }