1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
"""
StringIO functionality
This module provides essentially two types of StringIO's, and two types of modes
of operation; text versus bytes, and readonly versus writable.
The reason for separate classes is that when we're running on py2k, if all we're
doing is consuming/reading the data it's heavily preferable to use ``cStringIO.StringIO``
if at all possible for performance reasons. Thus we have readonly and writable
classes; the separation has clear performance benefits.
Note that while this functionality is based on StringIO and friends, there is some
differences in behavior from stdlib- stdlib's ``cStringIO.StringIO`` is
pseudo-writable; it has a truncate method (which works). This is suboptimal since
the majority of consumers treat it as write only, thus in these classes we specifically
raise a TypeError if you try to truncate a readonly instance. Further, instead of
just lacking `write` and `writelines` methods, we supply those (to maintain file
like IO compatibility) but have them raise TypeError if invoked
Exempting the caveats above, usage of these classes is basically no different
than interacting with a normal StringIO.
Finally note that the __slots__ layout for py2k cStringIO differs from
io.BytesIO (or io.TextIO) in py3k; as such if you're deriving from a writable
instance you'll need to compensate for this if you want to have source that
is usable under both py2k and py3k.
"""
# TODO: deprecated, remove in 0.9.0
__all__ = ("text_readonly", "bytes_readonly")
import io
def _generic_immutable_method(self, *a, **kwds):
raise TypeError(f"{self} isn't opened for writing")
class _make_ro_cls(type):
def __new__(cls, name, bases, dct):
x = super().__new__(cls, name, bases, dct)
for k in ("write", "writelines", "truncate"):
setattr(x, k, _generic_immutable_method)
return x
class text_readonly(io.StringIO, metaclass=_make_ro_cls): ...
class bytes_readonly(io.BytesIO, metaclass=_make_ro_cls): ...
|