/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005 Canonical Ltd
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
2
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1553.5.6 by Martin Pool
Clean up comments
16
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
17
# \subsection{\emph{rio} - simple text metaformat}
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
18
#
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
19
# \emph{r} stands for `restricted', `reproducible', or `rfc822-like'.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
20
#
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
21
# The stored data consists of a series of \emph{stanzas}, each of which contains
22
# \emph{fields} identified by an ascii name, with Unicode or string contents.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
23
# The field tag is constrained to alphanumeric characters.
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
24
# There may be more than one field in a stanza with the same name.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
25
#
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
26
# The format itself does not deal with character encoding issues, though
27
# the result will normally be written in Unicode.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
28
#
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
29
# The format is intended to be simple enough that there is exactly one character
30
# stream representation of an object and vice versa, and that this relation
31
# will continue to hold for future versions of bzr.
32
33
import re
34
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
35
from . import osutils
36
from .iterablefile import IterableFile
1534.10.2 by Aaron Bentley
Implemented rio_file to produce a light file object from stanzas
37
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
38
# XXX: some redundancy is allowing to write stanzas in isolation as well as
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
39
# through a writer object.
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
40
7143.15.2 by Jelmer Vernooij
Run autopep8.
41
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
42
class RioWriter(object):
7045.1.15 by Jelmer Vernooij
fix version info tests
43
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
44
    def __init__(self, to_file):
45
        self._soft_nl = False
46
        self._to_file = to_file
47
48
    def write_stanza(self, stanza):
49
        if self._soft_nl:
6926.2.15 by Jelmer Vernooij
Fix some tests.
50
            self._to_file.write(b'\n')
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
51
        stanza.write(self._to_file)
52
        self._soft_nl = True
53
54
55
class RioReader(object):
56
    """Read stanzas from a file as a sequence
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
57
58
    to_file can be anything that can be enumerated as a sequence of
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
59
    lines (with newlines.)
60
    """
7143.15.2 by Jelmer Vernooij
Run autopep8.
61
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
62
    def __init__(self, from_file):
63
        self._from_file = from_file
64
65
    def __iter__(self):
66
        while True:
67
            s = read_stanza(self._from_file)
68
            if s is None:
69
                break
70
            else:
71
                yield s
72
1534.10.2 by Aaron Bentley
Implemented rio_file to produce a light file object from stanzas
73
74
def rio_file(stanzas, header=None):
75
    """Produce a rio IterableFile from an iterable of stanzas"""
76
    def str_iter():
77
        if header is not None:
6677.1.1 by Martin
Go back to native str for urls and many other py3 changes
78
            yield header + b'\n'
1534.10.2 by Aaron Bentley
Implemented rio_file to produce a light file object from stanzas
79
        first_stanza = True
80
        for s in stanzas:
81
            if first_stanza is not True:
6677.1.1 by Martin
Go back to native str for urls and many other py3 changes
82
                yield b'\n'
1534.10.2 by Aaron Bentley
Implemented rio_file to produce a light file object from stanzas
83
            for line in s.to_lines():
84
                yield line
85
            first_stanza = False
86
    return IterableFile(str_iter())
87
88
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
89
def read_stanzas(from_file):
7045.1.15 by Jelmer Vernooij
fix version info tests
90
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
91
    while True:
92
        s = read_stanza(from_file)
93
        if s is None:
94
            break
7045.1.21 by Jelmer Vernooij
Review comments & test fixes.
95
        yield s
7045.1.15 by Jelmer Vernooij
fix version info tests
96
97
98
def read_stanzas_unicode(from_file):
99
100
    while True:
101
        s = read_stanza_unicode(from_file)
102
        if s is None:
103
            break
7045.1.21 by Jelmer Vernooij
Review comments & test fixes.
104
        yield s
7045.1.15 by Jelmer Vernooij
fix version info tests
105
106
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
107
class Stanza(object):
108
    """One stanza for rio.
109
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
110
    Each stanza contains a set of named fields.
111
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
112
    Names must be non-empty ascii alphanumeric plus _.  Names can be repeated
113
    within a stanza.  Names are case-sensitive.  The ordering of fields is
114
    preserved.
115
116
    Each field value must be either an int or a string.
117
    """
118
119
    __slots__ = ['items']
120
121
    def __init__(self, **kwargs):
122
        """Construct a new Stanza.
123
124
        The keyword arguments, if any, are added in sorted order to the stanza.
125
        """
