1*cda5da8dSAndroid Build Coastguard Worker""" 2*cda5da8dSAndroid Build Coastguard WorkerPython implementation of the io module. 3*cda5da8dSAndroid Build Coastguard Worker""" 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Workerimport os 6*cda5da8dSAndroid Build Coastguard Workerimport abc 7*cda5da8dSAndroid Build Coastguard Workerimport codecs 8*cda5da8dSAndroid Build Coastguard Workerimport errno 9*cda5da8dSAndroid Build Coastguard Workerimport stat 10*cda5da8dSAndroid Build Coastguard Workerimport sys 11*cda5da8dSAndroid Build Coastguard Worker# Import _thread instead of threading to reduce startup cost 12*cda5da8dSAndroid Build Coastguard Workerfrom _thread import allocate_lock as Lock 13*cda5da8dSAndroid Build Coastguard Workerif sys.platform in {'win32', 'cygwin'}: 14*cda5da8dSAndroid Build Coastguard Worker from msvcrt import setmode as _setmode 15*cda5da8dSAndroid Build Coastguard Workerelse: 16*cda5da8dSAndroid Build Coastguard Worker _setmode = None 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard Workerimport io 19*cda5da8dSAndroid Build Coastguard Workerfrom io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Workervalid_seek_flags = {0, 1, 2} # Hardwired values 22*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, 'SEEK_HOLE') : 23*cda5da8dSAndroid Build Coastguard Worker valid_seek_flags.add(os.SEEK_HOLE) 24*cda5da8dSAndroid Build Coastguard Worker valid_seek_flags.add(os.SEEK_DATA) 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker# open() uses st_blksize whenever we can 27*cda5da8dSAndroid Build Coastguard WorkerDEFAULT_BUFFER_SIZE = 8 * 1024 # bytes 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker# NOTE: Base classes defined here are registered with the "official" ABCs 30*cda5da8dSAndroid Build Coastguard Worker# defined in io.py. We don't use real inheritance though, because we don't want 31*cda5da8dSAndroid Build Coastguard Worker# to inherit the C implementations. 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker# Rebind for compatibility 34*cda5da8dSAndroid Build Coastguard WorkerBlockingIOError = BlockingIOError 35*cda5da8dSAndroid Build Coastguard Worker 36*cda5da8dSAndroid Build Coastguard Worker# Does io.IOBase finalizer log the exception if the close() method fails? 37*cda5da8dSAndroid Build Coastguard Worker# The exception is ignored silently by default in release build. 38*cda5da8dSAndroid Build Coastguard Worker_IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode) 39*cda5da8dSAndroid Build Coastguard Worker# Does open() check its 'errors' argument? 40*cda5da8dSAndroid Build Coastguard Worker_CHECK_ERRORS = _IOBASE_EMITS_UNRAISABLE 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Workerdef text_encoding(encoding, stacklevel=2): 44*cda5da8dSAndroid Build Coastguard Worker """ 45*cda5da8dSAndroid Build Coastguard Worker A helper function to choose the text encoding. 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker When encoding is not None, this function returns it. 48*cda5da8dSAndroid Build Coastguard Worker Otherwise, this function returns the default text encoding 49*cda5da8dSAndroid Build Coastguard Worker (i.e. "locale" or "utf-8" depends on UTF-8 mode). 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker This function emits an EncodingWarning if *encoding* is None and 52*cda5da8dSAndroid Build Coastguard Worker sys.flags.warn_default_encoding is true. 53*cda5da8dSAndroid Build Coastguard Worker 54*cda5da8dSAndroid Build Coastguard Worker This can be used in APIs with an encoding=None parameter 55*cda5da8dSAndroid Build Coastguard Worker that pass it to TextIOWrapper or open. 56*cda5da8dSAndroid Build Coastguard Worker However, please consider using encoding="utf-8" for new APIs. 57*cda5da8dSAndroid Build Coastguard Worker """ 58*cda5da8dSAndroid Build Coastguard Worker if encoding is None: 59*cda5da8dSAndroid Build Coastguard Worker if sys.flags.utf8_mode: 60*cda5da8dSAndroid Build Coastguard Worker encoding = "utf-8" 61*cda5da8dSAndroid Build Coastguard Worker else: 62*cda5da8dSAndroid Build Coastguard Worker encoding = "locale" 63*cda5da8dSAndroid Build Coastguard Worker if sys.flags.warn_default_encoding: 64*cda5da8dSAndroid Build Coastguard Worker import warnings 65*cda5da8dSAndroid Build Coastguard Worker warnings.warn("'encoding' argument not specified.", 66*cda5da8dSAndroid Build Coastguard Worker EncodingWarning, stacklevel + 1) 67*cda5da8dSAndroid Build Coastguard Worker return encoding 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Worker 70*cda5da8dSAndroid Build Coastguard Worker# Wrapper for builtins.open 71*cda5da8dSAndroid Build Coastguard Worker# 72*cda5da8dSAndroid Build Coastguard Worker# Trick so that open() won't become a bound method when stored 73*cda5da8dSAndroid Build Coastguard Worker# as a class variable (as dbm.dumb does). 74*cda5da8dSAndroid Build Coastguard Worker# 75*cda5da8dSAndroid Build Coastguard Worker# See init_set_builtins_open() in Python/pylifecycle.c. 76*cda5da8dSAndroid Build Coastguard Worker@staticmethod 77*cda5da8dSAndroid Build Coastguard Workerdef open(file, mode="r", buffering=-1, encoding=None, errors=None, 78*cda5da8dSAndroid Build Coastguard Worker newline=None, closefd=True, opener=None): 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker r"""Open file and return a stream. Raise OSError upon failure. 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Worker file is either a text or byte string giving the name (and the path 83*cda5da8dSAndroid Build Coastguard Worker if the file isn't in the current working directory) of the file to 84*cda5da8dSAndroid Build Coastguard Worker be opened or an integer file descriptor of the file to be 85*cda5da8dSAndroid Build Coastguard Worker wrapped. (If a file descriptor is given, it is closed when the 86*cda5da8dSAndroid Build Coastguard Worker returned I/O object is closed, unless closefd is set to False.) 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Worker mode is an optional string that specifies the mode in which the file is 89*cda5da8dSAndroid Build Coastguard Worker opened. It defaults to 'r' which means open for reading in text mode. Other 90*cda5da8dSAndroid Build Coastguard Worker common values are 'w' for writing (truncating the file if it already 91*cda5da8dSAndroid Build Coastguard Worker exists), 'x' for exclusive creation of a new file, and 'a' for appending 92*cda5da8dSAndroid Build Coastguard Worker (which on some Unix systems, means that all writes append to the end of the 93*cda5da8dSAndroid Build Coastguard Worker file regardless of the current seek position). In text mode, if encoding is 94*cda5da8dSAndroid Build Coastguard Worker not specified the encoding used is platform dependent. (For reading and 95*cda5da8dSAndroid Build Coastguard Worker writing raw bytes use binary mode and leave encoding unspecified.) The 96*cda5da8dSAndroid Build Coastguard Worker available modes are: 97*cda5da8dSAndroid Build Coastguard Worker 98*cda5da8dSAndroid Build Coastguard Worker ========= =============================================================== 99*cda5da8dSAndroid Build Coastguard Worker Character Meaning 100*cda5da8dSAndroid Build Coastguard Worker --------- --------------------------------------------------------------- 101*cda5da8dSAndroid Build Coastguard Worker 'r' open for reading (default) 102*cda5da8dSAndroid Build Coastguard Worker 'w' open for writing, truncating the file first 103*cda5da8dSAndroid Build Coastguard Worker 'x' create a new file and open it for writing 104*cda5da8dSAndroid Build Coastguard Worker 'a' open for writing, appending to the end of the file if it exists 105*cda5da8dSAndroid Build Coastguard Worker 'b' binary mode 106*cda5da8dSAndroid Build Coastguard Worker 't' text mode (default) 107*cda5da8dSAndroid Build Coastguard Worker '+' open a disk file for updating (reading and writing) 108*cda5da8dSAndroid Build Coastguard Worker ========= =============================================================== 109*cda5da8dSAndroid Build Coastguard Worker 110*cda5da8dSAndroid Build Coastguard Worker The default mode is 'rt' (open for reading text). For binary random 111*cda5da8dSAndroid Build Coastguard Worker access, the mode 'w+b' opens and truncates the file to 0 bytes, while 112*cda5da8dSAndroid Build Coastguard Worker 'r+b' opens the file without truncation. The 'x' mode implies 'w' and 113*cda5da8dSAndroid Build Coastguard Worker raises an `FileExistsError` if the file already exists. 114*cda5da8dSAndroid Build Coastguard Worker 115*cda5da8dSAndroid Build Coastguard Worker Python distinguishes between files opened in binary and text modes, 116*cda5da8dSAndroid Build Coastguard Worker even when the underlying operating system doesn't. Files opened in 117*cda5da8dSAndroid Build Coastguard Worker binary mode (appending 'b' to the mode argument) return contents as 118*cda5da8dSAndroid Build Coastguard Worker bytes objects without any decoding. In text mode (the default, or when 119*cda5da8dSAndroid Build Coastguard Worker 't' is appended to the mode argument), the contents of the file are 120*cda5da8dSAndroid Build Coastguard Worker returned as strings, the bytes having been first decoded using a 121*cda5da8dSAndroid Build Coastguard Worker platform-dependent encoding or using the specified encoding if given. 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker buffering is an optional integer used to set the buffering policy. 124*cda5da8dSAndroid Build Coastguard Worker Pass 0 to switch buffering off (only allowed in binary mode), 1 to select 125*cda5da8dSAndroid Build Coastguard Worker line buffering (only usable in text mode), and an integer > 1 to indicate 126*cda5da8dSAndroid Build Coastguard Worker the size of a fixed-size chunk buffer. When no buffering argument is 127*cda5da8dSAndroid Build Coastguard Worker given, the default buffering policy works as follows: 128*cda5da8dSAndroid Build Coastguard Worker 129*cda5da8dSAndroid Build Coastguard Worker * Binary files are buffered in fixed-size chunks; the size of the buffer 130*cda5da8dSAndroid Build Coastguard Worker is chosen using a heuristic trying to determine the underlying device's 131*cda5da8dSAndroid Build Coastguard Worker "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`. 132*cda5da8dSAndroid Build Coastguard Worker On many systems, the buffer will typically be 4096 or 8192 bytes long. 133*cda5da8dSAndroid Build Coastguard Worker 134*cda5da8dSAndroid Build Coastguard Worker * "Interactive" text files (files for which isatty() returns True) 135*cda5da8dSAndroid Build Coastguard Worker use line buffering. Other text files use the policy described above 136*cda5da8dSAndroid Build Coastguard Worker for binary files. 137*cda5da8dSAndroid Build Coastguard Worker 138*cda5da8dSAndroid Build Coastguard Worker encoding is the str name of the encoding used to decode or encode the 139*cda5da8dSAndroid Build Coastguard Worker file. This should only be used in text mode. The default encoding is 140*cda5da8dSAndroid Build Coastguard Worker platform dependent, but any encoding supported by Python can be 141*cda5da8dSAndroid Build Coastguard Worker passed. See the codecs module for the list of supported encodings. 142*cda5da8dSAndroid Build Coastguard Worker 143*cda5da8dSAndroid Build Coastguard Worker errors is an optional string that specifies how encoding errors are to 144*cda5da8dSAndroid Build Coastguard Worker be handled---this argument should not be used in binary mode. Pass 145*cda5da8dSAndroid Build Coastguard Worker 'strict' to raise a ValueError exception if there is an encoding error 146*cda5da8dSAndroid Build Coastguard Worker (the default of None has the same effect), or pass 'ignore' to ignore 147*cda5da8dSAndroid Build Coastguard Worker errors. (Note that ignoring encoding errors can lead to data loss.) 148*cda5da8dSAndroid Build Coastguard Worker See the documentation for codecs.register for a list of the permitted 149*cda5da8dSAndroid Build Coastguard Worker encoding error strings. 150*cda5da8dSAndroid Build Coastguard Worker 151*cda5da8dSAndroid Build Coastguard Worker newline is a string controlling how universal newlines works (it only 152*cda5da8dSAndroid Build Coastguard Worker applies to text mode). It can be None, '', '\n', '\r', and '\r\n'. It works 153*cda5da8dSAndroid Build Coastguard Worker as follows: 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Worker * On input, if newline is None, universal newlines mode is 156*cda5da8dSAndroid Build Coastguard Worker enabled. Lines in the input can end in '\n', '\r', or '\r\n', and 157*cda5da8dSAndroid Build Coastguard Worker these are translated into '\n' before being returned to the 158*cda5da8dSAndroid Build Coastguard Worker caller. If it is '', universal newline mode is enabled, but line 159*cda5da8dSAndroid Build Coastguard Worker endings are returned to the caller untranslated. If it has any of 160*cda5da8dSAndroid Build Coastguard Worker the other legal values, input lines are only terminated by the given 161*cda5da8dSAndroid Build Coastguard Worker string, and the line ending is returned to the caller untranslated. 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker * On output, if newline is None, any '\n' characters written are 164*cda5da8dSAndroid Build Coastguard Worker translated to the system default line separator, os.linesep. If 165*cda5da8dSAndroid Build Coastguard Worker newline is '', no translation takes place. If newline is any of the 166*cda5da8dSAndroid Build Coastguard Worker other legal values, any '\n' characters written are translated to 167*cda5da8dSAndroid Build Coastguard Worker the given string. 168*cda5da8dSAndroid Build Coastguard Worker 169*cda5da8dSAndroid Build Coastguard Worker closedfd is a bool. If closefd is False, the underlying file descriptor will 170*cda5da8dSAndroid Build Coastguard Worker be kept open when the file is closed. This does not work when a file name is 171*cda5da8dSAndroid Build Coastguard Worker given and must be True in that case. 172*cda5da8dSAndroid Build Coastguard Worker 173*cda5da8dSAndroid Build Coastguard Worker The newly created file is non-inheritable. 174*cda5da8dSAndroid Build Coastguard Worker 175*cda5da8dSAndroid Build Coastguard Worker A custom opener can be used by passing a callable as *opener*. The 176*cda5da8dSAndroid Build Coastguard Worker underlying file descriptor for the file object is then obtained by calling 177*cda5da8dSAndroid Build Coastguard Worker *opener* with (*file*, *flags*). *opener* must return an open file 178*cda5da8dSAndroid Build Coastguard Worker descriptor (passing os.open as *opener* results in functionality similar to 179*cda5da8dSAndroid Build Coastguard Worker passing None). 180*cda5da8dSAndroid Build Coastguard Worker 181*cda5da8dSAndroid Build Coastguard Worker open() returns a file object whose type depends on the mode, and 182*cda5da8dSAndroid Build Coastguard Worker through which the standard file operations such as reading and writing 183*cda5da8dSAndroid Build Coastguard Worker are performed. When open() is used to open a file in a text mode ('w', 184*cda5da8dSAndroid Build Coastguard Worker 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open 185*cda5da8dSAndroid Build Coastguard Worker a file in a binary mode, the returned class varies: in read binary 186*cda5da8dSAndroid Build Coastguard Worker mode, it returns a BufferedReader; in write binary and append binary 187*cda5da8dSAndroid Build Coastguard Worker modes, it returns a BufferedWriter, and in read/write mode, it returns 188*cda5da8dSAndroid Build Coastguard Worker a BufferedRandom. 189*cda5da8dSAndroid Build Coastguard Worker 190*cda5da8dSAndroid Build Coastguard Worker It is also possible to use a string or bytearray as a file for both 191*cda5da8dSAndroid Build Coastguard Worker reading and writing. For strings StringIO can be used like a file 192*cda5da8dSAndroid Build Coastguard Worker opened in a text mode, and for bytes a BytesIO can be used like a file 193*cda5da8dSAndroid Build Coastguard Worker opened in a binary mode. 194*cda5da8dSAndroid Build Coastguard Worker """ 195*cda5da8dSAndroid Build Coastguard Worker if not isinstance(file, int): 196*cda5da8dSAndroid Build Coastguard Worker file = os.fspath(file) 197*cda5da8dSAndroid Build Coastguard Worker if not isinstance(file, (str, bytes, int)): 198*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid file: %r" % file) 199*cda5da8dSAndroid Build Coastguard Worker if not isinstance(mode, str): 200*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid mode: %r" % mode) 201*cda5da8dSAndroid Build Coastguard Worker if not isinstance(buffering, int): 202*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid buffering: %r" % buffering) 203*cda5da8dSAndroid Build Coastguard Worker if encoding is not None and not isinstance(encoding, str): 204*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid encoding: %r" % encoding) 205*cda5da8dSAndroid Build Coastguard Worker if errors is not None and not isinstance(errors, str): 206*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid errors: %r" % errors) 207*cda5da8dSAndroid Build Coastguard Worker modes = set(mode) 208*cda5da8dSAndroid Build Coastguard Worker if modes - set("axrwb+t") or len(mode) > len(modes): 209*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid mode: %r" % mode) 210*cda5da8dSAndroid Build Coastguard Worker creating = "x" in modes 211*cda5da8dSAndroid Build Coastguard Worker reading = "r" in modes 212*cda5da8dSAndroid Build Coastguard Worker writing = "w" in modes 213*cda5da8dSAndroid Build Coastguard Worker appending = "a" in modes 214*cda5da8dSAndroid Build Coastguard Worker updating = "+" in modes 215*cda5da8dSAndroid Build Coastguard Worker text = "t" in modes 216*cda5da8dSAndroid Build Coastguard Worker binary = "b" in modes 217*cda5da8dSAndroid Build Coastguard Worker if text and binary: 218*cda5da8dSAndroid Build Coastguard Worker raise ValueError("can't have text and binary mode at once") 219*cda5da8dSAndroid Build Coastguard Worker if creating + reading + writing + appending > 1: 220*cda5da8dSAndroid Build Coastguard Worker raise ValueError("can't have read/write/append mode at once") 221*cda5da8dSAndroid Build Coastguard Worker if not (creating or reading or writing or appending): 222*cda5da8dSAndroid Build Coastguard Worker raise ValueError("must have exactly one of read/write/append mode") 223*cda5da8dSAndroid Build Coastguard Worker if binary and encoding is not None: 224*cda5da8dSAndroid Build Coastguard Worker raise ValueError("binary mode doesn't take an encoding argument") 225*cda5da8dSAndroid Build Coastguard Worker if binary and errors is not None: 226*cda5da8dSAndroid Build Coastguard Worker raise ValueError("binary mode doesn't take an errors argument") 227*cda5da8dSAndroid Build Coastguard Worker if binary and newline is not None: 228*cda5da8dSAndroid Build Coastguard Worker raise ValueError("binary mode doesn't take a newline argument") 229*cda5da8dSAndroid Build Coastguard Worker if binary and buffering == 1: 230*cda5da8dSAndroid Build Coastguard Worker import warnings 231*cda5da8dSAndroid Build Coastguard Worker warnings.warn("line buffering (buffering=1) isn't supported in binary " 232*cda5da8dSAndroid Build Coastguard Worker "mode, the default buffer size will be used", 233*cda5da8dSAndroid Build Coastguard Worker RuntimeWarning, 2) 234*cda5da8dSAndroid Build Coastguard Worker raw = FileIO(file, 235*cda5da8dSAndroid Build Coastguard Worker (creating and "x" or "") + 236*cda5da8dSAndroid Build Coastguard Worker (reading and "r" or "") + 237*cda5da8dSAndroid Build Coastguard Worker (writing and "w" or "") + 238*cda5da8dSAndroid Build Coastguard Worker (appending and "a" or "") + 239*cda5da8dSAndroid Build Coastguard Worker (updating and "+" or ""), 240*cda5da8dSAndroid Build Coastguard Worker closefd, opener=opener) 241*cda5da8dSAndroid Build Coastguard Worker result = raw 242*cda5da8dSAndroid Build Coastguard Worker try: 243*cda5da8dSAndroid Build Coastguard Worker line_buffering = False 244*cda5da8dSAndroid Build Coastguard Worker if buffering == 1 or buffering < 0 and raw.isatty(): 245*cda5da8dSAndroid Build Coastguard Worker buffering = -1 246*cda5da8dSAndroid Build Coastguard Worker line_buffering = True 247*cda5da8dSAndroid Build Coastguard Worker if buffering < 0: 248*cda5da8dSAndroid Build Coastguard Worker buffering = DEFAULT_BUFFER_SIZE 249*cda5da8dSAndroid Build Coastguard Worker try: 250*cda5da8dSAndroid Build Coastguard Worker bs = os.fstat(raw.fileno()).st_blksize 251*cda5da8dSAndroid Build Coastguard Worker except (OSError, AttributeError): 252*cda5da8dSAndroid Build Coastguard Worker pass 253*cda5da8dSAndroid Build Coastguard Worker else: 254*cda5da8dSAndroid Build Coastguard Worker if bs > 1: 255*cda5da8dSAndroid Build Coastguard Worker buffering = bs 256*cda5da8dSAndroid Build Coastguard Worker if buffering < 0: 257*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid buffering size") 258*cda5da8dSAndroid Build Coastguard Worker if buffering == 0: 259*cda5da8dSAndroid Build Coastguard Worker if binary: 260*cda5da8dSAndroid Build Coastguard Worker return result 261*cda5da8dSAndroid Build Coastguard Worker raise ValueError("can't have unbuffered text I/O") 262*cda5da8dSAndroid Build Coastguard Worker if updating: 263*cda5da8dSAndroid Build Coastguard Worker buffer = BufferedRandom(raw, buffering) 264*cda5da8dSAndroid Build Coastguard Worker elif creating or writing or appending: 265*cda5da8dSAndroid Build Coastguard Worker buffer = BufferedWriter(raw, buffering) 266*cda5da8dSAndroid Build Coastguard Worker elif reading: 267*cda5da8dSAndroid Build Coastguard Worker buffer = BufferedReader(raw, buffering) 268*cda5da8dSAndroid Build Coastguard Worker else: 269*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unknown mode: %r" % mode) 270*cda5da8dSAndroid Build Coastguard Worker result = buffer 271*cda5da8dSAndroid Build Coastguard Worker if binary: 272*cda5da8dSAndroid Build Coastguard Worker return result 273*cda5da8dSAndroid Build Coastguard Worker encoding = text_encoding(encoding) 274*cda5da8dSAndroid Build Coastguard Worker text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) 275*cda5da8dSAndroid Build Coastguard Worker result = text 276*cda5da8dSAndroid Build Coastguard Worker text.mode = mode 277*cda5da8dSAndroid Build Coastguard Worker return result 278*cda5da8dSAndroid Build Coastguard Worker except: 279*cda5da8dSAndroid Build Coastguard Worker result.close() 280*cda5da8dSAndroid Build Coastguard Worker raise 281*cda5da8dSAndroid Build Coastguard Worker 282*cda5da8dSAndroid Build Coastguard Worker# Define a default pure-Python implementation for open_code() 283*cda5da8dSAndroid Build Coastguard Worker# that does not allow hooks. Warn on first use. Defined for tests. 284*cda5da8dSAndroid Build Coastguard Workerdef _open_code_with_warning(path): 285*cda5da8dSAndroid Build Coastguard Worker """Opens the provided file with mode ``'rb'``. This function 286*cda5da8dSAndroid Build Coastguard Worker should be used when the intent is to treat the contents as 287*cda5da8dSAndroid Build Coastguard Worker executable code. 288*cda5da8dSAndroid Build Coastguard Worker 289*cda5da8dSAndroid Build Coastguard Worker ``path`` should be an absolute path. 290*cda5da8dSAndroid Build Coastguard Worker 291*cda5da8dSAndroid Build Coastguard Worker When supported by the runtime, this function can be hooked 292*cda5da8dSAndroid Build Coastguard Worker in order to allow embedders more control over code files. 293*cda5da8dSAndroid Build Coastguard Worker This functionality is not supported on the current runtime. 294*cda5da8dSAndroid Build Coastguard Worker """ 295*cda5da8dSAndroid Build Coastguard Worker import warnings 296*cda5da8dSAndroid Build Coastguard Worker warnings.warn("_pyio.open_code() may not be using hooks", 297*cda5da8dSAndroid Build Coastguard Worker RuntimeWarning, 2) 298*cda5da8dSAndroid Build Coastguard Worker return open(path, "rb") 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Workertry: 301*cda5da8dSAndroid Build Coastguard Worker open_code = io.open_code 302*cda5da8dSAndroid Build Coastguard Workerexcept AttributeError: 303*cda5da8dSAndroid Build Coastguard Worker open_code = _open_code_with_warning 304*cda5da8dSAndroid Build Coastguard Worker 305*cda5da8dSAndroid Build Coastguard Worker 306*cda5da8dSAndroid Build Coastguard Workerdef __getattr__(name): 307*cda5da8dSAndroid Build Coastguard Worker if name == "OpenWrapper": 308*cda5da8dSAndroid Build Coastguard Worker # bpo-43680: Until Python 3.9, _pyio.open was not a static method and 309*cda5da8dSAndroid Build Coastguard Worker # builtins.open was set to OpenWrapper to not become a bound method 310*cda5da8dSAndroid Build Coastguard Worker # when set to a class variable. _io.open is a built-in function whereas 311*cda5da8dSAndroid Build Coastguard Worker # _pyio.open is a Python function. In Python 3.10, _pyio.open() is now 312*cda5da8dSAndroid Build Coastguard Worker # a static method, and builtins.open() is now io.open(). 313*cda5da8dSAndroid Build Coastguard Worker import warnings 314*cda5da8dSAndroid Build Coastguard Worker warnings.warn('OpenWrapper is deprecated, use open instead', 315*cda5da8dSAndroid Build Coastguard Worker DeprecationWarning, stacklevel=2) 316*cda5da8dSAndroid Build Coastguard Worker global OpenWrapper 317*cda5da8dSAndroid Build Coastguard Worker OpenWrapper = open 318*cda5da8dSAndroid Build Coastguard Worker return OpenWrapper 319*cda5da8dSAndroid Build Coastguard Worker raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 320*cda5da8dSAndroid Build Coastguard Worker 321*cda5da8dSAndroid Build Coastguard Worker 322*cda5da8dSAndroid Build Coastguard Worker# In normal operation, both `UnsupportedOperation`s should be bound to the 323*cda5da8dSAndroid Build Coastguard Worker# same object. 324*cda5da8dSAndroid Build Coastguard Workertry: 325*cda5da8dSAndroid Build Coastguard Worker UnsupportedOperation = io.UnsupportedOperation 326*cda5da8dSAndroid Build Coastguard Workerexcept AttributeError: 327*cda5da8dSAndroid Build Coastguard Worker class UnsupportedOperation(OSError, ValueError): 328*cda5da8dSAndroid Build Coastguard Worker pass 329*cda5da8dSAndroid Build Coastguard Worker 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Workerclass IOBase(metaclass=abc.ABCMeta): 332*cda5da8dSAndroid Build Coastguard Worker 333*cda5da8dSAndroid Build Coastguard Worker """The abstract base class for all I/O classes. 334*cda5da8dSAndroid Build Coastguard Worker 335*cda5da8dSAndroid Build Coastguard Worker This class provides dummy implementations for many methods that 336*cda5da8dSAndroid Build Coastguard Worker derived classes can override selectively; the default implementations 337*cda5da8dSAndroid Build Coastguard Worker represent a file that cannot be read, written or seeked. 338*cda5da8dSAndroid Build Coastguard Worker 339*cda5da8dSAndroid Build Coastguard Worker Even though IOBase does not declare read or write because 340*cda5da8dSAndroid Build Coastguard Worker their signatures will vary, implementations and clients should 341*cda5da8dSAndroid Build Coastguard Worker consider those methods part of the interface. Also, implementations 342*cda5da8dSAndroid Build Coastguard Worker may raise UnsupportedOperation when operations they do not support are 343*cda5da8dSAndroid Build Coastguard Worker called. 344*cda5da8dSAndroid Build Coastguard Worker 345*cda5da8dSAndroid Build Coastguard Worker The basic type used for binary data read from or written to a file is 346*cda5da8dSAndroid Build Coastguard Worker bytes. Other bytes-like objects are accepted as method arguments too. 347*cda5da8dSAndroid Build Coastguard Worker Text I/O classes work with str data. 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Worker Note that calling any method (even inquiries) on a closed stream is 350*cda5da8dSAndroid Build Coastguard Worker undefined. Implementations may raise OSError in this case. 351*cda5da8dSAndroid Build Coastguard Worker 352*cda5da8dSAndroid Build Coastguard Worker IOBase (and its subclasses) support the iterator protocol, meaning 353*cda5da8dSAndroid Build Coastguard Worker that an IOBase object can be iterated over yielding the lines in a 354*cda5da8dSAndroid Build Coastguard Worker stream. 355*cda5da8dSAndroid Build Coastguard Worker 356*cda5da8dSAndroid Build Coastguard Worker IOBase also supports the :keyword:`with` statement. In this example, 357*cda5da8dSAndroid Build Coastguard Worker fp is closed after the suite of the with statement is complete: 358*cda5da8dSAndroid Build Coastguard Worker 359*cda5da8dSAndroid Build Coastguard Worker with open('spam.txt', 'r') as fp: 360*cda5da8dSAndroid Build Coastguard Worker fp.write('Spam and eggs!') 361*cda5da8dSAndroid Build Coastguard Worker """ 362*cda5da8dSAndroid Build Coastguard Worker 363*cda5da8dSAndroid Build Coastguard Worker ### Internal ### 364*cda5da8dSAndroid Build Coastguard Worker 365*cda5da8dSAndroid Build Coastguard Worker def _unsupported(self, name): 366*cda5da8dSAndroid Build Coastguard Worker """Internal: raise an OSError exception for unsupported operations.""" 367*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("%s.%s() not supported" % 368*cda5da8dSAndroid Build Coastguard Worker (self.__class__.__name__, name)) 369*cda5da8dSAndroid Build Coastguard Worker 370*cda5da8dSAndroid Build Coastguard Worker ### Positioning ### 371*cda5da8dSAndroid Build Coastguard Worker 372*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 373*cda5da8dSAndroid Build Coastguard Worker """Change stream position. 374*cda5da8dSAndroid Build Coastguard Worker 375*cda5da8dSAndroid Build Coastguard Worker Change the stream position to byte offset pos. Argument pos is 376*cda5da8dSAndroid Build Coastguard Worker interpreted relative to the position indicated by whence. Values 377*cda5da8dSAndroid Build Coastguard Worker for whence are ints: 378*cda5da8dSAndroid Build Coastguard Worker 379*cda5da8dSAndroid Build Coastguard Worker * 0 -- start of stream (the default); offset should be zero or positive 380*cda5da8dSAndroid Build Coastguard Worker * 1 -- current stream position; offset may be negative 381*cda5da8dSAndroid Build Coastguard Worker * 2 -- end of stream; offset is usually negative 382*cda5da8dSAndroid Build Coastguard Worker Some operating systems / file systems could provide additional values. 383*cda5da8dSAndroid Build Coastguard Worker 384*cda5da8dSAndroid Build Coastguard Worker Return an int indicating the new absolute position. 385*cda5da8dSAndroid Build Coastguard Worker """ 386*cda5da8dSAndroid Build Coastguard Worker self._unsupported("seek") 387*cda5da8dSAndroid Build Coastguard Worker 388*cda5da8dSAndroid Build Coastguard Worker def tell(self): 389*cda5da8dSAndroid Build Coastguard Worker """Return an int indicating the current stream position.""" 390*cda5da8dSAndroid Build Coastguard Worker return self.seek(0, 1) 391*cda5da8dSAndroid Build Coastguard Worker 392*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 393*cda5da8dSAndroid Build Coastguard Worker """Truncate file to size bytes. 394*cda5da8dSAndroid Build Coastguard Worker 395*cda5da8dSAndroid Build Coastguard Worker Size defaults to the current IO position as reported by tell(). Return 396*cda5da8dSAndroid Build Coastguard Worker the new size. 397*cda5da8dSAndroid Build Coastguard Worker """ 398*cda5da8dSAndroid Build Coastguard Worker self._unsupported("truncate") 399*cda5da8dSAndroid Build Coastguard Worker 400*cda5da8dSAndroid Build Coastguard Worker ### Flush and close ### 401*cda5da8dSAndroid Build Coastguard Worker 402*cda5da8dSAndroid Build Coastguard Worker def flush(self): 403*cda5da8dSAndroid Build Coastguard Worker """Flush write buffers, if applicable. 404*cda5da8dSAndroid Build Coastguard Worker 405*cda5da8dSAndroid Build Coastguard Worker This is not implemented for read-only and non-blocking streams. 406*cda5da8dSAndroid Build Coastguard Worker """ 407*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 408*cda5da8dSAndroid Build Coastguard Worker # XXX Should this return the number of bytes written??? 409*cda5da8dSAndroid Build Coastguard Worker 410*cda5da8dSAndroid Build Coastguard Worker __closed = False 411*cda5da8dSAndroid Build Coastguard Worker 412*cda5da8dSAndroid Build Coastguard Worker def close(self): 413*cda5da8dSAndroid Build Coastguard Worker """Flush and close the IO object. 414*cda5da8dSAndroid Build Coastguard Worker 415*cda5da8dSAndroid Build Coastguard Worker This method has no effect if the file is already closed. 416*cda5da8dSAndroid Build Coastguard Worker """ 417*cda5da8dSAndroid Build Coastguard Worker if not self.__closed: 418*cda5da8dSAndroid Build Coastguard Worker try: 419*cda5da8dSAndroid Build Coastguard Worker self.flush() 420*cda5da8dSAndroid Build Coastguard Worker finally: 421*cda5da8dSAndroid Build Coastguard Worker self.__closed = True 422*cda5da8dSAndroid Build Coastguard Worker 423*cda5da8dSAndroid Build Coastguard Worker def __del__(self): 424*cda5da8dSAndroid Build Coastguard Worker """Destructor. Calls close().""" 425*cda5da8dSAndroid Build Coastguard Worker try: 426*cda5da8dSAndroid Build Coastguard Worker closed = self.closed 427*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 428*cda5da8dSAndroid Build Coastguard Worker # If getting closed fails, then the object is probably 429*cda5da8dSAndroid Build Coastguard Worker # in an unusable state, so ignore. 430*cda5da8dSAndroid Build Coastguard Worker return 431*cda5da8dSAndroid Build Coastguard Worker 432*cda5da8dSAndroid Build Coastguard Worker if closed: 433*cda5da8dSAndroid Build Coastguard Worker return 434*cda5da8dSAndroid Build Coastguard Worker 435*cda5da8dSAndroid Build Coastguard Worker if _IOBASE_EMITS_UNRAISABLE: 436*cda5da8dSAndroid Build Coastguard Worker self.close() 437*cda5da8dSAndroid Build Coastguard Worker else: 438*cda5da8dSAndroid Build Coastguard Worker # The try/except block is in case this is called at program 439*cda5da8dSAndroid Build Coastguard Worker # exit time, when it's possible that globals have already been 440*cda5da8dSAndroid Build Coastguard Worker # deleted, and then the close() call might fail. Since 441*cda5da8dSAndroid Build Coastguard Worker # there's nothing we can do about such failures and they annoy 442*cda5da8dSAndroid Build Coastguard Worker # the end users, we suppress the traceback. 443*cda5da8dSAndroid Build Coastguard Worker try: 444*cda5da8dSAndroid Build Coastguard Worker self.close() 445*cda5da8dSAndroid Build Coastguard Worker except: 446*cda5da8dSAndroid Build Coastguard Worker pass 447*cda5da8dSAndroid Build Coastguard Worker 448*cda5da8dSAndroid Build Coastguard Worker ### Inquiries ### 449*cda5da8dSAndroid Build Coastguard Worker 450*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 451*cda5da8dSAndroid Build Coastguard Worker """Return a bool indicating whether object supports random access. 452*cda5da8dSAndroid Build Coastguard Worker 453*cda5da8dSAndroid Build Coastguard Worker If False, seek(), tell() and truncate() will raise OSError. 454*cda5da8dSAndroid Build Coastguard Worker This method may need to do a test seek(). 455*cda5da8dSAndroid Build Coastguard Worker """ 456*cda5da8dSAndroid Build Coastguard Worker return False 457*cda5da8dSAndroid Build Coastguard Worker 458*cda5da8dSAndroid Build Coastguard Worker def _checkSeekable(self, msg=None): 459*cda5da8dSAndroid Build Coastguard Worker """Internal: raise UnsupportedOperation if file is not seekable 460*cda5da8dSAndroid Build Coastguard Worker """ 461*cda5da8dSAndroid Build Coastguard Worker if not self.seekable(): 462*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("File or stream is not seekable." 463*cda5da8dSAndroid Build Coastguard Worker if msg is None else msg) 464*cda5da8dSAndroid Build Coastguard Worker 465*cda5da8dSAndroid Build Coastguard Worker def readable(self): 466*cda5da8dSAndroid Build Coastguard Worker """Return a bool indicating whether object was opened for reading. 467*cda5da8dSAndroid Build Coastguard Worker 468*cda5da8dSAndroid Build Coastguard Worker If False, read() will raise OSError. 469*cda5da8dSAndroid Build Coastguard Worker """ 470*cda5da8dSAndroid Build Coastguard Worker return False 471*cda5da8dSAndroid Build Coastguard Worker 472*cda5da8dSAndroid Build Coastguard Worker def _checkReadable(self, msg=None): 473*cda5da8dSAndroid Build Coastguard Worker """Internal: raise UnsupportedOperation if file is not readable 474*cda5da8dSAndroid Build Coastguard Worker """ 475*cda5da8dSAndroid Build Coastguard Worker if not self.readable(): 476*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("File or stream is not readable." 477*cda5da8dSAndroid Build Coastguard Worker if msg is None else msg) 478*cda5da8dSAndroid Build Coastguard Worker 479*cda5da8dSAndroid Build Coastguard Worker def writable(self): 480*cda5da8dSAndroid Build Coastguard Worker """Return a bool indicating whether object was opened for writing. 481*cda5da8dSAndroid Build Coastguard Worker 482*cda5da8dSAndroid Build Coastguard Worker If False, write() and truncate() will raise OSError. 483*cda5da8dSAndroid Build Coastguard Worker """ 484*cda5da8dSAndroid Build Coastguard Worker return False 485*cda5da8dSAndroid Build Coastguard Worker 486*cda5da8dSAndroid Build Coastguard Worker def _checkWritable(self, msg=None): 487*cda5da8dSAndroid Build Coastguard Worker """Internal: raise UnsupportedOperation if file is not writable 488*cda5da8dSAndroid Build Coastguard Worker """ 489*cda5da8dSAndroid Build Coastguard Worker if not self.writable(): 490*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("File or stream is not writable." 491*cda5da8dSAndroid Build Coastguard Worker if msg is None else msg) 492*cda5da8dSAndroid Build Coastguard Worker 493*cda5da8dSAndroid Build Coastguard Worker @property 494*cda5da8dSAndroid Build Coastguard Worker def closed(self): 495*cda5da8dSAndroid Build Coastguard Worker """closed: bool. True iff the file has been closed. 496*cda5da8dSAndroid Build Coastguard Worker 497*cda5da8dSAndroid Build Coastguard Worker For backwards compatibility, this is a property, not a predicate. 498*cda5da8dSAndroid Build Coastguard Worker """ 499*cda5da8dSAndroid Build Coastguard Worker return self.__closed 500*cda5da8dSAndroid Build Coastguard Worker 501*cda5da8dSAndroid Build Coastguard Worker def _checkClosed(self, msg=None): 502*cda5da8dSAndroid Build Coastguard Worker """Internal: raise a ValueError if file is closed 503*cda5da8dSAndroid Build Coastguard Worker """ 504*cda5da8dSAndroid Build Coastguard Worker if self.closed: 505*cda5da8dSAndroid Build Coastguard Worker raise ValueError("I/O operation on closed file." 506*cda5da8dSAndroid Build Coastguard Worker if msg is None else msg) 507*cda5da8dSAndroid Build Coastguard Worker 508*cda5da8dSAndroid Build Coastguard Worker ### Context manager ### 509*cda5da8dSAndroid Build Coastguard Worker 510*cda5da8dSAndroid Build Coastguard Worker def __enter__(self): # That's a forward reference 511*cda5da8dSAndroid Build Coastguard Worker """Context management protocol. Returns self (an instance of IOBase).""" 512*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 513*cda5da8dSAndroid Build Coastguard Worker return self 514*cda5da8dSAndroid Build Coastguard Worker 515*cda5da8dSAndroid Build Coastguard Worker def __exit__(self, *args): 516*cda5da8dSAndroid Build Coastguard Worker """Context management protocol. Calls close()""" 517*cda5da8dSAndroid Build Coastguard Worker self.close() 518*cda5da8dSAndroid Build Coastguard Worker 519*cda5da8dSAndroid Build Coastguard Worker ### Lower-level APIs ### 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker # XXX Should these be present even if unimplemented? 522*cda5da8dSAndroid Build Coastguard Worker 523*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 524*cda5da8dSAndroid Build Coastguard Worker """Returns underlying file descriptor (an int) if one exists. 525*cda5da8dSAndroid Build Coastguard Worker 526*cda5da8dSAndroid Build Coastguard Worker An OSError is raised if the IO object does not use a file descriptor. 527*cda5da8dSAndroid Build Coastguard Worker """ 528*cda5da8dSAndroid Build Coastguard Worker self._unsupported("fileno") 529*cda5da8dSAndroid Build Coastguard Worker 530*cda5da8dSAndroid Build Coastguard Worker def isatty(self): 531*cda5da8dSAndroid Build Coastguard Worker """Return a bool indicating whether this is an 'interactive' stream. 532*cda5da8dSAndroid Build Coastguard Worker 533*cda5da8dSAndroid Build Coastguard Worker Return False if it can't be determined. 534*cda5da8dSAndroid Build Coastguard Worker """ 535*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 536*cda5da8dSAndroid Build Coastguard Worker return False 537*cda5da8dSAndroid Build Coastguard Worker 538*cda5da8dSAndroid Build Coastguard Worker ### Readline[s] and writelines ### 539*cda5da8dSAndroid Build Coastguard Worker 540*cda5da8dSAndroid Build Coastguard Worker def readline(self, size=-1): 541*cda5da8dSAndroid Build Coastguard Worker r"""Read and return a line of bytes from the stream. 542*cda5da8dSAndroid Build Coastguard Worker 543*cda5da8dSAndroid Build Coastguard Worker If size is specified, at most size bytes will be read. 544*cda5da8dSAndroid Build Coastguard Worker Size should be an int. 545*cda5da8dSAndroid Build Coastguard Worker 546*cda5da8dSAndroid Build Coastguard Worker The line terminator is always b'\n' for binary files; for text 547*cda5da8dSAndroid Build Coastguard Worker files, the newlines argument to open can be used to select the line 548*cda5da8dSAndroid Build Coastguard Worker terminator(s) recognized. 549*cda5da8dSAndroid Build Coastguard Worker """ 550*cda5da8dSAndroid Build Coastguard Worker # For backwards compatibility, a (slowish) readline(). 551*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, "peek"): 552*cda5da8dSAndroid Build Coastguard Worker def nreadahead(): 553*cda5da8dSAndroid Build Coastguard Worker readahead = self.peek(1) 554*cda5da8dSAndroid Build Coastguard Worker if not readahead: 555*cda5da8dSAndroid Build Coastguard Worker return 1 556*cda5da8dSAndroid Build Coastguard Worker n = (readahead.find(b"\n") + 1) or len(readahead) 557*cda5da8dSAndroid Build Coastguard Worker if size >= 0: 558*cda5da8dSAndroid Build Coastguard Worker n = min(n, size) 559*cda5da8dSAndroid Build Coastguard Worker return n 560*cda5da8dSAndroid Build Coastguard Worker else: 561*cda5da8dSAndroid Build Coastguard Worker def nreadahead(): 562*cda5da8dSAndroid Build Coastguard Worker return 1 563*cda5da8dSAndroid Build Coastguard Worker if size is None: 564*cda5da8dSAndroid Build Coastguard Worker size = -1 565*cda5da8dSAndroid Build Coastguard Worker else: 566*cda5da8dSAndroid Build Coastguard Worker try: 567*cda5da8dSAndroid Build Coastguard Worker size_index = size.__index__ 568*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 569*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{size!r} is not an integer") 570*cda5da8dSAndroid Build Coastguard Worker else: 571*cda5da8dSAndroid Build Coastguard Worker size = size_index() 572*cda5da8dSAndroid Build Coastguard Worker res = bytearray() 573*cda5da8dSAndroid Build Coastguard Worker while size < 0 or len(res) < size: 574*cda5da8dSAndroid Build Coastguard Worker b = self.read(nreadahead()) 575*cda5da8dSAndroid Build Coastguard Worker if not b: 576*cda5da8dSAndroid Build Coastguard Worker break 577*cda5da8dSAndroid Build Coastguard Worker res += b 578*cda5da8dSAndroid Build Coastguard Worker if res.endswith(b"\n"): 579*cda5da8dSAndroid Build Coastguard Worker break 580*cda5da8dSAndroid Build Coastguard Worker return bytes(res) 581*cda5da8dSAndroid Build Coastguard Worker 582*cda5da8dSAndroid Build Coastguard Worker def __iter__(self): 583*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 584*cda5da8dSAndroid Build Coastguard Worker return self 585*cda5da8dSAndroid Build Coastguard Worker 586*cda5da8dSAndroid Build Coastguard Worker def __next__(self): 587*cda5da8dSAndroid Build Coastguard Worker line = self.readline() 588*cda5da8dSAndroid Build Coastguard Worker if not line: 589*cda5da8dSAndroid Build Coastguard Worker raise StopIteration 590*cda5da8dSAndroid Build Coastguard Worker return line 591*cda5da8dSAndroid Build Coastguard Worker 592*cda5da8dSAndroid Build Coastguard Worker def readlines(self, hint=None): 593*cda5da8dSAndroid Build Coastguard Worker """Return a list of lines from the stream. 594*cda5da8dSAndroid Build Coastguard Worker 595*cda5da8dSAndroid Build Coastguard Worker hint can be specified to control the number of lines read: no more 596*cda5da8dSAndroid Build Coastguard Worker lines will be read if the total size (in bytes/characters) of all 597*cda5da8dSAndroid Build Coastguard Worker lines so far exceeds hint. 598*cda5da8dSAndroid Build Coastguard Worker """ 599*cda5da8dSAndroid Build Coastguard Worker if hint is None or hint <= 0: 600*cda5da8dSAndroid Build Coastguard Worker return list(self) 601*cda5da8dSAndroid Build Coastguard Worker n = 0 602*cda5da8dSAndroid Build Coastguard Worker lines = [] 603*cda5da8dSAndroid Build Coastguard Worker for line in self: 604*cda5da8dSAndroid Build Coastguard Worker lines.append(line) 605*cda5da8dSAndroid Build Coastguard Worker n += len(line) 606*cda5da8dSAndroid Build Coastguard Worker if n >= hint: 607*cda5da8dSAndroid Build Coastguard Worker break 608*cda5da8dSAndroid Build Coastguard Worker return lines 609*cda5da8dSAndroid Build Coastguard Worker 610*cda5da8dSAndroid Build Coastguard Worker def writelines(self, lines): 611*cda5da8dSAndroid Build Coastguard Worker """Write a list of lines to the stream. 612*cda5da8dSAndroid Build Coastguard Worker 613*cda5da8dSAndroid Build Coastguard Worker Line separators are not added, so it is usual for each of the lines 614*cda5da8dSAndroid Build Coastguard Worker provided to have a line separator at the end. 615*cda5da8dSAndroid Build Coastguard Worker """ 616*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 617*cda5da8dSAndroid Build Coastguard Worker for line in lines: 618*cda5da8dSAndroid Build Coastguard Worker self.write(line) 619*cda5da8dSAndroid Build Coastguard Worker 620*cda5da8dSAndroid Build Coastguard Workerio.IOBase.register(IOBase) 621*cda5da8dSAndroid Build Coastguard Worker 622*cda5da8dSAndroid Build Coastguard Worker 623*cda5da8dSAndroid Build Coastguard Workerclass RawIOBase(IOBase): 624*cda5da8dSAndroid Build Coastguard Worker 625*cda5da8dSAndroid Build Coastguard Worker """Base class for raw binary I/O.""" 626*cda5da8dSAndroid Build Coastguard Worker 627*cda5da8dSAndroid Build Coastguard Worker # The read() method is implemented by calling readinto(); derived 628*cda5da8dSAndroid Build Coastguard Worker # classes that want to support read() only need to implement 629*cda5da8dSAndroid Build Coastguard Worker # readinto() as a primitive operation. In general, readinto() can be 630*cda5da8dSAndroid Build Coastguard Worker # more efficient than read(). 631*cda5da8dSAndroid Build Coastguard Worker 632*cda5da8dSAndroid Build Coastguard Worker # (It would be tempting to also provide an implementation of 633*cda5da8dSAndroid Build Coastguard Worker # readinto() in terms of read(), in case the latter is a more suitable 634*cda5da8dSAndroid Build Coastguard Worker # primitive operation, but that would lead to nasty recursion in case 635*cda5da8dSAndroid Build Coastguard Worker # a subclass doesn't implement either.) 636*cda5da8dSAndroid Build Coastguard Worker 637*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 638*cda5da8dSAndroid Build Coastguard Worker """Read and return up to size bytes, where size is an int. 639*cda5da8dSAndroid Build Coastguard Worker 640*cda5da8dSAndroid Build Coastguard Worker Returns an empty bytes object on EOF, or None if the object is 641*cda5da8dSAndroid Build Coastguard Worker set not to block and has no data to read. 642*cda5da8dSAndroid Build Coastguard Worker """ 643*cda5da8dSAndroid Build Coastguard Worker if size is None: 644*cda5da8dSAndroid Build Coastguard Worker size = -1 645*cda5da8dSAndroid Build Coastguard Worker if size < 0: 646*cda5da8dSAndroid Build Coastguard Worker return self.readall() 647*cda5da8dSAndroid Build Coastguard Worker b = bytearray(size.__index__()) 648*cda5da8dSAndroid Build Coastguard Worker n = self.readinto(b) 649*cda5da8dSAndroid Build Coastguard Worker if n is None: 650*cda5da8dSAndroid Build Coastguard Worker return None 651*cda5da8dSAndroid Build Coastguard Worker del b[n:] 652*cda5da8dSAndroid Build Coastguard Worker return bytes(b) 653*cda5da8dSAndroid Build Coastguard Worker 654*cda5da8dSAndroid Build Coastguard Worker def readall(self): 655*cda5da8dSAndroid Build Coastguard Worker """Read until EOF, using multiple read() call.""" 656*cda5da8dSAndroid Build Coastguard Worker res = bytearray() 657*cda5da8dSAndroid Build Coastguard Worker while True: 658*cda5da8dSAndroid Build Coastguard Worker data = self.read(DEFAULT_BUFFER_SIZE) 659*cda5da8dSAndroid Build Coastguard Worker if not data: 660*cda5da8dSAndroid Build Coastguard Worker break 661*cda5da8dSAndroid Build Coastguard Worker res += data 662*cda5da8dSAndroid Build Coastguard Worker if res: 663*cda5da8dSAndroid Build Coastguard Worker return bytes(res) 664*cda5da8dSAndroid Build Coastguard Worker else: 665*cda5da8dSAndroid Build Coastguard Worker # b'' or None 666*cda5da8dSAndroid Build Coastguard Worker return data 667*cda5da8dSAndroid Build Coastguard Worker 668*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 669*cda5da8dSAndroid Build Coastguard Worker """Read bytes into a pre-allocated bytes-like object b. 670*cda5da8dSAndroid Build Coastguard Worker 671*cda5da8dSAndroid Build Coastguard Worker Returns an int representing the number of bytes read (0 for EOF), or 672*cda5da8dSAndroid Build Coastguard Worker None if the object is set not to block and has no data to read. 673*cda5da8dSAndroid Build Coastguard Worker """ 674*cda5da8dSAndroid Build Coastguard Worker self._unsupported("readinto") 675*cda5da8dSAndroid Build Coastguard Worker 676*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 677*cda5da8dSAndroid Build Coastguard Worker """Write the given buffer to the IO stream. 678*cda5da8dSAndroid Build Coastguard Worker 679*cda5da8dSAndroid Build Coastguard Worker Returns the number of bytes written, which may be less than the 680*cda5da8dSAndroid Build Coastguard Worker length of b in bytes. 681*cda5da8dSAndroid Build Coastguard Worker """ 682*cda5da8dSAndroid Build Coastguard Worker self._unsupported("write") 683*cda5da8dSAndroid Build Coastguard Worker 684*cda5da8dSAndroid Build Coastguard Workerio.RawIOBase.register(RawIOBase) 685*cda5da8dSAndroid Build Coastguard Workerfrom _io import FileIO 686*cda5da8dSAndroid Build Coastguard WorkerRawIOBase.register(FileIO) 687*cda5da8dSAndroid Build Coastguard Worker 688*cda5da8dSAndroid Build Coastguard Worker 689*cda5da8dSAndroid Build Coastguard Workerclass BufferedIOBase(IOBase): 690*cda5da8dSAndroid Build Coastguard Worker 691*cda5da8dSAndroid Build Coastguard Worker """Base class for buffered IO objects. 692*cda5da8dSAndroid Build Coastguard Worker 693*cda5da8dSAndroid Build Coastguard Worker The main difference with RawIOBase is that the read() method 694*cda5da8dSAndroid Build Coastguard Worker supports omitting the size argument, and does not have a default 695*cda5da8dSAndroid Build Coastguard Worker implementation that defers to readinto(). 696*cda5da8dSAndroid Build Coastguard Worker 697*cda5da8dSAndroid Build Coastguard Worker In addition, read(), readinto() and write() may raise 698*cda5da8dSAndroid Build Coastguard Worker BlockingIOError if the underlying raw stream is in non-blocking 699*cda5da8dSAndroid Build Coastguard Worker mode and not ready; unlike their raw counterparts, they will never 700*cda5da8dSAndroid Build Coastguard Worker return None. 701*cda5da8dSAndroid Build Coastguard Worker 702*cda5da8dSAndroid Build Coastguard Worker A typical implementation should not inherit from a RawIOBase 703*cda5da8dSAndroid Build Coastguard Worker implementation, but wrap one. 704*cda5da8dSAndroid Build Coastguard Worker """ 705*cda5da8dSAndroid Build Coastguard Worker 706*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 707*cda5da8dSAndroid Build Coastguard Worker """Read and return up to size bytes, where size is an int. 708*cda5da8dSAndroid Build Coastguard Worker 709*cda5da8dSAndroid Build Coastguard Worker If the argument is omitted, None, or negative, reads and 710*cda5da8dSAndroid Build Coastguard Worker returns all data until EOF. 711*cda5da8dSAndroid Build Coastguard Worker 712*cda5da8dSAndroid Build Coastguard Worker If the argument is positive, and the underlying raw stream is 713*cda5da8dSAndroid Build Coastguard Worker not 'interactive', multiple raw reads may be issued to satisfy 714*cda5da8dSAndroid Build Coastguard Worker the byte count (unless EOF is reached first). But for 715*cda5da8dSAndroid Build Coastguard Worker interactive raw streams (XXX and for pipes?), at most one raw 716*cda5da8dSAndroid Build Coastguard Worker read will be issued, and a short result does not imply that 717*cda5da8dSAndroid Build Coastguard Worker EOF is imminent. 718*cda5da8dSAndroid Build Coastguard Worker 719*cda5da8dSAndroid Build Coastguard Worker Returns an empty bytes array on EOF. 720*cda5da8dSAndroid Build Coastguard Worker 721*cda5da8dSAndroid Build Coastguard Worker Raises BlockingIOError if the underlying raw stream has no 722*cda5da8dSAndroid Build Coastguard Worker data at the moment. 723*cda5da8dSAndroid Build Coastguard Worker """ 724*cda5da8dSAndroid Build Coastguard Worker self._unsupported("read") 725*cda5da8dSAndroid Build Coastguard Worker 726*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 727*cda5da8dSAndroid Build Coastguard Worker """Read up to size bytes with at most one read() system call, 728*cda5da8dSAndroid Build Coastguard Worker where size is an int. 729*cda5da8dSAndroid Build Coastguard Worker """ 730*cda5da8dSAndroid Build Coastguard Worker self._unsupported("read1") 731*cda5da8dSAndroid Build Coastguard Worker 732*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 733*cda5da8dSAndroid Build Coastguard Worker """Read bytes into a pre-allocated bytes-like object b. 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Worker Like read(), this may issue multiple reads to the underlying raw 736*cda5da8dSAndroid Build Coastguard Worker stream, unless the latter is 'interactive'. 737*cda5da8dSAndroid Build Coastguard Worker 738*cda5da8dSAndroid Build Coastguard Worker Returns an int representing the number of bytes read (0 for EOF). 739*cda5da8dSAndroid Build Coastguard Worker 740*cda5da8dSAndroid Build Coastguard Worker Raises BlockingIOError if the underlying raw stream has no 741*cda5da8dSAndroid Build Coastguard Worker data at the moment. 742*cda5da8dSAndroid Build Coastguard Worker """ 743*cda5da8dSAndroid Build Coastguard Worker 744*cda5da8dSAndroid Build Coastguard Worker return self._readinto(b, read1=False) 745*cda5da8dSAndroid Build Coastguard Worker 746*cda5da8dSAndroid Build Coastguard Worker def readinto1(self, b): 747*cda5da8dSAndroid Build Coastguard Worker """Read bytes into buffer *b*, using at most one system call 748*cda5da8dSAndroid Build Coastguard Worker 749*cda5da8dSAndroid Build Coastguard Worker Returns an int representing the number of bytes read (0 for EOF). 750*cda5da8dSAndroid Build Coastguard Worker 751*cda5da8dSAndroid Build Coastguard Worker Raises BlockingIOError if the underlying raw stream has no 752*cda5da8dSAndroid Build Coastguard Worker data at the moment. 753*cda5da8dSAndroid Build Coastguard Worker """ 754*cda5da8dSAndroid Build Coastguard Worker 755*cda5da8dSAndroid Build Coastguard Worker return self._readinto(b, read1=True) 756*cda5da8dSAndroid Build Coastguard Worker 757*cda5da8dSAndroid Build Coastguard Worker def _readinto(self, b, read1): 758*cda5da8dSAndroid Build Coastguard Worker if not isinstance(b, memoryview): 759*cda5da8dSAndroid Build Coastguard Worker b = memoryview(b) 760*cda5da8dSAndroid Build Coastguard Worker b = b.cast('B') 761*cda5da8dSAndroid Build Coastguard Worker 762*cda5da8dSAndroid Build Coastguard Worker if read1: 763*cda5da8dSAndroid Build Coastguard Worker data = self.read1(len(b)) 764*cda5da8dSAndroid Build Coastguard Worker else: 765*cda5da8dSAndroid Build Coastguard Worker data = self.read(len(b)) 766*cda5da8dSAndroid Build Coastguard Worker n = len(data) 767*cda5da8dSAndroid Build Coastguard Worker 768*cda5da8dSAndroid Build Coastguard Worker b[:n] = data 769*cda5da8dSAndroid Build Coastguard Worker 770*cda5da8dSAndroid Build Coastguard Worker return n 771*cda5da8dSAndroid Build Coastguard Worker 772*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 773*cda5da8dSAndroid Build Coastguard Worker """Write the given bytes buffer to the IO stream. 774*cda5da8dSAndroid Build Coastguard Worker 775*cda5da8dSAndroid Build Coastguard Worker Return the number of bytes written, which is always the length of b 776*cda5da8dSAndroid Build Coastguard Worker in bytes. 777*cda5da8dSAndroid Build Coastguard Worker 778*cda5da8dSAndroid Build Coastguard Worker Raises BlockingIOError if the buffer is full and the 779*cda5da8dSAndroid Build Coastguard Worker underlying raw stream cannot accept more data at the moment. 780*cda5da8dSAndroid Build Coastguard Worker """ 781*cda5da8dSAndroid Build Coastguard Worker self._unsupported("write") 782*cda5da8dSAndroid Build Coastguard Worker 783*cda5da8dSAndroid Build Coastguard Worker def detach(self): 784*cda5da8dSAndroid Build Coastguard Worker """ 785*cda5da8dSAndroid Build Coastguard Worker Separate the underlying raw stream from the buffer and return it. 786*cda5da8dSAndroid Build Coastguard Worker 787*cda5da8dSAndroid Build Coastguard Worker After the raw stream has been detached, the buffer is in an unusable 788*cda5da8dSAndroid Build Coastguard Worker state. 789*cda5da8dSAndroid Build Coastguard Worker """ 790*cda5da8dSAndroid Build Coastguard Worker self._unsupported("detach") 791*cda5da8dSAndroid Build Coastguard Worker 792*cda5da8dSAndroid Build Coastguard Workerio.BufferedIOBase.register(BufferedIOBase) 793*cda5da8dSAndroid Build Coastguard Worker 794*cda5da8dSAndroid Build Coastguard Worker 795*cda5da8dSAndroid Build Coastguard Workerclass _BufferedIOMixin(BufferedIOBase): 796*cda5da8dSAndroid Build Coastguard Worker 797*cda5da8dSAndroid Build Coastguard Worker """A mixin implementation of BufferedIOBase with an underlying raw stream. 798*cda5da8dSAndroid Build Coastguard Worker 799*cda5da8dSAndroid Build Coastguard Worker This passes most requests on to the underlying raw stream. It 800*cda5da8dSAndroid Build Coastguard Worker does *not* provide implementations of read(), readinto() or 801*cda5da8dSAndroid Build Coastguard Worker write(). 802*cda5da8dSAndroid Build Coastguard Worker """ 803*cda5da8dSAndroid Build Coastguard Worker 804*cda5da8dSAndroid Build Coastguard Worker def __init__(self, raw): 805*cda5da8dSAndroid Build Coastguard Worker self._raw = raw 806*cda5da8dSAndroid Build Coastguard Worker 807*cda5da8dSAndroid Build Coastguard Worker ### Positioning ### 808*cda5da8dSAndroid Build Coastguard Worker 809*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 810*cda5da8dSAndroid Build Coastguard Worker new_position = self.raw.seek(pos, whence) 811*cda5da8dSAndroid Build Coastguard Worker if new_position < 0: 812*cda5da8dSAndroid Build Coastguard Worker raise OSError("seek() returned an invalid position") 813*cda5da8dSAndroid Build Coastguard Worker return new_position 814*cda5da8dSAndroid Build Coastguard Worker 815*cda5da8dSAndroid Build Coastguard Worker def tell(self): 816*cda5da8dSAndroid Build Coastguard Worker pos = self.raw.tell() 817*cda5da8dSAndroid Build Coastguard Worker if pos < 0: 818*cda5da8dSAndroid Build Coastguard Worker raise OSError("tell() returned an invalid position") 819*cda5da8dSAndroid Build Coastguard Worker return pos 820*cda5da8dSAndroid Build Coastguard Worker 821*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 822*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 823*cda5da8dSAndroid Build Coastguard Worker self._checkWritable() 824*cda5da8dSAndroid Build Coastguard Worker 825*cda5da8dSAndroid Build Coastguard Worker # Flush the stream. We're mixing buffered I/O with lower-level I/O, 826*cda5da8dSAndroid Build Coastguard Worker # and a flush may be necessary to synch both views of the current 827*cda5da8dSAndroid Build Coastguard Worker # file state. 828*cda5da8dSAndroid Build Coastguard Worker self.flush() 829*cda5da8dSAndroid Build Coastguard Worker 830*cda5da8dSAndroid Build Coastguard Worker if pos is None: 831*cda5da8dSAndroid Build Coastguard Worker pos = self.tell() 832*cda5da8dSAndroid Build Coastguard Worker # XXX: Should seek() be used, instead of passing the position 833*cda5da8dSAndroid Build Coastguard Worker # XXX directly to truncate? 834*cda5da8dSAndroid Build Coastguard Worker return self.raw.truncate(pos) 835*cda5da8dSAndroid Build Coastguard Worker 836*cda5da8dSAndroid Build Coastguard Worker ### Flush and close ### 837*cda5da8dSAndroid Build Coastguard Worker 838*cda5da8dSAndroid Build Coastguard Worker def flush(self): 839*cda5da8dSAndroid Build Coastguard Worker if self.closed: 840*cda5da8dSAndroid Build Coastguard Worker raise ValueError("flush on closed file") 841*cda5da8dSAndroid Build Coastguard Worker self.raw.flush() 842*cda5da8dSAndroid Build Coastguard Worker 843*cda5da8dSAndroid Build Coastguard Worker def close(self): 844*cda5da8dSAndroid Build Coastguard Worker if self.raw is not None and not self.closed: 845*cda5da8dSAndroid Build Coastguard Worker try: 846*cda5da8dSAndroid Build Coastguard Worker # may raise BlockingIOError or BrokenPipeError etc 847*cda5da8dSAndroid Build Coastguard Worker self.flush() 848*cda5da8dSAndroid Build Coastguard Worker finally: 849*cda5da8dSAndroid Build Coastguard Worker self.raw.close() 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Worker def detach(self): 852*cda5da8dSAndroid Build Coastguard Worker if self.raw is None: 853*cda5da8dSAndroid Build Coastguard Worker raise ValueError("raw stream already detached") 854*cda5da8dSAndroid Build Coastguard Worker self.flush() 855*cda5da8dSAndroid Build Coastguard Worker raw = self._raw 856*cda5da8dSAndroid Build Coastguard Worker self._raw = None 857*cda5da8dSAndroid Build Coastguard Worker return raw 858*cda5da8dSAndroid Build Coastguard Worker 859*cda5da8dSAndroid Build Coastguard Worker ### Inquiries ### 860*cda5da8dSAndroid Build Coastguard Worker 861*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 862*cda5da8dSAndroid Build Coastguard Worker return self.raw.seekable() 863*cda5da8dSAndroid Build Coastguard Worker 864*cda5da8dSAndroid Build Coastguard Worker @property 865*cda5da8dSAndroid Build Coastguard Worker def raw(self): 866*cda5da8dSAndroid Build Coastguard Worker return self._raw 867*cda5da8dSAndroid Build Coastguard Worker 868*cda5da8dSAndroid Build Coastguard Worker @property 869*cda5da8dSAndroid Build Coastguard Worker def closed(self): 870*cda5da8dSAndroid Build Coastguard Worker return self.raw.closed 871*cda5da8dSAndroid Build Coastguard Worker 872*cda5da8dSAndroid Build Coastguard Worker @property 873*cda5da8dSAndroid Build Coastguard Worker def name(self): 874*cda5da8dSAndroid Build Coastguard Worker return self.raw.name 875*cda5da8dSAndroid Build Coastguard Worker 876*cda5da8dSAndroid Build Coastguard Worker @property 877*cda5da8dSAndroid Build Coastguard Worker def mode(self): 878*cda5da8dSAndroid Build Coastguard Worker return self.raw.mode 879*cda5da8dSAndroid Build Coastguard Worker 880*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 881*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") 882*cda5da8dSAndroid Build Coastguard Worker 883*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 884*cda5da8dSAndroid Build Coastguard Worker modname = self.__class__.__module__ 885*cda5da8dSAndroid Build Coastguard Worker clsname = self.__class__.__qualname__ 886*cda5da8dSAndroid Build Coastguard Worker try: 887*cda5da8dSAndroid Build Coastguard Worker name = self.name 888*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 889*cda5da8dSAndroid Build Coastguard Worker return "<{}.{}>".format(modname, clsname) 890*cda5da8dSAndroid Build Coastguard Worker else: 891*cda5da8dSAndroid Build Coastguard Worker return "<{}.{} name={!r}>".format(modname, clsname, name) 892*cda5da8dSAndroid Build Coastguard Worker 893*cda5da8dSAndroid Build Coastguard Worker ### Lower-level APIs ### 894*cda5da8dSAndroid Build Coastguard Worker 895*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 896*cda5da8dSAndroid Build Coastguard Worker return self.raw.fileno() 897*cda5da8dSAndroid Build Coastguard Worker 898*cda5da8dSAndroid Build Coastguard Worker def isatty(self): 899*cda5da8dSAndroid Build Coastguard Worker return self.raw.isatty() 900*cda5da8dSAndroid Build Coastguard Worker 901*cda5da8dSAndroid Build Coastguard Worker 902*cda5da8dSAndroid Build Coastguard Workerclass BytesIO(BufferedIOBase): 903*cda5da8dSAndroid Build Coastguard Worker 904*cda5da8dSAndroid Build Coastguard Worker """Buffered I/O implementation using an in-memory bytes buffer.""" 905*cda5da8dSAndroid Build Coastguard Worker 906*cda5da8dSAndroid Build Coastguard Worker # Initialize _buffer as soon as possible since it's used by __del__() 907*cda5da8dSAndroid Build Coastguard Worker # which calls close() 908*cda5da8dSAndroid Build Coastguard Worker _buffer = None 909*cda5da8dSAndroid Build Coastguard Worker 910*cda5da8dSAndroid Build Coastguard Worker def __init__(self, initial_bytes=None): 911*cda5da8dSAndroid Build Coastguard Worker buf = bytearray() 912*cda5da8dSAndroid Build Coastguard Worker if initial_bytes is not None: 913*cda5da8dSAndroid Build Coastguard Worker buf += initial_bytes 914*cda5da8dSAndroid Build Coastguard Worker self._buffer = buf 915*cda5da8dSAndroid Build Coastguard Worker self._pos = 0 916*cda5da8dSAndroid Build Coastguard Worker 917*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 918*cda5da8dSAndroid Build Coastguard Worker if self.closed: 919*cda5da8dSAndroid Build Coastguard Worker raise ValueError("__getstate__ on closed file") 920*cda5da8dSAndroid Build Coastguard Worker return self.__dict__.copy() 921*cda5da8dSAndroid Build Coastguard Worker 922*cda5da8dSAndroid Build Coastguard Worker def getvalue(self): 923*cda5da8dSAndroid Build Coastguard Worker """Return the bytes value (contents) of the buffer 924*cda5da8dSAndroid Build Coastguard Worker """ 925*cda5da8dSAndroid Build Coastguard Worker if self.closed: 926*cda5da8dSAndroid Build Coastguard Worker raise ValueError("getvalue on closed file") 927*cda5da8dSAndroid Build Coastguard Worker return bytes(self._buffer) 928*cda5da8dSAndroid Build Coastguard Worker 929*cda5da8dSAndroid Build Coastguard Worker def getbuffer(self): 930*cda5da8dSAndroid Build Coastguard Worker """Return a readable and writable view of the buffer. 931*cda5da8dSAndroid Build Coastguard Worker """ 932*cda5da8dSAndroid Build Coastguard Worker if self.closed: 933*cda5da8dSAndroid Build Coastguard Worker raise ValueError("getbuffer on closed file") 934*cda5da8dSAndroid Build Coastguard Worker return memoryview(self._buffer) 935*cda5da8dSAndroid Build Coastguard Worker 936*cda5da8dSAndroid Build Coastguard Worker def close(self): 937*cda5da8dSAndroid Build Coastguard Worker if self._buffer is not None: 938*cda5da8dSAndroid Build Coastguard Worker self._buffer.clear() 939*cda5da8dSAndroid Build Coastguard Worker super().close() 940*cda5da8dSAndroid Build Coastguard Worker 941*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 942*cda5da8dSAndroid Build Coastguard Worker if self.closed: 943*cda5da8dSAndroid Build Coastguard Worker raise ValueError("read from closed file") 944*cda5da8dSAndroid Build Coastguard Worker if size is None: 945*cda5da8dSAndroid Build Coastguard Worker size = -1 946*cda5da8dSAndroid Build Coastguard Worker else: 947*cda5da8dSAndroid Build Coastguard Worker try: 948*cda5da8dSAndroid Build Coastguard Worker size_index = size.__index__ 949*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 950*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{size!r} is not an integer") 951*cda5da8dSAndroid Build Coastguard Worker else: 952*cda5da8dSAndroid Build Coastguard Worker size = size_index() 953*cda5da8dSAndroid Build Coastguard Worker if size < 0: 954*cda5da8dSAndroid Build Coastguard Worker size = len(self._buffer) 955*cda5da8dSAndroid Build Coastguard Worker if len(self._buffer) <= self._pos: 956*cda5da8dSAndroid Build Coastguard Worker return b"" 957*cda5da8dSAndroid Build Coastguard Worker newpos = min(len(self._buffer), self._pos + size) 958*cda5da8dSAndroid Build Coastguard Worker b = self._buffer[self._pos : newpos] 959*cda5da8dSAndroid Build Coastguard Worker self._pos = newpos 960*cda5da8dSAndroid Build Coastguard Worker return bytes(b) 961*cda5da8dSAndroid Build Coastguard Worker 962*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 963*cda5da8dSAndroid Build Coastguard Worker """This is the same as read. 964*cda5da8dSAndroid Build Coastguard Worker """ 965*cda5da8dSAndroid Build Coastguard Worker return self.read(size) 966*cda5da8dSAndroid Build Coastguard Worker 967*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 968*cda5da8dSAndroid Build Coastguard Worker if self.closed: 969*cda5da8dSAndroid Build Coastguard Worker raise ValueError("write to closed file") 970*cda5da8dSAndroid Build Coastguard Worker if isinstance(b, str): 971*cda5da8dSAndroid Build Coastguard Worker raise TypeError("can't write str to binary stream") 972*cda5da8dSAndroid Build Coastguard Worker with memoryview(b) as view: 973*cda5da8dSAndroid Build Coastguard Worker n = view.nbytes # Size of any bytes-like object 974*cda5da8dSAndroid Build Coastguard Worker if n == 0: 975*cda5da8dSAndroid Build Coastguard Worker return 0 976*cda5da8dSAndroid Build Coastguard Worker pos = self._pos 977*cda5da8dSAndroid Build Coastguard Worker if pos > len(self._buffer): 978*cda5da8dSAndroid Build Coastguard Worker # Inserts null bytes between the current end of the file 979*cda5da8dSAndroid Build Coastguard Worker # and the new write position. 980*cda5da8dSAndroid Build Coastguard Worker padding = b'\x00' * (pos - len(self._buffer)) 981*cda5da8dSAndroid Build Coastguard Worker self._buffer += padding 982*cda5da8dSAndroid Build Coastguard Worker self._buffer[pos:pos + n] = b 983*cda5da8dSAndroid Build Coastguard Worker self._pos += n 984*cda5da8dSAndroid Build Coastguard Worker return n 985*cda5da8dSAndroid Build Coastguard Worker 986*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 987*cda5da8dSAndroid Build Coastguard Worker if self.closed: 988*cda5da8dSAndroid Build Coastguard Worker raise ValueError("seek on closed file") 989*cda5da8dSAndroid Build Coastguard Worker try: 990*cda5da8dSAndroid Build Coastguard Worker pos_index = pos.__index__ 991*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 992*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{pos!r} is not an integer") 993*cda5da8dSAndroid Build Coastguard Worker else: 994*cda5da8dSAndroid Build Coastguard Worker pos = pos_index() 995*cda5da8dSAndroid Build Coastguard Worker if whence == 0: 996*cda5da8dSAndroid Build Coastguard Worker if pos < 0: 997*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative seek position %r" % (pos,)) 998*cda5da8dSAndroid Build Coastguard Worker self._pos = pos 999*cda5da8dSAndroid Build Coastguard Worker elif whence == 1: 1000*cda5da8dSAndroid Build Coastguard Worker self._pos = max(0, self._pos + pos) 1001*cda5da8dSAndroid Build Coastguard Worker elif whence == 2: 1002*cda5da8dSAndroid Build Coastguard Worker self._pos = max(0, len(self._buffer) + pos) 1003*cda5da8dSAndroid Build Coastguard Worker else: 1004*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unsupported whence value") 1005*cda5da8dSAndroid Build Coastguard Worker return self._pos 1006*cda5da8dSAndroid Build Coastguard Worker 1007*cda5da8dSAndroid Build Coastguard Worker def tell(self): 1008*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1009*cda5da8dSAndroid Build Coastguard Worker raise ValueError("tell on closed file") 1010*cda5da8dSAndroid Build Coastguard Worker return self._pos 1011*cda5da8dSAndroid Build Coastguard Worker 1012*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 1013*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1014*cda5da8dSAndroid Build Coastguard Worker raise ValueError("truncate on closed file") 1015*cda5da8dSAndroid Build Coastguard Worker if pos is None: 1016*cda5da8dSAndroid Build Coastguard Worker pos = self._pos 1017*cda5da8dSAndroid Build Coastguard Worker else: 1018*cda5da8dSAndroid Build Coastguard Worker try: 1019*cda5da8dSAndroid Build Coastguard Worker pos_index = pos.__index__ 1020*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1021*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{pos!r} is not an integer") 1022*cda5da8dSAndroid Build Coastguard Worker else: 1023*cda5da8dSAndroid Build Coastguard Worker pos = pos_index() 1024*cda5da8dSAndroid Build Coastguard Worker if pos < 0: 1025*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative truncate position %r" % (pos,)) 1026*cda5da8dSAndroid Build Coastguard Worker del self._buffer[pos:] 1027*cda5da8dSAndroid Build Coastguard Worker return pos 1028*cda5da8dSAndroid Build Coastguard Worker 1029*cda5da8dSAndroid Build Coastguard Worker def readable(self): 1030*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1031*cda5da8dSAndroid Build Coastguard Worker raise ValueError("I/O operation on closed file.") 1032*cda5da8dSAndroid Build Coastguard Worker return True 1033*cda5da8dSAndroid Build Coastguard Worker 1034*cda5da8dSAndroid Build Coastguard Worker def writable(self): 1035*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1036*cda5da8dSAndroid Build Coastguard Worker raise ValueError("I/O operation on closed file.") 1037*cda5da8dSAndroid Build Coastguard Worker return True 1038*cda5da8dSAndroid Build Coastguard Worker 1039*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 1040*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1041*cda5da8dSAndroid Build Coastguard Worker raise ValueError("I/O operation on closed file.") 1042*cda5da8dSAndroid Build Coastguard Worker return True 1043*cda5da8dSAndroid Build Coastguard Worker 1044*cda5da8dSAndroid Build Coastguard Worker 1045*cda5da8dSAndroid Build Coastguard Workerclass BufferedReader(_BufferedIOMixin): 1046*cda5da8dSAndroid Build Coastguard Worker 1047*cda5da8dSAndroid Build Coastguard Worker """BufferedReader(raw[, buffer_size]) 1048*cda5da8dSAndroid Build Coastguard Worker 1049*cda5da8dSAndroid Build Coastguard Worker A buffer for a readable, sequential BaseRawIO object. 1050*cda5da8dSAndroid Build Coastguard Worker 1051*cda5da8dSAndroid Build Coastguard Worker The constructor creates a BufferedReader for the given readable raw 1052*cda5da8dSAndroid Build Coastguard Worker stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE 1053*cda5da8dSAndroid Build Coastguard Worker is used. 1054*cda5da8dSAndroid Build Coastguard Worker """ 1055*cda5da8dSAndroid Build Coastguard Worker 1056*cda5da8dSAndroid Build Coastguard Worker def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 1057*cda5da8dSAndroid Build Coastguard Worker """Create a new buffered reader using the given readable raw IO object. 1058*cda5da8dSAndroid Build Coastguard Worker """ 1059*cda5da8dSAndroid Build Coastguard Worker if not raw.readable(): 1060*cda5da8dSAndroid Build Coastguard Worker raise OSError('"raw" argument must be readable.') 1061*cda5da8dSAndroid Build Coastguard Worker 1062*cda5da8dSAndroid Build Coastguard Worker _BufferedIOMixin.__init__(self, raw) 1063*cda5da8dSAndroid Build Coastguard Worker if buffer_size <= 0: 1064*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid buffer size") 1065*cda5da8dSAndroid Build Coastguard Worker self.buffer_size = buffer_size 1066*cda5da8dSAndroid Build Coastguard Worker self._reset_read_buf() 1067*cda5da8dSAndroid Build Coastguard Worker self._read_lock = Lock() 1068*cda5da8dSAndroid Build Coastguard Worker 1069*cda5da8dSAndroid Build Coastguard Worker def readable(self): 1070*cda5da8dSAndroid Build Coastguard Worker return self.raw.readable() 1071*cda5da8dSAndroid Build Coastguard Worker 1072*cda5da8dSAndroid Build Coastguard Worker def _reset_read_buf(self): 1073*cda5da8dSAndroid Build Coastguard Worker self._read_buf = b"" 1074*cda5da8dSAndroid Build Coastguard Worker self._read_pos = 0 1075*cda5da8dSAndroid Build Coastguard Worker 1076*cda5da8dSAndroid Build Coastguard Worker def read(self, size=None): 1077*cda5da8dSAndroid Build Coastguard Worker """Read size bytes. 1078*cda5da8dSAndroid Build Coastguard Worker 1079*cda5da8dSAndroid Build Coastguard Worker Returns exactly size bytes of data unless the underlying raw IO 1080*cda5da8dSAndroid Build Coastguard Worker stream reaches EOF or if the call would block in non-blocking 1081*cda5da8dSAndroid Build Coastguard Worker mode. If size is negative, read until EOF or until read() would 1082*cda5da8dSAndroid Build Coastguard Worker block. 1083*cda5da8dSAndroid Build Coastguard Worker """ 1084*cda5da8dSAndroid Build Coastguard Worker if size is not None and size < -1: 1085*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid number of bytes to read") 1086*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1087*cda5da8dSAndroid Build Coastguard Worker return self._read_unlocked(size) 1088*cda5da8dSAndroid Build Coastguard Worker 1089*cda5da8dSAndroid Build Coastguard Worker def _read_unlocked(self, n=None): 1090*cda5da8dSAndroid Build Coastguard Worker nodata_val = b"" 1091*cda5da8dSAndroid Build Coastguard Worker empty_values = (b"", None) 1092*cda5da8dSAndroid Build Coastguard Worker buf = self._read_buf 1093*cda5da8dSAndroid Build Coastguard Worker pos = self._read_pos 1094*cda5da8dSAndroid Build Coastguard Worker 1095*cda5da8dSAndroid Build Coastguard Worker # Special case for when the number of bytes to read is unspecified. 1096*cda5da8dSAndroid Build Coastguard Worker if n is None or n == -1: 1097*cda5da8dSAndroid Build Coastguard Worker self._reset_read_buf() 1098*cda5da8dSAndroid Build Coastguard Worker if hasattr(self.raw, 'readall'): 1099*cda5da8dSAndroid Build Coastguard Worker chunk = self.raw.readall() 1100*cda5da8dSAndroid Build Coastguard Worker if chunk is None: 1101*cda5da8dSAndroid Build Coastguard Worker return buf[pos:] or None 1102*cda5da8dSAndroid Build Coastguard Worker else: 1103*cda5da8dSAndroid Build Coastguard Worker return buf[pos:] + chunk 1104*cda5da8dSAndroid Build Coastguard Worker chunks = [buf[pos:]] # Strip the consumed bytes. 1105*cda5da8dSAndroid Build Coastguard Worker current_size = 0 1106*cda5da8dSAndroid Build Coastguard Worker while True: 1107*cda5da8dSAndroid Build Coastguard Worker # Read until EOF or until read() would block. 1108*cda5da8dSAndroid Build Coastguard Worker chunk = self.raw.read() 1109*cda5da8dSAndroid Build Coastguard Worker if chunk in empty_values: 1110*cda5da8dSAndroid Build Coastguard Worker nodata_val = chunk 1111*cda5da8dSAndroid Build Coastguard Worker break 1112*cda5da8dSAndroid Build Coastguard Worker current_size += len(chunk) 1113*cda5da8dSAndroid Build Coastguard Worker chunks.append(chunk) 1114*cda5da8dSAndroid Build Coastguard Worker return b"".join(chunks) or nodata_val 1115*cda5da8dSAndroid Build Coastguard Worker 1116*cda5da8dSAndroid Build Coastguard Worker # The number of bytes to read is specified, return at most n bytes. 1117*cda5da8dSAndroid Build Coastguard Worker avail = len(buf) - pos # Length of the available buffered data. 1118*cda5da8dSAndroid Build Coastguard Worker if n <= avail: 1119*cda5da8dSAndroid Build Coastguard Worker # Fast path: the data to read is fully buffered. 1120*cda5da8dSAndroid Build Coastguard Worker self._read_pos += n 1121*cda5da8dSAndroid Build Coastguard Worker return buf[pos:pos+n] 1122*cda5da8dSAndroid Build Coastguard Worker # Slow path: read from the stream until enough bytes are read, 1123*cda5da8dSAndroid Build Coastguard Worker # or until an EOF occurs or until read() would block. 1124*cda5da8dSAndroid Build Coastguard Worker chunks = [buf[pos:]] 1125*cda5da8dSAndroid Build Coastguard Worker wanted = max(self.buffer_size, n) 1126*cda5da8dSAndroid Build Coastguard Worker while avail < n: 1127*cda5da8dSAndroid Build Coastguard Worker chunk = self.raw.read(wanted) 1128*cda5da8dSAndroid Build Coastguard Worker if chunk in empty_values: 1129*cda5da8dSAndroid Build Coastguard Worker nodata_val = chunk 1130*cda5da8dSAndroid Build Coastguard Worker break 1131*cda5da8dSAndroid Build Coastguard Worker avail += len(chunk) 1132*cda5da8dSAndroid Build Coastguard Worker chunks.append(chunk) 1133*cda5da8dSAndroid Build Coastguard Worker # n is more than avail only when an EOF occurred or when 1134*cda5da8dSAndroid Build Coastguard Worker # read() would have blocked. 1135*cda5da8dSAndroid Build Coastguard Worker n = min(n, avail) 1136*cda5da8dSAndroid Build Coastguard Worker out = b"".join(chunks) 1137*cda5da8dSAndroid Build Coastguard Worker self._read_buf = out[n:] # Save the extra data in the buffer. 1138*cda5da8dSAndroid Build Coastguard Worker self._read_pos = 0 1139*cda5da8dSAndroid Build Coastguard Worker return out[:n] if out else nodata_val 1140*cda5da8dSAndroid Build Coastguard Worker 1141*cda5da8dSAndroid Build Coastguard Worker def peek(self, size=0): 1142*cda5da8dSAndroid Build Coastguard Worker """Returns buffered bytes without advancing the position. 1143*cda5da8dSAndroid Build Coastguard Worker 1144*cda5da8dSAndroid Build Coastguard Worker The argument indicates a desired minimal number of bytes; we 1145*cda5da8dSAndroid Build Coastguard Worker do at most one raw read to satisfy it. We never return more 1146*cda5da8dSAndroid Build Coastguard Worker than self.buffer_size. 1147*cda5da8dSAndroid Build Coastguard Worker """ 1148*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1149*cda5da8dSAndroid Build Coastguard Worker return self._peek_unlocked(size) 1150*cda5da8dSAndroid Build Coastguard Worker 1151*cda5da8dSAndroid Build Coastguard Worker def _peek_unlocked(self, n=0): 1152*cda5da8dSAndroid Build Coastguard Worker want = min(n, self.buffer_size) 1153*cda5da8dSAndroid Build Coastguard Worker have = len(self._read_buf) - self._read_pos 1154*cda5da8dSAndroid Build Coastguard Worker if have < want or have <= 0: 1155*cda5da8dSAndroid Build Coastguard Worker to_read = self.buffer_size - have 1156*cda5da8dSAndroid Build Coastguard Worker current = self.raw.read(to_read) 1157*cda5da8dSAndroid Build Coastguard Worker if current: 1158*cda5da8dSAndroid Build Coastguard Worker self._read_buf = self._read_buf[self._read_pos:] + current 1159*cda5da8dSAndroid Build Coastguard Worker self._read_pos = 0 1160*cda5da8dSAndroid Build Coastguard Worker return self._read_buf[self._read_pos:] 1161*cda5da8dSAndroid Build Coastguard Worker 1162*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 1163*cda5da8dSAndroid Build Coastguard Worker """Reads up to size bytes, with at most one read() system call.""" 1164*cda5da8dSAndroid Build Coastguard Worker # Returns up to size bytes. If at least one byte is buffered, we 1165*cda5da8dSAndroid Build Coastguard Worker # only return buffered bytes. Otherwise, we do one raw read. 1166*cda5da8dSAndroid Build Coastguard Worker if size < 0: 1167*cda5da8dSAndroid Build Coastguard Worker size = self.buffer_size 1168*cda5da8dSAndroid Build Coastguard Worker if size == 0: 1169*cda5da8dSAndroid Build Coastguard Worker return b"" 1170*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1171*cda5da8dSAndroid Build Coastguard Worker self._peek_unlocked(1) 1172*cda5da8dSAndroid Build Coastguard Worker return self._read_unlocked( 1173*cda5da8dSAndroid Build Coastguard Worker min(size, len(self._read_buf) - self._read_pos)) 1174*cda5da8dSAndroid Build Coastguard Worker 1175*cda5da8dSAndroid Build Coastguard Worker # Implementing readinto() and readinto1() is not strictly necessary (we 1176*cda5da8dSAndroid Build Coastguard Worker # could rely on the base class that provides an implementation in terms of 1177*cda5da8dSAndroid Build Coastguard Worker # read() and read1()). We do it anyway to keep the _pyio implementation 1178*cda5da8dSAndroid Build Coastguard Worker # similar to the io implementation (which implements the methods for 1179*cda5da8dSAndroid Build Coastguard Worker # performance reasons). 1180*cda5da8dSAndroid Build Coastguard Worker def _readinto(self, buf, read1): 1181*cda5da8dSAndroid Build Coastguard Worker """Read data into *buf* with at most one system call.""" 1182*cda5da8dSAndroid Build Coastguard Worker 1183*cda5da8dSAndroid Build Coastguard Worker # Need to create a memoryview object of type 'b', otherwise 1184*cda5da8dSAndroid Build Coastguard Worker # we may not be able to assign bytes to it, and slicing it 1185*cda5da8dSAndroid Build Coastguard Worker # would create a new object. 1186*cda5da8dSAndroid Build Coastguard Worker if not isinstance(buf, memoryview): 1187*cda5da8dSAndroid Build Coastguard Worker buf = memoryview(buf) 1188*cda5da8dSAndroid Build Coastguard Worker if buf.nbytes == 0: 1189*cda5da8dSAndroid Build Coastguard Worker return 0 1190*cda5da8dSAndroid Build Coastguard Worker buf = buf.cast('B') 1191*cda5da8dSAndroid Build Coastguard Worker 1192*cda5da8dSAndroid Build Coastguard Worker written = 0 1193*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1194*cda5da8dSAndroid Build Coastguard Worker while written < len(buf): 1195*cda5da8dSAndroid Build Coastguard Worker 1196*cda5da8dSAndroid Build Coastguard Worker # First try to read from internal buffer 1197*cda5da8dSAndroid Build Coastguard Worker avail = min(len(self._read_buf) - self._read_pos, len(buf)) 1198*cda5da8dSAndroid Build Coastguard Worker if avail: 1199*cda5da8dSAndroid Build Coastguard Worker buf[written:written+avail] = \ 1200*cda5da8dSAndroid Build Coastguard Worker self._read_buf[self._read_pos:self._read_pos+avail] 1201*cda5da8dSAndroid Build Coastguard Worker self._read_pos += avail 1202*cda5da8dSAndroid Build Coastguard Worker written += avail 1203*cda5da8dSAndroid Build Coastguard Worker if written == len(buf): 1204*cda5da8dSAndroid Build Coastguard Worker break 1205*cda5da8dSAndroid Build Coastguard Worker 1206*cda5da8dSAndroid Build Coastguard Worker # If remaining space in callers buffer is larger than 1207*cda5da8dSAndroid Build Coastguard Worker # internal buffer, read directly into callers buffer 1208*cda5da8dSAndroid Build Coastguard Worker if len(buf) - written > self.buffer_size: 1209*cda5da8dSAndroid Build Coastguard Worker n = self.raw.readinto(buf[written:]) 1210*cda5da8dSAndroid Build Coastguard Worker if not n: 1211*cda5da8dSAndroid Build Coastguard Worker break # eof 1212*cda5da8dSAndroid Build Coastguard Worker written += n 1213*cda5da8dSAndroid Build Coastguard Worker 1214*cda5da8dSAndroid Build Coastguard Worker # Otherwise refill internal buffer - unless we're 1215*cda5da8dSAndroid Build Coastguard Worker # in read1 mode and already got some data 1216*cda5da8dSAndroid Build Coastguard Worker elif not (read1 and written): 1217*cda5da8dSAndroid Build Coastguard Worker if not self._peek_unlocked(1): 1218*cda5da8dSAndroid Build Coastguard Worker break # eof 1219*cda5da8dSAndroid Build Coastguard Worker 1220*cda5da8dSAndroid Build Coastguard Worker # In readinto1 mode, return as soon as we have some data 1221*cda5da8dSAndroid Build Coastguard Worker if read1 and written: 1222*cda5da8dSAndroid Build Coastguard Worker break 1223*cda5da8dSAndroid Build Coastguard Worker 1224*cda5da8dSAndroid Build Coastguard Worker return written 1225*cda5da8dSAndroid Build Coastguard Worker 1226*cda5da8dSAndroid Build Coastguard Worker def tell(self): 1227*cda5da8dSAndroid Build Coastguard Worker return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos 1228*cda5da8dSAndroid Build Coastguard Worker 1229*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 1230*cda5da8dSAndroid Build Coastguard Worker if whence not in valid_seek_flags: 1231*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid whence value") 1232*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1233*cda5da8dSAndroid Build Coastguard Worker if whence == 1: 1234*cda5da8dSAndroid Build Coastguard Worker pos -= len(self._read_buf) - self._read_pos 1235*cda5da8dSAndroid Build Coastguard Worker pos = _BufferedIOMixin.seek(self, pos, whence) 1236*cda5da8dSAndroid Build Coastguard Worker self._reset_read_buf() 1237*cda5da8dSAndroid Build Coastguard Worker return pos 1238*cda5da8dSAndroid Build Coastguard Worker 1239*cda5da8dSAndroid Build Coastguard Workerclass BufferedWriter(_BufferedIOMixin): 1240*cda5da8dSAndroid Build Coastguard Worker 1241*cda5da8dSAndroid Build Coastguard Worker """A buffer for a writeable sequential RawIO object. 1242*cda5da8dSAndroid Build Coastguard Worker 1243*cda5da8dSAndroid Build Coastguard Worker The constructor creates a BufferedWriter for the given writeable raw 1244*cda5da8dSAndroid Build Coastguard Worker stream. If the buffer_size is not given, it defaults to 1245*cda5da8dSAndroid Build Coastguard Worker DEFAULT_BUFFER_SIZE. 1246*cda5da8dSAndroid Build Coastguard Worker """ 1247*cda5da8dSAndroid Build Coastguard Worker 1248*cda5da8dSAndroid Build Coastguard Worker def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 1249*cda5da8dSAndroid Build Coastguard Worker if not raw.writable(): 1250*cda5da8dSAndroid Build Coastguard Worker raise OSError('"raw" argument must be writable.') 1251*cda5da8dSAndroid Build Coastguard Worker 1252*cda5da8dSAndroid Build Coastguard Worker _BufferedIOMixin.__init__(self, raw) 1253*cda5da8dSAndroid Build Coastguard Worker if buffer_size <= 0: 1254*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid buffer size") 1255*cda5da8dSAndroid Build Coastguard Worker self.buffer_size = buffer_size 1256*cda5da8dSAndroid Build Coastguard Worker self._write_buf = bytearray() 1257*cda5da8dSAndroid Build Coastguard Worker self._write_lock = Lock() 1258*cda5da8dSAndroid Build Coastguard Worker 1259*cda5da8dSAndroid Build Coastguard Worker def writable(self): 1260*cda5da8dSAndroid Build Coastguard Worker return self.raw.writable() 1261*cda5da8dSAndroid Build Coastguard Worker 1262*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 1263*cda5da8dSAndroid Build Coastguard Worker if isinstance(b, str): 1264*cda5da8dSAndroid Build Coastguard Worker raise TypeError("can't write str to binary stream") 1265*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1266*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1267*cda5da8dSAndroid Build Coastguard Worker raise ValueError("write to closed file") 1268*cda5da8dSAndroid Build Coastguard Worker # XXX we can implement some more tricks to try and avoid 1269*cda5da8dSAndroid Build Coastguard Worker # partial writes 1270*cda5da8dSAndroid Build Coastguard Worker if len(self._write_buf) > self.buffer_size: 1271*cda5da8dSAndroid Build Coastguard Worker # We're full, so let's pre-flush the buffer. (This may 1272*cda5da8dSAndroid Build Coastguard Worker # raise BlockingIOError with characters_written == 0.) 1273*cda5da8dSAndroid Build Coastguard Worker self._flush_unlocked() 1274*cda5da8dSAndroid Build Coastguard Worker before = len(self._write_buf) 1275*cda5da8dSAndroid Build Coastguard Worker self._write_buf.extend(b) 1276*cda5da8dSAndroid Build Coastguard Worker written = len(self._write_buf) - before 1277*cda5da8dSAndroid Build Coastguard Worker if len(self._write_buf) > self.buffer_size: 1278*cda5da8dSAndroid Build Coastguard Worker try: 1279*cda5da8dSAndroid Build Coastguard Worker self._flush_unlocked() 1280*cda5da8dSAndroid Build Coastguard Worker except BlockingIOError as e: 1281*cda5da8dSAndroid Build Coastguard Worker if len(self._write_buf) > self.buffer_size: 1282*cda5da8dSAndroid Build Coastguard Worker # We've hit the buffer_size. We have to accept a partial 1283*cda5da8dSAndroid Build Coastguard Worker # write and cut back our buffer. 1284*cda5da8dSAndroid Build Coastguard Worker overage = len(self._write_buf) - self.buffer_size 1285*cda5da8dSAndroid Build Coastguard Worker written -= overage 1286*cda5da8dSAndroid Build Coastguard Worker self._write_buf = self._write_buf[:self.buffer_size] 1287*cda5da8dSAndroid Build Coastguard Worker raise BlockingIOError(e.errno, e.strerror, written) 1288*cda5da8dSAndroid Build Coastguard Worker return written 1289*cda5da8dSAndroid Build Coastguard Worker 1290*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 1291*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1292*cda5da8dSAndroid Build Coastguard Worker self._flush_unlocked() 1293*cda5da8dSAndroid Build Coastguard Worker if pos is None: 1294*cda5da8dSAndroid Build Coastguard Worker pos = self.raw.tell() 1295*cda5da8dSAndroid Build Coastguard Worker return self.raw.truncate(pos) 1296*cda5da8dSAndroid Build Coastguard Worker 1297*cda5da8dSAndroid Build Coastguard Worker def flush(self): 1298*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1299*cda5da8dSAndroid Build Coastguard Worker self._flush_unlocked() 1300*cda5da8dSAndroid Build Coastguard Worker 1301*cda5da8dSAndroid Build Coastguard Worker def _flush_unlocked(self): 1302*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1303*cda5da8dSAndroid Build Coastguard Worker raise ValueError("flush on closed file") 1304*cda5da8dSAndroid Build Coastguard Worker while self._write_buf: 1305*cda5da8dSAndroid Build Coastguard Worker try: 1306*cda5da8dSAndroid Build Coastguard Worker n = self.raw.write(self._write_buf) 1307*cda5da8dSAndroid Build Coastguard Worker except BlockingIOError: 1308*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("self.raw should implement RawIOBase: it " 1309*cda5da8dSAndroid Build Coastguard Worker "should not raise BlockingIOError") 1310*cda5da8dSAndroid Build Coastguard Worker if n is None: 1311*cda5da8dSAndroid Build Coastguard Worker raise BlockingIOError( 1312*cda5da8dSAndroid Build Coastguard Worker errno.EAGAIN, 1313*cda5da8dSAndroid Build Coastguard Worker "write could not complete without blocking", 0) 1314*cda5da8dSAndroid Build Coastguard Worker if n > len(self._write_buf) or n < 0: 1315*cda5da8dSAndroid Build Coastguard Worker raise OSError("write() returned incorrect number of bytes") 1316*cda5da8dSAndroid Build Coastguard Worker del self._write_buf[:n] 1317*cda5da8dSAndroid Build Coastguard Worker 1318*cda5da8dSAndroid Build Coastguard Worker def tell(self): 1319*cda5da8dSAndroid Build Coastguard Worker return _BufferedIOMixin.tell(self) + len(self._write_buf) 1320*cda5da8dSAndroid Build Coastguard Worker 1321*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 1322*cda5da8dSAndroid Build Coastguard Worker if whence not in valid_seek_flags: 1323*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid whence value") 1324*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1325*cda5da8dSAndroid Build Coastguard Worker self._flush_unlocked() 1326*cda5da8dSAndroid Build Coastguard Worker return _BufferedIOMixin.seek(self, pos, whence) 1327*cda5da8dSAndroid Build Coastguard Worker 1328*cda5da8dSAndroid Build Coastguard Worker def close(self): 1329*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1330*cda5da8dSAndroid Build Coastguard Worker if self.raw is None or self.closed: 1331*cda5da8dSAndroid Build Coastguard Worker return 1332*cda5da8dSAndroid Build Coastguard Worker # We have to release the lock and call self.flush() (which will 1333*cda5da8dSAndroid Build Coastguard Worker # probably just re-take the lock) in case flush has been overridden in 1334*cda5da8dSAndroid Build Coastguard Worker # a subclass or the user set self.flush to something. This is the same 1335*cda5da8dSAndroid Build Coastguard Worker # behavior as the C implementation. 1336*cda5da8dSAndroid Build Coastguard Worker try: 1337*cda5da8dSAndroid Build Coastguard Worker # may raise BlockingIOError or BrokenPipeError etc 1338*cda5da8dSAndroid Build Coastguard Worker self.flush() 1339*cda5da8dSAndroid Build Coastguard Worker finally: 1340*cda5da8dSAndroid Build Coastguard Worker with self._write_lock: 1341*cda5da8dSAndroid Build Coastguard Worker self.raw.close() 1342*cda5da8dSAndroid Build Coastguard Worker 1343*cda5da8dSAndroid Build Coastguard Worker 1344*cda5da8dSAndroid Build Coastguard Workerclass BufferedRWPair(BufferedIOBase): 1345*cda5da8dSAndroid Build Coastguard Worker 1346*cda5da8dSAndroid Build Coastguard Worker """A buffered reader and writer object together. 1347*cda5da8dSAndroid Build Coastguard Worker 1348*cda5da8dSAndroid Build Coastguard Worker A buffered reader object and buffered writer object put together to 1349*cda5da8dSAndroid Build Coastguard Worker form a sequential IO object that can read and write. This is typically 1350*cda5da8dSAndroid Build Coastguard Worker used with a socket or two-way pipe. 1351*cda5da8dSAndroid Build Coastguard Worker 1352*cda5da8dSAndroid Build Coastguard Worker reader and writer are RawIOBase objects that are readable and 1353*cda5da8dSAndroid Build Coastguard Worker writeable respectively. If the buffer_size is omitted it defaults to 1354*cda5da8dSAndroid Build Coastguard Worker DEFAULT_BUFFER_SIZE. 1355*cda5da8dSAndroid Build Coastguard Worker """ 1356*cda5da8dSAndroid Build Coastguard Worker 1357*cda5da8dSAndroid Build Coastguard Worker # XXX The usefulness of this (compared to having two separate IO 1358*cda5da8dSAndroid Build Coastguard Worker # objects) is questionable. 1359*cda5da8dSAndroid Build Coastguard Worker 1360*cda5da8dSAndroid Build Coastguard Worker def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE): 1361*cda5da8dSAndroid Build Coastguard Worker """Constructor. 1362*cda5da8dSAndroid Build Coastguard Worker 1363*cda5da8dSAndroid Build Coastguard Worker The arguments are two RawIO instances. 1364*cda5da8dSAndroid Build Coastguard Worker """ 1365*cda5da8dSAndroid Build Coastguard Worker if not reader.readable(): 1366*cda5da8dSAndroid Build Coastguard Worker raise OSError('"reader" argument must be readable.') 1367*cda5da8dSAndroid Build Coastguard Worker 1368*cda5da8dSAndroid Build Coastguard Worker if not writer.writable(): 1369*cda5da8dSAndroid Build Coastguard Worker raise OSError('"writer" argument must be writable.') 1370*cda5da8dSAndroid Build Coastguard Worker 1371*cda5da8dSAndroid Build Coastguard Worker self.reader = BufferedReader(reader, buffer_size) 1372*cda5da8dSAndroid Build Coastguard Worker self.writer = BufferedWriter(writer, buffer_size) 1373*cda5da8dSAndroid Build Coastguard Worker 1374*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 1375*cda5da8dSAndroid Build Coastguard Worker if size is None: 1376*cda5da8dSAndroid Build Coastguard Worker size = -1 1377*cda5da8dSAndroid Build Coastguard Worker return self.reader.read(size) 1378*cda5da8dSAndroid Build Coastguard Worker 1379*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 1380*cda5da8dSAndroid Build Coastguard Worker return self.reader.readinto(b) 1381*cda5da8dSAndroid Build Coastguard Worker 1382*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 1383*cda5da8dSAndroid Build Coastguard Worker return self.writer.write(b) 1384*cda5da8dSAndroid Build Coastguard Worker 1385*cda5da8dSAndroid Build Coastguard Worker def peek(self, size=0): 1386*cda5da8dSAndroid Build Coastguard Worker return self.reader.peek(size) 1387*cda5da8dSAndroid Build Coastguard Worker 1388*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 1389*cda5da8dSAndroid Build Coastguard Worker return self.reader.read1(size) 1390*cda5da8dSAndroid Build Coastguard Worker 1391*cda5da8dSAndroid Build Coastguard Worker def readinto1(self, b): 1392*cda5da8dSAndroid Build Coastguard Worker return self.reader.readinto1(b) 1393*cda5da8dSAndroid Build Coastguard Worker 1394*cda5da8dSAndroid Build Coastguard Worker def readable(self): 1395*cda5da8dSAndroid Build Coastguard Worker return self.reader.readable() 1396*cda5da8dSAndroid Build Coastguard Worker 1397*cda5da8dSAndroid Build Coastguard Worker def writable(self): 1398*cda5da8dSAndroid Build Coastguard Worker return self.writer.writable() 1399*cda5da8dSAndroid Build Coastguard Worker 1400*cda5da8dSAndroid Build Coastguard Worker def flush(self): 1401*cda5da8dSAndroid Build Coastguard Worker return self.writer.flush() 1402*cda5da8dSAndroid Build Coastguard Worker 1403*cda5da8dSAndroid Build Coastguard Worker def close(self): 1404*cda5da8dSAndroid Build Coastguard Worker try: 1405*cda5da8dSAndroid Build Coastguard Worker self.writer.close() 1406*cda5da8dSAndroid Build Coastguard Worker finally: 1407*cda5da8dSAndroid Build Coastguard Worker self.reader.close() 1408*cda5da8dSAndroid Build Coastguard Worker 1409*cda5da8dSAndroid Build Coastguard Worker def isatty(self): 1410*cda5da8dSAndroid Build Coastguard Worker return self.reader.isatty() or self.writer.isatty() 1411*cda5da8dSAndroid Build Coastguard Worker 1412*cda5da8dSAndroid Build Coastguard Worker @property 1413*cda5da8dSAndroid Build Coastguard Worker def closed(self): 1414*cda5da8dSAndroid Build Coastguard Worker return self.writer.closed 1415*cda5da8dSAndroid Build Coastguard Worker 1416*cda5da8dSAndroid Build Coastguard Worker 1417*cda5da8dSAndroid Build Coastguard Workerclass BufferedRandom(BufferedWriter, BufferedReader): 1418*cda5da8dSAndroid Build Coastguard Worker 1419*cda5da8dSAndroid Build Coastguard Worker """A buffered interface to random access streams. 1420*cda5da8dSAndroid Build Coastguard Worker 1421*cda5da8dSAndroid Build Coastguard Worker The constructor creates a reader and writer for a seekable stream, 1422*cda5da8dSAndroid Build Coastguard Worker raw, given in the first argument. If the buffer_size is omitted it 1423*cda5da8dSAndroid Build Coastguard Worker defaults to DEFAULT_BUFFER_SIZE. 1424*cda5da8dSAndroid Build Coastguard Worker """ 1425*cda5da8dSAndroid Build Coastguard Worker 1426*cda5da8dSAndroid Build Coastguard Worker def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 1427*cda5da8dSAndroid Build Coastguard Worker raw._checkSeekable() 1428*cda5da8dSAndroid Build Coastguard Worker BufferedReader.__init__(self, raw, buffer_size) 1429*cda5da8dSAndroid Build Coastguard Worker BufferedWriter.__init__(self, raw, buffer_size) 1430*cda5da8dSAndroid Build Coastguard Worker 1431*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=0): 1432*cda5da8dSAndroid Build Coastguard Worker if whence not in valid_seek_flags: 1433*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid whence value") 1434*cda5da8dSAndroid Build Coastguard Worker self.flush() 1435*cda5da8dSAndroid Build Coastguard Worker if self._read_buf: 1436*cda5da8dSAndroid Build Coastguard Worker # Undo read ahead. 1437*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1438*cda5da8dSAndroid Build Coastguard Worker self.raw.seek(self._read_pos - len(self._read_buf), 1) 1439*cda5da8dSAndroid Build Coastguard Worker # First do the raw seek, then empty the read buffer, so that 1440*cda5da8dSAndroid Build Coastguard Worker # if the raw seek fails, we don't lose buffered data forever. 1441*cda5da8dSAndroid Build Coastguard Worker pos = self.raw.seek(pos, whence) 1442*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1443*cda5da8dSAndroid Build Coastguard Worker self._reset_read_buf() 1444*cda5da8dSAndroid Build Coastguard Worker if pos < 0: 1445*cda5da8dSAndroid Build Coastguard Worker raise OSError("seek() returned invalid position") 1446*cda5da8dSAndroid Build Coastguard Worker return pos 1447*cda5da8dSAndroid Build Coastguard Worker 1448*cda5da8dSAndroid Build Coastguard Worker def tell(self): 1449*cda5da8dSAndroid Build Coastguard Worker if self._write_buf: 1450*cda5da8dSAndroid Build Coastguard Worker return BufferedWriter.tell(self) 1451*cda5da8dSAndroid Build Coastguard Worker else: 1452*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.tell(self) 1453*cda5da8dSAndroid Build Coastguard Worker 1454*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 1455*cda5da8dSAndroid Build Coastguard Worker if pos is None: 1456*cda5da8dSAndroid Build Coastguard Worker pos = self.tell() 1457*cda5da8dSAndroid Build Coastguard Worker # Use seek to flush the read buffer. 1458*cda5da8dSAndroid Build Coastguard Worker return BufferedWriter.truncate(self, pos) 1459*cda5da8dSAndroid Build Coastguard Worker 1460*cda5da8dSAndroid Build Coastguard Worker def read(self, size=None): 1461*cda5da8dSAndroid Build Coastguard Worker if size is None: 1462*cda5da8dSAndroid Build Coastguard Worker size = -1 1463*cda5da8dSAndroid Build Coastguard Worker self.flush() 1464*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.read(self, size) 1465*cda5da8dSAndroid Build Coastguard Worker 1466*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 1467*cda5da8dSAndroid Build Coastguard Worker self.flush() 1468*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.readinto(self, b) 1469*cda5da8dSAndroid Build Coastguard Worker 1470*cda5da8dSAndroid Build Coastguard Worker def peek(self, size=0): 1471*cda5da8dSAndroid Build Coastguard Worker self.flush() 1472*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.peek(self, size) 1473*cda5da8dSAndroid Build Coastguard Worker 1474*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 1475*cda5da8dSAndroid Build Coastguard Worker self.flush() 1476*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.read1(self, size) 1477*cda5da8dSAndroid Build Coastguard Worker 1478*cda5da8dSAndroid Build Coastguard Worker def readinto1(self, b): 1479*cda5da8dSAndroid Build Coastguard Worker self.flush() 1480*cda5da8dSAndroid Build Coastguard Worker return BufferedReader.readinto1(self, b) 1481*cda5da8dSAndroid Build Coastguard Worker 1482*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 1483*cda5da8dSAndroid Build Coastguard Worker if self._read_buf: 1484*cda5da8dSAndroid Build Coastguard Worker # Undo readahead 1485*cda5da8dSAndroid Build Coastguard Worker with self._read_lock: 1486*cda5da8dSAndroid Build Coastguard Worker self.raw.seek(self._read_pos - len(self._read_buf), 1) 1487*cda5da8dSAndroid Build Coastguard Worker self._reset_read_buf() 1488*cda5da8dSAndroid Build Coastguard Worker return BufferedWriter.write(self, b) 1489*cda5da8dSAndroid Build Coastguard Worker 1490*cda5da8dSAndroid Build Coastguard Worker 1491*cda5da8dSAndroid Build Coastguard Workerclass FileIO(RawIOBase): 1492*cda5da8dSAndroid Build Coastguard Worker _fd = -1 1493*cda5da8dSAndroid Build Coastguard Worker _created = False 1494*cda5da8dSAndroid Build Coastguard Worker _readable = False 1495*cda5da8dSAndroid Build Coastguard Worker _writable = False 1496*cda5da8dSAndroid Build Coastguard Worker _appending = False 1497*cda5da8dSAndroid Build Coastguard Worker _seekable = None 1498*cda5da8dSAndroid Build Coastguard Worker _closefd = True 1499*cda5da8dSAndroid Build Coastguard Worker 1500*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file, mode='r', closefd=True, opener=None): 1501*cda5da8dSAndroid Build Coastguard Worker """Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading, 1502*cda5da8dSAndroid Build Coastguard Worker writing, exclusive creation or appending. The file will be created if it 1503*cda5da8dSAndroid Build Coastguard Worker doesn't exist when opened for writing or appending; it will be truncated 1504*cda5da8dSAndroid Build Coastguard Worker when opened for writing. A FileExistsError will be raised if it already 1505*cda5da8dSAndroid Build Coastguard Worker exists when opened for creating. Opening a file for creating implies 1506*cda5da8dSAndroid Build Coastguard Worker writing so this mode behaves in a similar way to 'w'. Add a '+' to the mode 1507*cda5da8dSAndroid Build Coastguard Worker to allow simultaneous reading and writing. A custom opener can be used by 1508*cda5da8dSAndroid Build Coastguard Worker passing a callable as *opener*. The underlying file descriptor for the file 1509*cda5da8dSAndroid Build Coastguard Worker object is then obtained by calling opener with (*name*, *flags*). 1510*cda5da8dSAndroid Build Coastguard Worker *opener* must return an open file descriptor (passing os.open as *opener* 1511*cda5da8dSAndroid Build Coastguard Worker results in functionality similar to passing None). 1512*cda5da8dSAndroid Build Coastguard Worker """ 1513*cda5da8dSAndroid Build Coastguard Worker if self._fd >= 0: 1514*cda5da8dSAndroid Build Coastguard Worker # Have to close the existing file first. 1515*cda5da8dSAndroid Build Coastguard Worker try: 1516*cda5da8dSAndroid Build Coastguard Worker if self._closefd: 1517*cda5da8dSAndroid Build Coastguard Worker os.close(self._fd) 1518*cda5da8dSAndroid Build Coastguard Worker finally: 1519*cda5da8dSAndroid Build Coastguard Worker self._fd = -1 1520*cda5da8dSAndroid Build Coastguard Worker 1521*cda5da8dSAndroid Build Coastguard Worker if isinstance(file, float): 1522*cda5da8dSAndroid Build Coastguard Worker raise TypeError('integer argument expected, got float') 1523*cda5da8dSAndroid Build Coastguard Worker if isinstance(file, int): 1524*cda5da8dSAndroid Build Coastguard Worker fd = file 1525*cda5da8dSAndroid Build Coastguard Worker if fd < 0: 1526*cda5da8dSAndroid Build Coastguard Worker raise ValueError('negative file descriptor') 1527*cda5da8dSAndroid Build Coastguard Worker else: 1528*cda5da8dSAndroid Build Coastguard Worker fd = -1 1529*cda5da8dSAndroid Build Coastguard Worker 1530*cda5da8dSAndroid Build Coastguard Worker if not isinstance(mode, str): 1531*cda5da8dSAndroid Build Coastguard Worker raise TypeError('invalid mode: %s' % (mode,)) 1532*cda5da8dSAndroid Build Coastguard Worker if not set(mode) <= set('xrwab+'): 1533*cda5da8dSAndroid Build Coastguard Worker raise ValueError('invalid mode: %s' % (mode,)) 1534*cda5da8dSAndroid Build Coastguard Worker if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1: 1535*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Must have exactly one of create/read/write/append ' 1536*cda5da8dSAndroid Build Coastguard Worker 'mode and at most one plus') 1537*cda5da8dSAndroid Build Coastguard Worker 1538*cda5da8dSAndroid Build Coastguard Worker if 'x' in mode: 1539*cda5da8dSAndroid Build Coastguard Worker self._created = True 1540*cda5da8dSAndroid Build Coastguard Worker self._writable = True 1541*cda5da8dSAndroid Build Coastguard Worker flags = os.O_EXCL | os.O_CREAT 1542*cda5da8dSAndroid Build Coastguard Worker elif 'r' in mode: 1543*cda5da8dSAndroid Build Coastguard Worker self._readable = True 1544*cda5da8dSAndroid Build Coastguard Worker flags = 0 1545*cda5da8dSAndroid Build Coastguard Worker elif 'w' in mode: 1546*cda5da8dSAndroid Build Coastguard Worker self._writable = True 1547*cda5da8dSAndroid Build Coastguard Worker flags = os.O_CREAT | os.O_TRUNC 1548*cda5da8dSAndroid Build Coastguard Worker elif 'a' in mode: 1549*cda5da8dSAndroid Build Coastguard Worker self._writable = True 1550*cda5da8dSAndroid Build Coastguard Worker self._appending = True 1551*cda5da8dSAndroid Build Coastguard Worker flags = os.O_APPEND | os.O_CREAT 1552*cda5da8dSAndroid Build Coastguard Worker 1553*cda5da8dSAndroid Build Coastguard Worker if '+' in mode: 1554*cda5da8dSAndroid Build Coastguard Worker self._readable = True 1555*cda5da8dSAndroid Build Coastguard Worker self._writable = True 1556*cda5da8dSAndroid Build Coastguard Worker 1557*cda5da8dSAndroid Build Coastguard Worker if self._readable and self._writable: 1558*cda5da8dSAndroid Build Coastguard Worker flags |= os.O_RDWR 1559*cda5da8dSAndroid Build Coastguard Worker elif self._readable: 1560*cda5da8dSAndroid Build Coastguard Worker flags |= os.O_RDONLY 1561*cda5da8dSAndroid Build Coastguard Worker else: 1562*cda5da8dSAndroid Build Coastguard Worker flags |= os.O_WRONLY 1563*cda5da8dSAndroid Build Coastguard Worker 1564*cda5da8dSAndroid Build Coastguard Worker flags |= getattr(os, 'O_BINARY', 0) 1565*cda5da8dSAndroid Build Coastguard Worker 1566*cda5da8dSAndroid Build Coastguard Worker noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or 1567*cda5da8dSAndroid Build Coastguard Worker getattr(os, 'O_CLOEXEC', 0)) 1568*cda5da8dSAndroid Build Coastguard Worker flags |= noinherit_flag 1569*cda5da8dSAndroid Build Coastguard Worker 1570*cda5da8dSAndroid Build Coastguard Worker owned_fd = None 1571*cda5da8dSAndroid Build Coastguard Worker try: 1572*cda5da8dSAndroid Build Coastguard Worker if fd < 0: 1573*cda5da8dSAndroid Build Coastguard Worker if not closefd: 1574*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Cannot use closefd=False with file name') 1575*cda5da8dSAndroid Build Coastguard Worker if opener is None: 1576*cda5da8dSAndroid Build Coastguard Worker fd = os.open(file, flags, 0o666) 1577*cda5da8dSAndroid Build Coastguard Worker else: 1578*cda5da8dSAndroid Build Coastguard Worker fd = opener(file, flags) 1579*cda5da8dSAndroid Build Coastguard Worker if not isinstance(fd, int): 1580*cda5da8dSAndroid Build Coastguard Worker raise TypeError('expected integer from opener') 1581*cda5da8dSAndroid Build Coastguard Worker if fd < 0: 1582*cda5da8dSAndroid Build Coastguard Worker raise OSError('Negative file descriptor') 1583*cda5da8dSAndroid Build Coastguard Worker owned_fd = fd 1584*cda5da8dSAndroid Build Coastguard Worker if not noinherit_flag: 1585*cda5da8dSAndroid Build Coastguard Worker os.set_inheritable(fd, False) 1586*cda5da8dSAndroid Build Coastguard Worker 1587*cda5da8dSAndroid Build Coastguard Worker self._closefd = closefd 1588*cda5da8dSAndroid Build Coastguard Worker fdfstat = os.fstat(fd) 1589*cda5da8dSAndroid Build Coastguard Worker try: 1590*cda5da8dSAndroid Build Coastguard Worker if stat.S_ISDIR(fdfstat.st_mode): 1591*cda5da8dSAndroid Build Coastguard Worker raise IsADirectoryError(errno.EISDIR, 1592*cda5da8dSAndroid Build Coastguard Worker os.strerror(errno.EISDIR), file) 1593*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1594*cda5da8dSAndroid Build Coastguard Worker # Ignore the AttributeError if stat.S_ISDIR or errno.EISDIR 1595*cda5da8dSAndroid Build Coastguard Worker # don't exist. 1596*cda5da8dSAndroid Build Coastguard Worker pass 1597*cda5da8dSAndroid Build Coastguard Worker self._blksize = getattr(fdfstat, 'st_blksize', 0) 1598*cda5da8dSAndroid Build Coastguard Worker if self._blksize <= 1: 1599*cda5da8dSAndroid Build Coastguard Worker self._blksize = DEFAULT_BUFFER_SIZE 1600*cda5da8dSAndroid Build Coastguard Worker 1601*cda5da8dSAndroid Build Coastguard Worker if _setmode: 1602*cda5da8dSAndroid Build Coastguard Worker # don't translate newlines (\r\n <=> \n) 1603*cda5da8dSAndroid Build Coastguard Worker _setmode(fd, os.O_BINARY) 1604*cda5da8dSAndroid Build Coastguard Worker 1605*cda5da8dSAndroid Build Coastguard Worker self.name = file 1606*cda5da8dSAndroid Build Coastguard Worker if self._appending: 1607*cda5da8dSAndroid Build Coastguard Worker # For consistent behaviour, we explicitly seek to the 1608*cda5da8dSAndroid Build Coastguard Worker # end of file (otherwise, it might be done only on the 1609*cda5da8dSAndroid Build Coastguard Worker # first write()). 1610*cda5da8dSAndroid Build Coastguard Worker try: 1611*cda5da8dSAndroid Build Coastguard Worker os.lseek(fd, 0, SEEK_END) 1612*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1613*cda5da8dSAndroid Build Coastguard Worker if e.errno != errno.ESPIPE: 1614*cda5da8dSAndroid Build Coastguard Worker raise 1615*cda5da8dSAndroid Build Coastguard Worker except: 1616*cda5da8dSAndroid Build Coastguard Worker if owned_fd is not None: 1617*cda5da8dSAndroid Build Coastguard Worker os.close(owned_fd) 1618*cda5da8dSAndroid Build Coastguard Worker raise 1619*cda5da8dSAndroid Build Coastguard Worker self._fd = fd 1620*cda5da8dSAndroid Build Coastguard Worker 1621*cda5da8dSAndroid Build Coastguard Worker def __del__(self): 1622*cda5da8dSAndroid Build Coastguard Worker if self._fd >= 0 and self._closefd and not self.closed: 1623*cda5da8dSAndroid Build Coastguard Worker import warnings 1624*cda5da8dSAndroid Build Coastguard Worker warnings.warn('unclosed file %r' % (self,), ResourceWarning, 1625*cda5da8dSAndroid Build Coastguard Worker stacklevel=2, source=self) 1626*cda5da8dSAndroid Build Coastguard Worker self.close() 1627*cda5da8dSAndroid Build Coastguard Worker 1628*cda5da8dSAndroid Build Coastguard Worker def __getstate__(self): 1629*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") 1630*cda5da8dSAndroid Build Coastguard Worker 1631*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1632*cda5da8dSAndroid Build Coastguard Worker class_name = '%s.%s' % (self.__class__.__module__, 1633*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__) 1634*cda5da8dSAndroid Build Coastguard Worker if self.closed: 1635*cda5da8dSAndroid Build Coastguard Worker return '<%s [closed]>' % class_name 1636*cda5da8dSAndroid Build Coastguard Worker try: 1637*cda5da8dSAndroid Build Coastguard Worker name = self.name 1638*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1639*cda5da8dSAndroid Build Coastguard Worker return ('<%s fd=%d mode=%r closefd=%r>' % 1640*cda5da8dSAndroid Build Coastguard Worker (class_name, self._fd, self.mode, self._closefd)) 1641*cda5da8dSAndroid Build Coastguard Worker else: 1642*cda5da8dSAndroid Build Coastguard Worker return ('<%s name=%r mode=%r closefd=%r>' % 1643*cda5da8dSAndroid Build Coastguard Worker (class_name, name, self.mode, self._closefd)) 1644*cda5da8dSAndroid Build Coastguard Worker 1645*cda5da8dSAndroid Build Coastguard Worker def _checkReadable(self): 1646*cda5da8dSAndroid Build Coastguard Worker if not self._readable: 1647*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation('File not open for reading') 1648*cda5da8dSAndroid Build Coastguard Worker 1649*cda5da8dSAndroid Build Coastguard Worker def _checkWritable(self, msg=None): 1650*cda5da8dSAndroid Build Coastguard Worker if not self._writable: 1651*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation('File not open for writing') 1652*cda5da8dSAndroid Build Coastguard Worker 1653*cda5da8dSAndroid Build Coastguard Worker def read(self, size=None): 1654*cda5da8dSAndroid Build Coastguard Worker """Read at most size bytes, returned as bytes. 1655*cda5da8dSAndroid Build Coastguard Worker 1656*cda5da8dSAndroid Build Coastguard Worker Only makes one system call, so less data may be returned than requested 1657*cda5da8dSAndroid Build Coastguard Worker In non-blocking mode, returns None if no data is available. 1658*cda5da8dSAndroid Build Coastguard Worker Return an empty bytes object at EOF. 1659*cda5da8dSAndroid Build Coastguard Worker """ 1660*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1661*cda5da8dSAndroid Build Coastguard Worker self._checkReadable() 1662*cda5da8dSAndroid Build Coastguard Worker if size is None or size < 0: 1663*cda5da8dSAndroid Build Coastguard Worker return self.readall() 1664*cda5da8dSAndroid Build Coastguard Worker try: 1665*cda5da8dSAndroid Build Coastguard Worker return os.read(self._fd, size) 1666*cda5da8dSAndroid Build Coastguard Worker except BlockingIOError: 1667*cda5da8dSAndroid Build Coastguard Worker return None 1668*cda5da8dSAndroid Build Coastguard Worker 1669*cda5da8dSAndroid Build Coastguard Worker def readall(self): 1670*cda5da8dSAndroid Build Coastguard Worker """Read all data from the file, returned as bytes. 1671*cda5da8dSAndroid Build Coastguard Worker 1672*cda5da8dSAndroid Build Coastguard Worker In non-blocking mode, returns as much as is immediately available, 1673*cda5da8dSAndroid Build Coastguard Worker or None if no data is available. Return an empty bytes object at EOF. 1674*cda5da8dSAndroid Build Coastguard Worker """ 1675*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1676*cda5da8dSAndroid Build Coastguard Worker self._checkReadable() 1677*cda5da8dSAndroid Build Coastguard Worker bufsize = DEFAULT_BUFFER_SIZE 1678*cda5da8dSAndroid Build Coastguard Worker try: 1679*cda5da8dSAndroid Build Coastguard Worker pos = os.lseek(self._fd, 0, SEEK_CUR) 1680*cda5da8dSAndroid Build Coastguard Worker end = os.fstat(self._fd).st_size 1681*cda5da8dSAndroid Build Coastguard Worker if end >= pos: 1682*cda5da8dSAndroid Build Coastguard Worker bufsize = end - pos + 1 1683*cda5da8dSAndroid Build Coastguard Worker except OSError: 1684*cda5da8dSAndroid Build Coastguard Worker pass 1685*cda5da8dSAndroid Build Coastguard Worker 1686*cda5da8dSAndroid Build Coastguard Worker result = bytearray() 1687*cda5da8dSAndroid Build Coastguard Worker while True: 1688*cda5da8dSAndroid Build Coastguard Worker if len(result) >= bufsize: 1689*cda5da8dSAndroid Build Coastguard Worker bufsize = len(result) 1690*cda5da8dSAndroid Build Coastguard Worker bufsize += max(bufsize, DEFAULT_BUFFER_SIZE) 1691*cda5da8dSAndroid Build Coastguard Worker n = bufsize - len(result) 1692*cda5da8dSAndroid Build Coastguard Worker try: 1693*cda5da8dSAndroid Build Coastguard Worker chunk = os.read(self._fd, n) 1694*cda5da8dSAndroid Build Coastguard Worker except BlockingIOError: 1695*cda5da8dSAndroid Build Coastguard Worker if result: 1696*cda5da8dSAndroid Build Coastguard Worker break 1697*cda5da8dSAndroid Build Coastguard Worker return None 1698*cda5da8dSAndroid Build Coastguard Worker if not chunk: # reached the end of the file 1699*cda5da8dSAndroid Build Coastguard Worker break 1700*cda5da8dSAndroid Build Coastguard Worker result += chunk 1701*cda5da8dSAndroid Build Coastguard Worker 1702*cda5da8dSAndroid Build Coastguard Worker return bytes(result) 1703*cda5da8dSAndroid Build Coastguard Worker 1704*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 1705*cda5da8dSAndroid Build Coastguard Worker """Same as RawIOBase.readinto().""" 1706*cda5da8dSAndroid Build Coastguard Worker m = memoryview(b).cast('B') 1707*cda5da8dSAndroid Build Coastguard Worker data = self.read(len(m)) 1708*cda5da8dSAndroid Build Coastguard Worker n = len(data) 1709*cda5da8dSAndroid Build Coastguard Worker m[:n] = data 1710*cda5da8dSAndroid Build Coastguard Worker return n 1711*cda5da8dSAndroid Build Coastguard Worker 1712*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 1713*cda5da8dSAndroid Build Coastguard Worker """Write bytes b to file, return number written. 1714*cda5da8dSAndroid Build Coastguard Worker 1715*cda5da8dSAndroid Build Coastguard Worker Only makes one system call, so not all of the data may be written. 1716*cda5da8dSAndroid Build Coastguard Worker The number of bytes actually written is returned. In non-blocking mode, 1717*cda5da8dSAndroid Build Coastguard Worker returns None if the write would block. 1718*cda5da8dSAndroid Build Coastguard Worker """ 1719*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1720*cda5da8dSAndroid Build Coastguard Worker self._checkWritable() 1721*cda5da8dSAndroid Build Coastguard Worker try: 1722*cda5da8dSAndroid Build Coastguard Worker return os.write(self._fd, b) 1723*cda5da8dSAndroid Build Coastguard Worker except BlockingIOError: 1724*cda5da8dSAndroid Build Coastguard Worker return None 1725*cda5da8dSAndroid Build Coastguard Worker 1726*cda5da8dSAndroid Build Coastguard Worker def seek(self, pos, whence=SEEK_SET): 1727*cda5da8dSAndroid Build Coastguard Worker """Move to new file position. 1728*cda5da8dSAndroid Build Coastguard Worker 1729*cda5da8dSAndroid Build Coastguard Worker Argument offset is a byte count. Optional argument whence defaults to 1730*cda5da8dSAndroid Build Coastguard Worker SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values 1731*cda5da8dSAndroid Build Coastguard Worker are SEEK_CUR or 1 (move relative to current position, positive or negative), 1732*cda5da8dSAndroid Build Coastguard Worker and SEEK_END or 2 (move relative to end of file, usually negative, although 1733*cda5da8dSAndroid Build Coastguard Worker many platforms allow seeking beyond the end of a file). 1734*cda5da8dSAndroid Build Coastguard Worker 1735*cda5da8dSAndroid Build Coastguard Worker Note that not all file objects are seekable. 1736*cda5da8dSAndroid Build Coastguard Worker """ 1737*cda5da8dSAndroid Build Coastguard Worker if isinstance(pos, float): 1738*cda5da8dSAndroid Build Coastguard Worker raise TypeError('an integer is required') 1739*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1740*cda5da8dSAndroid Build Coastguard Worker return os.lseek(self._fd, pos, whence) 1741*cda5da8dSAndroid Build Coastguard Worker 1742*cda5da8dSAndroid Build Coastguard Worker def tell(self): 1743*cda5da8dSAndroid Build Coastguard Worker """tell() -> int. Current file position. 1744*cda5da8dSAndroid Build Coastguard Worker 1745*cda5da8dSAndroid Build Coastguard Worker Can raise OSError for non seekable files.""" 1746*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1747*cda5da8dSAndroid Build Coastguard Worker return os.lseek(self._fd, 0, SEEK_CUR) 1748*cda5da8dSAndroid Build Coastguard Worker 1749*cda5da8dSAndroid Build Coastguard Worker def truncate(self, size=None): 1750*cda5da8dSAndroid Build Coastguard Worker """Truncate the file to at most size bytes. 1751*cda5da8dSAndroid Build Coastguard Worker 1752*cda5da8dSAndroid Build Coastguard Worker Size defaults to the current file position, as returned by tell(). 1753*cda5da8dSAndroid Build Coastguard Worker The current file position is changed to the value of size. 1754*cda5da8dSAndroid Build Coastguard Worker """ 1755*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1756*cda5da8dSAndroid Build Coastguard Worker self._checkWritable() 1757*cda5da8dSAndroid Build Coastguard Worker if size is None: 1758*cda5da8dSAndroid Build Coastguard Worker size = self.tell() 1759*cda5da8dSAndroid Build Coastguard Worker os.ftruncate(self._fd, size) 1760*cda5da8dSAndroid Build Coastguard Worker return size 1761*cda5da8dSAndroid Build Coastguard Worker 1762*cda5da8dSAndroid Build Coastguard Worker def close(self): 1763*cda5da8dSAndroid Build Coastguard Worker """Close the file. 1764*cda5da8dSAndroid Build Coastguard Worker 1765*cda5da8dSAndroid Build Coastguard Worker A closed file cannot be used for further I/O operations. close() may be 1766*cda5da8dSAndroid Build Coastguard Worker called more than once without error. 1767*cda5da8dSAndroid Build Coastguard Worker """ 1768*cda5da8dSAndroid Build Coastguard Worker if not self.closed: 1769*cda5da8dSAndroid Build Coastguard Worker try: 1770*cda5da8dSAndroid Build Coastguard Worker if self._closefd: 1771*cda5da8dSAndroid Build Coastguard Worker os.close(self._fd) 1772*cda5da8dSAndroid Build Coastguard Worker finally: 1773*cda5da8dSAndroid Build Coastguard Worker super().close() 1774*cda5da8dSAndroid Build Coastguard Worker 1775*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 1776*cda5da8dSAndroid Build Coastguard Worker """True if file supports random-access.""" 1777*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1778*cda5da8dSAndroid Build Coastguard Worker if self._seekable is None: 1779*cda5da8dSAndroid Build Coastguard Worker try: 1780*cda5da8dSAndroid Build Coastguard Worker self.tell() 1781*cda5da8dSAndroid Build Coastguard Worker except OSError: 1782*cda5da8dSAndroid Build Coastguard Worker self._seekable = False 1783*cda5da8dSAndroid Build Coastguard Worker else: 1784*cda5da8dSAndroid Build Coastguard Worker self._seekable = True 1785*cda5da8dSAndroid Build Coastguard Worker return self._seekable 1786*cda5da8dSAndroid Build Coastguard Worker 1787*cda5da8dSAndroid Build Coastguard Worker def readable(self): 1788*cda5da8dSAndroid Build Coastguard Worker """True if file was opened in a read mode.""" 1789*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1790*cda5da8dSAndroid Build Coastguard Worker return self._readable 1791*cda5da8dSAndroid Build Coastguard Worker 1792*cda5da8dSAndroid Build Coastguard Worker def writable(self): 1793*cda5da8dSAndroid Build Coastguard Worker """True if file was opened in a write mode.""" 1794*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1795*cda5da8dSAndroid Build Coastguard Worker return self._writable 1796*cda5da8dSAndroid Build Coastguard Worker 1797*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 1798*cda5da8dSAndroid Build Coastguard Worker """Return the underlying file descriptor (an integer).""" 1799*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1800*cda5da8dSAndroid Build Coastguard Worker return self._fd 1801*cda5da8dSAndroid Build Coastguard Worker 1802*cda5da8dSAndroid Build Coastguard Worker def isatty(self): 1803*cda5da8dSAndroid Build Coastguard Worker """True if the file is connected to a TTY device.""" 1804*cda5da8dSAndroid Build Coastguard Worker self._checkClosed() 1805*cda5da8dSAndroid Build Coastguard Worker return os.isatty(self._fd) 1806*cda5da8dSAndroid Build Coastguard Worker 1807*cda5da8dSAndroid Build Coastguard Worker @property 1808*cda5da8dSAndroid Build Coastguard Worker def closefd(self): 1809*cda5da8dSAndroid Build Coastguard Worker """True if the file descriptor will be closed by close().""" 1810*cda5da8dSAndroid Build Coastguard Worker return self._closefd 1811*cda5da8dSAndroid Build Coastguard Worker 1812*cda5da8dSAndroid Build Coastguard Worker @property 1813*cda5da8dSAndroid Build Coastguard Worker def mode(self): 1814*cda5da8dSAndroid Build Coastguard Worker """String giving the file mode""" 1815*cda5da8dSAndroid Build Coastguard Worker if self._created: 1816*cda5da8dSAndroid Build Coastguard Worker if self._readable: 1817*cda5da8dSAndroid Build Coastguard Worker return 'xb+' 1818*cda5da8dSAndroid Build Coastguard Worker else: 1819*cda5da8dSAndroid Build Coastguard Worker return 'xb' 1820*cda5da8dSAndroid Build Coastguard Worker elif self._appending: 1821*cda5da8dSAndroid Build Coastguard Worker if self._readable: 1822*cda5da8dSAndroid Build Coastguard Worker return 'ab+' 1823*cda5da8dSAndroid Build Coastguard Worker else: 1824*cda5da8dSAndroid Build Coastguard Worker return 'ab' 1825*cda5da8dSAndroid Build Coastguard Worker elif self._readable: 1826*cda5da8dSAndroid Build Coastguard Worker if self._writable: 1827*cda5da8dSAndroid Build Coastguard Worker return 'rb+' 1828*cda5da8dSAndroid Build Coastguard Worker else: 1829*cda5da8dSAndroid Build Coastguard Worker return 'rb' 1830*cda5da8dSAndroid Build Coastguard Worker else: 1831*cda5da8dSAndroid Build Coastguard Worker return 'wb' 1832*cda5da8dSAndroid Build Coastguard Worker 1833*cda5da8dSAndroid Build Coastguard Worker 1834*cda5da8dSAndroid Build Coastguard Workerclass TextIOBase(IOBase): 1835*cda5da8dSAndroid Build Coastguard Worker 1836*cda5da8dSAndroid Build Coastguard Worker """Base class for text I/O. 1837*cda5da8dSAndroid Build Coastguard Worker 1838*cda5da8dSAndroid Build Coastguard Worker This class provides a character and line based interface to stream 1839*cda5da8dSAndroid Build Coastguard Worker I/O. 1840*cda5da8dSAndroid Build Coastguard Worker """ 1841*cda5da8dSAndroid Build Coastguard Worker 1842*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 1843*cda5da8dSAndroid Build Coastguard Worker """Read at most size characters from stream, where size is an int. 1844*cda5da8dSAndroid Build Coastguard Worker 1845*cda5da8dSAndroid Build Coastguard Worker Read from underlying buffer until we have size characters or we hit EOF. 1846*cda5da8dSAndroid Build Coastguard Worker If size is negative or omitted, read until EOF. 1847*cda5da8dSAndroid Build Coastguard Worker 1848*cda5da8dSAndroid Build Coastguard Worker Returns a string. 1849*cda5da8dSAndroid Build Coastguard Worker """ 1850*cda5da8dSAndroid Build Coastguard Worker self._unsupported("read") 1851*cda5da8dSAndroid Build Coastguard Worker 1852*cda5da8dSAndroid Build Coastguard Worker def write(self, s): 1853*cda5da8dSAndroid Build Coastguard Worker """Write string s to stream and returning an int.""" 1854*cda5da8dSAndroid Build Coastguard Worker self._unsupported("write") 1855*cda5da8dSAndroid Build Coastguard Worker 1856*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 1857*cda5da8dSAndroid Build Coastguard Worker """Truncate size to pos, where pos is an int.""" 1858*cda5da8dSAndroid Build Coastguard Worker self._unsupported("truncate") 1859*cda5da8dSAndroid Build Coastguard Worker 1860*cda5da8dSAndroid Build Coastguard Worker def readline(self): 1861*cda5da8dSAndroid Build Coastguard Worker """Read until newline or EOF. 1862*cda5da8dSAndroid Build Coastguard Worker 1863*cda5da8dSAndroid Build Coastguard Worker Returns an empty string if EOF is hit immediately. 1864*cda5da8dSAndroid Build Coastguard Worker """ 1865*cda5da8dSAndroid Build Coastguard Worker self._unsupported("readline") 1866*cda5da8dSAndroid Build Coastguard Worker 1867*cda5da8dSAndroid Build Coastguard Worker def detach(self): 1868*cda5da8dSAndroid Build Coastguard Worker """ 1869*cda5da8dSAndroid Build Coastguard Worker Separate the underlying buffer from the TextIOBase and return it. 1870*cda5da8dSAndroid Build Coastguard Worker 1871*cda5da8dSAndroid Build Coastguard Worker After the underlying buffer has been detached, the TextIO is in an 1872*cda5da8dSAndroid Build Coastguard Worker unusable state. 1873*cda5da8dSAndroid Build Coastguard Worker """ 1874*cda5da8dSAndroid Build Coastguard Worker self._unsupported("detach") 1875*cda5da8dSAndroid Build Coastguard Worker 1876*cda5da8dSAndroid Build Coastguard Worker @property 1877*cda5da8dSAndroid Build Coastguard Worker def encoding(self): 1878*cda5da8dSAndroid Build Coastguard Worker """Subclasses should override.""" 1879*cda5da8dSAndroid Build Coastguard Worker return None 1880*cda5da8dSAndroid Build Coastguard Worker 1881*cda5da8dSAndroid Build Coastguard Worker @property 1882*cda5da8dSAndroid Build Coastguard Worker def newlines(self): 1883*cda5da8dSAndroid Build Coastguard Worker """Line endings translated so far. 1884*cda5da8dSAndroid Build Coastguard Worker 1885*cda5da8dSAndroid Build Coastguard Worker Only line endings translated during reading are considered. 1886*cda5da8dSAndroid Build Coastguard Worker 1887*cda5da8dSAndroid Build Coastguard Worker Subclasses should override. 1888*cda5da8dSAndroid Build Coastguard Worker """ 1889*cda5da8dSAndroid Build Coastguard Worker return None 1890*cda5da8dSAndroid Build Coastguard Worker 1891*cda5da8dSAndroid Build Coastguard Worker @property 1892*cda5da8dSAndroid Build Coastguard Worker def errors(self): 1893*cda5da8dSAndroid Build Coastguard Worker """Error setting of the decoder or encoder. 1894*cda5da8dSAndroid Build Coastguard Worker 1895*cda5da8dSAndroid Build Coastguard Worker Subclasses should override.""" 1896*cda5da8dSAndroid Build Coastguard Worker return None 1897*cda5da8dSAndroid Build Coastguard Worker 1898*cda5da8dSAndroid Build Coastguard Workerio.TextIOBase.register(TextIOBase) 1899*cda5da8dSAndroid Build Coastguard Worker 1900*cda5da8dSAndroid Build Coastguard Worker 1901*cda5da8dSAndroid Build Coastguard Workerclass IncrementalNewlineDecoder(codecs.IncrementalDecoder): 1902*cda5da8dSAndroid Build Coastguard Worker r"""Codec used when reading a file in universal newlines mode. It wraps 1903*cda5da8dSAndroid Build Coastguard Worker another incremental decoder, translating \r\n and \r into \n. It also 1904*cda5da8dSAndroid Build Coastguard Worker records the types of newlines encountered. When used with 1905*cda5da8dSAndroid Build Coastguard Worker translate=False, it ensures that the newline sequence is returned in 1906*cda5da8dSAndroid Build Coastguard Worker one piece. 1907*cda5da8dSAndroid Build Coastguard Worker """ 1908*cda5da8dSAndroid Build Coastguard Worker def __init__(self, decoder, translate, errors='strict'): 1909*cda5da8dSAndroid Build Coastguard Worker codecs.IncrementalDecoder.__init__(self, errors=errors) 1910*cda5da8dSAndroid Build Coastguard Worker self.translate = translate 1911*cda5da8dSAndroid Build Coastguard Worker self.decoder = decoder 1912*cda5da8dSAndroid Build Coastguard Worker self.seennl = 0 1913*cda5da8dSAndroid Build Coastguard Worker self.pendingcr = False 1914*cda5da8dSAndroid Build Coastguard Worker 1915*cda5da8dSAndroid Build Coastguard Worker def decode(self, input, final=False): 1916*cda5da8dSAndroid Build Coastguard Worker # decode input (with the eventual \r from a previous pass) 1917*cda5da8dSAndroid Build Coastguard Worker if self.decoder is None: 1918*cda5da8dSAndroid Build Coastguard Worker output = input 1919*cda5da8dSAndroid Build Coastguard Worker else: 1920*cda5da8dSAndroid Build Coastguard Worker output = self.decoder.decode(input, final=final) 1921*cda5da8dSAndroid Build Coastguard Worker if self.pendingcr and (output or final): 1922*cda5da8dSAndroid Build Coastguard Worker output = "\r" + output 1923*cda5da8dSAndroid Build Coastguard Worker self.pendingcr = False 1924*cda5da8dSAndroid Build Coastguard Worker 1925*cda5da8dSAndroid Build Coastguard Worker # retain last \r even when not translating data: 1926*cda5da8dSAndroid Build Coastguard Worker # then readline() is sure to get \r\n in one pass 1927*cda5da8dSAndroid Build Coastguard Worker if output.endswith("\r") and not final: 1928*cda5da8dSAndroid Build Coastguard Worker output = output[:-1] 1929*cda5da8dSAndroid Build Coastguard Worker self.pendingcr = True 1930*cda5da8dSAndroid Build Coastguard Worker 1931*cda5da8dSAndroid Build Coastguard Worker # Record which newlines are read 1932*cda5da8dSAndroid Build Coastguard Worker crlf = output.count('\r\n') 1933*cda5da8dSAndroid Build Coastguard Worker cr = output.count('\r') - crlf 1934*cda5da8dSAndroid Build Coastguard Worker lf = output.count('\n') - crlf 1935*cda5da8dSAndroid Build Coastguard Worker self.seennl |= (lf and self._LF) | (cr and self._CR) \ 1936*cda5da8dSAndroid Build Coastguard Worker | (crlf and self._CRLF) 1937*cda5da8dSAndroid Build Coastguard Worker 1938*cda5da8dSAndroid Build Coastguard Worker if self.translate: 1939*cda5da8dSAndroid Build Coastguard Worker if crlf: 1940*cda5da8dSAndroid Build Coastguard Worker output = output.replace("\r\n", "\n") 1941*cda5da8dSAndroid Build Coastguard Worker if cr: 1942*cda5da8dSAndroid Build Coastguard Worker output = output.replace("\r", "\n") 1943*cda5da8dSAndroid Build Coastguard Worker 1944*cda5da8dSAndroid Build Coastguard Worker return output 1945*cda5da8dSAndroid Build Coastguard Worker 1946*cda5da8dSAndroid Build Coastguard Worker def getstate(self): 1947*cda5da8dSAndroid Build Coastguard Worker if self.decoder is None: 1948*cda5da8dSAndroid Build Coastguard Worker buf = b"" 1949*cda5da8dSAndroid Build Coastguard Worker flag = 0 1950*cda5da8dSAndroid Build Coastguard Worker else: 1951*cda5da8dSAndroid Build Coastguard Worker buf, flag = self.decoder.getstate() 1952*cda5da8dSAndroid Build Coastguard Worker flag <<= 1 1953*cda5da8dSAndroid Build Coastguard Worker if self.pendingcr: 1954*cda5da8dSAndroid Build Coastguard Worker flag |= 1 1955*cda5da8dSAndroid Build Coastguard Worker return buf, flag 1956*cda5da8dSAndroid Build Coastguard Worker 1957*cda5da8dSAndroid Build Coastguard Worker def setstate(self, state): 1958*cda5da8dSAndroid Build Coastguard Worker buf, flag = state 1959*cda5da8dSAndroid Build Coastguard Worker self.pendingcr = bool(flag & 1) 1960*cda5da8dSAndroid Build Coastguard Worker if self.decoder is not None: 1961*cda5da8dSAndroid Build Coastguard Worker self.decoder.setstate((buf, flag >> 1)) 1962*cda5da8dSAndroid Build Coastguard Worker 1963*cda5da8dSAndroid Build Coastguard Worker def reset(self): 1964*cda5da8dSAndroid Build Coastguard Worker self.seennl = 0 1965*cda5da8dSAndroid Build Coastguard Worker self.pendingcr = False 1966*cda5da8dSAndroid Build Coastguard Worker if self.decoder is not None: 1967*cda5da8dSAndroid Build Coastguard Worker self.decoder.reset() 1968*cda5da8dSAndroid Build Coastguard Worker 1969*cda5da8dSAndroid Build Coastguard Worker _LF = 1 1970*cda5da8dSAndroid Build Coastguard Worker _CR = 2 1971*cda5da8dSAndroid Build Coastguard Worker _CRLF = 4 1972*cda5da8dSAndroid Build Coastguard Worker 1973*cda5da8dSAndroid Build Coastguard Worker @property 1974*cda5da8dSAndroid Build Coastguard Worker def newlines(self): 1975*cda5da8dSAndroid Build Coastguard Worker return (None, 1976*cda5da8dSAndroid Build Coastguard Worker "\n", 1977*cda5da8dSAndroid Build Coastguard Worker "\r", 1978*cda5da8dSAndroid Build Coastguard Worker ("\r", "\n"), 1979*cda5da8dSAndroid Build Coastguard Worker "\r\n", 1980*cda5da8dSAndroid Build Coastguard Worker ("\n", "\r\n"), 1981*cda5da8dSAndroid Build Coastguard Worker ("\r", "\r\n"), 1982*cda5da8dSAndroid Build Coastguard Worker ("\r", "\n", "\r\n") 1983*cda5da8dSAndroid Build Coastguard Worker )[self.seennl] 1984*cda5da8dSAndroid Build Coastguard Worker 1985*cda5da8dSAndroid Build Coastguard Worker 1986*cda5da8dSAndroid Build Coastguard Workerclass TextIOWrapper(TextIOBase): 1987*cda5da8dSAndroid Build Coastguard Worker 1988*cda5da8dSAndroid Build Coastguard Worker r"""Character and line based layer over a BufferedIOBase object, buffer. 1989*cda5da8dSAndroid Build Coastguard Worker 1990*cda5da8dSAndroid Build Coastguard Worker encoding gives the name of the encoding that the stream will be 1991*cda5da8dSAndroid Build Coastguard Worker decoded or encoded with. It defaults to locale.getencoding(). 1992*cda5da8dSAndroid Build Coastguard Worker 1993*cda5da8dSAndroid Build Coastguard Worker errors determines the strictness of encoding and decoding (see the 1994*cda5da8dSAndroid Build Coastguard Worker codecs.register) and defaults to "strict". 1995*cda5da8dSAndroid Build Coastguard Worker 1996*cda5da8dSAndroid Build Coastguard Worker newline can be None, '', '\n', '\r', or '\r\n'. It controls the 1997*cda5da8dSAndroid Build Coastguard Worker handling of line endings. If it is None, universal newlines is 1998*cda5da8dSAndroid Build Coastguard Worker enabled. With this enabled, on input, the lines endings '\n', '\r', 1999*cda5da8dSAndroid Build Coastguard Worker or '\r\n' are translated to '\n' before being returned to the 2000*cda5da8dSAndroid Build Coastguard Worker caller. Conversely, on output, '\n' is translated to the system 2001*cda5da8dSAndroid Build Coastguard Worker default line separator, os.linesep. If newline is any other of its 2002*cda5da8dSAndroid Build Coastguard Worker legal values, that newline becomes the newline when the file is read 2003*cda5da8dSAndroid Build Coastguard Worker and it is returned untranslated. On output, '\n' is converted to the 2004*cda5da8dSAndroid Build Coastguard Worker newline. 2005*cda5da8dSAndroid Build Coastguard Worker 2006*cda5da8dSAndroid Build Coastguard Worker If line_buffering is True, a call to flush is implied when a call to 2007*cda5da8dSAndroid Build Coastguard Worker write contains a newline character. 2008*cda5da8dSAndroid Build Coastguard Worker """ 2009*cda5da8dSAndroid Build Coastguard Worker 2010*cda5da8dSAndroid Build Coastguard Worker _CHUNK_SIZE = 2048 2011*cda5da8dSAndroid Build Coastguard Worker 2012*cda5da8dSAndroid Build Coastguard Worker # Initialize _buffer as soon as possible since it's used by __del__() 2013*cda5da8dSAndroid Build Coastguard Worker # which calls close() 2014*cda5da8dSAndroid Build Coastguard Worker _buffer = None 2015*cda5da8dSAndroid Build Coastguard Worker 2016*cda5da8dSAndroid Build Coastguard Worker # The write_through argument has no effect here since this 2017*cda5da8dSAndroid Build Coastguard Worker # implementation always writes through. The argument is present only 2018*cda5da8dSAndroid Build Coastguard Worker # so that the signature can match the signature of the C version. 2019*cda5da8dSAndroid Build Coastguard Worker def __init__(self, buffer, encoding=None, errors=None, newline=None, 2020*cda5da8dSAndroid Build Coastguard Worker line_buffering=False, write_through=False): 2021*cda5da8dSAndroid Build Coastguard Worker self._check_newline(newline) 2022*cda5da8dSAndroid Build Coastguard Worker encoding = text_encoding(encoding) 2023*cda5da8dSAndroid Build Coastguard Worker 2024*cda5da8dSAndroid Build Coastguard Worker if encoding == "locale": 2025*cda5da8dSAndroid Build Coastguard Worker encoding = self._get_locale_encoding() 2026*cda5da8dSAndroid Build Coastguard Worker 2027*cda5da8dSAndroid Build Coastguard Worker if not isinstance(encoding, str): 2028*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid encoding: %r" % encoding) 2029*cda5da8dSAndroid Build Coastguard Worker 2030*cda5da8dSAndroid Build Coastguard Worker if not codecs.lookup(encoding)._is_text_encoding: 2031*cda5da8dSAndroid Build Coastguard Worker msg = ("%r is not a text encoding; " 2032*cda5da8dSAndroid Build Coastguard Worker "use codecs.open() to handle arbitrary codecs") 2033*cda5da8dSAndroid Build Coastguard Worker raise LookupError(msg % encoding) 2034*cda5da8dSAndroid Build Coastguard Worker 2035*cda5da8dSAndroid Build Coastguard Worker if errors is None: 2036*cda5da8dSAndroid Build Coastguard Worker errors = "strict" 2037*cda5da8dSAndroid Build Coastguard Worker else: 2038*cda5da8dSAndroid Build Coastguard Worker if not isinstance(errors, str): 2039*cda5da8dSAndroid Build Coastguard Worker raise ValueError("invalid errors: %r" % errors) 2040*cda5da8dSAndroid Build Coastguard Worker if _CHECK_ERRORS: 2041*cda5da8dSAndroid Build Coastguard Worker codecs.lookup_error(errors) 2042*cda5da8dSAndroid Build Coastguard Worker 2043*cda5da8dSAndroid Build Coastguard Worker self._buffer = buffer 2044*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars = '' # buffer for text returned from decoder 2045*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars_used = 0 # offset into _decoded_chars for read() 2046*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None # info for reconstructing decoder state 2047*cda5da8dSAndroid Build Coastguard Worker self._seekable = self._telling = self.buffer.seekable() 2048*cda5da8dSAndroid Build Coastguard Worker self._has_read1 = hasattr(self.buffer, 'read1') 2049*cda5da8dSAndroid Build Coastguard Worker self._configure(encoding, errors, newline, 2050*cda5da8dSAndroid Build Coastguard Worker line_buffering, write_through) 2051*cda5da8dSAndroid Build Coastguard Worker 2052*cda5da8dSAndroid Build Coastguard Worker def _check_newline(self, newline): 2053*cda5da8dSAndroid Build Coastguard Worker if newline is not None and not isinstance(newline, str): 2054*cda5da8dSAndroid Build Coastguard Worker raise TypeError("illegal newline type: %r" % (type(newline),)) 2055*cda5da8dSAndroid Build Coastguard Worker if newline not in (None, "", "\n", "\r", "\r\n"): 2056*cda5da8dSAndroid Build Coastguard Worker raise ValueError("illegal newline value: %r" % (newline,)) 2057*cda5da8dSAndroid Build Coastguard Worker 2058*cda5da8dSAndroid Build Coastguard Worker def _configure(self, encoding=None, errors=None, newline=None, 2059*cda5da8dSAndroid Build Coastguard Worker line_buffering=False, write_through=False): 2060*cda5da8dSAndroid Build Coastguard Worker self._encoding = encoding 2061*cda5da8dSAndroid Build Coastguard Worker self._errors = errors 2062*cda5da8dSAndroid Build Coastguard Worker self._encoder = None 2063*cda5da8dSAndroid Build Coastguard Worker self._decoder = None 2064*cda5da8dSAndroid Build Coastguard Worker self._b2cratio = 0.0 2065*cda5da8dSAndroid Build Coastguard Worker 2066*cda5da8dSAndroid Build Coastguard Worker self._readuniversal = not newline 2067*cda5da8dSAndroid Build Coastguard Worker self._readtranslate = newline is None 2068*cda5da8dSAndroid Build Coastguard Worker self._readnl = newline 2069*cda5da8dSAndroid Build Coastguard Worker self._writetranslate = newline != '' 2070*cda5da8dSAndroid Build Coastguard Worker self._writenl = newline or os.linesep 2071*cda5da8dSAndroid Build Coastguard Worker 2072*cda5da8dSAndroid Build Coastguard Worker self._line_buffering = line_buffering 2073*cda5da8dSAndroid Build Coastguard Worker self._write_through = write_through 2074*cda5da8dSAndroid Build Coastguard Worker 2075*cda5da8dSAndroid Build Coastguard Worker # don't write a BOM in the middle of a file 2076*cda5da8dSAndroid Build Coastguard Worker if self._seekable and self.writable(): 2077*cda5da8dSAndroid Build Coastguard Worker position = self.buffer.tell() 2078*cda5da8dSAndroid Build Coastguard Worker if position != 0: 2079*cda5da8dSAndroid Build Coastguard Worker try: 2080*cda5da8dSAndroid Build Coastguard Worker self._get_encoder().setstate(0) 2081*cda5da8dSAndroid Build Coastguard Worker except LookupError: 2082*cda5da8dSAndroid Build Coastguard Worker # Sometimes the encoder doesn't exist 2083*cda5da8dSAndroid Build Coastguard Worker pass 2084*cda5da8dSAndroid Build Coastguard Worker 2085*cda5da8dSAndroid Build Coastguard Worker # self._snapshot is either None, or a tuple (dec_flags, next_input) 2086*cda5da8dSAndroid Build Coastguard Worker # where dec_flags is the second (integer) item of the decoder state 2087*cda5da8dSAndroid Build Coastguard Worker # and next_input is the chunk of input bytes that comes next after the 2088*cda5da8dSAndroid Build Coastguard Worker # snapshot point. We use this to reconstruct decoder states in tell(). 2089*cda5da8dSAndroid Build Coastguard Worker 2090*cda5da8dSAndroid Build Coastguard Worker # Naming convention: 2091*cda5da8dSAndroid Build Coastguard Worker # - "bytes_..." for integer variables that count input bytes 2092*cda5da8dSAndroid Build Coastguard Worker # - "chars_..." for integer variables that count decoded characters 2093*cda5da8dSAndroid Build Coastguard Worker 2094*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2095*cda5da8dSAndroid Build Coastguard Worker result = "<{}.{}".format(self.__class__.__module__, 2096*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__) 2097*cda5da8dSAndroid Build Coastguard Worker try: 2098*cda5da8dSAndroid Build Coastguard Worker name = self.name 2099*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2100*cda5da8dSAndroid Build Coastguard Worker pass 2101*cda5da8dSAndroid Build Coastguard Worker else: 2102*cda5da8dSAndroid Build Coastguard Worker result += " name={0!r}".format(name) 2103*cda5da8dSAndroid Build Coastguard Worker try: 2104*cda5da8dSAndroid Build Coastguard Worker mode = self.mode 2105*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2106*cda5da8dSAndroid Build Coastguard Worker pass 2107*cda5da8dSAndroid Build Coastguard Worker else: 2108*cda5da8dSAndroid Build Coastguard Worker result += " mode={0!r}".format(mode) 2109*cda5da8dSAndroid Build Coastguard Worker return result + " encoding={0!r}>".format(self.encoding) 2110*cda5da8dSAndroid Build Coastguard Worker 2111*cda5da8dSAndroid Build Coastguard Worker @property 2112*cda5da8dSAndroid Build Coastguard Worker def encoding(self): 2113*cda5da8dSAndroid Build Coastguard Worker return self._encoding 2114*cda5da8dSAndroid Build Coastguard Worker 2115*cda5da8dSAndroid Build Coastguard Worker @property 2116*cda5da8dSAndroid Build Coastguard Worker def errors(self): 2117*cda5da8dSAndroid Build Coastguard Worker return self._errors 2118*cda5da8dSAndroid Build Coastguard Worker 2119*cda5da8dSAndroid Build Coastguard Worker @property 2120*cda5da8dSAndroid Build Coastguard Worker def line_buffering(self): 2121*cda5da8dSAndroid Build Coastguard Worker return self._line_buffering 2122*cda5da8dSAndroid Build Coastguard Worker 2123*cda5da8dSAndroid Build Coastguard Worker @property 2124*cda5da8dSAndroid Build Coastguard Worker def write_through(self): 2125*cda5da8dSAndroid Build Coastguard Worker return self._write_through 2126*cda5da8dSAndroid Build Coastguard Worker 2127*cda5da8dSAndroid Build Coastguard Worker @property 2128*cda5da8dSAndroid Build Coastguard Worker def buffer(self): 2129*cda5da8dSAndroid Build Coastguard Worker return self._buffer 2130*cda5da8dSAndroid Build Coastguard Worker 2131*cda5da8dSAndroid Build Coastguard Worker def reconfigure(self, *, 2132*cda5da8dSAndroid Build Coastguard Worker encoding=None, errors=None, newline=Ellipsis, 2133*cda5da8dSAndroid Build Coastguard Worker line_buffering=None, write_through=None): 2134*cda5da8dSAndroid Build Coastguard Worker """Reconfigure the text stream with new parameters. 2135*cda5da8dSAndroid Build Coastguard Worker 2136*cda5da8dSAndroid Build Coastguard Worker This also flushes the stream. 2137*cda5da8dSAndroid Build Coastguard Worker """ 2138*cda5da8dSAndroid Build Coastguard Worker if (self._decoder is not None 2139*cda5da8dSAndroid Build Coastguard Worker and (encoding is not None or errors is not None 2140*cda5da8dSAndroid Build Coastguard Worker or newline is not Ellipsis)): 2141*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation( 2142*cda5da8dSAndroid Build Coastguard Worker "It is not possible to set the encoding or newline of stream " 2143*cda5da8dSAndroid Build Coastguard Worker "after the first read") 2144*cda5da8dSAndroid Build Coastguard Worker 2145*cda5da8dSAndroid Build Coastguard Worker if errors is None: 2146*cda5da8dSAndroid Build Coastguard Worker if encoding is None: 2147*cda5da8dSAndroid Build Coastguard Worker errors = self._errors 2148*cda5da8dSAndroid Build Coastguard Worker else: 2149*cda5da8dSAndroid Build Coastguard Worker errors = 'strict' 2150*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(errors, str): 2151*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid errors: %r" % errors) 2152*cda5da8dSAndroid Build Coastguard Worker 2153*cda5da8dSAndroid Build Coastguard Worker if encoding is None: 2154*cda5da8dSAndroid Build Coastguard Worker encoding = self._encoding 2155*cda5da8dSAndroid Build Coastguard Worker else: 2156*cda5da8dSAndroid Build Coastguard Worker if not isinstance(encoding, str): 2157*cda5da8dSAndroid Build Coastguard Worker raise TypeError("invalid encoding: %r" % encoding) 2158*cda5da8dSAndroid Build Coastguard Worker if encoding == "locale": 2159*cda5da8dSAndroid Build Coastguard Worker encoding = self._get_locale_encoding() 2160*cda5da8dSAndroid Build Coastguard Worker 2161*cda5da8dSAndroid Build Coastguard Worker if newline is Ellipsis: 2162*cda5da8dSAndroid Build Coastguard Worker newline = self._readnl 2163*cda5da8dSAndroid Build Coastguard Worker self._check_newline(newline) 2164*cda5da8dSAndroid Build Coastguard Worker 2165*cda5da8dSAndroid Build Coastguard Worker if line_buffering is None: 2166*cda5da8dSAndroid Build Coastguard Worker line_buffering = self.line_buffering 2167*cda5da8dSAndroid Build Coastguard Worker if write_through is None: 2168*cda5da8dSAndroid Build Coastguard Worker write_through = self.write_through 2169*cda5da8dSAndroid Build Coastguard Worker 2170*cda5da8dSAndroid Build Coastguard Worker self.flush() 2171*cda5da8dSAndroid Build Coastguard Worker self._configure(encoding, errors, newline, 2172*cda5da8dSAndroid Build Coastguard Worker line_buffering, write_through) 2173*cda5da8dSAndroid Build Coastguard Worker 2174*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 2175*cda5da8dSAndroid Build Coastguard Worker if self.closed: 2176*cda5da8dSAndroid Build Coastguard Worker raise ValueError("I/O operation on closed file.") 2177*cda5da8dSAndroid Build Coastguard Worker return self._seekable 2178*cda5da8dSAndroid Build Coastguard Worker 2179*cda5da8dSAndroid Build Coastguard Worker def readable(self): 2180*cda5da8dSAndroid Build Coastguard Worker return self.buffer.readable() 2181*cda5da8dSAndroid Build Coastguard Worker 2182*cda5da8dSAndroid Build Coastguard Worker def writable(self): 2183*cda5da8dSAndroid Build Coastguard Worker return self.buffer.writable() 2184*cda5da8dSAndroid Build Coastguard Worker 2185*cda5da8dSAndroid Build Coastguard Worker def flush(self): 2186*cda5da8dSAndroid Build Coastguard Worker self.buffer.flush() 2187*cda5da8dSAndroid Build Coastguard Worker self._telling = self._seekable 2188*cda5da8dSAndroid Build Coastguard Worker 2189*cda5da8dSAndroid Build Coastguard Worker def close(self): 2190*cda5da8dSAndroid Build Coastguard Worker if self.buffer is not None and not self.closed: 2191*cda5da8dSAndroid Build Coastguard Worker try: 2192*cda5da8dSAndroid Build Coastguard Worker self.flush() 2193*cda5da8dSAndroid Build Coastguard Worker finally: 2194*cda5da8dSAndroid Build Coastguard Worker self.buffer.close() 2195*cda5da8dSAndroid Build Coastguard Worker 2196*cda5da8dSAndroid Build Coastguard Worker @property 2197*cda5da8dSAndroid Build Coastguard Worker def closed(self): 2198*cda5da8dSAndroid Build Coastguard Worker return self.buffer.closed 2199*cda5da8dSAndroid Build Coastguard Worker 2200*cda5da8dSAndroid Build Coastguard Worker @property 2201*cda5da8dSAndroid Build Coastguard Worker def name(self): 2202*cda5da8dSAndroid Build Coastguard Worker return self.buffer.name 2203*cda5da8dSAndroid Build Coastguard Worker 2204*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 2205*cda5da8dSAndroid Build Coastguard Worker return self.buffer.fileno() 2206*cda5da8dSAndroid Build Coastguard Worker 2207*cda5da8dSAndroid Build Coastguard Worker def isatty(self): 2208*cda5da8dSAndroid Build Coastguard Worker return self.buffer.isatty() 2209*cda5da8dSAndroid Build Coastguard Worker 2210*cda5da8dSAndroid Build Coastguard Worker def write(self, s): 2211*cda5da8dSAndroid Build Coastguard Worker 'Write data, where s is a str' 2212*cda5da8dSAndroid Build Coastguard Worker if self.closed: 2213*cda5da8dSAndroid Build Coastguard Worker raise ValueError("write to closed file") 2214*cda5da8dSAndroid Build Coastguard Worker if not isinstance(s, str): 2215*cda5da8dSAndroid Build Coastguard Worker raise TypeError("can't write %s to text stream" % 2216*cda5da8dSAndroid Build Coastguard Worker s.__class__.__name__) 2217*cda5da8dSAndroid Build Coastguard Worker length = len(s) 2218*cda5da8dSAndroid Build Coastguard Worker haslf = (self._writetranslate or self._line_buffering) and "\n" in s 2219*cda5da8dSAndroid Build Coastguard Worker if haslf and self._writetranslate and self._writenl != "\n": 2220*cda5da8dSAndroid Build Coastguard Worker s = s.replace("\n", self._writenl) 2221*cda5da8dSAndroid Build Coastguard Worker encoder = self._encoder or self._get_encoder() 2222*cda5da8dSAndroid Build Coastguard Worker # XXX What if we were just reading? 2223*cda5da8dSAndroid Build Coastguard Worker b = encoder.encode(s) 2224*cda5da8dSAndroid Build Coastguard Worker self.buffer.write(b) 2225*cda5da8dSAndroid Build Coastguard Worker if self._line_buffering and (haslf or "\r" in s): 2226*cda5da8dSAndroid Build Coastguard Worker self.flush() 2227*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars('') 2228*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2229*cda5da8dSAndroid Build Coastguard Worker if self._decoder: 2230*cda5da8dSAndroid Build Coastguard Worker self._decoder.reset() 2231*cda5da8dSAndroid Build Coastguard Worker return length 2232*cda5da8dSAndroid Build Coastguard Worker 2233*cda5da8dSAndroid Build Coastguard Worker def _get_encoder(self): 2234*cda5da8dSAndroid Build Coastguard Worker make_encoder = codecs.getincrementalencoder(self._encoding) 2235*cda5da8dSAndroid Build Coastguard Worker self._encoder = make_encoder(self._errors) 2236*cda5da8dSAndroid Build Coastguard Worker return self._encoder 2237*cda5da8dSAndroid Build Coastguard Worker 2238*cda5da8dSAndroid Build Coastguard Worker def _get_decoder(self): 2239*cda5da8dSAndroid Build Coastguard Worker make_decoder = codecs.getincrementaldecoder(self._encoding) 2240*cda5da8dSAndroid Build Coastguard Worker decoder = make_decoder(self._errors) 2241*cda5da8dSAndroid Build Coastguard Worker if self._readuniversal: 2242*cda5da8dSAndroid Build Coastguard Worker decoder = IncrementalNewlineDecoder(decoder, self._readtranslate) 2243*cda5da8dSAndroid Build Coastguard Worker self._decoder = decoder 2244*cda5da8dSAndroid Build Coastguard Worker return decoder 2245*cda5da8dSAndroid Build Coastguard Worker 2246*cda5da8dSAndroid Build Coastguard Worker # The following three methods implement an ADT for _decoded_chars. 2247*cda5da8dSAndroid Build Coastguard Worker # Text returned from the decoder is buffered here until the client 2248*cda5da8dSAndroid Build Coastguard Worker # requests it by calling our read() or readline() method. 2249*cda5da8dSAndroid Build Coastguard Worker def _set_decoded_chars(self, chars): 2250*cda5da8dSAndroid Build Coastguard Worker """Set the _decoded_chars buffer.""" 2251*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars = chars 2252*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars_used = 0 2253*cda5da8dSAndroid Build Coastguard Worker 2254*cda5da8dSAndroid Build Coastguard Worker def _get_decoded_chars(self, n=None): 2255*cda5da8dSAndroid Build Coastguard Worker """Advance into the _decoded_chars buffer.""" 2256*cda5da8dSAndroid Build Coastguard Worker offset = self._decoded_chars_used 2257*cda5da8dSAndroid Build Coastguard Worker if n is None: 2258*cda5da8dSAndroid Build Coastguard Worker chars = self._decoded_chars[offset:] 2259*cda5da8dSAndroid Build Coastguard Worker else: 2260*cda5da8dSAndroid Build Coastguard Worker chars = self._decoded_chars[offset:offset + n] 2261*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars_used += len(chars) 2262*cda5da8dSAndroid Build Coastguard Worker return chars 2263*cda5da8dSAndroid Build Coastguard Worker 2264*cda5da8dSAndroid Build Coastguard Worker def _get_locale_encoding(self): 2265*cda5da8dSAndroid Build Coastguard Worker try: 2266*cda5da8dSAndroid Build Coastguard Worker import locale 2267*cda5da8dSAndroid Build Coastguard Worker except ImportError: 2268*cda5da8dSAndroid Build Coastguard Worker # Importing locale may fail if Python is being built 2269*cda5da8dSAndroid Build Coastguard Worker return "utf-8" 2270*cda5da8dSAndroid Build Coastguard Worker else: 2271*cda5da8dSAndroid Build Coastguard Worker return locale.getencoding() 2272*cda5da8dSAndroid Build Coastguard Worker 2273*cda5da8dSAndroid Build Coastguard Worker def _rewind_decoded_chars(self, n): 2274*cda5da8dSAndroid Build Coastguard Worker """Rewind the _decoded_chars buffer.""" 2275*cda5da8dSAndroid Build Coastguard Worker if self._decoded_chars_used < n: 2276*cda5da8dSAndroid Build Coastguard Worker raise AssertionError("rewind decoded_chars out of bounds") 2277*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars_used -= n 2278*cda5da8dSAndroid Build Coastguard Worker 2279*cda5da8dSAndroid Build Coastguard Worker def _read_chunk(self): 2280*cda5da8dSAndroid Build Coastguard Worker """ 2281*cda5da8dSAndroid Build Coastguard Worker Read and decode the next chunk of data from the BufferedReader. 2282*cda5da8dSAndroid Build Coastguard Worker """ 2283*cda5da8dSAndroid Build Coastguard Worker 2284*cda5da8dSAndroid Build Coastguard Worker # The return value is True unless EOF was reached. The decoded 2285*cda5da8dSAndroid Build Coastguard Worker # string is placed in self._decoded_chars (replacing its previous 2286*cda5da8dSAndroid Build Coastguard Worker # value). The entire input chunk is sent to the decoder, though 2287*cda5da8dSAndroid Build Coastguard Worker # some of it may remain buffered in the decoder, yet to be 2288*cda5da8dSAndroid Build Coastguard Worker # converted. 2289*cda5da8dSAndroid Build Coastguard Worker 2290*cda5da8dSAndroid Build Coastguard Worker if self._decoder is None: 2291*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no decoder") 2292*cda5da8dSAndroid Build Coastguard Worker 2293*cda5da8dSAndroid Build Coastguard Worker if self._telling: 2294*cda5da8dSAndroid Build Coastguard Worker # To prepare for tell(), we need to snapshot a point in the 2295*cda5da8dSAndroid Build Coastguard Worker # file where the decoder's input buffer is empty. 2296*cda5da8dSAndroid Build Coastguard Worker 2297*cda5da8dSAndroid Build Coastguard Worker dec_buffer, dec_flags = self._decoder.getstate() 2298*cda5da8dSAndroid Build Coastguard Worker # Given this, we know there was a valid snapshot point 2299*cda5da8dSAndroid Build Coastguard Worker # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). 2300*cda5da8dSAndroid Build Coastguard Worker 2301*cda5da8dSAndroid Build Coastguard Worker # Read a chunk, decode it, and put the result in self._decoded_chars. 2302*cda5da8dSAndroid Build Coastguard Worker if self._has_read1: 2303*cda5da8dSAndroid Build Coastguard Worker input_chunk = self.buffer.read1(self._CHUNK_SIZE) 2304*cda5da8dSAndroid Build Coastguard Worker else: 2305*cda5da8dSAndroid Build Coastguard Worker input_chunk = self.buffer.read(self._CHUNK_SIZE) 2306*cda5da8dSAndroid Build Coastguard Worker eof = not input_chunk 2307*cda5da8dSAndroid Build Coastguard Worker decoded_chars = self._decoder.decode(input_chunk, eof) 2308*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars(decoded_chars) 2309*cda5da8dSAndroid Build Coastguard Worker if decoded_chars: 2310*cda5da8dSAndroid Build Coastguard Worker self._b2cratio = len(input_chunk) / len(self._decoded_chars) 2311*cda5da8dSAndroid Build Coastguard Worker else: 2312*cda5da8dSAndroid Build Coastguard Worker self._b2cratio = 0.0 2313*cda5da8dSAndroid Build Coastguard Worker 2314*cda5da8dSAndroid Build Coastguard Worker if self._telling: 2315*cda5da8dSAndroid Build Coastguard Worker # At the snapshot point, len(dec_buffer) bytes before the read, 2316*cda5da8dSAndroid Build Coastguard Worker # the next input to be decoded is dec_buffer + input_chunk. 2317*cda5da8dSAndroid Build Coastguard Worker self._snapshot = (dec_flags, dec_buffer + input_chunk) 2318*cda5da8dSAndroid Build Coastguard Worker 2319*cda5da8dSAndroid Build Coastguard Worker return not eof 2320*cda5da8dSAndroid Build Coastguard Worker 2321*cda5da8dSAndroid Build Coastguard Worker def _pack_cookie(self, position, dec_flags=0, 2322*cda5da8dSAndroid Build Coastguard Worker bytes_to_feed=0, need_eof=False, chars_to_skip=0): 2323*cda5da8dSAndroid Build Coastguard Worker # The meaning of a tell() cookie is: seek to position, set the 2324*cda5da8dSAndroid Build Coastguard Worker # decoder flags to dec_flags, read bytes_to_feed bytes, feed them 2325*cda5da8dSAndroid Build Coastguard Worker # into the decoder with need_eof as the EOF flag, then skip 2326*cda5da8dSAndroid Build Coastguard Worker # chars_to_skip characters of the decoded result. For most simple 2327*cda5da8dSAndroid Build Coastguard Worker # decoders, tell() will often just give a byte offset in the file. 2328*cda5da8dSAndroid Build Coastguard Worker return (position | (dec_flags<<64) | (bytes_to_feed<<128) | 2329*cda5da8dSAndroid Build Coastguard Worker (chars_to_skip<<192) | bool(need_eof)<<256) 2330*cda5da8dSAndroid Build Coastguard Worker 2331*cda5da8dSAndroid Build Coastguard Worker def _unpack_cookie(self, bigint): 2332*cda5da8dSAndroid Build Coastguard Worker rest, position = divmod(bigint, 1<<64) 2333*cda5da8dSAndroid Build Coastguard Worker rest, dec_flags = divmod(rest, 1<<64) 2334*cda5da8dSAndroid Build Coastguard Worker rest, bytes_to_feed = divmod(rest, 1<<64) 2335*cda5da8dSAndroid Build Coastguard Worker need_eof, chars_to_skip = divmod(rest, 1<<64) 2336*cda5da8dSAndroid Build Coastguard Worker return position, dec_flags, bytes_to_feed, bool(need_eof), chars_to_skip 2337*cda5da8dSAndroid Build Coastguard Worker 2338*cda5da8dSAndroid Build Coastguard Worker def tell(self): 2339*cda5da8dSAndroid Build Coastguard Worker if not self._seekable: 2340*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("underlying stream is not seekable") 2341*cda5da8dSAndroid Build Coastguard Worker if not self._telling: 2342*cda5da8dSAndroid Build Coastguard Worker raise OSError("telling position disabled by next() call") 2343*cda5da8dSAndroid Build Coastguard Worker self.flush() 2344*cda5da8dSAndroid Build Coastguard Worker position = self.buffer.tell() 2345*cda5da8dSAndroid Build Coastguard Worker decoder = self._decoder 2346*cda5da8dSAndroid Build Coastguard Worker if decoder is None or self._snapshot is None: 2347*cda5da8dSAndroid Build Coastguard Worker if self._decoded_chars: 2348*cda5da8dSAndroid Build Coastguard Worker # This should never happen. 2349*cda5da8dSAndroid Build Coastguard Worker raise AssertionError("pending decoded text") 2350*cda5da8dSAndroid Build Coastguard Worker return position 2351*cda5da8dSAndroid Build Coastguard Worker 2352*cda5da8dSAndroid Build Coastguard Worker # Skip backward to the snapshot point (see _read_chunk). 2353*cda5da8dSAndroid Build Coastguard Worker dec_flags, next_input = self._snapshot 2354*cda5da8dSAndroid Build Coastguard Worker position -= len(next_input) 2355*cda5da8dSAndroid Build Coastguard Worker 2356*cda5da8dSAndroid Build Coastguard Worker # How many decoded characters have been used up since the snapshot? 2357*cda5da8dSAndroid Build Coastguard Worker chars_to_skip = self._decoded_chars_used 2358*cda5da8dSAndroid Build Coastguard Worker if chars_to_skip == 0: 2359*cda5da8dSAndroid Build Coastguard Worker # We haven't moved from the snapshot point. 2360*cda5da8dSAndroid Build Coastguard Worker return self._pack_cookie(position, dec_flags) 2361*cda5da8dSAndroid Build Coastguard Worker 2362*cda5da8dSAndroid Build Coastguard Worker # Starting from the snapshot position, we will walk the decoder 2363*cda5da8dSAndroid Build Coastguard Worker # forward until it gives us enough decoded characters. 2364*cda5da8dSAndroid Build Coastguard Worker saved_state = decoder.getstate() 2365*cda5da8dSAndroid Build Coastguard Worker try: 2366*cda5da8dSAndroid Build Coastguard Worker # Fast search for an acceptable start point, close to our 2367*cda5da8dSAndroid Build Coastguard Worker # current pos. 2368*cda5da8dSAndroid Build Coastguard Worker # Rationale: calling decoder.decode() has a large overhead 2369*cda5da8dSAndroid Build Coastguard Worker # regardless of chunk size; we want the number of such calls to 2370*cda5da8dSAndroid Build Coastguard Worker # be O(1) in most situations (common decoders, sensible input). 2371*cda5da8dSAndroid Build Coastguard Worker # Actually, it will be exactly 1 for fixed-size codecs (all 2372*cda5da8dSAndroid Build Coastguard Worker # 8-bit codecs, also UTF-16 and UTF-32). 2373*cda5da8dSAndroid Build Coastguard Worker skip_bytes = int(self._b2cratio * chars_to_skip) 2374*cda5da8dSAndroid Build Coastguard Worker skip_back = 1 2375*cda5da8dSAndroid Build Coastguard Worker assert skip_bytes <= len(next_input) 2376*cda5da8dSAndroid Build Coastguard Worker while skip_bytes > 0: 2377*cda5da8dSAndroid Build Coastguard Worker decoder.setstate((b'', dec_flags)) 2378*cda5da8dSAndroid Build Coastguard Worker # Decode up to temptative start point 2379*cda5da8dSAndroid Build Coastguard Worker n = len(decoder.decode(next_input[:skip_bytes])) 2380*cda5da8dSAndroid Build Coastguard Worker if n <= chars_to_skip: 2381*cda5da8dSAndroid Build Coastguard Worker b, d = decoder.getstate() 2382*cda5da8dSAndroid Build Coastguard Worker if not b: 2383*cda5da8dSAndroid Build Coastguard Worker # Before pos and no bytes buffered in decoder => OK 2384*cda5da8dSAndroid Build Coastguard Worker dec_flags = d 2385*cda5da8dSAndroid Build Coastguard Worker chars_to_skip -= n 2386*cda5da8dSAndroid Build Coastguard Worker break 2387*cda5da8dSAndroid Build Coastguard Worker # Skip back by buffered amount and reset heuristic 2388*cda5da8dSAndroid Build Coastguard Worker skip_bytes -= len(b) 2389*cda5da8dSAndroid Build Coastguard Worker skip_back = 1 2390*cda5da8dSAndroid Build Coastguard Worker else: 2391*cda5da8dSAndroid Build Coastguard Worker # We're too far ahead, skip back a bit 2392*cda5da8dSAndroid Build Coastguard Worker skip_bytes -= skip_back 2393*cda5da8dSAndroid Build Coastguard Worker skip_back = skip_back * 2 2394*cda5da8dSAndroid Build Coastguard Worker else: 2395*cda5da8dSAndroid Build Coastguard Worker skip_bytes = 0 2396*cda5da8dSAndroid Build Coastguard Worker decoder.setstate((b'', dec_flags)) 2397*cda5da8dSAndroid Build Coastguard Worker 2398*cda5da8dSAndroid Build Coastguard Worker # Note our initial start point. 2399*cda5da8dSAndroid Build Coastguard Worker start_pos = position + skip_bytes 2400*cda5da8dSAndroid Build Coastguard Worker start_flags = dec_flags 2401*cda5da8dSAndroid Build Coastguard Worker if chars_to_skip == 0: 2402*cda5da8dSAndroid Build Coastguard Worker # We haven't moved from the start point. 2403*cda5da8dSAndroid Build Coastguard Worker return self._pack_cookie(start_pos, start_flags) 2404*cda5da8dSAndroid Build Coastguard Worker 2405*cda5da8dSAndroid Build Coastguard Worker # Feed the decoder one byte at a time. As we go, note the 2406*cda5da8dSAndroid Build Coastguard Worker # nearest "safe start point" before the current location 2407*cda5da8dSAndroid Build Coastguard Worker # (a point where the decoder has nothing buffered, so seek() 2408*cda5da8dSAndroid Build Coastguard Worker # can safely start from there and advance to this location). 2409*cda5da8dSAndroid Build Coastguard Worker bytes_fed = 0 2410*cda5da8dSAndroid Build Coastguard Worker need_eof = False 2411*cda5da8dSAndroid Build Coastguard Worker # Chars decoded since `start_pos` 2412*cda5da8dSAndroid Build Coastguard Worker chars_decoded = 0 2413*cda5da8dSAndroid Build Coastguard Worker for i in range(skip_bytes, len(next_input)): 2414*cda5da8dSAndroid Build Coastguard Worker bytes_fed += 1 2415*cda5da8dSAndroid Build Coastguard Worker chars_decoded += len(decoder.decode(next_input[i:i+1])) 2416*cda5da8dSAndroid Build Coastguard Worker dec_buffer, dec_flags = decoder.getstate() 2417*cda5da8dSAndroid Build Coastguard Worker if not dec_buffer and chars_decoded <= chars_to_skip: 2418*cda5da8dSAndroid Build Coastguard Worker # Decoder buffer is empty, so this is a safe start point. 2419*cda5da8dSAndroid Build Coastguard Worker start_pos += bytes_fed 2420*cda5da8dSAndroid Build Coastguard Worker chars_to_skip -= chars_decoded 2421*cda5da8dSAndroid Build Coastguard Worker start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 2422*cda5da8dSAndroid Build Coastguard Worker if chars_decoded >= chars_to_skip: 2423*cda5da8dSAndroid Build Coastguard Worker break 2424*cda5da8dSAndroid Build Coastguard Worker else: 2425*cda5da8dSAndroid Build Coastguard Worker # We didn't get enough decoded data; signal EOF to get more. 2426*cda5da8dSAndroid Build Coastguard Worker chars_decoded += len(decoder.decode(b'', final=True)) 2427*cda5da8dSAndroid Build Coastguard Worker need_eof = True 2428*cda5da8dSAndroid Build Coastguard Worker if chars_decoded < chars_to_skip: 2429*cda5da8dSAndroid Build Coastguard Worker raise OSError("can't reconstruct logical file position") 2430*cda5da8dSAndroid Build Coastguard Worker 2431*cda5da8dSAndroid Build Coastguard Worker # The returned cookie corresponds to the last safe start point. 2432*cda5da8dSAndroid Build Coastguard Worker return self._pack_cookie( 2433*cda5da8dSAndroid Build Coastguard Worker start_pos, start_flags, bytes_fed, need_eof, chars_to_skip) 2434*cda5da8dSAndroid Build Coastguard Worker finally: 2435*cda5da8dSAndroid Build Coastguard Worker decoder.setstate(saved_state) 2436*cda5da8dSAndroid Build Coastguard Worker 2437*cda5da8dSAndroid Build Coastguard Worker def truncate(self, pos=None): 2438*cda5da8dSAndroid Build Coastguard Worker self.flush() 2439*cda5da8dSAndroid Build Coastguard Worker if pos is None: 2440*cda5da8dSAndroid Build Coastguard Worker pos = self.tell() 2441*cda5da8dSAndroid Build Coastguard Worker return self.buffer.truncate(pos) 2442*cda5da8dSAndroid Build Coastguard Worker 2443*cda5da8dSAndroid Build Coastguard Worker def detach(self): 2444*cda5da8dSAndroid Build Coastguard Worker if self.buffer is None: 2445*cda5da8dSAndroid Build Coastguard Worker raise ValueError("buffer is already detached") 2446*cda5da8dSAndroid Build Coastguard Worker self.flush() 2447*cda5da8dSAndroid Build Coastguard Worker buffer = self._buffer 2448*cda5da8dSAndroid Build Coastguard Worker self._buffer = None 2449*cda5da8dSAndroid Build Coastguard Worker return buffer 2450*cda5da8dSAndroid Build Coastguard Worker 2451*cda5da8dSAndroid Build Coastguard Worker def seek(self, cookie, whence=0): 2452*cda5da8dSAndroid Build Coastguard Worker def _reset_encoder(position): 2453*cda5da8dSAndroid Build Coastguard Worker """Reset the encoder (merely useful for proper BOM handling)""" 2454*cda5da8dSAndroid Build Coastguard Worker try: 2455*cda5da8dSAndroid Build Coastguard Worker encoder = self._encoder or self._get_encoder() 2456*cda5da8dSAndroid Build Coastguard Worker except LookupError: 2457*cda5da8dSAndroid Build Coastguard Worker # Sometimes the encoder doesn't exist 2458*cda5da8dSAndroid Build Coastguard Worker pass 2459*cda5da8dSAndroid Build Coastguard Worker else: 2460*cda5da8dSAndroid Build Coastguard Worker if position != 0: 2461*cda5da8dSAndroid Build Coastguard Worker encoder.setstate(0) 2462*cda5da8dSAndroid Build Coastguard Worker else: 2463*cda5da8dSAndroid Build Coastguard Worker encoder.reset() 2464*cda5da8dSAndroid Build Coastguard Worker 2465*cda5da8dSAndroid Build Coastguard Worker if self.closed: 2466*cda5da8dSAndroid Build Coastguard Worker raise ValueError("tell on closed file") 2467*cda5da8dSAndroid Build Coastguard Worker if not self._seekable: 2468*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("underlying stream is not seekable") 2469*cda5da8dSAndroid Build Coastguard Worker if whence == SEEK_CUR: 2470*cda5da8dSAndroid Build Coastguard Worker if cookie != 0: 2471*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("can't do nonzero cur-relative seeks") 2472*cda5da8dSAndroid Build Coastguard Worker # Seeking to the current position should attempt to 2473*cda5da8dSAndroid Build Coastguard Worker # sync the underlying buffer with the current position. 2474*cda5da8dSAndroid Build Coastguard Worker whence = 0 2475*cda5da8dSAndroid Build Coastguard Worker cookie = self.tell() 2476*cda5da8dSAndroid Build Coastguard Worker elif whence == SEEK_END: 2477*cda5da8dSAndroid Build Coastguard Worker if cookie != 0: 2478*cda5da8dSAndroid Build Coastguard Worker raise UnsupportedOperation("can't do nonzero end-relative seeks") 2479*cda5da8dSAndroid Build Coastguard Worker self.flush() 2480*cda5da8dSAndroid Build Coastguard Worker position = self.buffer.seek(0, whence) 2481*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars('') 2482*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2483*cda5da8dSAndroid Build Coastguard Worker if self._decoder: 2484*cda5da8dSAndroid Build Coastguard Worker self._decoder.reset() 2485*cda5da8dSAndroid Build Coastguard Worker _reset_encoder(position) 2486*cda5da8dSAndroid Build Coastguard Worker return position 2487*cda5da8dSAndroid Build Coastguard Worker if whence != 0: 2488*cda5da8dSAndroid Build Coastguard Worker raise ValueError("unsupported whence (%r)" % (whence,)) 2489*cda5da8dSAndroid Build Coastguard Worker if cookie < 0: 2490*cda5da8dSAndroid Build Coastguard Worker raise ValueError("negative seek position %r" % (cookie,)) 2491*cda5da8dSAndroid Build Coastguard Worker self.flush() 2492*cda5da8dSAndroid Build Coastguard Worker 2493*cda5da8dSAndroid Build Coastguard Worker # The strategy of seek() is to go back to the safe start point 2494*cda5da8dSAndroid Build Coastguard Worker # and replay the effect of read(chars_to_skip) from there. 2495*cda5da8dSAndroid Build Coastguard Worker start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \ 2496*cda5da8dSAndroid Build Coastguard Worker self._unpack_cookie(cookie) 2497*cda5da8dSAndroid Build Coastguard Worker 2498*cda5da8dSAndroid Build Coastguard Worker # Seek back to the safe start point. 2499*cda5da8dSAndroid Build Coastguard Worker self.buffer.seek(start_pos) 2500*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars('') 2501*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2502*cda5da8dSAndroid Build Coastguard Worker 2503*cda5da8dSAndroid Build Coastguard Worker # Restore the decoder to its state from the safe start point. 2504*cda5da8dSAndroid Build Coastguard Worker if cookie == 0 and self._decoder: 2505*cda5da8dSAndroid Build Coastguard Worker self._decoder.reset() 2506*cda5da8dSAndroid Build Coastguard Worker elif self._decoder or dec_flags or chars_to_skip: 2507*cda5da8dSAndroid Build Coastguard Worker self._decoder = self._decoder or self._get_decoder() 2508*cda5da8dSAndroid Build Coastguard Worker self._decoder.setstate((b'', dec_flags)) 2509*cda5da8dSAndroid Build Coastguard Worker self._snapshot = (dec_flags, b'') 2510*cda5da8dSAndroid Build Coastguard Worker 2511*cda5da8dSAndroid Build Coastguard Worker if chars_to_skip: 2512*cda5da8dSAndroid Build Coastguard Worker # Just like _read_chunk, feed the decoder and save a snapshot. 2513*cda5da8dSAndroid Build Coastguard Worker input_chunk = self.buffer.read(bytes_to_feed) 2514*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars( 2515*cda5da8dSAndroid Build Coastguard Worker self._decoder.decode(input_chunk, need_eof)) 2516*cda5da8dSAndroid Build Coastguard Worker self._snapshot = (dec_flags, input_chunk) 2517*cda5da8dSAndroid Build Coastguard Worker 2518*cda5da8dSAndroid Build Coastguard Worker # Skip chars_to_skip of the decoded characters. 2519*cda5da8dSAndroid Build Coastguard Worker if len(self._decoded_chars) < chars_to_skip: 2520*cda5da8dSAndroid Build Coastguard Worker raise OSError("can't restore logical file position") 2521*cda5da8dSAndroid Build Coastguard Worker self._decoded_chars_used = chars_to_skip 2522*cda5da8dSAndroid Build Coastguard Worker 2523*cda5da8dSAndroid Build Coastguard Worker _reset_encoder(cookie) 2524*cda5da8dSAndroid Build Coastguard Worker return cookie 2525*cda5da8dSAndroid Build Coastguard Worker 2526*cda5da8dSAndroid Build Coastguard Worker def read(self, size=None): 2527*cda5da8dSAndroid Build Coastguard Worker self._checkReadable() 2528*cda5da8dSAndroid Build Coastguard Worker if size is None: 2529*cda5da8dSAndroid Build Coastguard Worker size = -1 2530*cda5da8dSAndroid Build Coastguard Worker else: 2531*cda5da8dSAndroid Build Coastguard Worker try: 2532*cda5da8dSAndroid Build Coastguard Worker size_index = size.__index__ 2533*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2534*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{size!r} is not an integer") 2535*cda5da8dSAndroid Build Coastguard Worker else: 2536*cda5da8dSAndroid Build Coastguard Worker size = size_index() 2537*cda5da8dSAndroid Build Coastguard Worker decoder = self._decoder or self._get_decoder() 2538*cda5da8dSAndroid Build Coastguard Worker if size < 0: 2539*cda5da8dSAndroid Build Coastguard Worker # Read everything. 2540*cda5da8dSAndroid Build Coastguard Worker result = (self._get_decoded_chars() + 2541*cda5da8dSAndroid Build Coastguard Worker decoder.decode(self.buffer.read(), final=True)) 2542*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars('') 2543*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2544*cda5da8dSAndroid Build Coastguard Worker return result 2545*cda5da8dSAndroid Build Coastguard Worker else: 2546*cda5da8dSAndroid Build Coastguard Worker # Keep reading chunks until we have size characters to return. 2547*cda5da8dSAndroid Build Coastguard Worker eof = False 2548*cda5da8dSAndroid Build Coastguard Worker result = self._get_decoded_chars(size) 2549*cda5da8dSAndroid Build Coastguard Worker while len(result) < size and not eof: 2550*cda5da8dSAndroid Build Coastguard Worker eof = not self._read_chunk() 2551*cda5da8dSAndroid Build Coastguard Worker result += self._get_decoded_chars(size - len(result)) 2552*cda5da8dSAndroid Build Coastguard Worker return result 2553*cda5da8dSAndroid Build Coastguard Worker 2554*cda5da8dSAndroid Build Coastguard Worker def __next__(self): 2555*cda5da8dSAndroid Build Coastguard Worker self._telling = False 2556*cda5da8dSAndroid Build Coastguard Worker line = self.readline() 2557*cda5da8dSAndroid Build Coastguard Worker if not line: 2558*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2559*cda5da8dSAndroid Build Coastguard Worker self._telling = self._seekable 2560*cda5da8dSAndroid Build Coastguard Worker raise StopIteration 2561*cda5da8dSAndroid Build Coastguard Worker return line 2562*cda5da8dSAndroid Build Coastguard Worker 2563*cda5da8dSAndroid Build Coastguard Worker def readline(self, size=None): 2564*cda5da8dSAndroid Build Coastguard Worker if self.closed: 2565*cda5da8dSAndroid Build Coastguard Worker raise ValueError("read from closed file") 2566*cda5da8dSAndroid Build Coastguard Worker if size is None: 2567*cda5da8dSAndroid Build Coastguard Worker size = -1 2568*cda5da8dSAndroid Build Coastguard Worker else: 2569*cda5da8dSAndroid Build Coastguard Worker try: 2570*cda5da8dSAndroid Build Coastguard Worker size_index = size.__index__ 2571*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 2572*cda5da8dSAndroid Build Coastguard Worker raise TypeError(f"{size!r} is not an integer") 2573*cda5da8dSAndroid Build Coastguard Worker else: 2574*cda5da8dSAndroid Build Coastguard Worker size = size_index() 2575*cda5da8dSAndroid Build Coastguard Worker 2576*cda5da8dSAndroid Build Coastguard Worker # Grab all the decoded text (we will rewind any extra bits later). 2577*cda5da8dSAndroid Build Coastguard Worker line = self._get_decoded_chars() 2578*cda5da8dSAndroid Build Coastguard Worker 2579*cda5da8dSAndroid Build Coastguard Worker start = 0 2580*cda5da8dSAndroid Build Coastguard Worker # Make the decoder if it doesn't already exist. 2581*cda5da8dSAndroid Build Coastguard Worker if not self._decoder: 2582*cda5da8dSAndroid Build Coastguard Worker self._get_decoder() 2583*cda5da8dSAndroid Build Coastguard Worker 2584*cda5da8dSAndroid Build Coastguard Worker pos = endpos = None 2585*cda5da8dSAndroid Build Coastguard Worker while True: 2586*cda5da8dSAndroid Build Coastguard Worker if self._readtranslate: 2587*cda5da8dSAndroid Build Coastguard Worker # Newlines are already translated, only search for \n 2588*cda5da8dSAndroid Build Coastguard Worker pos = line.find('\n', start) 2589*cda5da8dSAndroid Build Coastguard Worker if pos >= 0: 2590*cda5da8dSAndroid Build Coastguard Worker endpos = pos + 1 2591*cda5da8dSAndroid Build Coastguard Worker break 2592*cda5da8dSAndroid Build Coastguard Worker else: 2593*cda5da8dSAndroid Build Coastguard Worker start = len(line) 2594*cda5da8dSAndroid Build Coastguard Worker 2595*cda5da8dSAndroid Build Coastguard Worker elif self._readuniversal: 2596*cda5da8dSAndroid Build Coastguard Worker # Universal newline search. Find any of \r, \r\n, \n 2597*cda5da8dSAndroid Build Coastguard Worker # The decoder ensures that \r\n are not split in two pieces 2598*cda5da8dSAndroid Build Coastguard Worker 2599*cda5da8dSAndroid Build Coastguard Worker # In C we'd look for these in parallel of course. 2600*cda5da8dSAndroid Build Coastguard Worker nlpos = line.find("\n", start) 2601*cda5da8dSAndroid Build Coastguard Worker crpos = line.find("\r", start) 2602*cda5da8dSAndroid Build Coastguard Worker if crpos == -1: 2603*cda5da8dSAndroid Build Coastguard Worker if nlpos == -1: 2604*cda5da8dSAndroid Build Coastguard Worker # Nothing found 2605*cda5da8dSAndroid Build Coastguard Worker start = len(line) 2606*cda5da8dSAndroid Build Coastguard Worker else: 2607*cda5da8dSAndroid Build Coastguard Worker # Found \n 2608*cda5da8dSAndroid Build Coastguard Worker endpos = nlpos + 1 2609*cda5da8dSAndroid Build Coastguard Worker break 2610*cda5da8dSAndroid Build Coastguard Worker elif nlpos == -1: 2611*cda5da8dSAndroid Build Coastguard Worker # Found lone \r 2612*cda5da8dSAndroid Build Coastguard Worker endpos = crpos + 1 2613*cda5da8dSAndroid Build Coastguard Worker break 2614*cda5da8dSAndroid Build Coastguard Worker elif nlpos < crpos: 2615*cda5da8dSAndroid Build Coastguard Worker # Found \n 2616*cda5da8dSAndroid Build Coastguard Worker endpos = nlpos + 1 2617*cda5da8dSAndroid Build Coastguard Worker break 2618*cda5da8dSAndroid Build Coastguard Worker elif nlpos == crpos + 1: 2619*cda5da8dSAndroid Build Coastguard Worker # Found \r\n 2620*cda5da8dSAndroid Build Coastguard Worker endpos = crpos + 2 2621*cda5da8dSAndroid Build Coastguard Worker break 2622*cda5da8dSAndroid Build Coastguard Worker else: 2623*cda5da8dSAndroid Build Coastguard Worker # Found \r 2624*cda5da8dSAndroid Build Coastguard Worker endpos = crpos + 1 2625*cda5da8dSAndroid Build Coastguard Worker break 2626*cda5da8dSAndroid Build Coastguard Worker else: 2627*cda5da8dSAndroid Build Coastguard Worker # non-universal 2628*cda5da8dSAndroid Build Coastguard Worker pos = line.find(self._readnl) 2629*cda5da8dSAndroid Build Coastguard Worker if pos >= 0: 2630*cda5da8dSAndroid Build Coastguard Worker endpos = pos + len(self._readnl) 2631*cda5da8dSAndroid Build Coastguard Worker break 2632*cda5da8dSAndroid Build Coastguard Worker 2633*cda5da8dSAndroid Build Coastguard Worker if size >= 0 and len(line) >= size: 2634*cda5da8dSAndroid Build Coastguard Worker endpos = size # reached length size 2635*cda5da8dSAndroid Build Coastguard Worker break 2636*cda5da8dSAndroid Build Coastguard Worker 2637*cda5da8dSAndroid Build Coastguard Worker # No line ending seen yet - get more data' 2638*cda5da8dSAndroid Build Coastguard Worker while self._read_chunk(): 2639*cda5da8dSAndroid Build Coastguard Worker if self._decoded_chars: 2640*cda5da8dSAndroid Build Coastguard Worker break 2641*cda5da8dSAndroid Build Coastguard Worker if self._decoded_chars: 2642*cda5da8dSAndroid Build Coastguard Worker line += self._get_decoded_chars() 2643*cda5da8dSAndroid Build Coastguard Worker else: 2644*cda5da8dSAndroid Build Coastguard Worker # end of file 2645*cda5da8dSAndroid Build Coastguard Worker self._set_decoded_chars('') 2646*cda5da8dSAndroid Build Coastguard Worker self._snapshot = None 2647*cda5da8dSAndroid Build Coastguard Worker return line 2648*cda5da8dSAndroid Build Coastguard Worker 2649*cda5da8dSAndroid Build Coastguard Worker if size >= 0 and endpos > size: 2650*cda5da8dSAndroid Build Coastguard Worker endpos = size # don't exceed size 2651*cda5da8dSAndroid Build Coastguard Worker 2652*cda5da8dSAndroid Build Coastguard Worker # Rewind _decoded_chars to just after the line ending we found. 2653*cda5da8dSAndroid Build Coastguard Worker self._rewind_decoded_chars(len(line) - endpos) 2654*cda5da8dSAndroid Build Coastguard Worker return line[:endpos] 2655*cda5da8dSAndroid Build Coastguard Worker 2656*cda5da8dSAndroid Build Coastguard Worker @property 2657*cda5da8dSAndroid Build Coastguard Worker def newlines(self): 2658*cda5da8dSAndroid Build Coastguard Worker return self._decoder.newlines if self._decoder else None 2659*cda5da8dSAndroid Build Coastguard Worker 2660*cda5da8dSAndroid Build Coastguard Worker 2661*cda5da8dSAndroid Build Coastguard Workerclass StringIO(TextIOWrapper): 2662*cda5da8dSAndroid Build Coastguard Worker """Text I/O implementation using an in-memory buffer. 2663*cda5da8dSAndroid Build Coastguard Worker 2664*cda5da8dSAndroid Build Coastguard Worker The initial_value argument sets the value of object. The newline 2665*cda5da8dSAndroid Build Coastguard Worker argument is like the one of TextIOWrapper's constructor. 2666*cda5da8dSAndroid Build Coastguard Worker """ 2667*cda5da8dSAndroid Build Coastguard Worker 2668*cda5da8dSAndroid Build Coastguard Worker def __init__(self, initial_value="", newline="\n"): 2669*cda5da8dSAndroid Build Coastguard Worker super(StringIO, self).__init__(BytesIO(), 2670*cda5da8dSAndroid Build Coastguard Worker encoding="utf-8", 2671*cda5da8dSAndroid Build Coastguard Worker errors="surrogatepass", 2672*cda5da8dSAndroid Build Coastguard Worker newline=newline) 2673*cda5da8dSAndroid Build Coastguard Worker # Issue #5645: make universal newlines semantics the same as in the 2674*cda5da8dSAndroid Build Coastguard Worker # C version, even under Windows. 2675*cda5da8dSAndroid Build Coastguard Worker if newline is None: 2676*cda5da8dSAndroid Build Coastguard Worker self._writetranslate = False 2677*cda5da8dSAndroid Build Coastguard Worker if initial_value is not None: 2678*cda5da8dSAndroid Build Coastguard Worker if not isinstance(initial_value, str): 2679*cda5da8dSAndroid Build Coastguard Worker raise TypeError("initial_value must be str or None, not {0}" 2680*cda5da8dSAndroid Build Coastguard Worker .format(type(initial_value).__name__)) 2681*cda5da8dSAndroid Build Coastguard Worker self.write(initial_value) 2682*cda5da8dSAndroid Build Coastguard Worker self.seek(0) 2683*cda5da8dSAndroid Build Coastguard Worker 2684*cda5da8dSAndroid Build Coastguard Worker def getvalue(self): 2685*cda5da8dSAndroid Build Coastguard Worker self.flush() 2686*cda5da8dSAndroid Build Coastguard Worker decoder = self._decoder or self._get_decoder() 2687*cda5da8dSAndroid Build Coastguard Worker old_state = decoder.getstate() 2688*cda5da8dSAndroid Build Coastguard Worker decoder.reset() 2689*cda5da8dSAndroid Build Coastguard Worker try: 2690*cda5da8dSAndroid Build Coastguard Worker return decoder.decode(self.buffer.getvalue(), final=True) 2691*cda5da8dSAndroid Build Coastguard Worker finally: 2692*cda5da8dSAndroid Build Coastguard Worker decoder.setstate(old_state) 2693*cda5da8dSAndroid Build Coastguard Worker 2694*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2695*cda5da8dSAndroid Build Coastguard Worker # TextIOWrapper tells the encoding in its repr. In StringIO, 2696*cda5da8dSAndroid Build Coastguard Worker # that's an implementation detail. 2697*cda5da8dSAndroid Build Coastguard Worker return object.__repr__(self) 2698*cda5da8dSAndroid Build Coastguard Worker 2699*cda5da8dSAndroid Build Coastguard Worker @property 2700*cda5da8dSAndroid Build Coastguard Worker def errors(self): 2701*cda5da8dSAndroid Build Coastguard Worker return None 2702*cda5da8dSAndroid Build Coastguard Worker 2703*cda5da8dSAndroid Build Coastguard Worker @property 2704*cda5da8dSAndroid Build Coastguard Worker def encoding(self): 2705*cda5da8dSAndroid Build Coastguard Worker return None 2706*cda5da8dSAndroid Build Coastguard Worker 2707*cda5da8dSAndroid Build Coastguard Worker def detach(self): 2708*cda5da8dSAndroid Build Coastguard Worker # This doesn't make sense on StringIO. 2709*cda5da8dSAndroid Build Coastguard Worker self._unsupported("detach") 2710