Passed
Push — master ( 0c68df...e3ee72 )
by Dongxin
01:27
created

NodeWalker   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 53
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 53
rs 10
wmc 12

5 Methods

Rating   Name   Duplication   Size   Complexity  
C __next__() 0 26 7
A nxt() 0 10 2
A __init__() 0 4 1
A __iter__() 0 2 1
A resume_at() 0 3 1
1
from __future__ import unicode_literals
2
3
import re
4
5
6
reContainer = re.compile(
7
    r'(document|block_quote|list|item|paragraph|'
8
    r'heading|emph|strong|link|image|'
9
    r'custom_inline|custom_block)')
10
11
12
def is_container(node):
13
    return (re.match(reContainer, node.t) is not None)
14
15
16
class NodeWalker(object):
17
18
    def __init__(self, root):
19
        self.current = root
20
        self.root = root
21
        self.entering = True
22
23
    def __next__(self):
24
        cur = self.current
25
        entering = self.entering
26
27
        if cur is None:
28
            raise StopIteration
29
30
        container = is_container(cur)
31
32
        if entering and container:
33
            if cur.first_child:
34
                self.current = cur.first_child
35
                self.entering = True
36
            else:
37
                # stay on node but exit
38
                self.entering = False
39
        elif cur == self.root:
40
            self.current = None
41
        elif cur.nxt is None:
42
            self.current = cur.parent
43
            self.entering = False
44
        else:
45
            self.current = cur.nxt
46
            self.entering = True
47
48
        return cur, entering
49
50
    next = __next__
51
52
    def __iter__(self):
53
        return self
54
55
    def nxt(self):
56
        """ for backwards compatibility """
57
        try:
58
            cur, entering = next(self)
59
            return {
60
                'entering': entering,
61
                'node': cur,
62
            }
63
        except StopIteration:
64
            return None
65
66
    def resume_at(self, node, entering):
67
        self.current = node
68
        self.entering = (entering is True)
69
70
71
class Node(object):
72
    def __init__(self, node_type, sourcepos):
73
        self.t = node_type
74
        self.parent = None
75
        self.first_child = None
76
        self.last_child = None
77
        self.prv = None
78
        self.nxt = None
79
        self.sourcepos = sourcepos
80
        self.last_line_blank = False
81
        self.is_open = True
82
        self.string_content = ''
83
        self.literal = None
84
        self.list_data = {}
85
        self.info = None
86
        self.destination = None
87
        self.title = None
88
        self.is_fenced = False
89
        self.fence_char = None
90
        self.fence_length = 0
91
        self.fence_offset = None
92
        self.level = None
93
        self.on_enter = None
94
        self.on_exit = None
95
96
    def __repr__(self):
97
        return "Node {} [{}]".format(self.t, self.literal)
98
99
    def pretty(self):
100
        from pprint import pprint
101
        pprint(self.__dict__)
102
103
    def is_container(self):
104
        return is_container(self)
105
106
    def append_child(self, child):
107
        child.unlink()
108
        child.parent = self
109
        if self.last_child:
110
            self.last_child.nxt = child
111
            child.prv = self.last_child
112
            self.last_child = child
113
        else:
114
            self.first_child = child
115
            self.last_child = child
116
117
    def prepend_child(self, child):
118
        child.unlink()
119
        child.parent = self
120
        if self.first_child:
121
            self.first_child.prv = child
122
            child.nxt = self.first_child
123
            self.first_child = child
124
        else:
125
            self.first_child = child
126
            self.last_child = child
127
128
    def unlink(self):
129
        if self.prv:
130
            self.prv.nxt = self.nxt
131
        elif self.parent:
132
            self.parent.first_child = self.nxt
133
134
        if self.nxt:
135
            self.nxt.prv = self.prv
136
        elif self.parent:
137
            self.parent.last_child = self.prv
138
139
        self.parent = None
140
        self.nxt = None
141
        self.prv = None
142
143
    def insert_after(self, sibling):
144
        sibling.unlink()
145
        sibling.nxt = self.nxt
146
        if sibling.nxt:
147
            sibling.nxt.prv = sibling
148
        sibling.prv = self
149
        self.nxt = sibling
150
        sibling.parent = self.parent
151
        if not sibling.nxt:
152
            sibling.parent.last_child = sibling
153
154
    def insert_before(self, sibling):
155
        sibling.unlink()
156
        sibling.prv = self.prv
157
        if sibling.prv:
158
            sibling.prv.nxt = sibling
159
        sibling.nxt = self
160
        self.prv = sibling
161
        sibling.parent = self.parent
162
        if not sibling.prv:
163
            sibling.parent.first_child = sibling
164
165
    def walker(self):
166
        return NodeWalker(self)
167