126
        self.items = []
127
        if kwargs:
128
            for tag, value in sorted(kwargs.items()):
129
                self.add(tag, value)
130
131
    def add(self, tag, value):
132
        """Append a name and value to the stanza."""
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
133
        if not valid_tag(tag):
134
            raise ValueError("invalid tag %r" % (tag,))
6677.1.1 by Martin
Go back to native str for urls and many other py3 changes
135
        if isinstance(value, bytes):
136
            value = value.decode('ascii')
7479.2.1 by Jelmer Vernooij
Drop python2 support.
137
        elif isinstance(value, str):
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
138
            pass
139
        else:
1553.5.7 by Martin Pool
rio.Stanza.add should raise TypeError on invalid types.
140
            raise TypeError("invalid type for rio value: %r of type %s"
141
                            % (value, type(value)))
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
142
        self.items.append((tag, value))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
143
4354.3.3 by Jelmer Vernooij
More performance tweaks.
144
    @classmethod
145
    def from_pairs(cls, pairs):
146
        ret = cls()
147
        ret.items = pairs
148
        return ret
149
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
150
    def __contains__(self, find_tag):
151
        """True if there is any field in this stanza with the given tag."""
152
        for tag, value in self.items:
153
            if tag == find_tag:
154
                return True
155
        return False
156
157
    def __len__(self):
158
        """Return number of pairs in the stanza."""
159
        return len(self.items)
160
161
    def __eq__(self, other):
162
        if not isinstance(other, Stanza):
163
            return False
164
        return self.items == other.items
165
166
    def __ne__(self, other):
167
        return not self.__eq__(other)
168
169
    def __repr__(self):
170
        return "Stanza(%r)" % self.items
171
172
    def iter_pairs(self):
173
        """Return iterator of tag, value pairs."""
174
        return iter(self.items)
175
176
    def to_lines(self):
1553.5.32 by Martin Pool
rio files are always externalized in utf-8. test this.
177
        """Generate sequence of lines for external version of this file.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
178
1553.5.32 by Martin Pool
rio files are always externalized in utf-8. test this.
179
        The lines are always utf-8 encoded strings.
180
        """
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
181
        if not self.items:
182
            # max() complains if sequence is empty
183
            return []
184
        result = []
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
185
        for text_tag, text_value in self.items:
186
            tag = text_tag.encode('ascii')
7490.74.1 by Jelmer Vernooij
Use surrogateescape in rio.
187
            value = text_value.encode('utf-8', 'surrogateescape')
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
188
            if value == b'':
189
                result.append(tag + b': \n')
190
            elif b'\n' in value:
1185.47.2 by Martin Pool
Finish rio format and tests.
191
                # don't want splitlines behaviour on empty lines
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
192
                val_lines = value.split(b'\n')
193
                result.append(tag + b': ' + val_lines[0] + b'\n')
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
194
                for line in val_lines[1:]:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
195
                    result.append(b'\t' + line + b'\n')
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
196
            else:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
197
                result.append(tag + b': ' + value + b'\n')
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
198
        return result
199
200
    def to_string(self):
201
        """Return stanza as a single string"""
6677.1.1 by Martin
Go back to native str for urls and many other py3 changes
202
        return b''.join(self.to_lines())
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
203
2030.1.1 by John Arbash Meinel
Make it easier to nest Stanzas with Unicode contents
204
    def to_unicode(self):
205
        """Return stanza as a single Unicode string.
206
207
        This is most useful when adding a Stanza to a parent Stanza
208
        """
209
        if not self.items:
210
            return u''
211
212
        result = []
213
        for tag, value in self.items:
4354.3.3 by Jelmer Vernooij
More performance tweaks.
214
            if value == u'':
215
                result.append(tag + u': \n')
216
            elif u'\n' in value:
2030.1.1 by John Arbash Meinel
Make it easier to nest Stanzas with Unicode contents
217
                # don't want splitlines behaviour on empty lines
4354.3.3 by Jelmer Vernooij
More performance tweaks.
218
                val_lines = value.split(u'\n')
219
                result.append(tag + u': ' + val_lines[0] + u'\n')
2030.1.1 by John Arbash Meinel
Make it easier to nest Stanzas with Unicode contents
220
                for line in val_lines[1:]:
4354.3.3 by Jelmer Vernooij
More performance tweaks.
221
                    result.append(u'\t' + line + u'\n')
2030.1.1 by John Arbash Meinel
Make it easier to nest Stanzas with Unicode contents
222
            else:
