cython

Форк
0
/
StringIOTree.py 
170 строк · 5.4 Кб
1
r"""
2
Implements a buffer with insertion points. When you know you need to
3
"get back" to a place and write more later, simply call insertion_point()
4
at that spot and get a new StringIOTree object that is "left behind".
5

6
EXAMPLE:
7

8
>>> a = StringIOTree()
9
>>> _= a.write('first\n')
10
>>> b = a.insertion_point()
11
>>> _= a.write('third\n')
12
>>> _= b.write('second\n')
13
>>> a.getvalue().split()
14
['first', 'second', 'third']
15

16
>>> c = b.insertion_point()
17
>>> d = c.insertion_point()
18
>>> _= d.write('alpha\n')
19
>>> _= b.write('gamma\n')
20
>>> _= c.write('beta\n')
21
>>> b.getvalue().split()
22
['second', 'alpha', 'beta', 'gamma']
23

24
>>> try: from cStringIO import StringIO
25
... except ImportError: from io import StringIO
26

27
>>> i = StringIOTree()
28
>>> d.insert(i)
29
>>> _= i.write('inserted\n')
30
>>> out = StringIO()
31
>>> a.copyto(out)
32
>>> out.getvalue().split()
33
['first', 'second', 'alpha', 'inserted', 'beta', 'gamma', 'third']
34
"""
35

36

37
from io import StringIO
38

39

40
class StringIOTree:
41
    """
42
    See module docs.
43
    """
44

45
    def __init__(self, stream=None):
46
        self.prepended_children = []
47
        if stream is None:
48
            stream = StringIO()
49
        self.stream = stream
50
        self.write = stream.write
51
        self.markers = []
52

53
    def empty(self):
54
        if self.stream.tell():
55
            return False
56
        return all([child.empty() for child in self.prepended_children]) if self.prepended_children else True
57

58
    def getvalue(self):
59
        content = []
60
        self._collect_in(content)
61
        return "".join(content)
62

63
    def _collect_in(self, target_list):
64
        x: StringIOTree
65
        for x in self.prepended_children:
66
            x._collect_in(target_list)
67
        stream_content = self.stream.getvalue()
68
        if stream_content:
69
            target_list.append(stream_content)
70

71
    def copyto(self, target):
72
        """Potentially cheaper than getvalue as no string concatenation
73
        needs to happen."""
74
        child: StringIOTree
75
        for child in self.prepended_children:
76
            child.copyto(target)
77
        stream_content = self.stream.getvalue()
78
        if stream_content:
79
            target.write(stream_content)
80

81
    def commit(self):
82
        # Save what we have written until now so that the buffer
83
        # itself is empty -- this makes it ready for insertion
84
        if self.stream.tell():
85
            self.prepended_children.append(StringIOTree(self.stream))
86
            self.prepended_children[-1].markers = self.markers
87
            self.markers = []
88
            self.stream = StringIO()
89
            self.write = self.stream.write
90

91
    def reset(self):
92
        self.prepended_children = []
93
        self.markers = []
94
        self.stream = StringIO()
95
        self.write = self.stream.write
96

97
    def insert(self, iotree):
98
        """
99
        Insert a StringIOTree (and all of its contents) at this location.
100
        Further writing to self appears after what is inserted.
101
        """
102
        self.commit()
103
        self.prepended_children.append(iotree)
104

105
    def insertion_point(self):
106
        """
107
        Returns a new StringIOTree, which is left behind at the current position
108
        (it what is written to the result will appear right before whatever is
109
        next written to self).
110

111
        Calling getvalue() or copyto() on the result will only return the
112
        contents written to it.
113
        """
114
        # Save what we have written until now
115
        # This is so that getvalue on the result doesn't include it.
116
        self.commit()
117
        # Construct the new forked object to return
118
        other = StringIOTree()
119
        self.prepended_children.append(other)
120
        return other
121

122
    def allmarkers(self):
123
        c: StringIOTree
124
        children = self.prepended_children
125
        return [m for c in children for m in c.allmarkers()] + self.markers
126

127
    """
128
    # Print the result of allmarkers in a nice human-readable form. Use it only for debugging.
129
    # Prints e.g.
130
    # /path/to/source.pyx:
131
    #     cython line 2 maps to 3299-3343
132
    #     cython line 4 maps to 2236-2245  2306  3188-3201
133
    # /path/to/othersource.pyx:
134
    #     cython line 3 maps to 1234-1270
135
    # ...
136
    # Note: In the example above, 3343 maps to line 2, 3344 does not.
137
    def print_hr_allmarkers(self):
138
        from collections import defaultdict
139
        markers = self.allmarkers()
140
        totmap = defaultdict(lambda: defaultdict(list))
141
        for c_lineno, (cython_desc, cython_lineno) in enumerate(markers):
142
            if cython_lineno > 0 and cython_desc.filename is not None:
143
                totmap[cython_desc.filename][cython_lineno].append(c_lineno + 1)
144
        reprstr = ""
145
        if totmap == 0:
146
            reprstr += "allmarkers is empty\n"
147
        try:
148
            sorted(totmap.items())
149
        except:
150
            print(totmap)
151
            print(totmap.items())
152
        for cython_path, filemap in sorted(totmap.items()):
153
            reprstr += cython_path + ":\n"
154
            for cython_lineno, c_linenos in sorted(filemap.items()):
155
                reprstr += "\tcython line " + str(cython_lineno) + " maps to "
156
                i = 0
157
                while i < len(c_linenos):
158
                    reprstr += str(c_linenos[i])
159
                    flag = False
160
                    while i+1 < len(c_linenos) and c_linenos[i+1] == c_linenos[i]+1:
161
                        i += 1
162
                        flag = True
163
                    if flag:
164
                        reprstr += "-" + str(c_linenos[i]) + " "
165
                    i += 1
166
                reprstr += "\n"
167

168
        import sys
169
        sys.stdout.write(reprstr)
170
    """
171

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.