Grep Coroutines

Set Up

Imports

Python

from io import StringIO

PyPi

import requests

Constants

PRIDE_AND_PREJUDICE = "https://www.gutenberg.org/files/1342/1342-0.txt"

Grab the Source

response = requests.get(PRIDE_AND_PREJUDICE)
assert response.ok

Functions

Coroutine

def coroutine(function):
    """Sets up the co-routine

    Args:
     function: coroutine function

    Returns:
     wrapper futnction that starts the co-routine
    """
    def wrapper(*args, **kwargs):
        co_routine = function(*args, **kwargs)
        next(co_routine)
        return co_routine
    return wrapper

A Cat

def process(lines, receiver, case_insensitive: bool=True):
    """Sends the lines in the text to the receiver

    Args:
     text: iterable text lines
     receiver: thing to send lines to
     case_insensitive: whether to lowercase the lines
    """
    lines = StringIO(lines)
    if case_insensitive:
        processor = lambda line: line.lower()
    else:
        processor = lambda line: line

    for line in lines:
        receiver.send(processor(line))

GREP

@coroutine
def tokens(token, case_insensitive, receiver):
    """count tokens in the line"""
    if case_insensitive:
        token = token.lower()
    while True:
        text = (yield)
        receiver.send(text.count(token))

Count

@coroutine
def count(token):
    counter = 0
    try:
        while True:
            counter += (yield)
    except GeneratorExit:
        print(token, counter)
    return

Fanout

@coroutine
def fork(children):
    while True:
        data = (yield)
        for child in children:
            child.send(data)
    return

Try It

text = StringIO(response.content.decode("utf-8"))
process(text, tokens("feelings", True, count("feelings")))
feelings 86

text = StringIO(response.content.decode("utf-8"))
process(text, tokens("beauty", True, count("beauty")))
beauty 27

text = response.content.decode("utf-8")
process(text, tokens("cried", True, count("cried")))
cried 91