4354.3.3 by Jelmer Vernooij
More performance tweaks.
223
                result.append(tag + u': ' + value + u'\n')
2030.1.1 by John Arbash Meinel
Make it easier to nest Stanzas with Unicode contents
224
        return u''.join(result)
225
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
226
    def write(self, to_file):
227
        """Write stanza to a file"""
228
        to_file.writelines(self.to_lines())
229
230
    def get(self, tag):
231
        """Return the value for a field wih given tag.
232
233
        If there is more than one value, only the first is returned.  If the
234
        tag is not present, KeyError is raised.
235
        """
236
        for t, v in self.items:
237
            if t == tag:
238
                return v
239
        else:
240
            raise KeyError(tag)
241
242
    __getitem__ = get
243
244
    def get_all(self, tag):
245
        r = []
246
        for t, v in self.items:
247
            if t == tag:
248
                r.append(v)
249
        return r
1553.5.8 by Martin Pool
New Rio.as_dict method
250
251
    def as_dict(self):
252
        """Return a dict containing the unique values of the stanza.
253
        """
254
        d = {}
255
        for tag, value in self.items:
256
            d[tag] = value
257
        return d
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
258
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
259
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
260
def valid_tag(tag):
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
261
    return _valid_tag(tag)
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
262
263
264
def read_stanza(line_iter):
265
    """Return new Stanza read from list of lines or a file
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
266
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
267
    Returns one Stanza that was read, or returns None at end of file.  If a
268
    blank line follows the stanza, it is consumed.  It's not an error for
269
    there to be no blank at end of file.  If there is a blank file at the
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
270
    start of the input this is really an empty stanza and that is returned.
1185.47.2 by Martin Pool
Finish rio format and tests.
271
272
    Only the stanza lines and the trailing blank (if any) are consumed
273
    from the line_iter.
1553.5.32 by Martin Pool
rio files are always externalized in utf-8. test this.
274
275
    The raw lines must be in utf-8 encoding.
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
276
    """
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
277
    return _read_stanza_utf8(line_iter)
2030.1.5 by John Arbash Meinel
Create a 'read_stanza_unicode' to handle unicode processing
278
279
280
def read_stanza_unicode(unicode_iter):
281
    """Read a Stanza from a list of lines or a file.
282
283
    The lines should already be in unicode form. This returns a single
284
    stanza that was read. If there is a blank line at the end of the Stanza,
285
    it is consumed. It is not an error for there to be no blank line at
286
    the end of the iterable. If there is a blank line at the beginning,
287
    this is treated as an empty Stanza and None is returned.
288
289
    Only the stanza lines and the trailing blank (if any) are consumed
290
    from the unicode_iter
291
292
    :param unicode_iter: A iterable, yeilding Unicode strings. See read_stanza
293
        if you have a utf-8 encoded string.
294
    :return: A Stanza object if there are any lines in the file.
295
        None otherwise
296
    """
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
297
    return _read_stanza_unicode(unicode_iter)
1551.12.38 by Aaron Bentley
Add docs for MergeDirective and RIO-patch functions
298
299
1551.12.10 by Aaron Bentley
Reduce max width to 72
300
def to_patch_lines(stanza, max_width=72):
1551.12.38 by Aaron Bentley
Add docs for MergeDirective and RIO-patch functions
301
    """Convert a stanza into RIO-Patch format lines.
302
303
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
304
    It resists common forms of damage such as newline conversion or the removal
305
    of trailing whitespace, yet is also reasonably easy to read.
306
307
    :param max_width: The maximum number of characters per physical line.
308
    :return: a list of lines
309
    """
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
310
    if max_width <= 6:
311
        raise ValueError(max_width)
1551.12.10 by Aaron Bentley
Reduce max width to 72
312
    max_rio_width = max_width - 4
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
313
    lines = []
314
    for pline in stanza.to_lines():
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
315
        for line in pline.split(b'\n')[:-1]:
316
            line = re.sub(b'\\\\', b'\\\\\\\\', line)
1551.12.9 by Aaron Bentley
force patch-rio to 76 characters
317
            while len(line) > 0:
1551.12.10 by Aaron Bentley
Reduce max width to 72
318
                partline = line[:max_rio_width]
319
                line = line[max_rio_width:]
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
320
                if len(line) > 0 and line[:1] != [b' ']:
