| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| from __future__ import absolute_import |
| from __future__ import print_function |
| from __future__ import unicode_literals |
|
|
|
|
| class STARTEVENT: |
| pass |
|
|
|
|
| class ENDEVENT: |
| pass |
|
|
|
|
| def prefix_event(level_prefixed_items, root_item=None): |
| ''' convert iterable of (level, item) into iterable of (event, item) |
| ''' |
| baselevel = None |
| stack = [root_item] |
| for level, item in level_prefixed_items: |
| if baselevel is None: |
| baselevel = level |
| level = 0 |
| else: |
| level -= baselevel |
|
|
| while level + 1 < len(stack): |
| yield ENDEVENT, stack.pop() |
| while len(stack) < level + 1: |
| raise Exception('invalid level: %d, %d, %s' % |
| (level, len(stack) - 1, item)) |
| assert(len(stack) == level + 1) |
|
|
| stack.append(item) |
| yield STARTEVENT, item |
|
|
| while 1 < len(stack): |
| yield ENDEVENT, stack.pop() |
|
|
|
|
| def prefix_ancestors(event_prefixed_items, root_item=None): |
| ''' convert iterable of (event, item) into iterable of (ancestors, item) |
| ''' |
| stack = [root_item] |
| for event, item in event_prefixed_items: |
| if event is STARTEVENT: |
| yield stack, item |
| stack.append(item) |
| elif event is ENDEVENT: |
| stack.pop() |
|
|
|
|
| def prefix_ancestors_from_level(level_prefixed_items, root_item=None): |
| ''' convert iterable of (level, item) into iterable of (ancestors, item) |
| |
| @param level_prefixed items: iterable of tuple(level, item) |
| @return iterable of tuple(ancestors, item) |
| ''' |
| baselevel = None |
| stack = [root_item] |
| for level, item in level_prefixed_items: |
| if baselevel is None: |
| baselevel = level |
| level = 0 |
| else: |
| level -= baselevel |
|
|
| while level + 1 < len(stack): |
| stack.pop() |
| while len(stack) < level + 1: |
| raise Exception('invalid level: %d, %d, %s' % |
| (level, len(stack) - 1, item)) |
| assert(len(stack) == level + 1) |
|
|
| yield stack, item |
| stack.append(item) |
|
|
|
|
| def build_subtree(event_prefixed_items): |
| ''' build a tree from (event, item) stream |
| |
| Example Scenario:: |
| |
| ... |
| (STARTEVENT, rootitem) # should be consumed by the caller |
| --- call build_subtree() --- |
| (STARTEVENT, child1) # consumed by build_subtree() |
| (STARTEVENT, grandchild) # (same) |
| (ENDEVENT, grandchild) # (same) |
| (ENDEVENT, child1) # (same) |
| (STARTEVENT, child2) # (same) |
| (ENDEVENT, child2) # (same) |
| (ENDEVENT, rootitem) # same, buildsubtree() returns |
| --- build_subtree() returns --- |
| (STARTEVENT, another_root) |
| ... |
| |
| result will be (rootitem, [(child1, [(grandchild, [])]), |
| (child2, [])]) |
| |
| ''' |
| childs = [] |
| for event, item in event_prefixed_items: |
| if event == STARTEVENT: |
| childs.append(build_subtree(event_prefixed_items)) |
| elif event == ENDEVENT: |
| return item, childs |
|
|
|
|
| def iter_subevents(event_prefixed_items): |
| level = 0 |
| for event, item in event_prefixed_items: |
| yield event, item |
| if event is STARTEVENT: |
| level += 1 |
| elif event is ENDEVENT: |
| if level > 0: |
| level -= 1 |
| else: |
| return |
|
|
|
|
| def tree_events(rootitem, childs): |
| ''' generate tuples of (event, item) from a tree |
| ''' |
| yield STARTEVENT, rootitem |
| for k in tree_events_multi(childs): |
| yield k |
| yield ENDEVENT, rootitem |
|
|
|
|
| def tree_events_multi(trees): |
| ''' generate tuples of (event, item) from trees |
| ''' |
| for rootitem, childs in trees: |
| for k in tree_events(rootitem, childs): |
| yield k |
|
|