mirror of https://github.com/python/cpython
Added some comments and docstrings. More is needed.
This commit is contained in:
parent
b3f568f167
commit
17e43e582c
78
Lib/io.py
78
Lib/io.py
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
"""New I/O library.
|
"""New I/O library.
|
||||||
|
|
||||||
|
This is an early prototype; eventually some of this will be
|
||||||
|
reimplemented in C and the rest may be turned into a package.
|
||||||
|
|
||||||
See PEP XXX; for now: http://docs.google.com/Doc?id=dfksfvqd_1cn5g5m
|
See PEP XXX; for now: http://docs.google.com/Doc?id=dfksfvqd_1cn5g5m
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -13,7 +16,34 @@ __all__ = ["open", "RawIOBase", "FileIO", "SocketIO", "BytesIO"]
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def open(filename, mode="r", buffering=None, *, encoding=None):
|
def open(filename, mode="r", buffering=None, *, encoding=None):
|
||||||
"""Replacement for the built-in open function, with encoding parameter."""
|
"""Replacement for the built-in open function.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename: string giving the name of the file to be opened
|
||||||
|
mode: optional mode string; see below
|
||||||
|
buffering: optional int >= 0 giving the buffer size; values
|
||||||
|
can be: 0 = unbuffered, 1 = line buffered,
|
||||||
|
larger = fully buffered
|
||||||
|
encoding: optional string giving the text encoding (*must* be given
|
||||||
|
as a keyword argument)
|
||||||
|
|
||||||
|
Mode strings characters:
|
||||||
|
'r': open for reading (default)
|
||||||
|
'w': open for writing, truncating the file first
|
||||||
|
'a': open for writing, appending to the end if the file exists
|
||||||
|
'b': binary mode
|
||||||
|
't': text mode (default)
|
||||||
|
'+': open a disk file for updating (implies reading and writing)
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
- encoding must not be given when a binary mode is given
|
||||||
|
- buffering must not be zero when a text mode is given
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Depending on the mode and buffering arguments, either a raw
|
||||||
|
binary stream, a buffered binary stream, or a buffered text
|
||||||
|
stream, open for reading and/or writing.
|
||||||
|
"""
|
||||||
assert isinstance(filename, str)
|
assert isinstance(filename, str)
|
||||||
assert isinstance(mode, str)
|
assert isinstance(mode, str)
|
||||||
assert buffering is None or isinstance(buffering, int)
|
assert buffering is None or isinstance(buffering, int)
|
||||||
|
@ -22,11 +52,11 @@ def open(filename, mode="r", buffering=None, *, encoding=None):
|
||||||
if modes - set("arwb+t") or len(mode) > len(modes):
|
if modes - set("arwb+t") or len(mode) > len(modes):
|
||||||
raise ValueError("invalid mode: %r" % mode)
|
raise ValueError("invalid mode: %r" % mode)
|
||||||
reading = "r" in modes
|
reading = "r" in modes
|
||||||
writing = "w" in modes or "a" in modes
|
writing = "w" in modes
|
||||||
binary = "b" in modes
|
|
||||||
appending = "a" in modes
|
appending = "a" in modes
|
||||||
updating = "+" in modes
|
updating = "+" in modes
|
||||||
text = "t" in modes or not binary
|
text = "t" in modes
|
||||||
|
binary = "b" in modes
|
||||||
if text and binary:
|
if text and binary:
|
||||||
raise ValueError("can't have text and binary mode at once")
|
raise ValueError("can't have text and binary mode at once")
|
||||||
if reading + writing + appending > 1:
|
if reading + writing + appending > 1:
|
||||||
|
@ -42,6 +72,12 @@ def open(filename, mode="r", buffering=None, *, encoding=None):
|
||||||
(updating and "+" or ""))
|
(updating and "+" or ""))
|
||||||
if buffering is None:
|
if buffering is None:
|
||||||
buffering = 8*1024 # International standard buffer size
|
buffering = 8*1024 # International standard buffer size
|
||||||
|
# Should default to line buffering if os.isatty(raw.fileno())
|
||||||
|
try:
|
||||||
|
bs = os.fstat(raw.fileno()).st_blksize
|
||||||
|
except (os.error, AttributeError):
|
||||||
|
if bs > 1:
|
||||||
|
buffering = bs
|
||||||
if buffering < 0:
|
if buffering < 0:
|
||||||
raise ValueError("invalid buffering size")
|
raise ValueError("invalid buffering size")
|
||||||
if buffering == 0:
|
if buffering == 0:
|
||||||
|
@ -50,21 +86,33 @@ def open(filename, mode="r", buffering=None, *, encoding=None):
|
||||||
raise ValueError("can't have unbuffered text I/O")
|
raise ValueError("can't have unbuffered text I/O")
|
||||||
if updating:
|
if updating:
|
||||||
buffer = BufferedRandom(raw, buffering)
|
buffer = BufferedRandom(raw, buffering)
|
||||||
elif writing:
|
elif writing or appending:
|
||||||
buffer = BufferedWriter(raw, buffering)
|
buffer = BufferedWriter(raw, buffering)
|
||||||
else:
|
else:
|
||||||
assert reading
|
assert reading
|
||||||
buffer = BufferedReader(raw, buffering)
|
buffer = BufferedReader(raw, buffering)
|
||||||
if binary:
|
if binary:
|
||||||
return buffer
|
return buffer
|
||||||
assert text
|
# XXX What about newline conventions?
|
||||||
textio = TextIOWrapper(buffer) # Universal newlines default to on
|
textio = TextIOWrapper(buffer, encoding)
|
||||||
return textio
|
return textio
|
||||||
|
|
||||||
|
|
||||||
class RawIOBase:
|
class RawIOBase:
|
||||||
|
|
||||||
"""Base class for raw binary I/O."""
|
"""Base class for raw binary I/O.
|
||||||
|
|
||||||
|
This class provides dummy implementations for all methods that
|
||||||
|
derived classes can override selectively; the default
|
||||||
|
implementations represent a file that cannot be read, written or
|
||||||
|
seeked.
|
||||||
|
|
||||||
|
The read() method is implemented by calling readinto(); derived
|
||||||
|
classes that want to support readon only need to implement
|
||||||
|
readinto() as a primitive operation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# XXX Add individual method docstrings
|
||||||
|
|
||||||
def read(self, n):
|
def read(self, n):
|
||||||
b = bytes(n.__index__())
|
b = bytes(n.__index__())
|
||||||
|
@ -112,6 +160,8 @@ class FileIO(RawIOBase):
|
||||||
|
|
||||||
"""Raw I/O implementation for OS files."""
|
"""Raw I/O implementation for OS files."""
|
||||||
|
|
||||||
|
# XXX More docs
|
||||||
|
|
||||||
def __init__(self, filename, mode):
|
def __init__(self, filename, mode):
|
||||||
self._seekable = None
|
self._seekable = None
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
|
@ -166,14 +216,6 @@ class FileIO(RawIOBase):
|
||||||
self._seekable = True
|
self._seekable = True
|
||||||
return self._seekable
|
return self._seekable
|
||||||
|
|
||||||
# XXX(nnorwitz): is there any reason to redefine __enter__ & __exit__?
|
|
||||||
# Both already have the same impl in the base class.
|
|
||||||
def __enter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, *args):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def fileno(self):
|
def fileno(self):
|
||||||
return self._fd
|
return self._fd
|
||||||
|
|
||||||
|
@ -182,6 +224,8 @@ class SocketIO(RawIOBase):
|
||||||
|
|
||||||
"""Raw I/O implementation for stream sockets."""
|
"""Raw I/O implementation for stream sockets."""
|
||||||
|
|
||||||
|
# XXX More docs
|
||||||
|
|
||||||
def __init__(self, sock, mode):
|
def __init__(self, sock, mode):
|
||||||
assert mode in ("r", "w", "rw")
|
assert mode in ("r", "w", "rw")
|
||||||
self._sock = sock
|
self._sock = sock
|
||||||
|
@ -212,6 +256,8 @@ class BytesIO(RawIOBase):
|
||||||
|
|
||||||
"""Raw I/O implementation for bytes, like StringIO."""
|
"""Raw I/O implementation for bytes, like StringIO."""
|
||||||
|
|
||||||
|
# XXX More docs
|
||||||
|
|
||||||
def __init__(self, inital_bytes=None):
|
def __init__(self, inital_bytes=None):
|
||||||
self._buffer = b""
|
self._buffer = b""
|
||||||
self._pos = 0
|
self._pos = 0
|
||||||
|
|
Loading…
Reference in New Issue