1551.12.21 by Aaron Bentley
Patch-RIO does line breaks in slightly more readable places
321
                    break_index = -1
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
322
                    break_index = partline.rfind(b' ', -20)
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
323
                    if break_index < 3:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
324
                        break_index = partline.rfind(b'-', -20)
1551.12.21 by Aaron Bentley
Patch-RIO does line breaks in slightly more readable places
325
                        break_index += 1
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
326
                    if break_index < 3:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
327
                        break_index = partline.rfind(b'/', -20)
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
328
                    if break_index >= 3:
1551.12.21 by Aaron Bentley
Patch-RIO does line breaks in slightly more readable places
329
                        line = partline[break_index:] + line
330
                        partline = partline[:break_index]
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
331
                if len(line) > 0:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
332
                    line = b'  ' + line
333
                partline = re.sub(b'\r', b'\\\\r', partline)
1551.12.11 by Aaron Bentley
Handle trailing whitepace cleanly
334
                blank_line = False
1551.12.9 by Aaron Bentley
force patch-rio to 76 characters
335
                if len(line) > 0:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
336
                    partline += b'\\'
337
                elif re.search(b' $', partline):
338
                    partline += b'\\'
1551.12.11 by Aaron Bentley
Handle trailing whitepace cleanly
339
                    blank_line = True
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
340
                lines.append(b'# ' + partline + b'\n')
1551.12.11 by Aaron Bentley
Handle trailing whitepace cleanly
341
                if blank_line:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
342
                    lines.append(b'#   \n')
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
343
    return lines
344
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
345
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
346
def _patch_stanza_iter(line_iter):
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
347
    map = {b'\\\\': b'\\',
7143.15.2 by Jelmer Vernooij
Run autopep8.
348
           b'\\r': b'\r',
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
349
           b'\\\n': b''}
7143.15.2 by Jelmer Vernooij
Run autopep8.
350
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
351
    def mapget(match):
352
        return map[match.group(0)]
353
1551.12.9 by Aaron Bentley
force patch-rio to 76 characters
354
    last_line = None
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
355
    for line in line_iter:
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
356
        if line.startswith(b'# '):
1551.12.22 by Aaron Bentley
Fix handling of whitespace-stripping without newline munging
357
            line = line[2:]
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
358
        elif line.startswith(b'#'):
1551.12.22 by Aaron Bentley
Fix handling of whitespace-stripping without newline munging
359
            line = line[1:]
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
360
        else:
361
            raise ValueError("bad line %r" % (line,))
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
362
        if last_line is not None and len(line) > 2:
363
            line = line[2:]
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
364
        line = re.sub(b'\r', b'', line)
365
        line = re.sub(b'\\\\(.|\n)', mapget, line)
1551.12.9 by Aaron Bentley
force patch-rio to 76 characters
366
        if last_line is None:
367
            last_line = line
368
        else:
369
            last_line += line
6684.1.6 by Martin
Finish making rio module string usage work on Python 3
370
        if last_line[-1:] == b'\n':
1551.12.9 by Aaron Bentley
force patch-rio to 76 characters
371
            yield last_line
372
            last_line = None
373
    if last_line is not None:
374
        yield last_line
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
375
1551.12.23 by Aaron Bentley
Indent line continuations in Patch-RIO, to improve readability
376
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
377
def read_patch_stanza(line_iter):
1551.12.38 by Aaron Bentley
Add docs for MergeDirective and RIO-patch functions
378
    """Convert an iterable of RIO-Patch format lines into a Stanza.
379
380
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
381
    It resists common forms of damage such as newline conversion or the removal
382
    of trailing whitespace, yet is also reasonably easy to read.
383
384
    :return: a Stanza
385
    """
1551.12.1 by Aaron Bentley
Basic RIO patch-compatible format is working
386
    return read_stanza(_patch_stanza_iter(line_iter))
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
387
388
389
try:
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
390
    from ._rio_pyx import (
4354.3.1 by Jelmer Vernooij
Move core RIO parsing functionality to _rio_py.py.
391
        _read_stanza_utf8,
392
        _read_stanza_unicode,
393
        _valid_tag,
394
        )
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
395
except ImportError as e:
4574.3.8 by Martin Pool
Only mutter extension load errors when they occur, and record for later
396
    osutils.failed_to_load_extension(e)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
397
    from ._rio_py import (
7143.15.2 by Jelmer Vernooij
Run autopep8.
398
        _read_stanza_utf8,
399
        _read_stanza_unicode,
400
        _valid_tag,
401
        )