2 from functools import wraps
7 Wraps a generator which intended to be used as a pure coroutine by
8 .send()ing it values. The only thing that the wrapper does is calling
9 .next() for the first time which is required by Python generator protocol.
12 def wrapper(*args, **kwargs):
13 g = func(*args, **kwargs)
19 def foreach(coroutine_func):
21 Dispatches each JSON array item to a handler coroutine. A coroutine is
22 created anew for each item by calling `coroutine_func` callable. The
23 resulting coroutine should accept value in the form of tuple of values
24 generated by rich JSON parser: (prefix, event, value).
26 First event received by foreach should be a "start_array" event.
29 base, event, value = yield
30 if event != 'start_array':
31 raise Exception('foreach requires "start_array" as the first event, got %s' % repr((base, event, value)))
32 START_EVENTS = set(['start_map', 'start_array', 'null', 'boolean', 'number', 'string'])
33 itemprefix = base + '.item' if base else 'item'
35 prefix, event, value = yield
36 if prefix == itemprefix and event in START_EVENTS:
38 if (prefix, event) != (base, 'end_array'):
39 g.send((prefix, event, value))
42 def dispatcher(targets):
44 Dispatches JSON parser events into several handlers depending on event
47 Accepts a list of tuples (base_prefix, coroutine). A coroutine then
48 receives all the events with prefixes starting with its base_prefix.
51 prefix, event, value = yield
52 for base, target in targets:
53 if prefix.startswith(base):
54 target.send((prefix, event, value))