import of github code used for the hackathon
[github-barcamp-201407] / ijson-1.1 / ijson / utils.py
1 # -*- coding:utf-8 -*-
2 from functools import wraps
3
4
5 def coroutine(func):
6     '''
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.
10     '''
11     @wraps(func)
12     def wrapper(*args, **kwargs):
13         g = func(*args, **kwargs)
14         next(g)
15         return g
16     return wrapper
17
18 @coroutine
19 def foreach(coroutine_func):
20     '''
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).
25
26     First event received by foreach should be a "start_array" event.
27     '''
28     g = None
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'
34     while True:
35         prefix, event, value = yield
36         if prefix == itemprefix and event in START_EVENTS:
37             g = coroutine_func()
38         if (prefix, event) != (base, 'end_array'):
39             g.send((prefix, event, value))
40
41 @coroutine
42 def dispatcher(targets):
43     '''
44     Dispatches JSON parser events into several handlers depending on event
45     prefixes.
46
47     Accepts a list of tuples (base_prefix, coroutine). A coroutine then
48     receives all the events with prefixes starting with its base_prefix.
49     '''
50     while True:
51         prefix, event, value = yield
52         for base, target in targets:
53             if prefix.startswith(base):
54                 target.send((prefix, event, value))
55                 break

Benjamin Mako Hill || Want to submit a patch?