diff options
Diffstat (limited to 'Lib/_pyio.py')
-rw-r--r-- | Lib/_pyio.py | 280 |
1 files changed, 147 insertions, 133 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py index a0c4b25977..01683f8285 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -34,7 +34,7 @@ BlockingIOError = BlockingIOError def open(file, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): - r"""Open file and return a stream. Raise IOError upon failure. + r"""Open file and return a stream. Raise OSError upon failure. file is either a text or byte string giving the name (and the path if the file isn't in the current working directory) of the file to @@ -62,8 +62,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, 'b' binary mode 't' text mode (default) '+' open a disk file for updating (reading and writing) - 'U' universal newline mode (for backwards compatibility; unneeded - for new code) + 'U' universal newline mode (deprecated) ========= =============================================================== The default mode is 'rt' (open for reading text). For binary random @@ -79,6 +78,10 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, returned as strings, the bytes having been first decoded using a platform-dependent encoding or using the specified encoding if given. + 'U' mode is deprecated and will raise an exception in future versions + of Python. It has no effect in Python 3. Use newline to control + universal newlines mode. + buffering is an optional integer used to set the buffering policy. Pass 0 to switch buffering off (only allowed in binary mode), 1 to select line buffering (only usable in text mode), and an integer > 1 to indicate @@ -129,6 +132,8 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, be kept open when the file is closed. This does not work when a file name is given and must be True in that case. + The newly created file is non-inheritable. + A custom opener can be used by passing a callable as *opener*. The underlying file descriptor for the file object is then obtained by calling *opener* with (*file*, *flags*). *opener* must return an open file @@ -172,6 +177,9 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, if "U" in modes: if creating or writing or appending: raise ValueError("can't use U and writing mode at once") + import warnings + warnings.warn("'U' mode is deprecated", + DeprecationWarning, 2) reading = True if text and binary: raise ValueError("can't have text and binary mode at once") @@ -192,38 +200,45 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, (appending and "a" or "") + (updating and "+" or ""), closefd, opener=opener) - line_buffering = False - if buffering == 1 or buffering < 0 and raw.isatty(): - buffering = -1 - line_buffering = True - if buffering < 0: - buffering = DEFAULT_BUFFER_SIZE - try: - bs = os.fstat(raw.fileno()).st_blksize - except (os.error, AttributeError): - pass + result = raw + try: + line_buffering = False + if buffering == 1 or buffering < 0 and raw.isatty(): + buffering = -1 + line_buffering = True + if buffering < 0: + buffering = DEFAULT_BUFFER_SIZE + try: + bs = os.fstat(raw.fileno()).st_blksize + except (OSError, AttributeError): + pass + else: + if bs > 1: + buffering = bs + if buffering < 0: + raise ValueError("invalid buffering size") + if buffering == 0: + if binary: + return result + raise ValueError("can't have unbuffered text I/O") + if updating: + buffer = BufferedRandom(raw, buffering) + elif creating or writing or appending: + buffer = BufferedWriter(raw, buffering) + elif reading: + buffer = BufferedReader(raw, buffering) else: - if bs > 1: - buffering = bs - if buffering < 0: - raise ValueError("invalid buffering size") - if buffering == 0: + raise ValueError("unknown mode: %r" % mode) + result = buffer if binary: - return raw - raise ValueError("can't have unbuffered text I/O") - if updating: - buffer = BufferedRandom(raw, buffering) - elif creating or writing or appending: - buffer = BufferedWriter(raw, buffering) - elif reading: - buffer = BufferedReader(raw, buffering) - else: - raise ValueError("unknown mode: %r" % mode) - if binary: - return buffer - text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) - text.mode = mode - return text + return result + text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) + result = text + text.mode = mode + return result + except: + result.close() + raise class DocDescriptor: @@ -254,7 +269,7 @@ class OpenWrapper: try: UnsupportedOperation = io.UnsupportedOperation except AttributeError: - class UnsupportedOperation(ValueError, IOError): + class UnsupportedOperation(ValueError, OSError): pass @@ -278,7 +293,7 @@ class IOBase(metaclass=abc.ABCMeta): readinto) needed. Text I/O classes work with str data. Note that calling any method (even inquiries) on a closed stream is - undefined. Implementations may raise IOError in this case. + undefined. Implementations may raise OSError in this case. IOBase (and its subclasses) support the iterator protocol, meaning that an IOBase object can be iterated over yielding the lines in a @@ -294,7 +309,7 @@ class IOBase(metaclass=abc.ABCMeta): ### Internal ### def _unsupported(self, name): - """Internal: raise an IOError exception for unsupported operations.""" + """Internal: raise an OSError exception for unsupported operations.""" raise UnsupportedOperation("%s.%s() not supported" % (self.__class__.__name__, name)) @@ -441,7 +456,7 @@ class IOBase(metaclass=abc.ABCMeta): def fileno(self): """Returns underlying file descriptor (an int) if one exists. - An IOError is raised if the IO object does not use a file descriptor. + An OSError is raised if the IO object does not use a file descriptor. """ self._unsupported("fileno") @@ -455,11 +470,11 @@ class IOBase(metaclass=abc.ABCMeta): ### Readline[s] and writelines ### - def readline(self, limit=-1): + def readline(self, size=-1): r"""Read and return a line of bytes from the stream. - If limit is specified, at most limit bytes will be read. - Limit should be an int. + If size is specified, at most size bytes will be read. + Size should be an int. The line terminator is always b'\n' for binary files; for text files, the newlines argument to open can be used to select the line @@ -472,18 +487,18 @@ class IOBase(metaclass=abc.ABCMeta): if not readahead: return 1 n = (readahead.find(b"\n") + 1) or len(readahead) - if limit >= 0: - n = min(n, limit) + if size >= 0: + n = min(n, size) return n else: def nreadahead(): return 1 - if limit is None: - limit = -1 - elif not isinstance(limit, int): - raise TypeError("limit must be an integer") + if size is None: + size = -1 + elif not isinstance(size, int): + raise TypeError("size must be an integer") res = bytearray() - while limit < 0 or len(res) < limit: + while size < 0 or len(res) < size: b = self.read(nreadahead()) if not b: break @@ -542,17 +557,17 @@ class RawIOBase(IOBase): # primitive operation, but that would lead to nasty recursion in case # a subclass doesn't implement either.) - def read(self, n=-1): - """Read and return up to n bytes, where n is an int. + def read(self, size=-1): + """Read and return up to size bytes, where size is an int. Returns an empty bytes object on EOF, or None if the object is set not to block and has no data to read. """ - if n is None: - n = -1 - if n < 0: + if size is None: + size = -1 + if size < 0: return self.readall() - b = bytearray(n.__index__()) + b = bytearray(size.__index__()) n = self.readinto(b) if n is None: return None @@ -610,8 +625,8 @@ class BufferedIOBase(IOBase): implementation, but wrap one. """ - def read(self, n=None): - """Read and return up to n bytes, where n is an int. + def read(self, size=None): + """Read and return up to size bytes, where size is an int. If the argument is omitted, None, or negative, reads and returns all data until EOF. @@ -630,9 +645,9 @@ class BufferedIOBase(IOBase): """ self._unsupported("read") - def read1(self, n=None): - """Read up to n bytes with at most one read() system call, - where n is an int. + def read1(self, size=None): + """Read up to size bytes with at most one read() system call, + where size is an int. """ self._unsupported("read1") @@ -699,13 +714,13 @@ class _BufferedIOMixin(BufferedIOBase): def seek(self, pos, whence=0): new_position = self.raw.seek(pos, whence) if new_position < 0: - raise IOError("seek() returned an invalid position") + raise OSError("seek() returned an invalid position") return new_position def tell(self): pos = self.raw.tell() if pos < 0: - raise IOError("tell() returned an invalid position") + raise OSError("tell() returned an invalid position") return pos def truncate(self, pos=None): @@ -778,7 +793,7 @@ class _BufferedIOMixin(BufferedIOBase): clsname = self.__class__.__name__ try: name = self.name - except AttributeError: + except Exception: return "<_pyio.{0}>".format(clsname) else: return "<_pyio.{0} name={1!r}>".format(clsname, name) @@ -820,24 +835,24 @@ class BytesIO(BufferedIOBase): """ return memoryview(self._buffer) - def read(self, n=None): + def read(self, size=None): if self.closed: raise ValueError("read from closed file") - if n is None: - n = -1 - if n < 0: - n = len(self._buffer) + if size is None: + size = -1 + if size < 0: + size = len(self._buffer) if len(self._buffer) <= self._pos: return b"" - newpos = min(len(self._buffer), self._pos + n) + newpos = min(len(self._buffer), self._pos + size) b = self._buffer[self._pos : newpos] self._pos = newpos return bytes(b) - def read1(self, n): + def read1(self, size): """This is the same as read. """ - return self.read(n) + return self.read(size) def write(self, b): if self.closed: @@ -927,7 +942,7 @@ class BufferedReader(_BufferedIOMixin): """Create a new buffered reader using the given readable raw IO object. """ if not raw.readable(): - raise IOError('"raw" argument must be readable.') + raise OSError('"raw" argument must be readable.') _BufferedIOMixin.__init__(self, raw) if buffer_size <= 0: @@ -940,18 +955,18 @@ class BufferedReader(_BufferedIOMixin): self._read_buf = b"" self._read_pos = 0 - def read(self, n=None): - """Read n bytes. + def read(self, size=None): + """Read size bytes. - Returns exactly n bytes of data unless the underlying raw IO + Returns exactly size bytes of data unless the underlying raw IO stream reaches EOF or if the call would block in non-blocking - mode. If n is negative, read until EOF or until read() would + mode. If size is negative, read until EOF or until read() would block. """ - if n is not None and n < -1: + if size is not None and size < -1: raise ValueError("invalid number of bytes to read") with self._read_lock: - return self._read_unlocked(n) + return self._read_unlocked(size) def _read_unlocked(self, n=None): nodata_val = b"" @@ -1011,7 +1026,7 @@ class BufferedReader(_BufferedIOMixin): self._read_pos = 0 return out[:n] if out else nodata_val - def peek(self, n=0): + def peek(self, size=0): """Returns buffered bytes without advancing the position. The argument indicates a desired minimal number of bytes; we @@ -1019,7 +1034,7 @@ class BufferedReader(_BufferedIOMixin): than self.buffer_size. """ with self._read_lock: - return self._peek_unlocked(n) + return self._peek_unlocked(size) def _peek_unlocked(self, n=0): want = min(n, self.buffer_size) @@ -1037,18 +1052,18 @@ class BufferedReader(_BufferedIOMixin): self._read_pos = 0 return self._read_buf[self._read_pos:] - def read1(self, n): - """Reads up to n bytes, with at most one read() system call.""" - # Returns up to n bytes. If at least one byte is buffered, we + def read1(self, size): + """Reads up to size bytes, with at most one read() system call.""" + # Returns up to size bytes. If at least one byte is buffered, we # only return buffered bytes. Otherwise, we do one raw read. - if n < 0: + if size < 0: raise ValueError("number of bytes to read must be positive") - if n == 0: + if size == 0: return b"" with self._read_lock: self._peek_unlocked(1) return self._read_unlocked( - min(n, len(self._read_buf) - self._read_pos)) + min(size, len(self._read_buf) - self._read_pos)) def tell(self): return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos @@ -1074,7 +1089,7 @@ class BufferedWriter(_BufferedIOMixin): def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): if not raw.writable(): - raise IOError('"raw" argument must be writable.') + raise OSError('"raw" argument must be writable.') _BufferedIOMixin.__init__(self, raw) if buffer_size <= 0: @@ -1138,7 +1153,7 @@ class BufferedWriter(_BufferedIOMixin): errno.EAGAIN, "write could not complete without blocking", 0) if n > len(self._write_buf) or n < 0: - raise IOError("write() returned incorrect number of bytes") + raise OSError("write() returned incorrect number of bytes") del self._write_buf[:n] def tell(self): @@ -1174,18 +1189,18 @@ class BufferedRWPair(BufferedIOBase): The arguments are two RawIO instances. """ if not reader.readable(): - raise IOError('"reader" argument must be readable.') + raise OSError('"reader" argument must be readable.') if not writer.writable(): - raise IOError('"writer" argument must be writable.') + raise OSError('"writer" argument must be writable.') self.reader = BufferedReader(reader, buffer_size) self.writer = BufferedWriter(writer, buffer_size) - def read(self, n=None): - if n is None: - n = -1 - return self.reader.read(n) + def read(self, size=None): + if size is None: + size = -1 + return self.reader.read(size) def readinto(self, b): return self.reader.readinto(b) @@ -1193,11 +1208,11 @@ class BufferedRWPair(BufferedIOBase): def write(self, b): return self.writer.write(b) - def peek(self, n=0): - return self.reader.peek(n) + def peek(self, size=0): + return self.reader.peek(size) - def read1(self, n): - return self.reader.read1(n) + def read1(self, size): + return self.reader.read1(size) def readable(self): return self.reader.readable() @@ -1248,7 +1263,7 @@ class BufferedRandom(BufferedWriter, BufferedReader): with self._read_lock: self._reset_read_buf() if pos < 0: - raise IOError("seek() returned invalid position") + raise OSError("seek() returned invalid position") return pos def tell(self): @@ -1263,23 +1278,23 @@ class BufferedRandom(BufferedWriter, BufferedReader): # Use seek to flush the read buffer. return BufferedWriter.truncate(self, pos) - def read(self, n=None): - if n is None: - n = -1 + def read(self, size=None): + if size is None: + size = -1 self.flush() - return BufferedReader.read(self, n) + return BufferedReader.read(self, size) def readinto(self, b): self.flush() return BufferedReader.readinto(self, b) - def peek(self, n=0): + def peek(self, size=0): self.flush() - return BufferedReader.peek(self, n) + return BufferedReader.peek(self, size) - def read1(self, n): + def read1(self, size): self.flush() - return BufferedReader.read1(self, n) + return BufferedReader.read1(self, size) def write(self, b): if self._read_buf: @@ -1299,11 +1314,11 @@ class TextIOBase(IOBase): are immutable. There is no public constructor. """ - def read(self, n=-1): - """Read at most n characters from stream, where n is an int. + def read(self, size=-1): + """Read at most size characters from stream, where size is an int. - Read from underlying buffer until we have n characters or we hit EOF. - If n is negative or omitted, read until EOF. + Read from underlying buffer until we have size characters or we hit EOF. + If size is negative or omitted, read until EOF. Returns a string. """ @@ -1546,13 +1561,13 @@ class TextIOWrapper(TextIOBase): result = "<_pyio.TextIOWrapper" try: name = self.name - except AttributeError: + except Exception: pass else: result += " name={0!r}".format(name) try: mode = self.mode - except AttributeError: + except Exception: pass else: result += " mode={0!r}".format(mode) @@ -1732,7 +1747,7 @@ class TextIOWrapper(TextIOBase): if not self._seekable: raise UnsupportedOperation("underlying stream is not seekable") if not self._telling: - raise IOError("telling position disabled by next() call") + raise OSError("telling position disabled by next() call") self.flush() position = self.buffer.tell() decoder = self._decoder @@ -1819,7 +1834,7 @@ class TextIOWrapper(TextIOBase): chars_decoded += len(decoder.decode(b'', final=True)) need_eof = 1 if chars_decoded < chars_to_skip: - raise IOError("can't reconstruct logical file position") + raise OSError("can't reconstruct logical file position") # The returned cookie corresponds to the last safe start point. return self._pack_cookie( @@ -1896,7 +1911,7 @@ class TextIOWrapper(TextIOBase): # Skip chars_to_skip of the decoded characters. if len(self._decoded_chars) < chars_to_skip: - raise IOError("can't restore logical file position") + raise OSError("can't restore logical file position") self._decoded_chars_used = chars_to_skip # Finally, reset the encoder (merely useful for proper BOM handling) @@ -1912,16 +1927,16 @@ class TextIOWrapper(TextIOBase): encoder.reset() return cookie - def read(self, n=None): + def read(self, size=None): self._checkReadable() - if n is None: - n = -1 + if size is None: + size = -1 decoder = self._decoder or self._get_decoder() try: - n.__index__ + size.__index__ except AttributeError as err: raise TypeError("an integer is required") from err - if n < 0: + if size < 0: # Read everything. result = (self._get_decoded_chars() + decoder.decode(self.buffer.read(), final=True)) @@ -1929,12 +1944,12 @@ class TextIOWrapper(TextIOBase): self._snapshot = None return result else: - # Keep reading chunks until we have n characters to return. + # Keep reading chunks until we have size characters to return. eof = False - result = self._get_decoded_chars(n) - while len(result) < n and not eof: + result = self._get_decoded_chars(size) + while len(result) < size and not eof: eof = not self._read_chunk() - result += self._get_decoded_chars(n - len(result)) + result += self._get_decoded_chars(size - len(result)) return result def __next__(self): @@ -1946,13 +1961,13 @@ class TextIOWrapper(TextIOBase): raise StopIteration return line - def readline(self, limit=None): + def readline(self, size=None): if self.closed: raise ValueError("read from closed file") - if limit is None: - limit = -1 - elif not isinstance(limit, int): - raise TypeError("limit must be an integer") + if size is None: + size = -1 + elif not isinstance(size, int): + raise TypeError("size must be an integer") # Grab all the decoded text (we will rewind any extra bits later). line = self._get_decoded_chars() @@ -2011,8 +2026,8 @@ class TextIOWrapper(TextIOBase): endpos = pos + len(self._readnl) break - if limit >= 0 and len(line) >= limit: - endpos = limit # reached length limit + if size >= 0 and len(line) >= size: + endpos = size # reached length size break # No line ending seen yet - get more data' @@ -2027,8 +2042,8 @@ class TextIOWrapper(TextIOBase): self._snapshot = None return line - if limit >= 0 and endpos > limit: - endpos = limit # don't exceed limit + if size >= 0 and endpos > size: + endpos = size # don't exceed size # Rewind _decoded_chars to just after the line ending we found. self._rewind_decoded_chars(len(line) - endpos) @@ -2059,7 +2074,6 @@ class StringIO(TextIOWrapper): if not isinstance(initial_value, str): raise TypeError("initial_value must be str or None, not {0}" .format(type(initial_value).__name__)) - initial_value = str(initial_value) self.write(initial_value) self.seek(0) |