| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  | """New I/O library conforming to PEP 3116.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  | This is a prototype; hopefully eventually some of this will be | 
					
						
							|  |  |  | reimplemented in C. | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  | Conformance of alternative implementations: all arguments are intended | 
					
						
							|  |  |  | to be positional-only except the arguments of the open() function. | 
					
						
							|  |  |  | Argument names except those of the open() function are not part of the | 
					
						
							|  |  |  | specification.  Instance variables and methods whose name starts with | 
					
						
							|  |  |  | a leading underscore are not part of the specification (except "magic" | 
					
						
							|  |  |  | names like __iter__).  Only the top-level names listed in the __all__ | 
					
						
							|  |  |  | variable are part of the specification. | 
					
						
							| 
									
										
										
										
											2007-03-15 18:59:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  | XXX edge cases when switching between reading/writing | 
					
						
							| 
									
										
										
										
											2007-03-15 18:59:31 +00:00
										 |  |  | XXX need to default buffer size to 1 if isatty() | 
					
						
							|  |  |  | XXX need to support 1 meaning line-buffered | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  | XXX don't use assert to validate input requirements | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | XXX whenever an argument is None, use the default value | 
					
						
							|  |  |  | XXX read/write ops should check readable/writable | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  | XXX buffered readinto should work with arbitrary buffer objects | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  | XXX use incremental encoder for text output, at least for UTF-16 and UTF-8-SIG | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | __author__ = ("Guido van Rossum <guido@python.org>, " | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |               "Mike Verdone <mike.verdone@gmail.com>, " | 
					
						
							|  |  |  |               "Mark Russell <mark.russell@zen.co.uk>") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | __all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", | 
					
						
							|  |  |  |            "SocketIO", "BytesIO", "StringIO", "BufferedIOBase", | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |            "BufferedReader", "BufferedWriter", "BufferedRWPair", | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |            "BufferedRandom", "TextIOBase", "TextIOWrapper"] | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | import codecs | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | import _fileio | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | # XXX Shouldn't we use st_blksize whenever we can? | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | DEFAULT_BUFFER_SIZE = 8 * 1024  # bytes | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class BlockingIOError(IOError): | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     """Exception raised when I/O would block on a non-blocking I/O stream.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, errno, strerror, characters_written=0): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         IOError.__init__(self, errno, strerror) | 
					
						
							|  |  |  |         self.characters_written = characters_written | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 00:54:15 +00:00
										 |  |  | def open(file, mode="r", buffering=None, encoding=None, newline=None): | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     """Replacement for the built-in open function.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Args: | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |       file: string giving the name of the file to be opened; | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |             or integer file descriptor of the file to be wrapped (*). | 
					
						
							|  |  |  |       mode: optional mode string; see below. | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |       buffering: optional int >= 0 giving the buffer size; values | 
					
						
							|  |  |  |                  can be: 0 = unbuffered, 1 = line buffered, | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |                  larger = fully buffered. | 
					
						
							|  |  |  |       encoding: optional string giving the text encoding. | 
					
						
							|  |  |  |       newline: optional newlines specifier; must be None, '\n' or '\r\n'; | 
					
						
							|  |  |  |                specifies the line ending expected on input and written on | 
					
						
							|  |  |  |                output.  If None, use universal newlines on input and | 
					
						
							|  |  |  |                use os.linesep on output. | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     (*) If a file descriptor is given, it is closed when the returned | 
					
						
							|  |  |  |     I/O object is closed.  If you don't want this to happen, use | 
					
						
							|  |  |  |     os.dup() to create a duplicate file descriptor. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     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) | 
					
						
							| 
									
										
										
										
											2007-04-07 02:59:27 +00:00
										 |  |  |       'U': universal newline mode (for backwards compatibility) | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |     # XXX Don't use asserts for these checks; raise TypeError or ValueError | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     assert isinstance(file, (basestring, int)), repr(file) | 
					
						
							|  |  |  |     assert isinstance(mode, basestring), repr(mode) | 
					
						
							|  |  |  |     assert buffering is None or isinstance(buffering, int), repr(buffering) | 
					
						
							|  |  |  |     assert encoding is None or isinstance(encoding, basestring), repr(encoding) | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     modes = set(mode) | 
					
						
							| 
									
										
										
										
											2007-04-07 02:59:27 +00:00
										 |  |  |     if modes - set("arwb+tU") or len(mode) > len(modes): | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         raise ValueError("invalid mode: %r" % mode) | 
					
						
							|  |  |  |     reading = "r" in modes | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     writing = "w" in modes | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     appending = "a" in modes | 
					
						
							|  |  |  |     updating = "+" in modes | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     text = "t" in modes | 
					
						
							|  |  |  |     binary = "b" in modes | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |     if "U" in modes: | 
					
						
							|  |  |  |         if writing or appending: | 
					
						
							|  |  |  |             raise ValueError("can't use U and writing mode at once") | 
					
						
							| 
									
										
										
										
											2007-04-07 02:59:27 +00:00
										 |  |  |         reading = True | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     if text and binary: | 
					
						
							|  |  |  |         raise ValueError("can't have text and binary mode at once") | 
					
						
							|  |  |  |     if reading + writing + appending > 1: | 
					
						
							|  |  |  |         raise ValueError("can't have read/write/append mode at once") | 
					
						
							|  |  |  |     if not (reading or writing or appending): | 
					
						
							|  |  |  |         raise ValueError("must have exactly one of read/write/append mode") | 
					
						
							|  |  |  |     if binary and encoding is not None: | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         raise ValueError("binary mode doesn't take an encoding argument") | 
					
						
							|  |  |  |     if binary and newline is not None: | 
					
						
							|  |  |  |         raise ValueError("binary mode doesn't take a newline argument") | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     raw = FileIO(file, | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |                  (reading and "r" or "") + | 
					
						
							|  |  |  |                  (writing and "w" or "") + | 
					
						
							|  |  |  |                  (appending and "a" or "") + | 
					
						
							|  |  |  |                  (updating and "+" or "")) | 
					
						
							|  |  |  |     if buffering is None: | 
					
						
							| 
									
										
										
										
											2007-05-24 00:50:02 +00:00
										 |  |  |         buffering = -1 | 
					
						
							|  |  |  |     if buffering < 0: | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |         buffering = DEFAULT_BUFFER_SIZE | 
					
						
							|  |  |  |         # XXX Should default to line buffering if os.isatty(raw.fileno()) | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             bs = os.fstat(raw.fileno()).st_blksize | 
					
						
							|  |  |  |         except (os.error, AttributeError): | 
					
						
							| 
									
										
										
										
											2007-03-18 03:36:28 +00:00
										 |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |             if bs > 1: | 
					
						
							|  |  |  |                 buffering = bs | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     if buffering < 0: | 
					
						
							|  |  |  |         raise ValueError("invalid buffering size") | 
					
						
							|  |  |  |     if buffering == 0: | 
					
						
							|  |  |  |         if binary: | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |             raw._name = file | 
					
						
							|  |  |  |             raw._mode = mode | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |             return raw | 
					
						
							|  |  |  |         raise ValueError("can't have unbuffered text I/O") | 
					
						
							|  |  |  |     if updating: | 
					
						
							|  |  |  |         buffer = BufferedRandom(raw, buffering) | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     elif writing or appending: | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         buffer = BufferedWriter(raw, buffering) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         assert reading | 
					
						
							|  |  |  |         buffer = BufferedReader(raw, buffering) | 
					
						
							|  |  |  |     if binary: | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |         buffer.name = file | 
					
						
							|  |  |  |         buffer.mode = mode | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         return buffer | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |     text = TextIOWrapper(buffer, encoding, newline) | 
					
						
							|  |  |  |     text.name = file | 
					
						
							|  |  |  |     text.mode = mode | 
					
						
							|  |  |  |     return text | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  | class UnsupportedOperation(ValueError, IOError): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class IOBase: | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     """Base class for all I/O classes.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     This class provides dummy implementations for many methods that | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     derived classes can override selectively; the default | 
					
						
							|  |  |  |     implementations represent a file that cannot be read, written or | 
					
						
							|  |  |  |     seeked. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     This does not define read(), readinto() and write(), nor | 
					
						
							|  |  |  |     readline() and friends, since their signatures vary per layer. | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Not that calling any method (even inquiries) on a closed file is | 
					
						
							|  |  |  |     undefined.  Implementations may raise IOError in this case. | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     ### Internal ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _unsupported(self, name: str) -> IOError: | 
					
						
							|  |  |  |         """Internal: raise an exception for unsupported operations.""" | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         raise UnsupportedOperation("%s.%s() not supported" % | 
					
						
							|  |  |  |                                    (self.__class__.__name__, name)) | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     ### Positioning ### | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |     def seek(self, pos: int, whence: int = 0) -> int: | 
					
						
							|  |  |  |         """seek(pos: int, whence: int = 0) -> int.  Change stream position.
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Seek to byte offset pos relative to position indicated by whence: | 
					
						
							|  |  |  |              0  Start of stream (the default).  pos should be >= 0; | 
					
						
							|  |  |  |              1  Current position - whence may be negative; | 
					
						
							|  |  |  |              2  End of stream - whence usually negative. | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         Returns the new absolute position. | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("seek") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def tell(self) -> int: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """tell() -> int.  Return current stream position.""" | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return self.seek(0, 1) | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |     def truncate(self, pos: int = None) -> int: | 
					
						
							|  |  |  |         """truncate(size: int = None) -> int. Truncate file to size bytes.
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Size defaults to the current IO position as reported by tell(). | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |         Returns the new size. | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("truncate") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     ### Flush and close ### | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def flush(self) -> None: | 
					
						
							|  |  |  |         """flush() -> None.  Flushes write buffers, if applicable.
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         This is a no-op for read-only and non-blocking streams. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  |         # XXX Should this return the number of bytes written??? | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     __closed = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def close(self) -> None: | 
					
						
							|  |  |  |         """close() -> None.  Flushes and closes the IO object.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This must be idempotent.  It should also set a flag for the | 
					
						
							|  |  |  |         'closed' property (see below) to test. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if not self.__closed: | 
					
						
							| 
									
										
										
										
											2007-07-10 12:00:45 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 self.flush() | 
					
						
							| 
									
										
										
										
											2007-07-22 20:38:07 +00:00
										 |  |  |             except IOError: | 
					
						
							|  |  |  |                 pass  # If flush() fails, just give up | 
					
						
							|  |  |  |             self.__closed = True | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __del__(self) -> None: | 
					
						
							|  |  |  |         """Destructor.  Calls close().""" | 
					
						
							|  |  |  |         # The try/except block is in case this is called at program | 
					
						
							|  |  |  |         # exit time, when it's possible that globals have already been | 
					
						
							|  |  |  |         # deleted, and then the close() call might fail.  Since | 
					
						
							|  |  |  |         # there's nothing we can do about such failures and they annoy | 
					
						
							|  |  |  |         # the end users, we suppress the traceback. | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self.close() | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ### Inquiries ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seekable(self) -> bool: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """seekable() -> bool.  Return whether object supports random access.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If False, seek(), tell() and truncate() will raise IOError. | 
					
						
							|  |  |  |         This method may need to do a test seek(). | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def readable(self) -> bool: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """readable() -> bool.  Return whether object was opened for reading.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If False, read() will raise IOError. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def writable(self) -> bool: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """writable() -> bool.  Return whether object was opened for writing.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If False, write() and truncate() will raise IOError. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def closed(self): | 
					
						
							|  |  |  |         """closed: bool.  True iff the file has been closed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         For backwards compatibility, this is a property, not a predicate. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         return self.__closed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ### Context manager ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __enter__(self) -> "IOBase":  # That's a forward reference | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         """Context management protocol.  Returns self.""" | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def __exit__(self, *args) -> None: | 
					
						
							|  |  |  |         """Context management protocol.  Calls close()""" | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         self.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     ### Lower-level APIs ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # XXX Should these be present even if unimplemented? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fileno(self) -> int: | 
					
						
							|  |  |  |         """fileno() -> int.  Returns underlying file descriptor if one exists.
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Raises IOError if the IO object does not use a file descriptor. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("fileno") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def isatty(self) -> bool: | 
					
						
							|  |  |  |         """isatty() -> int.  Returns whether this is an 'interactive' stream.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         Returns False if we don't know. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |     ### Readline[s] and writelines ### | 
					
						
							| 
									
										
										
										
											2007-05-21 23:13:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-07 23:45:37 +00:00
										 |  |  |     def readline(self, limit: int = -1) -> bytes: | 
					
						
							|  |  |  |         """For backwards compatibility, a (slowish) readline().""" | 
					
						
							| 
									
										
										
										
											2007-06-08 00:07:57 +00:00
										 |  |  |         if hasattr(self, "peek"): | 
					
						
							|  |  |  |             def nreadahead(): | 
					
						
							|  |  |  |                 readahead = self.peek(1, unsafe=True) | 
					
						
							|  |  |  |                 if not readahead: | 
					
						
							|  |  |  |                     return 1 | 
					
						
							|  |  |  |                 n = (readahead.find(b"\n") + 1) or len(readahead) | 
					
						
							|  |  |  |                 if limit >= 0: | 
					
						
							|  |  |  |                     n = min(n, limit) | 
					
						
							|  |  |  |                 return n | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             def nreadahead(): | 
					
						
							|  |  |  |                 return 1 | 
					
						
							| 
									
										
										
										
											2007-06-07 23:45:37 +00:00
										 |  |  |         if limit is None: | 
					
						
							|  |  |  |             limit = -1 | 
					
						
							|  |  |  |         res = bytes() | 
					
						
							|  |  |  |         while limit < 0 or len(res) < limit: | 
					
						
							| 
									
										
										
										
											2007-06-08 00:07:57 +00:00
										 |  |  |             b = self.read(nreadahead()) | 
					
						
							| 
									
										
										
										
											2007-05-21 23:13:11 +00:00
										 |  |  |             if not b: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             res += b | 
					
						
							| 
									
										
										
										
											2007-06-07 23:45:37 +00:00
										 |  |  |             if res.endswith(b"\n"): | 
					
						
							| 
									
										
										
										
											2007-05-21 23:13:11 +00:00
										 |  |  |                 break | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |     def __iter__(self): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("__iter__ on closed file") | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __next__(self): | 
					
						
							|  |  |  |         line = self.readline() | 
					
						
							|  |  |  |         if not line: | 
					
						
							|  |  |  |             raise StopIteration | 
					
						
							|  |  |  |         return line | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def readlines(self, hint=None): | 
					
						
							|  |  |  |         if hint is None: | 
					
						
							|  |  |  |             return list(self) | 
					
						
							|  |  |  |         n = 0 | 
					
						
							|  |  |  |         lines = [] | 
					
						
							|  |  |  |         for line in self: | 
					
						
							|  |  |  |             lines.append(line) | 
					
						
							|  |  |  |             n += len(line) | 
					
						
							|  |  |  |             if n >= hint: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         return lines | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writelines(self, lines): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("write to closed file") | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |         for line in lines: | 
					
						
							|  |  |  |             self.write(line) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class RawIOBase(IOBase): | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     """Base class for raw binary I/O.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     The read() method is implemented by calling readinto(); derived | 
					
						
							|  |  |  |     classes that want to support read() only need to implement | 
					
						
							|  |  |  |     readinto() as a primitive operation.  In general, readinto() | 
					
						
							|  |  |  |     can be more efficient than read(). | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     (It would be tempting to also provide an implementation of | 
					
						
							|  |  |  |     readinto() in terms of read(), in case the latter is a more | 
					
						
							|  |  |  |     suitable primitive operation, but that would lead to nasty | 
					
						
							|  |  |  |     recursion in case a subclass doesn't implement either.) | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |     def read(self, n: int = -1) -> bytes: | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         """read(n: int) -> bytes.  Read and return up to n bytes.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         Returns an empty bytes array on EOF, or None if the object is | 
					
						
							|  |  |  |         set not to block and has no data to read. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							|  |  |  |         if n < 0: | 
					
						
							|  |  |  |             return self.readall() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         b = bytes(n.__index__()) | 
					
						
							|  |  |  |         n = self.readinto(b) | 
					
						
							|  |  |  |         del b[n:] | 
					
						
							|  |  |  |         return b | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |     def readall(self): | 
					
						
							|  |  |  |         """readall() -> bytes.  Read until EOF, using multiple read() call.""" | 
					
						
							|  |  |  |         res = bytes() | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             data = self.read(DEFAULT_BUFFER_SIZE) | 
					
						
							|  |  |  |             if not data: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             res += data | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def readinto(self, b: bytes) -> int: | 
					
						
							|  |  |  |         """readinto(b: bytes) -> int.  Read up to len(b) bytes into b.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         Returns number of bytes read (0 for EOF), or None if the object | 
					
						
							|  |  |  |         is set not to block as has no data to read. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self._unsupported("readinto") | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def write(self, b: bytes) -> int: | 
					
						
							|  |  |  |         """write(b: bytes) -> int.  Write the given buffer to the IO stream.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         Returns the number of bytes written, which may be less than len(b). | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self._unsupported("write") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class FileIO(_fileio._FileIO, RawIOBase): | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     """Raw I/O implementation for OS files.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     This multiply inherits from _FileIO and RawIOBase to make | 
					
						
							|  |  |  |     isinstance(io.FileIO(), io.RawIOBase) return True without | 
					
						
							|  |  |  |     requiring that _fileio._FileIO inherits from io.RawIOBase (which | 
					
						
							|  |  |  |     would be hard to do since _fileio.c is written in C). | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2007-03-08 00:43:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |     def close(self): | 
					
						
							|  |  |  |         _fileio._FileIO.close(self) | 
					
						
							|  |  |  |         RawIOBase.close(self) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def name(self): | 
					
						
							|  |  |  |         return self._name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def mode(self): | 
					
						
							|  |  |  |         return self._mode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-08 00:43:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | class SocketIO(RawIOBase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """Raw I/O implementation for stream sockets.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 15:45:13 +00:00
										 |  |  |     # XXX More docs | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     def __init__(self, sock, mode): | 
					
						
							|  |  |  |         assert mode in ("r", "w", "rw") | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         RawIOBase.__init__(self) | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         self._sock = sock | 
					
						
							|  |  |  |         self._mode = mode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def readinto(self, b): | 
					
						
							|  |  |  |         return self._sock.recv_into(b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-21 23:13:11 +00:00
										 |  |  |     def read(self, n: int = None) -> bytes: | 
					
						
							|  |  |  |         """read(n: int) -> bytes.  Read and return up to n bytes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns an empty bytes array 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: | 
					
						
							|  |  |  |             return RawIOBase.read(self, n) | 
					
						
							|  |  |  |         # Support reading until the end. | 
					
						
							|  |  |  |         # XXX Why doesn't RawIOBase support this? | 
					
						
							|  |  |  |         data = b"" | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             more = RawIOBase.read(self, DEFAULT_BUFFER_SIZE) | 
					
						
							|  |  |  |             if not more: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             data += more | 
					
						
							|  |  |  |         return data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     def write(self, b): | 
					
						
							|  |  |  |         return self._sock.send(b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         if not self.closed: | 
					
						
							| 
									
										
										
										
											2007-05-21 23:13:11 +00:00
										 |  |  |             RawIOBase.close(self) | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     def readable(self): | 
					
						
							|  |  |  |         return "r" in self._mode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writable(self): | 
					
						
							|  |  |  |         return "w" in self._mode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |     def fileno(self): | 
					
						
							|  |  |  |         return self._sock.fileno() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 14:41:39 +00:00
										 |  |  | class BufferedIOBase(IOBase): | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     """Base class for buffered IO objects.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The main difference with RawIOBase is that the read() method | 
					
						
							|  |  |  |     supports omitting the size argument, and does not have a default | 
					
						
							|  |  |  |     implementation that defers to readinto(). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In addition, read(), readinto() and write() may raise | 
					
						
							|  |  |  |     BlockingIOError if the underlying raw stream is in non-blocking | 
					
						
							|  |  |  |     mode and not ready; unlike their raw counterparts, they will never | 
					
						
							|  |  |  |     return None. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     A typical implementation should not inherit from a RawIOBase | 
					
						
							|  |  |  |     implementation, but wrap one. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-24 00:50:02 +00:00
										 |  |  |     def read(self, n: int = None) -> bytes: | 
					
						
							|  |  |  |         """read(n: int = None) -> bytes.  Read and return up to n bytes.
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |         If the argument is omitted, None, or negative, reads and | 
					
						
							|  |  |  |         returns all data until EOF. | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         If the argument is positive, and the underlying raw stream is | 
					
						
							|  |  |  |         not 'interactive', multiple raw reads may be issued to satisfy | 
					
						
							|  |  |  |         the byte count (unless EOF is reached first).  But for | 
					
						
							|  |  |  |         interactive raw streams (XXX and for pipes?), at most one raw | 
					
						
							|  |  |  |         read will be issued, and a short result does not imply that | 
					
						
							|  |  |  |         EOF is imminent. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns an empty bytes array on EOF. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raises BlockingIOError if the underlying raw stream has no | 
					
						
							|  |  |  |         data at the moment. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self._unsupported("read") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def readinto(self, b: bytes) -> int: | 
					
						
							|  |  |  |         """readinto(b: bytes) -> int.  Read up to len(b) bytes into b.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Like read(), this may issue multiple reads to the underlying | 
					
						
							|  |  |  |         raw stream, unless the latter is 'interactive' (XXX or a | 
					
						
							|  |  |  |         pipe?). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns the number of bytes read (0 for EOF). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raises BlockingIOError if the underlying raw stream has no | 
					
						
							|  |  |  |         data at the moment. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  |         # XXX This ought to work with anything that supports the buffer API | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |         data = self.read(len(b)) | 
					
						
							|  |  |  |         n = len(data) | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             b[:n] = data | 
					
						
							|  |  |  |         except TypeError as err: | 
					
						
							|  |  |  |             import array | 
					
						
							|  |  |  |             if not isinstance(b, array.array): | 
					
						
							|  |  |  |                 raise err | 
					
						
							|  |  |  |             b[:n] = array.array('b', data) | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |         return n | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def write(self, b: bytes) -> int: | 
					
						
							|  |  |  |         """write(b: bytes) -> int.  Write the given buffer to the IO stream.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns the number of bytes written, which is never less than | 
					
						
							|  |  |  |         len(b). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raises BlockingIOError if the buffer is full and the | 
					
						
							|  |  |  |         underlying raw stream cannot accept more data at the moment. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self._unsupported("write") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _BufferedIOMixin(BufferedIOBase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """A mixin implementation of BufferedIOBase with an underlying raw stream.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This passes most requests on to the underlying raw stream.  It | 
					
						
							|  |  |  |     does *not* provide implementations of read(), readinto() or | 
					
						
							|  |  |  |     write(). | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, raw): | 
					
						
							|  |  |  |         self.raw = raw | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ### Positioning ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return self.raw.seek(pos, whence) | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def tell(self): | 
					
						
							|  |  |  |         return self.raw.tell() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def truncate(self, pos=None): | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |         if pos is None: | 
					
						
							|  |  |  |             pos = self.tell() | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |         return self.raw.truncate(pos) | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ### Flush and close ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def flush(self): | 
					
						
							|  |  |  |         self.raw.flush() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if not self.closed: | 
					
						
							| 
									
										
										
										
											2007-07-22 20:38:07 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 self.flush() | 
					
						
							|  |  |  |             except IOError: | 
					
						
							|  |  |  |                 pass  # If flush() fails, just give up | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |             self.raw.close() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ### Inquiries ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seekable(self): | 
					
						
							|  |  |  |         return self.raw.seekable() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def readable(self): | 
					
						
							|  |  |  |         return self.raw.readable() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writable(self): | 
					
						
							|  |  |  |         return self.raw.writable() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def closed(self): | 
					
						
							|  |  |  |         return self.raw.closed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ### Lower-level APIs ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fileno(self): | 
					
						
							|  |  |  |         return self.raw.fileno() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isatty(self): | 
					
						
							|  |  |  |         return self.raw.isatty() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  | class BytesIO(BufferedIOBase): | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     """Buffered I/O implementation using an in-memory bytes buffer.""" | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     # XXX More docs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, initial_bytes=None): | 
					
						
							|  |  |  |         buffer = b"" | 
					
						
							|  |  |  |         if initial_bytes is not None: | 
					
						
							|  |  |  |             buffer += initial_bytes | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         self._buffer = buffer | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         self._pos = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getvalue(self): | 
					
						
							|  |  |  |         return self._buffer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read(self, n=None): | 
					
						
							|  |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         if n < 0: | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |             n = len(self._buffer) | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         newpos = min(len(self._buffer), self._pos + n) | 
					
						
							|  |  |  |         b = self._buffer[self._pos : newpos] | 
					
						
							|  |  |  |         self._pos = newpos | 
					
						
							|  |  |  |         return b | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read1(self, n): | 
					
						
							|  |  |  |         return self.read(n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |     def write(self, b): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("write to closed file") | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         n = len(b) | 
					
						
							|  |  |  |         newpos = self._pos + n | 
					
						
							| 
									
										
										
										
											2007-07-21 00:25:15 +00:00
										 |  |  |         if newpos > len(self._buffer): | 
					
						
							|  |  |  |             # Inserts null bytes between the current end of the file | 
					
						
							|  |  |  |             # and the new write position. | 
					
						
							|  |  |  |             padding = '\x00' * (newpos - len(self._buffer) - n) | 
					
						
							|  |  |  |             self._buffer[self._pos:newpos - n] = padding | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  |         self._buffer[self._pos:newpos] = b | 
					
						
							|  |  |  |         self._pos = newpos | 
					
						
							|  |  |  |         return n | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							|  |  |  |         if whence == 0: | 
					
						
							|  |  |  |             self._pos = max(0, pos) | 
					
						
							|  |  |  |         elif whence == 1: | 
					
						
							|  |  |  |             self._pos = max(0, self._pos + pos) | 
					
						
							|  |  |  |         elif whence == 2: | 
					
						
							|  |  |  |             self._pos = max(0, len(self._buffer) + pos) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise IOError("invalid whence value") | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return self._pos | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def tell(self): | 
					
						
							|  |  |  |         return self._pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def truncate(self, pos=None): | 
					
						
							|  |  |  |         if pos is None: | 
					
						
							|  |  |  |             pos = self._pos | 
					
						
							|  |  |  |         del self._buffer[pos:] | 
					
						
							| 
									
										
										
										
											2007-04-10 21:06:59 +00:00
										 |  |  |         return pos | 
					
						
							| 
									
										
										
										
											2007-02-27 05:47:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def readable(self): | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writable(self): | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seekable(self): | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class BufferedReader(_BufferedIOMixin): | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     """Buffer for a readable sequential RawIO object.""" | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         """Create a new buffered reader using the given readable raw IO object.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         assert raw.readable() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         _BufferedIOMixin.__init__(self, raw) | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         self._read_buf = b"" | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         self.buffer_size = buffer_size | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read(self, n=None): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         """Read n bytes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns exactly n bytes of data unless the underlying raw IO | 
					
						
							| 
									
										
										
										
											2007-05-29 19:13:29 +00:00
										 |  |  |         stream reaches EOF or if the call would block in non-blocking | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         mode. If n is negative, read until EOF or until read() would | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         block. | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         nodata_val = b"" | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         while n < 0 or len(self._read_buf) < n: | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |             to_read = max(self.buffer_size, | 
					
						
							|  |  |  |                           n if n is not None else 2*len(self._read_buf)) | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |             current = self.raw.read(to_read) | 
					
						
							|  |  |  |             if current in (b"", None): | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |                 nodata_val = current | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |             self._read_buf += current | 
					
						
							|  |  |  |         if self._read_buf: | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |             if n < 0: | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |                 n = len(self._read_buf) | 
					
						
							|  |  |  |             out = self._read_buf[:n] | 
					
						
							|  |  |  |             self._read_buf = self._read_buf[n:] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             out = nodata_val | 
					
						
							|  |  |  |         return out | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |     def peek(self, n=0, *, unsafe=False): | 
					
						
							|  |  |  |         """Returns buffered bytes without advancing the position.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The argument indicates a desired minimal number of bytes; we | 
					
						
							|  |  |  |         do at most one raw read to satisfy it.  We never return more | 
					
						
							|  |  |  |         than self.buffer_size. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Unless unsafe=True is passed, we return a copy. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         want = min(n, self.buffer_size) | 
					
						
							|  |  |  |         have = len(self._read_buf) | 
					
						
							|  |  |  |         if have < want: | 
					
						
							|  |  |  |             to_read = self.buffer_size - have | 
					
						
							|  |  |  |             current = self.raw.read(to_read) | 
					
						
							|  |  |  |             if current: | 
					
						
							|  |  |  |                 self._read_buf += current | 
					
						
							|  |  |  |         result = self._read_buf | 
					
						
							|  |  |  |         if unsafe: | 
					
						
							|  |  |  |             result = result[:] | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read1(self, n): | 
					
						
							|  |  |  |         """Reads up to n bytes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns up to n bytes.  If at least one byte is buffered, | 
					
						
							|  |  |  |         we only return buffered bytes.  Otherwise, we do one | 
					
						
							|  |  |  |         raw read. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if n <= 0: | 
					
						
							|  |  |  |             return b"" | 
					
						
							|  |  |  |         self.peek(1, unsafe=True) | 
					
						
							|  |  |  |         return self.read(min(n, len(self._read_buf))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |     def tell(self): | 
					
						
							|  |  |  |         return self.raw.tell() - len(self._read_buf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							|  |  |  |         if whence == 1: | 
					
						
							|  |  |  |             pos -= len(self._read_buf) | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         pos = self.raw.seek(pos, whence) | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         self._read_buf = b"" | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return pos | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class BufferedWriter(_BufferedIOMixin): | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     # XXX docstring | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def __init__(self, raw, | 
					
						
							|  |  |  |                  buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         assert raw.writable() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         _BufferedIOMixin.__init__(self, raw) | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |         self.buffer_size = buffer_size | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         self.max_buffer_size = (2*buffer_size | 
					
						
							|  |  |  |                                 if max_buffer_size is None | 
					
						
							|  |  |  |                                 else max_buffer_size) | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         self._write_buf = b"" | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def write(self, b): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("write to closed file") | 
					
						
							| 
									
										
										
										
											2007-05-24 00:50:02 +00:00
										 |  |  |         if not isinstance(b, bytes): | 
					
						
							| 
									
										
										
										
											2007-07-10 06:54:34 +00:00
										 |  |  |             if hasattr(b, "__index__"): | 
					
						
							|  |  |  |                 raise TypeError("Can't write object of type %s" % | 
					
						
							|  |  |  |                                 type(b).__name__) | 
					
						
							| 
									
										
										
										
											2007-05-24 00:50:02 +00:00
										 |  |  |             b = bytes(b) | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         # XXX we can implement some more tricks to try and avoid partial writes | 
					
						
							|  |  |  |         if len(self._write_buf) > self.buffer_size: | 
					
						
							|  |  |  |             # We're full, so let's pre-flush the buffer | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |             except BlockingIOError as e: | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |                 # We can't accept anything else. | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |                 # XXX Why not just let the exception pass through? | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |                 raise BlockingIOError(e.errno, e.strerror, 0) | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  |         before = len(self._write_buf) | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._write_buf.extend(b) | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  |         written = len(self._write_buf) - before | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         if len(self._write_buf) > self.buffer_size: | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |             except BlockingIOError as e: | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |                 if (len(self._write_buf) > self.max_buffer_size): | 
					
						
							|  |  |  |                     # We've hit max_buffer_size. We have to accept a partial | 
					
						
							|  |  |  |                     # write and cut back our buffer. | 
					
						
							|  |  |  |                     overage = len(self._write_buf) - self.max_buffer_size | 
					
						
							|  |  |  |                     self._write_buf = self._write_buf[:self.max_buffer_size] | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |                     raise BlockingIOError(e.errno, e.strerror, overage) | 
					
						
							| 
									
										
										
										
											2007-04-12 05:44:49 +00:00
										 |  |  |         return written | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def flush(self): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("flush of closed file") | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         written = 0 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |             while self._write_buf: | 
					
						
							|  |  |  |                 n = self.raw.write(self._write_buf) | 
					
						
							|  |  |  |                 del self._write_buf[:n] | 
					
						
							|  |  |  |                 written += n | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         except BlockingIOError as e: | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |             n = e.characters_written | 
					
						
							|  |  |  |             del self._write_buf[:n] | 
					
						
							|  |  |  |             written += n | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |             raise BlockingIOError(e.errno, e.strerror, written) | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def tell(self): | 
					
						
							|  |  |  |         return self.raw.tell() + len(self._write_buf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							|  |  |  |         self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return self.raw.seek(pos, whence) | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class BufferedRWPair(BufferedIOBase): | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |     """A buffered reader and writer object together.
 | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     A buffered reader object and buffered writer object put together | 
					
						
							|  |  |  |     to form a sequential IO object that can read and write. | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This is typically used with a socket or two-way pipe. | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     XXX The usefulness of this (compared to having two separate IO | 
					
						
							|  |  |  |     objects) is questionable. | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def __init__(self, reader, writer, | 
					
						
							|  |  |  |                  buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): | 
					
						
							|  |  |  |         """Constructor.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The arguments are two RawIO instances. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         assert reader.readable() | 
					
						
							|  |  |  |         assert writer.writable() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         self.reader = BufferedReader(reader, buffer_size) | 
					
						
							|  |  |  |         self.writer = BufferedWriter(writer, buffer_size, max_buffer_size) | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read(self, n=None): | 
					
						
							|  |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         return self.reader.read(n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def readinto(self, b): | 
					
						
							|  |  |  |         return self.reader.readinto(b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |     def write(self, b): | 
					
						
							|  |  |  |         return self.writer.write(b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |     def peek(self, n=0, *, unsafe=False): | 
					
						
							|  |  |  |         return self.reader.peek(n, unsafe=unsafe) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read1(self, n): | 
					
						
							|  |  |  |         return self.reader.read1(n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |     def readable(self): | 
					
						
							|  |  |  |         return self.reader.readable() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def writable(self): | 
					
						
							|  |  |  |         return self.writer.writable() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def flush(self): | 
					
						
							|  |  |  |         return self.writer.flush() | 
					
						
							| 
									
										
										
										
											2007-02-27 17:19:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |     def close(self): | 
					
						
							|  |  |  |         self.writer.close() | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         self.reader.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isatty(self): | 
					
						
							|  |  |  |         return self.reader.isatty() or self.writer.isatty() | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def closed(self): | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |         return self.writer.closed() | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  | class BufferedRandom(BufferedWriter, BufferedReader): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     # XXX docstring | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def __init__(self, raw, | 
					
						
							|  |  |  |                  buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         assert raw.seekable() | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         BufferedReader.__init__(self, raw, buffer_size) | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							|  |  |  |         self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         # First do the raw seek, then empty the read buffer, so that | 
					
						
							|  |  |  |         # if the raw seek fails, we don't lose buffered data forever. | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         pos = self.raw.seek(pos, whence) | 
					
						
							| 
									
										
										
										
											2007-04-06 19:10:29 +00:00
										 |  |  |         self._read_buf = b"" | 
					
						
							| 
									
										
										
										
											2007-04-10 19:01:47 +00:00
										 |  |  |         return pos | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def tell(self): | 
					
						
							|  |  |  |         if (self._write_buf): | 
					
						
							|  |  |  |             return self.raw.tell() + len(self._write_buf) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return self.raw.tell() - len(self._read_buf) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read(self, n=None): | 
					
						
							|  |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         self.flush() | 
					
						
							|  |  |  |         return BufferedReader.read(self, n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |     def readinto(self, b): | 
					
						
							|  |  |  |         self.flush() | 
					
						
							|  |  |  |         return BufferedReader.readinto(self, b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |     def peek(self, n=0, *, unsafe=False): | 
					
						
							|  |  |  |         self.flush() | 
					
						
							|  |  |  |         return BufferedReader.peek(self, n, unsafe=unsafe) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read1(self, n): | 
					
						
							|  |  |  |         self.flush() | 
					
						
							|  |  |  |         return BufferedReader.read1(self, n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |     def write(self, b): | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         if self._read_buf: | 
					
						
							|  |  |  |             self.raw.seek(-len(self._read_buf), 1) # Undo readahead | 
					
						
							|  |  |  |             self._read_buf = b"" | 
					
						
							| 
									
										
										
										
											2007-03-07 01:00:12 +00:00
										 |  |  |         return BufferedWriter.write(self, b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-10 14:41:39 +00:00
										 |  |  | class TextIOBase(IOBase): | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     """Base class for text I/O.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This class provides a character and line based interface to stream I/O. | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     There is no readinto() method, as character strings are immutable. | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read(self, n: int = -1) -> str: | 
					
						
							|  |  |  |         """read(n: int = -1) -> str.  Read at most n characters from stream.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Read from underlying buffer until we have n characters or we hit EOF. | 
					
						
							|  |  |  |         If n is negative or omitted, read until EOF. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("read") | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |     def write(self, s: str) -> int: | 
					
						
							|  |  |  |         """write(s: str) -> int.  Write string s to stream.""" | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("write") | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |     def truncate(self, pos: int = None) -> int: | 
					
						
							|  |  |  |         """truncate(pos: int = None) -> int.  Truncate size to pos.""" | 
					
						
							|  |  |  |         self.flush() | 
					
						
							|  |  |  |         if pos is None: | 
					
						
							|  |  |  |             pos = self.tell() | 
					
						
							|  |  |  |         self.seek(pos) | 
					
						
							|  |  |  |         return self.buffer.truncate() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     def readline(self) -> str: | 
					
						
							|  |  |  |         """readline() -> str.  Read until newline or EOF.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns an empty string if EOF is hit immediately. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self._unsupported("readline") | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-24 17:58:06 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def encoding(self): | 
					
						
							|  |  |  |         """Subclasses should override.""" | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TextIOWrapper(TextIOBase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """Buffered text stream.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Character and line based layer over a BufferedIOBase object. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |     _CHUNK_SIZE = 128 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, buffer, encoding=None, newline=None): | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         if newline not in (None, "\n", "\r\n"): | 
					
						
							|  |  |  |             raise ValueError("illegal newline value: %r" % (newline,)) | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         if encoding is None: | 
					
						
							|  |  |  |             # XXX This is questionable | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |             encoding = sys.getfilesystemencoding() or "latin-1" | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.buffer = buffer | 
					
						
							|  |  |  |         self._encoding = encoding | 
					
						
							|  |  |  |         self._newline = newline or os.linesep | 
					
						
							|  |  |  |         self._fix_newlines = newline is None | 
					
						
							|  |  |  |         self._decoder = None | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         self._pending = "" | 
					
						
							|  |  |  |         self._snapshot = None | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         self._seekable = self._telling = self.buffer.seekable() | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-24 17:58:06 +00:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def encoding(self): | 
					
						
							|  |  |  |         return self._encoding | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |     # A word about _snapshot.  This attribute is either None, or a | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |     # tuple (decoder_state, readahead, pending) where decoder_state is | 
					
						
							|  |  |  |     # the second (integer) item of the decoder state, readahead is the | 
					
						
							|  |  |  |     # chunk of bytes that was read, and pending is the characters that | 
					
						
							|  |  |  |     # were rendered by the decoder after feeding it those bytes.  We | 
					
						
							|  |  |  |     # use this to reconstruct intermediate decoder states in tell(). | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _seekable(self): | 
					
						
							|  |  |  |         return self._seekable | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     def flush(self): | 
					
						
							|  |  |  |         self.buffer.flush() | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         self._telling = self._seekable | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											2007-07-22 20:38:07 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             self.flush() | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             pass  # If flush() fails, just give up | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         self.buffer.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def closed(self): | 
					
						
							|  |  |  |         return self.buffer.closed | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-07 02:59:27 +00:00
										 |  |  |     def fileno(self): | 
					
						
							|  |  |  |         return self.buffer.fileno() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-27 09:14:51 +00:00
										 |  |  |     def isatty(self): | 
					
						
							|  |  |  |         return self.buffer.isatty() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |     def write(self, s: str): | 
					
						
							| 
									
										
										
										
											2007-07-10 09:12:49 +00:00
										 |  |  |         if self.closed: | 
					
						
							|  |  |  |             raise ValueError("write to closed file") | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         # XXX What if we were just reading? | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         b = s.encode(self._encoding) | 
					
						
							|  |  |  |         if isinstance(b, str): | 
					
						
							|  |  |  |             b = bytes(b) | 
					
						
							|  |  |  |         n = self.buffer.write(b) | 
					
						
							|  |  |  |         if "\n" in s: | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |             # XXX only if isatty | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |             self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         self._snapshot = self._decoder = None | 
					
						
							|  |  |  |         return len(s) | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _get_decoder(self): | 
					
						
							|  |  |  |         make_decoder = codecs.getincrementaldecoder(self._encoding) | 
					
						
							|  |  |  |         if make_decoder is None: | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |             raise IOError("Can't find an incremental decoder for encoding %s" % | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |                           self._encoding) | 
					
						
							|  |  |  |         decoder = self._decoder = make_decoder()  # XXX: errors | 
					
						
							|  |  |  |         return decoder | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |     def _read_chunk(self): | 
					
						
							|  |  |  |         assert self._decoder is not None | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         if not self._telling: | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |             readahead = self.buffer.read1(self._CHUNK_SIZE) | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |             pending = self._decoder.decode(readahead, not readahead) | 
					
						
							|  |  |  |             return readahead, pending | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |         decoder_buffer, decoder_state = self._decoder.getstate() | 
					
						
							| 
									
										
										
										
											2007-04-13 18:42:35 +00:00
										 |  |  |         readahead = self.buffer.read1(self._CHUNK_SIZE) | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |         pending = self._decoder.decode(readahead, not readahead) | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |         self._snapshot = (decoder_state, decoder_buffer + readahead, pending) | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |         return readahead, pending | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _encode_decoder_state(self, ds, pos): | 
					
						
							|  |  |  |         x = 0 | 
					
						
							|  |  |  |         for i in bytes(ds): | 
					
						
							|  |  |  |             x = x<<8 | i | 
					
						
							|  |  |  |         return (x<<64) | pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _decode_decoder_state(self, pos): | 
					
						
							|  |  |  |         x, pos = divmod(pos, 1<<64) | 
					
						
							|  |  |  |         if not x: | 
					
						
							|  |  |  |             return None, pos | 
					
						
							|  |  |  |         b = b"" | 
					
						
							|  |  |  |         while x: | 
					
						
							|  |  |  |             b.append(x&0xff) | 
					
						
							|  |  |  |             x >>= 8 | 
					
						
							|  |  |  |         return str(b[::-1]), pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tell(self): | 
					
						
							|  |  |  |         if not self._seekable: | 
					
						
							|  |  |  |             raise IOError("Underlying stream is not seekable") | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         if not self._telling: | 
					
						
							|  |  |  |             raise IOError("Telling position disabled by next() call") | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |         position = self.buffer.tell() | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |         decoder = self._decoder | 
					
						
							|  |  |  |         if decoder is None or self._snapshot is None: | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |             assert self._pending == "" | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |             return position | 
					
						
							|  |  |  |         decoder_state, readahead, pending = self._snapshot | 
					
						
							|  |  |  |         position -= len(readahead) | 
					
						
							|  |  |  |         needed = len(pending) - len(self._pending) | 
					
						
							|  |  |  |         if not needed: | 
					
						
							|  |  |  |             return self._encode_decoder_state(decoder_state, position) | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |         saved_state = decoder.getstate() | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2007-05-08 20:18:39 +00:00
										 |  |  |             decoder.setstate((b"", decoder_state)) | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |             n = 0 | 
					
						
							|  |  |  |             bb = bytes(1) | 
					
						
							|  |  |  |             for i, bb[0] in enumerate(readahead): | 
					
						
							|  |  |  |                 n += len(decoder.decode(bb)) | 
					
						
							|  |  |  |                 if n >= needed: | 
					
						
							|  |  |  |                     decoder_buffer, decoder_state = decoder.getstate() | 
					
						
							|  |  |  |                     return self._encode_decoder_state( | 
					
						
							|  |  |  |                         decoder_state, | 
					
						
							|  |  |  |                         position + (i+1) - len(decoder_buffer)) | 
					
						
							|  |  |  |             raise IOError("Can't reconstruct logical file position") | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             decoder.setstate(saved_state) | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def seek(self, pos, whence=0): | 
					
						
							|  |  |  |         if not self._seekable: | 
					
						
							|  |  |  |             raise IOError("Underlying stream is not seekable") | 
					
						
							|  |  |  |         if whence == 1: | 
					
						
							|  |  |  |             if pos != 0: | 
					
						
							|  |  |  |                 raise IOError("Can't do nonzero cur-relative seeks") | 
					
						
							| 
									
										
										
										
											2007-04-12 05:24:24 +00:00
										 |  |  |             pos = self.tell() | 
					
						
							|  |  |  |             whence = 0 | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         if whence == 2: | 
					
						
							|  |  |  |             if pos != 0: | 
					
						
							|  |  |  |                 raise IOError("Can't do nonzero end-relative seeks") | 
					
						
							|  |  |  |             self.flush() | 
					
						
							|  |  |  |             pos = self.buffer.seek(0, 2) | 
					
						
							|  |  |  |             self._snapshot = None | 
					
						
							|  |  |  |             self._pending = "" | 
					
						
							|  |  |  |             self._decoder = None | 
					
						
							|  |  |  |             return pos | 
					
						
							|  |  |  |         if whence != 0: | 
					
						
							|  |  |  |             raise ValueError("Invalid whence (%r, should be 0, 1 or 2)" % | 
					
						
							|  |  |  |                              (whence,)) | 
					
						
							|  |  |  |         if pos < 0: | 
					
						
							|  |  |  |             raise ValueError("Negative seek position %r" % (pos,)) | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         self.flush() | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         orig_pos = pos | 
					
						
							|  |  |  |         ds, pos = self._decode_decoder_state(pos) | 
					
						
							|  |  |  |         if not ds: | 
					
						
							|  |  |  |             self.buffer.seek(pos) | 
					
						
							|  |  |  |             self._snapshot = None | 
					
						
							|  |  |  |             self._pending = "" | 
					
						
							|  |  |  |             self._decoder = None | 
					
						
							|  |  |  |             return pos | 
					
						
							| 
									
										
										
										
											2007-04-17 02:38:04 +00:00
										 |  |  |         decoder = self._decoder or self._get_decoder() | 
					
						
							|  |  |  |         decoder.set_state(("", ds)) | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         self.buffer.seek(pos) | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |         self._snapshot = (ds, b"", "") | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         self._pending = "" | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |         self._decoder = decoder | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |         return orig_pos | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def read(self, n=None): | 
					
						
							|  |  |  |         if n is None: | 
					
						
							|  |  |  |             n = -1 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         decoder = self._decoder or self._get_decoder() | 
					
						
							|  |  |  |         res = self._pending | 
					
						
							|  |  |  |         if n < 0: | 
					
						
							|  |  |  |             res += decoder.decode(self.buffer.read(), True) | 
					
						
							| 
									
										
										
										
											2007-04-10 00:22:16 +00:00
										 |  |  |             self._pending = "" | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |             self._snapshot = None | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |             return res.replace("\r\n", "\n") | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             while len(res) < n: | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |                 readahead, pending = self._read_chunk() | 
					
						
							|  |  |  |                 res += pending | 
					
						
							|  |  |  |                 if not readahead: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |                     break | 
					
						
							|  |  |  |             self._pending = res[n:] | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |             return res[:n].replace("\r\n", "\n") | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  |     def __next__(self): | 
					
						
							| 
									
										
										
										
											2007-04-11 16:07:50 +00:00
										 |  |  |         self._telling = False | 
					
						
							|  |  |  |         line = self.readline() | 
					
						
							|  |  |  |         if not line: | 
					
						
							|  |  |  |             self._snapshot = None | 
					
						
							|  |  |  |             self._telling = self._seekable | 
					
						
							|  |  |  |             raise StopIteration | 
					
						
							|  |  |  |         return line | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |     def readline(self, limit=None): | 
					
						
							|  |  |  |         if limit is not None: | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |             # XXX Hack to support limit argument, for backwards compatibility | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |             line = self.readline() | 
					
						
							|  |  |  |             if len(line) <= limit: | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |                 return line | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |             line, self._pending = line[:limit], line[limit:] + self._pending | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |             return line | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         line = self._pending | 
					
						
							|  |  |  |         start = 0 | 
					
						
							|  |  |  |         decoder = self._decoder or self._get_decoder() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             # In C we'd look for these in parallel of course. | 
					
						
							|  |  |  |             nlpos = line.find("\n", start) | 
					
						
							|  |  |  |             crpos = line.find("\r", start) | 
					
						
							|  |  |  |             if nlpos >= 0 and crpos >= 0: | 
					
						
							|  |  |  |                 endpos = min(nlpos, crpos) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 endpos = nlpos if nlpos >= 0 else crpos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if endpos != -1: | 
					
						
							|  |  |  |                 endc = line[endpos] | 
					
						
							|  |  |  |                 if endc == "\n": | 
					
						
							|  |  |  |                     ending = "\n" | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # We've seen \r - is it standalone, \r\n or \r at end of line? | 
					
						
							|  |  |  |                 if endpos + 1 < len(line): | 
					
						
							| 
									
										
										
										
											2007-04-11 01:09:03 +00:00
										 |  |  |                     if line[endpos+1] == "\n": | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |                         ending = "\r\n" | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         ending = "\r" | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |                 # There might be a following \n in the next block of data ... | 
					
						
							|  |  |  |                 start = endpos | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 start = len(line) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # No line ending seen yet - get more data | 
					
						
							|  |  |  |             while True: | 
					
						
							| 
									
										
										
										
											2007-04-11 14:19:59 +00:00
										 |  |  |                 readahead, pending = self._read_chunk() | 
					
						
							|  |  |  |                 more_line = pending | 
					
						
							|  |  |  |                 if more_line or not readahead: | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |             if not more_line: | 
					
						
							|  |  |  |                 ending = "" | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |                 endpos = len(line) | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             line += more_line | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nextpos = endpos + len(ending) | 
					
						
							|  |  |  |         self._pending = line[nextpos:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # XXX Update self.newlines here if we want to support that | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-08 23:59:06 +00:00
										 |  |  |         if self._fix_newlines and ending not in ("\n", ""): | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |             return line[:endpos] + "\n" | 
					
						
							| 
									
										
										
										
											2007-04-06 17:31:18 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2007-05-24 04:05:35 +00:00
										 |  |  |             return line[:nextpos] | 
					
						
							| 
									
										
										
										
											2007-05-17 23:59:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class StringIO(TextIOWrapper): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # XXX This is really slow, but fully functional | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, initial_value=""): | 
					
						
							|  |  |  |         super(StringIO, self).__init__(BytesIO(), "utf-8") | 
					
						
							|  |  |  |         if initial_value: | 
					
						
							|  |  |  |             self.write(initial_value) | 
					
						
							|  |  |  |             self.seek(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getvalue(self): | 
					
						
							|  |  |  |         return self.buffer.getvalue().decode("utf-8") |