Metadata-Version: 2.1
Name: execution-pipeline
Version: 0.5.0
Summary: This library allows users to easily wrap functions with a series of decorators.
Home-page: https://bitbucket.org/jjorissen/python-pipeline
Author: John-Paul Jorissen
Author-email: jjorissen52@gmail.com
License: MIT
Description: # python-pipeline
        
        This library allows users to easily wrap functions with a series of decorators to form 
        an execution pipeline. 
        This is useful in scenarios where input needs to be cleaned and output needs to be processed in a systematic way.
        
        ## Installation
            pip install execution-pipeline
        
        
        ## Usage
        A pipeline consists of four optional segments
        ### Pre
        The `pre` execution segment allows you to modify any input parameters passed to the decorated function. Any functions 
        passed to the `pre` segment will always be executed first.
        ```python
        from pipeline import execution_pipeline
        
        def do_thing_before(params):
            params['arg1'] = 'okay'
            return params
        
        
        @execution_pipeline(pre=[do_thing_before])
        def do_thing(arg1=5):
            return arg1*10
         
        
        
        do_thing()
        # okayokayokayokayokayokayokayokayokayokay
        ```
        
        ### Post
        The `post` execution segment allows you to modify or handle the result after the decorated function has already run.
        ```python
        def do_thing_after(response):
            response['added'] = 'yup'
            return response
                
        @execution_pipeline(post=[do_thing_after])
        def do_thing(**kwargs):
            return {**kwargs}  # just make a new dictionary using the passed keyword arguments
            
            
        do_thing(apples=2, oranges=3, bananas=0)
         # {'apples': 2, 'oranges': 3, 'bananas': 0, 'added': 'yup'}
        ```
            
             
        Just like the other segments, you can use as many post processing functions as you need; they will be executed in the order
        that they are passed.
        
        ```python
        def do_another_thing_after(response):
            assert response['added'] == 'yup' # the one that is first in the pipeline happens first.
            response['also_added'] = 'also yup'
            return response
            
            
        @execution_pipeline(post=[do_thing_after, do_another_thing_after])
        def do_thing(**kwargs):
            return {**kwargs}
            
         
        do_thing()
        # {'apples': 2, 'oranges': 3, 'bananas': 0, 'added': 'yup', 'also_added': 'also yup'}
        ```  
                
        ### Error
        The `error` execution segment allows you to pass error handling to log, modify, absorb, etc. any exceptions that are 
        raised by the wrapped function.
        
        ```python
        class MyException(BaseException):
            pass
            
        
        def handle_this_error(e, response=None):
            print(f"oh no, Bob! {e}")
            return "Don't worry, we handled a TypeError."
        
        
        def handle_that_error(e, response=None):
            print(f"oh no, Bob! {e}")
            return "Don't worry, we handled MyException."
            
        def handle_other_errors(e, response=None):
            print(f"? {e}")
            return "Other errors?"
            
        error_handlers = [
            {"exception_class": TypeError, "handler": handle_this_error},
            {"exception_class": MyException, "handler": handle_that_error},
            {"exception_classes": (Exception, BaseException), "handler": handle_other_errors},
        ]
        
        
        @execution_pipeline(pre=[do_thing_before], post=[do_thing_after], error=error_handlers)
        def fun_boys(arg1, arg4, arg2, arg3, thing=None):
            raise MyException('Something went wrong!')
            
        
        result = fun_boys(1, 2, 3, 4, 5)
        # oh no, Bob! Something went wrong!
        
        print(result) 
        # Don't worry, we handled MyException.
        ```
            
        You can also use class instances instead of dictionaries to define your error handlers if you prefer.
        
        ```python
        class ErrorHandler:
            def __init__(self, exception_class, handler):
                self.exception_class = exception_class
                self.handler = handler
                
        
        error_handlers = [
            ErrorHandler(TypeError, handle_this_error),
            ErrorHandler(MyException, handle_that_error),
        ]
        ```
            
        ### Cache
        The `cache` execution segment will record all arguments (before and after the `pre` segment) and store the result 
        (after the `post` and `error` segments). 
        ```python
        from pipeline.cache.mock import MockCache
        # MockCache is basically just a dict() with some expiration convenience methods.
        mock_cache = MockCache()
        
        changing_value = 0
        
        @execution_pipeline(cache=mock_cache)
        def fun_boys(arg1, arg4, arg2, arg3, thing=None):
            return changing_value
            
        
            
        fun_boys(1, 2, 3, 4, 5)
        # 0
        
        changing_value = 100
        
        
        fun_boys(1, 2, 3, 4, 5)
        # 0 # ignores the changes ( ¯\_(ツ)_/¯ that's caching! )
        ```
                
        #### Supported Cache Backends
        Note: if the appropriate backend is not installed, they will be replaced with a `MockCache` instance at runtime. This 
        is intended to improve portability of pipeline code. 
        
        ##### Redis
        ```bash
        pip install redis
        ```
        And then same as above except with
        ```python
        from pipeline.cache.redis import RedisCache
        redis = RedisCache(host='localhost', port=6379) # defaults
        ```
          
            
        ##### MemCached
        ```bash
        pip install memcached
        ```
        And then the same as above except with
        
            from pipeline.cache.mem_cache import MemCache 
            mem_cache = MemCache(host='localhost', port=11211) # defaults
        
        
Keywords: python decorators execution pipeline execution_pipeline caching error handling
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Office/Business
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.6
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: memcache
Provides-Extra: redis
