Source code for translate.coroutines
# -*- coding: utf-8 -*-
"""
coroutines
~~~~~~~~~~
All functions definied within this file are essentially coroutines or
helper functions for working with coroutines.
Therefore members follow the coroutine pattern either as consumers, producers or
consumer/producers
"""
from __future__ import print_function
import sys
import operator
from functools import wraps, partial, reduce
from concurrent.futures import ThreadPoolExecutor
__all__ = 'coroutine', 'spool', 'source', 'set_task', 'write_stream', 'accumulator'
[docs]def coroutine(func):
"""
Initializes coroutine essentially priming it to the yield statement.
Used as a decorator over functions that generate coroutines.
.. code-block:: python
# Basic coroutine producer/consumer pattern
from translate import coroutine
@coroutine
def coroutine_foo(bar):
try:
while True:
baz = (yield)
bar.send(baz)
except GeneratorExit:
bar.close()
:param func: Unprimed Generator
:type func: Function
:return: Initialized Coroutine
:rtype: Function
"""
@wraps(func)
def initialization(*args, **kwargs):
start = func(*args, **kwargs)
next(start)
return start
return initialization
[docs]def accumulator(init, update):
"""
Generic accumulator function.
:param init: Initial Value
:param update: Value to accumulate
:return: Combined Values
"""
return (
init + len(update)
if isinstance(init, int) else
init + update
)
[docs]def write_stream(script, output='trans'):
"""
:param script: Translated Text
:type script: Iterable
:return None:
"""
first = operator.itemgetter(0)
sentence = script.get('sentences', None)
output = output if first(sentence).get(output, None) else 'trans'
printer = partial(print, file=sys.stdout, end='')
assert output in first(sentence)
for line in sentence:
if isinstance(line[output], str):
printer(line[output])
else:
printer(line[output].encode('UTF-8'))
printer('\n')
return sys.stdout.flush()
# TODO: Get rid of all this context crap
@coroutine
[docs]def set_task(translator, translit=False):
"""
Task Setter Coroutine
End point destination coroutine of a purely consumer type.
Delegates Text IO to the `write_stream` function.
:param translation_function: Translator
:type translation_function: Function
:param translit: Transliteration Switch
:type: Bool
"""
# Initialize Task Queue
task = str()
queue = list()
# Function Partial
output = ('translit' if translit else 'trans')
stream = partial(write_stream, output=output)
workers = ThreadPoolExecutor(max_workers=8)
try:
while True:
task = yield
queue.append(task)
except GeneratorExit:
list(map(stream, workers.map(translator, queue)))
@coroutine
[docs]def spool(iterable, maxlen=1250):
"""
Consumes text streams and spools them together for more io
efficient processes.
:param iterable: Sends text stream for further processing
:type iterable: Coroutine
:param maxlen: Maximum query string size
:type maxlen: Integer
"""
words = int()
text = str()
try:
while True:
while words < maxlen:
stream = yield
text = reduce(accumulator, stream, text)
words = reduce(accumulator, stream, words)
iterable.send(text)
words = int()
text = str()
except GeneratorExit:
iterable.send(text)
iterable.close()
[docs]def source(target, inputstream=sys.stdin):
"""
Coroutine starting point. Produces text stream and forwards to consumers
:param target: Target coroutine consumer
:type target: Coroutine
"""
for line in inputstream:
while len(line) > 600:
init, sep, line = line.partition(' ')
assert len(init) <= 600
target.send(''.join([init, sep]))
target.send(line)
inputstream.close()
return target.close()