Metadata-Version: 2.1
Name: greengen
Version: 1.0.1
Summary: Nesting generators using greenlets
Home-page: https://github.com/guylapid/greengen
Author: guylapid
License: UNKNOWN
Description: # Greengen
        Greengen is a python package that allows implementing generators without yielding items all the way up.
        Instead, any inner function called from a greengen generator, can yield items directly to the outer generator.
        ## Installation
        ```
        pip install greengen
        ```
        ## Usage
        For example, suppose we want to implement a function that performs some heavy business logic, and generates logs.
        We want to handle the logs the moment they are created.
        But our function has to call a deep stack of helper functions, which in their turn call more functions,
        and logs may be written anywhere inside any function.
        The implementation with regular generators will be utterly annoying:
        ```python
        import time
        
        
        def do_business_logic_and_yield_logs(some_input):
            yield from _helper_function(some_input)
            yield from _more_helper_function(some_input)
        
        
        def _helper_function(some_input):
            for i in range(some_input):
                logs_and_result = _inner_helper_function(i)
                # Notice the enormous effort needed in order to retrieve the last result (using StopIteration etc.)
                while True:
                    try:
                        yield next(logs_and_result)  # This is a log
                    except StopIteration as e:
                        result = e.value  # This is the result
                        yield log('Result for {} is {}'.format(i, result))
                        break
        
        
        def _more_helper_function(some_input):
            yield from _helper_function(some_input * 100)
            yield from _helper_function(some_input ** 2)
        
        
        def _inner_helper_function(some_input):
            yield log('Started calculating')
            result = 2 ** some_input  # (Or whatever other heavy calculation)
            yield log('Finished calculating')
            return result  # Will be raised as StopIteration
        
        
        def log(stuff):
            return {'message': str(stuff), 'timestamp': time.time()}
        
        
        def main():
            for l in do_business_logic_and_yield_logs(42):
                # Consume the logs however we want
                print('{}: {}'.format(l['timestamp'], l['message']))
        ```
        Using Greengen, this example can be simplified into the following:
        ```python
        import time
        import greengen
        
        @greengen.greengen
        def do_business_logic_and_yield_logs(some_input):
            # Notice how we don't need the "yield from" anymore
            _helper_function(some_input)
            _more_helper_function(some_input)
        
        
        def _helper_function(some_input):
            for i in range(some_input):
                # Notice how easy it is to retrieve the result now
                result = _inner_helper_function(i)
                log('Result for {} is {}'.format(i, result))
        
        
        def _more_helper_function(some_input):
            _helper_function(some_input * 100)
            _helper_function(some_input ** 2)
        
        
        def _inner_helper_function(some_input):
            log('Started calculating')
            result = 2 ** some_input  # (Or whatever other heavy calculation)
            log('Finished calculating')
            return result
        
        
        def log(stuff):
            # This is the only place in the entire code where we need to be aware of the fact that we are inside a generator.
            # This will directly yield the log as the next item in the outer generator ("do_business_logic_and_yield_logs")
            greengen.yield_({'message': str(stuff), 'timestamp': time.time()})
        
        
        def main():
            for l in do_business_logic_and_yield_logs(42):
                # Consume the logs however we want
                print('{}: {}'.format(l['timestamp'], l['message']))
        ```
        ## Contributing
        1. Fork it!
        2. Create your feature branch: `git checkout -b my-new-feature`
        3. Commit your changes: `git commit -am 'Add some feature'`
        4. Push to the branch: `git push origin my-new-feature`
        5. Submit a pull request :D
        ## History
        TODO: Write history
        ## Credits
        TODO: Write credits
        ## License
        TODO: Write license
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Description-Content-Type: text/markdown
