17db96d56Sopenharmony_ci""" 27db96d56Sopenharmony_ciPython implementation of the io module. 37db96d56Sopenharmony_ci""" 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ciimport os 67db96d56Sopenharmony_ciimport abc 77db96d56Sopenharmony_ciimport codecs 87db96d56Sopenharmony_ciimport errno 97db96d56Sopenharmony_ciimport stat 107db96d56Sopenharmony_ciimport sys 117db96d56Sopenharmony_ci# Import _thread instead of threading to reduce startup cost 127db96d56Sopenharmony_cifrom _thread import allocate_lock as Lock 137db96d56Sopenharmony_ciif sys.platform in {'win32', 'cygwin'}: 147db96d56Sopenharmony_ci from msvcrt import setmode as _setmode 157db96d56Sopenharmony_cielse: 167db96d56Sopenharmony_ci _setmode = None 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciimport io 197db96d56Sopenharmony_cifrom io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_civalid_seek_flags = {0, 1, 2} # Hardwired values 227db96d56Sopenharmony_ciif hasattr(os, 'SEEK_HOLE') : 237db96d56Sopenharmony_ci valid_seek_flags.add(os.SEEK_HOLE) 247db96d56Sopenharmony_ci valid_seek_flags.add(os.SEEK_DATA) 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ci# open() uses st_blksize whenever we can 277db96d56Sopenharmony_ciDEFAULT_BUFFER_SIZE = 8 * 1024 # bytes 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci# NOTE: Base classes defined here are registered with the "official" ABCs 307db96d56Sopenharmony_ci# defined in io.py. We don't use real inheritance though, because we don't want 317db96d56Sopenharmony_ci# to inherit the C implementations. 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci# Rebind for compatibility 347db96d56Sopenharmony_ciBlockingIOError = BlockingIOError 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci# Does io.IOBase finalizer log the exception if the close() method fails? 377db96d56Sopenharmony_ci# The exception is ignored silently by default in release build. 387db96d56Sopenharmony_ci_IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode) 397db96d56Sopenharmony_ci# Does open() check its 'errors' argument? 407db96d56Sopenharmony_ci_CHECK_ERRORS = _IOBASE_EMITS_UNRAISABLE 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_cidef text_encoding(encoding, stacklevel=2): 447db96d56Sopenharmony_ci """ 457db96d56Sopenharmony_ci A helper function to choose the text encoding. 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci When encoding is not None, this function returns it. 487db96d56Sopenharmony_ci Otherwise, this function returns the default text encoding 497db96d56Sopenharmony_ci (i.e. "locale" or "utf-8" depends on UTF-8 mode). 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci This function emits an EncodingWarning if *encoding* is None and 527db96d56Sopenharmony_ci sys.flags.warn_default_encoding is true. 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci This can be used in APIs with an encoding=None parameter 557db96d56Sopenharmony_ci that pass it to TextIOWrapper or open. 567db96d56Sopenharmony_ci However, please consider using encoding="utf-8" for new APIs. 577db96d56Sopenharmony_ci """ 587db96d56Sopenharmony_ci if encoding is None: 597db96d56Sopenharmony_ci if sys.flags.utf8_mode: 607db96d56Sopenharmony_ci encoding = "utf-8" 617db96d56Sopenharmony_ci else: 627db96d56Sopenharmony_ci encoding = "locale" 637db96d56Sopenharmony_ci if sys.flags.warn_default_encoding: 647db96d56Sopenharmony_ci import warnings 657db96d56Sopenharmony_ci warnings.warn("'encoding' argument not specified.", 667db96d56Sopenharmony_ci EncodingWarning, stacklevel + 1) 677db96d56Sopenharmony_ci return encoding 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci# Wrapper for builtins.open 717db96d56Sopenharmony_ci# 727db96d56Sopenharmony_ci# Trick so that open() won't become a bound method when stored 737db96d56Sopenharmony_ci# as a class variable (as dbm.dumb does). 747db96d56Sopenharmony_ci# 757db96d56Sopenharmony_ci# See init_set_builtins_open() in Python/pylifecycle.c. 767db96d56Sopenharmony_ci@staticmethod 777db96d56Sopenharmony_cidef open(file, mode="r", buffering=-1, encoding=None, errors=None, 787db96d56Sopenharmony_ci newline=None, closefd=True, opener=None): 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci r"""Open file and return a stream. Raise OSError upon failure. 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci file is either a text or byte string giving the name (and the path 837db96d56Sopenharmony_ci if the file isn't in the current working directory) of the file to 847db96d56Sopenharmony_ci be opened or an integer file descriptor of the file to be 857db96d56Sopenharmony_ci wrapped. (If a file descriptor is given, it is closed when the 867db96d56Sopenharmony_ci returned I/O object is closed, unless closefd is set to False.) 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ci mode is an optional string that specifies the mode in which the file is 897db96d56Sopenharmony_ci opened. It defaults to 'r' which means open for reading in text mode. Other 907db96d56Sopenharmony_ci common values are 'w' for writing (truncating the file if it already 917db96d56Sopenharmony_ci exists), 'x' for exclusive creation of a new file, and 'a' for appending 927db96d56Sopenharmony_ci (which on some Unix systems, means that all writes append to the end of the 937db96d56Sopenharmony_ci file regardless of the current seek position). In text mode, if encoding is 947db96d56Sopenharmony_ci not specified the encoding used is platform dependent. (For reading and 957db96d56Sopenharmony_ci writing raw bytes use binary mode and leave encoding unspecified.) The 967db96d56Sopenharmony_ci available modes are: 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci ========= =============================================================== 997db96d56Sopenharmony_ci Character Meaning 1007db96d56Sopenharmony_ci --------- --------------------------------------------------------------- 1017db96d56Sopenharmony_ci 'r' open for reading (default) 1027db96d56Sopenharmony_ci 'w' open for writing, truncating the file first 1037db96d56Sopenharmony_ci 'x' create a new file and open it for writing 1047db96d56Sopenharmony_ci 'a' open for writing, appending to the end of the file if it exists 1057db96d56Sopenharmony_ci 'b' binary mode 1067db96d56Sopenharmony_ci 't' text mode (default) 1077db96d56Sopenharmony_ci '+' open a disk file for updating (reading and writing) 1087db96d56Sopenharmony_ci ========= =============================================================== 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci The default mode is 'rt' (open for reading text). For binary random 1117db96d56Sopenharmony_ci access, the mode 'w+b' opens and truncates the file to 0 bytes, while 1127db96d56Sopenharmony_ci 'r+b' opens the file without truncation. The 'x' mode implies 'w' and 1137db96d56Sopenharmony_ci raises an `FileExistsError` if the file already exists. 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci Python distinguishes between files opened in binary and text modes, 1167db96d56Sopenharmony_ci even when the underlying operating system doesn't. Files opened in 1177db96d56Sopenharmony_ci binary mode (appending 'b' to the mode argument) return contents as 1187db96d56Sopenharmony_ci bytes objects without any decoding. In text mode (the default, or when 1197db96d56Sopenharmony_ci 't' is appended to the mode argument), the contents of the file are 1207db96d56Sopenharmony_ci returned as strings, the bytes having been first decoded using a 1217db96d56Sopenharmony_ci platform-dependent encoding or using the specified encoding if given. 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci buffering is an optional integer used to set the buffering policy. 1247db96d56Sopenharmony_ci Pass 0 to switch buffering off (only allowed in binary mode), 1 to select 1257db96d56Sopenharmony_ci line buffering (only usable in text mode), and an integer > 1 to indicate 1267db96d56Sopenharmony_ci the size of a fixed-size chunk buffer. When no buffering argument is 1277db96d56Sopenharmony_ci given, the default buffering policy works as follows: 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci * Binary files are buffered in fixed-size chunks; the size of the buffer 1307db96d56Sopenharmony_ci is chosen using a heuristic trying to determine the underlying device's 1317db96d56Sopenharmony_ci "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`. 1327db96d56Sopenharmony_ci On many systems, the buffer will typically be 4096 or 8192 bytes long. 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci * "Interactive" text files (files for which isatty() returns True) 1357db96d56Sopenharmony_ci use line buffering. Other text files use the policy described above 1367db96d56Sopenharmony_ci for binary files. 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci encoding is the str name of the encoding used to decode or encode the 1397db96d56Sopenharmony_ci file. This should only be used in text mode. The default encoding is 1407db96d56Sopenharmony_ci platform dependent, but any encoding supported by Python can be 1417db96d56Sopenharmony_ci passed. See the codecs module for the list of supported encodings. 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci errors is an optional string that specifies how encoding errors are to 1447db96d56Sopenharmony_ci be handled---this argument should not be used in binary mode. Pass 1457db96d56Sopenharmony_ci 'strict' to raise a ValueError exception if there is an encoding error 1467db96d56Sopenharmony_ci (the default of None has the same effect), or pass 'ignore' to ignore 1477db96d56Sopenharmony_ci errors. (Note that ignoring encoding errors can lead to data loss.) 1487db96d56Sopenharmony_ci See the documentation for codecs.register for a list of the permitted 1497db96d56Sopenharmony_ci encoding error strings. 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ci newline is a string controlling how universal newlines works (it only 1527db96d56Sopenharmony_ci applies to text mode). It can be None, '', '\n', '\r', and '\r\n'. It works 1537db96d56Sopenharmony_ci as follows: 1547db96d56Sopenharmony_ci 1557db96d56Sopenharmony_ci * On input, if newline is None, universal newlines mode is 1567db96d56Sopenharmony_ci enabled. Lines in the input can end in '\n', '\r', or '\r\n', and 1577db96d56Sopenharmony_ci these are translated into '\n' before being returned to the 1587db96d56Sopenharmony_ci caller. If it is '', universal newline mode is enabled, but line 1597db96d56Sopenharmony_ci endings are returned to the caller untranslated. If it has any of 1607db96d56Sopenharmony_ci the other legal values, input lines are only terminated by the given 1617db96d56Sopenharmony_ci string, and the line ending is returned to the caller untranslated. 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci * On output, if newline is None, any '\n' characters written are 1647db96d56Sopenharmony_ci translated to the system default line separator, os.linesep. If 1657db96d56Sopenharmony_ci newline is '', no translation takes place. If newline is any of the 1667db96d56Sopenharmony_ci other legal values, any '\n' characters written are translated to 1677db96d56Sopenharmony_ci the given string. 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci closedfd is a bool. If closefd is False, the underlying file descriptor will 1707db96d56Sopenharmony_ci be kept open when the file is closed. This does not work when a file name is 1717db96d56Sopenharmony_ci given and must be True in that case. 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci The newly created file is non-inheritable. 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_ci A custom opener can be used by passing a callable as *opener*. The 1767db96d56Sopenharmony_ci underlying file descriptor for the file object is then obtained by calling 1777db96d56Sopenharmony_ci *opener* with (*file*, *flags*). *opener* must return an open file 1787db96d56Sopenharmony_ci descriptor (passing os.open as *opener* results in functionality similar to 1797db96d56Sopenharmony_ci passing None). 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci open() returns a file object whose type depends on the mode, and 1827db96d56Sopenharmony_ci through which the standard file operations such as reading and writing 1837db96d56Sopenharmony_ci are performed. When open() is used to open a file in a text mode ('w', 1847db96d56Sopenharmony_ci 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open 1857db96d56Sopenharmony_ci a file in a binary mode, the returned class varies: in read binary 1867db96d56Sopenharmony_ci mode, it returns a BufferedReader; in write binary and append binary 1877db96d56Sopenharmony_ci modes, it returns a BufferedWriter, and in read/write mode, it returns 1887db96d56Sopenharmony_ci a BufferedRandom. 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci It is also possible to use a string or bytearray as a file for both 1917db96d56Sopenharmony_ci reading and writing. For strings StringIO can be used like a file 1927db96d56Sopenharmony_ci opened in a text mode, and for bytes a BytesIO can be used like a file 1937db96d56Sopenharmony_ci opened in a binary mode. 1947db96d56Sopenharmony_ci """ 1957db96d56Sopenharmony_ci if not isinstance(file, int): 1967db96d56Sopenharmony_ci file = os.fspath(file) 1977db96d56Sopenharmony_ci if not isinstance(file, (str, bytes, int)): 1987db96d56Sopenharmony_ci raise TypeError("invalid file: %r" % file) 1997db96d56Sopenharmony_ci if not isinstance(mode, str): 2007db96d56Sopenharmony_ci raise TypeError("invalid mode: %r" % mode) 2017db96d56Sopenharmony_ci if not isinstance(buffering, int): 2027db96d56Sopenharmony_ci raise TypeError("invalid buffering: %r" % buffering) 2037db96d56Sopenharmony_ci if encoding is not None and not isinstance(encoding, str): 2047db96d56Sopenharmony_ci raise TypeError("invalid encoding: %r" % encoding) 2057db96d56Sopenharmony_ci if errors is not None and not isinstance(errors, str): 2067db96d56Sopenharmony_ci raise TypeError("invalid errors: %r" % errors) 2077db96d56Sopenharmony_ci modes = set(mode) 2087db96d56Sopenharmony_ci if modes - set("axrwb+t") or len(mode) > len(modes): 2097db96d56Sopenharmony_ci raise ValueError("invalid mode: %r" % mode) 2107db96d56Sopenharmony_ci creating = "x" in modes 2117db96d56Sopenharmony_ci reading = "r" in modes 2127db96d56Sopenharmony_ci writing = "w" in modes 2137db96d56Sopenharmony_ci appending = "a" in modes 2147db96d56Sopenharmony_ci updating = "+" in modes 2157db96d56Sopenharmony_ci text = "t" in modes 2167db96d56Sopenharmony_ci binary = "b" in modes 2177db96d56Sopenharmony_ci if text and binary: 2187db96d56Sopenharmony_ci raise ValueError("can't have text and binary mode at once") 2197db96d56Sopenharmony_ci if creating + reading + writing + appending > 1: 2207db96d56Sopenharmony_ci raise ValueError("can't have read/write/append mode at once") 2217db96d56Sopenharmony_ci if not (creating or reading or writing or appending): 2227db96d56Sopenharmony_ci raise ValueError("must have exactly one of read/write/append mode") 2237db96d56Sopenharmony_ci if binary and encoding is not None: 2247db96d56Sopenharmony_ci raise ValueError("binary mode doesn't take an encoding argument") 2257db96d56Sopenharmony_ci if binary and errors is not None: 2267db96d56Sopenharmony_ci raise ValueError("binary mode doesn't take an errors argument") 2277db96d56Sopenharmony_ci if binary and newline is not None: 2287db96d56Sopenharmony_ci raise ValueError("binary mode doesn't take a newline argument") 2297db96d56Sopenharmony_ci if binary and buffering == 1: 2307db96d56Sopenharmony_ci import warnings 2317db96d56Sopenharmony_ci warnings.warn("line buffering (buffering=1) isn't supported in binary " 2327db96d56Sopenharmony_ci "mode, the default buffer size will be used", 2337db96d56Sopenharmony_ci RuntimeWarning, 2) 2347db96d56Sopenharmony_ci raw = FileIO(file, 2357db96d56Sopenharmony_ci (creating and "x" or "") + 2367db96d56Sopenharmony_ci (reading and "r" or "") + 2377db96d56Sopenharmony_ci (writing and "w" or "") + 2387db96d56Sopenharmony_ci (appending and "a" or "") + 2397db96d56Sopenharmony_ci (updating and "+" or ""), 2407db96d56Sopenharmony_ci closefd, opener=opener) 2417db96d56Sopenharmony_ci result = raw 2427db96d56Sopenharmony_ci try: 2437db96d56Sopenharmony_ci line_buffering = False 2447db96d56Sopenharmony_ci if buffering == 1 or buffering < 0 and raw.isatty(): 2457db96d56Sopenharmony_ci buffering = -1 2467db96d56Sopenharmony_ci line_buffering = True 2477db96d56Sopenharmony_ci if buffering < 0: 2487db96d56Sopenharmony_ci buffering = DEFAULT_BUFFER_SIZE 2497db96d56Sopenharmony_ci try: 2507db96d56Sopenharmony_ci bs = os.fstat(raw.fileno()).st_blksize 2517db96d56Sopenharmony_ci except (OSError, AttributeError): 2527db96d56Sopenharmony_ci pass 2537db96d56Sopenharmony_ci else: 2547db96d56Sopenharmony_ci if bs > 1: 2557db96d56Sopenharmony_ci buffering = bs 2567db96d56Sopenharmony_ci if buffering < 0: 2577db96d56Sopenharmony_ci raise ValueError("invalid buffering size") 2587db96d56Sopenharmony_ci if buffering == 0: 2597db96d56Sopenharmony_ci if binary: 2607db96d56Sopenharmony_ci return result 2617db96d56Sopenharmony_ci raise ValueError("can't have unbuffered text I/O") 2627db96d56Sopenharmony_ci if updating: 2637db96d56Sopenharmony_ci buffer = BufferedRandom(raw, buffering) 2647db96d56Sopenharmony_ci elif creating or writing or appending: 2657db96d56Sopenharmony_ci buffer = BufferedWriter(raw, buffering) 2667db96d56Sopenharmony_ci elif reading: 2677db96d56Sopenharmony_ci buffer = BufferedReader(raw, buffering) 2687db96d56Sopenharmony_ci else: 2697db96d56Sopenharmony_ci raise ValueError("unknown mode: %r" % mode) 2707db96d56Sopenharmony_ci result = buffer 2717db96d56Sopenharmony_ci if binary: 2727db96d56Sopenharmony_ci return result 2737db96d56Sopenharmony_ci encoding = text_encoding(encoding) 2747db96d56Sopenharmony_ci text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) 2757db96d56Sopenharmony_ci result = text 2767db96d56Sopenharmony_ci text.mode = mode 2777db96d56Sopenharmony_ci return result 2787db96d56Sopenharmony_ci except: 2797db96d56Sopenharmony_ci result.close() 2807db96d56Sopenharmony_ci raise 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci# Define a default pure-Python implementation for open_code() 2837db96d56Sopenharmony_ci# that does not allow hooks. Warn on first use. Defined for tests. 2847db96d56Sopenharmony_cidef _open_code_with_warning(path): 2857db96d56Sopenharmony_ci """Opens the provided file with mode ``'rb'``. This function 2867db96d56Sopenharmony_ci should be used when the intent is to treat the contents as 2877db96d56Sopenharmony_ci executable code. 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci ``path`` should be an absolute path. 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci When supported by the runtime, this function can be hooked 2927db96d56Sopenharmony_ci in order to allow embedders more control over code files. 2937db96d56Sopenharmony_ci This functionality is not supported on the current runtime. 2947db96d56Sopenharmony_ci """ 2957db96d56Sopenharmony_ci import warnings 2967db96d56Sopenharmony_ci warnings.warn("_pyio.open_code() may not be using hooks", 2977db96d56Sopenharmony_ci RuntimeWarning, 2) 2987db96d56Sopenharmony_ci return open(path, "rb") 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_citry: 3017db96d56Sopenharmony_ci open_code = io.open_code 3027db96d56Sopenharmony_ciexcept AttributeError: 3037db96d56Sopenharmony_ci open_code = _open_code_with_warning 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci 3067db96d56Sopenharmony_cidef __getattr__(name): 3077db96d56Sopenharmony_ci if name == "OpenWrapper": 3087db96d56Sopenharmony_ci # bpo-43680: Until Python 3.9, _pyio.open was not a static method and 3097db96d56Sopenharmony_ci # builtins.open was set to OpenWrapper to not become a bound method 3107db96d56Sopenharmony_ci # when set to a class variable. _io.open is a built-in function whereas 3117db96d56Sopenharmony_ci # _pyio.open is a Python function. In Python 3.10, _pyio.open() is now 3127db96d56Sopenharmony_ci # a static method, and builtins.open() is now io.open(). 3137db96d56Sopenharmony_ci import warnings 3147db96d56Sopenharmony_ci warnings.warn('OpenWrapper is deprecated, use open instead', 3157db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 3167db96d56Sopenharmony_ci global OpenWrapper 3177db96d56Sopenharmony_ci OpenWrapper = open 3187db96d56Sopenharmony_ci return OpenWrapper 3197db96d56Sopenharmony_ci raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci# In normal operation, both `UnsupportedOperation`s should be bound to the 3237db96d56Sopenharmony_ci# same object. 3247db96d56Sopenharmony_citry: 3257db96d56Sopenharmony_ci UnsupportedOperation = io.UnsupportedOperation 3267db96d56Sopenharmony_ciexcept AttributeError: 3277db96d56Sopenharmony_ci class UnsupportedOperation(OSError, ValueError): 3287db96d56Sopenharmony_ci pass 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ciclass IOBase(metaclass=abc.ABCMeta): 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci """The abstract base class for all I/O classes. 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci This class provides dummy implementations for many methods that 3367db96d56Sopenharmony_ci derived classes can override selectively; the default implementations 3377db96d56Sopenharmony_ci represent a file that cannot be read, written or seeked. 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci Even though IOBase does not declare read or write because 3407db96d56Sopenharmony_ci their signatures will vary, implementations and clients should 3417db96d56Sopenharmony_ci consider those methods part of the interface. Also, implementations 3427db96d56Sopenharmony_ci may raise UnsupportedOperation when operations they do not support are 3437db96d56Sopenharmony_ci called. 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci The basic type used for binary data read from or written to a file is 3467db96d56Sopenharmony_ci bytes. Other bytes-like objects are accepted as method arguments too. 3477db96d56Sopenharmony_ci Text I/O classes work with str data. 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci Note that calling any method (even inquiries) on a closed stream is 3507db96d56Sopenharmony_ci undefined. Implementations may raise OSError in this case. 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci IOBase (and its subclasses) support the iterator protocol, meaning 3537db96d56Sopenharmony_ci that an IOBase object can be iterated over yielding the lines in a 3547db96d56Sopenharmony_ci stream. 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci IOBase also supports the :keyword:`with` statement. In this example, 3577db96d56Sopenharmony_ci fp is closed after the suite of the with statement is complete: 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci with open('spam.txt', 'r') as fp: 3607db96d56Sopenharmony_ci fp.write('Spam and eggs!') 3617db96d56Sopenharmony_ci """ 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci ### Internal ### 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci def _unsupported(self, name): 3667db96d56Sopenharmony_ci """Internal: raise an OSError exception for unsupported operations.""" 3677db96d56Sopenharmony_ci raise UnsupportedOperation("%s.%s() not supported" % 3687db96d56Sopenharmony_ci (self.__class__.__name__, name)) 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci ### Positioning ### 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci def seek(self, pos, whence=0): 3737db96d56Sopenharmony_ci """Change stream position. 3747db96d56Sopenharmony_ci 3757db96d56Sopenharmony_ci Change the stream position to byte offset pos. Argument pos is 3767db96d56Sopenharmony_ci interpreted relative to the position indicated by whence. Values 3777db96d56Sopenharmony_ci for whence are ints: 3787db96d56Sopenharmony_ci 3797db96d56Sopenharmony_ci * 0 -- start of stream (the default); offset should be zero or positive 3807db96d56Sopenharmony_ci * 1 -- current stream position; offset may be negative 3817db96d56Sopenharmony_ci * 2 -- end of stream; offset is usually negative 3827db96d56Sopenharmony_ci Some operating systems / file systems could provide additional values. 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci Return an int indicating the new absolute position. 3857db96d56Sopenharmony_ci """ 3867db96d56Sopenharmony_ci self._unsupported("seek") 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci def tell(self): 3897db96d56Sopenharmony_ci """Return an int indicating the current stream position.""" 3907db96d56Sopenharmony_ci return self.seek(0, 1) 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci def truncate(self, pos=None): 3937db96d56Sopenharmony_ci """Truncate file to size bytes. 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci Size defaults to the current IO position as reported by tell(). Return 3967db96d56Sopenharmony_ci the new size. 3977db96d56Sopenharmony_ci """ 3987db96d56Sopenharmony_ci self._unsupported("truncate") 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci ### Flush and close ### 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_ci def flush(self): 4037db96d56Sopenharmony_ci """Flush write buffers, if applicable. 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ci This is not implemented for read-only and non-blocking streams. 4067db96d56Sopenharmony_ci """ 4077db96d56Sopenharmony_ci self._checkClosed() 4087db96d56Sopenharmony_ci # XXX Should this return the number of bytes written??? 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_ci __closed = False 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ci def close(self): 4137db96d56Sopenharmony_ci """Flush and close the IO object. 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci This method has no effect if the file is already closed. 4167db96d56Sopenharmony_ci """ 4177db96d56Sopenharmony_ci if not self.__closed: 4187db96d56Sopenharmony_ci try: 4197db96d56Sopenharmony_ci self.flush() 4207db96d56Sopenharmony_ci finally: 4217db96d56Sopenharmony_ci self.__closed = True 4227db96d56Sopenharmony_ci 4237db96d56Sopenharmony_ci def __del__(self): 4247db96d56Sopenharmony_ci """Destructor. Calls close().""" 4257db96d56Sopenharmony_ci try: 4267db96d56Sopenharmony_ci closed = self.closed 4277db96d56Sopenharmony_ci except AttributeError: 4287db96d56Sopenharmony_ci # If getting closed fails, then the object is probably 4297db96d56Sopenharmony_ci # in an unusable state, so ignore. 4307db96d56Sopenharmony_ci return 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci if closed: 4337db96d56Sopenharmony_ci return 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci if _IOBASE_EMITS_UNRAISABLE: 4367db96d56Sopenharmony_ci self.close() 4377db96d56Sopenharmony_ci else: 4387db96d56Sopenharmony_ci # The try/except block is in case this is called at program 4397db96d56Sopenharmony_ci # exit time, when it's possible that globals have already been 4407db96d56Sopenharmony_ci # deleted, and then the close() call might fail. Since 4417db96d56Sopenharmony_ci # there's nothing we can do about such failures and they annoy 4427db96d56Sopenharmony_ci # the end users, we suppress the traceback. 4437db96d56Sopenharmony_ci try: 4447db96d56Sopenharmony_ci self.close() 4457db96d56Sopenharmony_ci except: 4467db96d56Sopenharmony_ci pass 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ci ### Inquiries ### 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ci def seekable(self): 4517db96d56Sopenharmony_ci """Return a bool indicating whether object supports random access. 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci If False, seek(), tell() and truncate() will raise OSError. 4547db96d56Sopenharmony_ci This method may need to do a test seek(). 4557db96d56Sopenharmony_ci """ 4567db96d56Sopenharmony_ci return False 4577db96d56Sopenharmony_ci 4587db96d56Sopenharmony_ci def _checkSeekable(self, msg=None): 4597db96d56Sopenharmony_ci """Internal: raise UnsupportedOperation if file is not seekable 4607db96d56Sopenharmony_ci """ 4617db96d56Sopenharmony_ci if not self.seekable(): 4627db96d56Sopenharmony_ci raise UnsupportedOperation("File or stream is not seekable." 4637db96d56Sopenharmony_ci if msg is None else msg) 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_ci def readable(self): 4667db96d56Sopenharmony_ci """Return a bool indicating whether object was opened for reading. 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci If False, read() will raise OSError. 4697db96d56Sopenharmony_ci """ 4707db96d56Sopenharmony_ci return False 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci def _checkReadable(self, msg=None): 4737db96d56Sopenharmony_ci """Internal: raise UnsupportedOperation if file is not readable 4747db96d56Sopenharmony_ci """ 4757db96d56Sopenharmony_ci if not self.readable(): 4767db96d56Sopenharmony_ci raise UnsupportedOperation("File or stream is not readable." 4777db96d56Sopenharmony_ci if msg is None else msg) 4787db96d56Sopenharmony_ci 4797db96d56Sopenharmony_ci def writable(self): 4807db96d56Sopenharmony_ci """Return a bool indicating whether object was opened for writing. 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci If False, write() and truncate() will raise OSError. 4837db96d56Sopenharmony_ci """ 4847db96d56Sopenharmony_ci return False 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci def _checkWritable(self, msg=None): 4877db96d56Sopenharmony_ci """Internal: raise UnsupportedOperation if file is not writable 4887db96d56Sopenharmony_ci """ 4897db96d56Sopenharmony_ci if not self.writable(): 4907db96d56Sopenharmony_ci raise UnsupportedOperation("File or stream is not writable." 4917db96d56Sopenharmony_ci if msg is None else msg) 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci @property 4947db96d56Sopenharmony_ci def closed(self): 4957db96d56Sopenharmony_ci """closed: bool. True iff the file has been closed. 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci For backwards compatibility, this is a property, not a predicate. 4987db96d56Sopenharmony_ci """ 4997db96d56Sopenharmony_ci return self.__closed 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci def _checkClosed(self, msg=None): 5027db96d56Sopenharmony_ci """Internal: raise a ValueError if file is closed 5037db96d56Sopenharmony_ci """ 5047db96d56Sopenharmony_ci if self.closed: 5057db96d56Sopenharmony_ci raise ValueError("I/O operation on closed file." 5067db96d56Sopenharmony_ci if msg is None else msg) 5077db96d56Sopenharmony_ci 5087db96d56Sopenharmony_ci ### Context manager ### 5097db96d56Sopenharmony_ci 5107db96d56Sopenharmony_ci def __enter__(self): # That's a forward reference 5117db96d56Sopenharmony_ci """Context management protocol. Returns self (an instance of IOBase).""" 5127db96d56Sopenharmony_ci self._checkClosed() 5137db96d56Sopenharmony_ci return self 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci def __exit__(self, *args): 5167db96d56Sopenharmony_ci """Context management protocol. Calls close()""" 5177db96d56Sopenharmony_ci self.close() 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci ### Lower-level APIs ### 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci # XXX Should these be present even if unimplemented? 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci def fileno(self): 5247db96d56Sopenharmony_ci """Returns underlying file descriptor (an int) if one exists. 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci An OSError is raised if the IO object does not use a file descriptor. 5277db96d56Sopenharmony_ci """ 5287db96d56Sopenharmony_ci self._unsupported("fileno") 5297db96d56Sopenharmony_ci 5307db96d56Sopenharmony_ci def isatty(self): 5317db96d56Sopenharmony_ci """Return a bool indicating whether this is an 'interactive' stream. 5327db96d56Sopenharmony_ci 5337db96d56Sopenharmony_ci Return False if it can't be determined. 5347db96d56Sopenharmony_ci """ 5357db96d56Sopenharmony_ci self._checkClosed() 5367db96d56Sopenharmony_ci return False 5377db96d56Sopenharmony_ci 5387db96d56Sopenharmony_ci ### Readline[s] and writelines ### 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci def readline(self, size=-1): 5417db96d56Sopenharmony_ci r"""Read and return a line of bytes from the stream. 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci If size is specified, at most size bytes will be read. 5447db96d56Sopenharmony_ci Size should be an int. 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci The line terminator is always b'\n' for binary files; for text 5477db96d56Sopenharmony_ci files, the newlines argument to open can be used to select the line 5487db96d56Sopenharmony_ci terminator(s) recognized. 5497db96d56Sopenharmony_ci """ 5507db96d56Sopenharmony_ci # For backwards compatibility, a (slowish) readline(). 5517db96d56Sopenharmony_ci if hasattr(self, "peek"): 5527db96d56Sopenharmony_ci def nreadahead(): 5537db96d56Sopenharmony_ci readahead = self.peek(1) 5547db96d56Sopenharmony_ci if not readahead: 5557db96d56Sopenharmony_ci return 1 5567db96d56Sopenharmony_ci n = (readahead.find(b"\n") + 1) or len(readahead) 5577db96d56Sopenharmony_ci if size >= 0: 5587db96d56Sopenharmony_ci n = min(n, size) 5597db96d56Sopenharmony_ci return n 5607db96d56Sopenharmony_ci else: 5617db96d56Sopenharmony_ci def nreadahead(): 5627db96d56Sopenharmony_ci return 1 5637db96d56Sopenharmony_ci if size is None: 5647db96d56Sopenharmony_ci size = -1 5657db96d56Sopenharmony_ci else: 5667db96d56Sopenharmony_ci try: 5677db96d56Sopenharmony_ci size_index = size.__index__ 5687db96d56Sopenharmony_ci except AttributeError: 5697db96d56Sopenharmony_ci raise TypeError(f"{size!r} is not an integer") 5707db96d56Sopenharmony_ci else: 5717db96d56Sopenharmony_ci size = size_index() 5727db96d56Sopenharmony_ci res = bytearray() 5737db96d56Sopenharmony_ci while size < 0 or len(res) < size: 5747db96d56Sopenharmony_ci b = self.read(nreadahead()) 5757db96d56Sopenharmony_ci if not b: 5767db96d56Sopenharmony_ci break 5777db96d56Sopenharmony_ci res += b 5787db96d56Sopenharmony_ci if res.endswith(b"\n"): 5797db96d56Sopenharmony_ci break 5807db96d56Sopenharmony_ci return bytes(res) 5817db96d56Sopenharmony_ci 5827db96d56Sopenharmony_ci def __iter__(self): 5837db96d56Sopenharmony_ci self._checkClosed() 5847db96d56Sopenharmony_ci return self 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci def __next__(self): 5877db96d56Sopenharmony_ci line = self.readline() 5887db96d56Sopenharmony_ci if not line: 5897db96d56Sopenharmony_ci raise StopIteration 5907db96d56Sopenharmony_ci return line 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci def readlines(self, hint=None): 5937db96d56Sopenharmony_ci """Return a list of lines from the stream. 5947db96d56Sopenharmony_ci 5957db96d56Sopenharmony_ci hint can be specified to control the number of lines read: no more 5967db96d56Sopenharmony_ci lines will be read if the total size (in bytes/characters) of all 5977db96d56Sopenharmony_ci lines so far exceeds hint. 5987db96d56Sopenharmony_ci """ 5997db96d56Sopenharmony_ci if hint is None or hint <= 0: 6007db96d56Sopenharmony_ci return list(self) 6017db96d56Sopenharmony_ci n = 0 6027db96d56Sopenharmony_ci lines = [] 6037db96d56Sopenharmony_ci for line in self: 6047db96d56Sopenharmony_ci lines.append(line) 6057db96d56Sopenharmony_ci n += len(line) 6067db96d56Sopenharmony_ci if n >= hint: 6077db96d56Sopenharmony_ci break 6087db96d56Sopenharmony_ci return lines 6097db96d56Sopenharmony_ci 6107db96d56Sopenharmony_ci def writelines(self, lines): 6117db96d56Sopenharmony_ci """Write a list of lines to the stream. 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci Line separators are not added, so it is usual for each of the lines 6147db96d56Sopenharmony_ci provided to have a line separator at the end. 6157db96d56Sopenharmony_ci """ 6167db96d56Sopenharmony_ci self._checkClosed() 6177db96d56Sopenharmony_ci for line in lines: 6187db96d56Sopenharmony_ci self.write(line) 6197db96d56Sopenharmony_ci 6207db96d56Sopenharmony_ciio.IOBase.register(IOBase) 6217db96d56Sopenharmony_ci 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_ciclass RawIOBase(IOBase): 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci """Base class for raw binary I/O.""" 6267db96d56Sopenharmony_ci 6277db96d56Sopenharmony_ci # The read() method is implemented by calling readinto(); derived 6287db96d56Sopenharmony_ci # classes that want to support read() only need to implement 6297db96d56Sopenharmony_ci # readinto() as a primitive operation. In general, readinto() can be 6307db96d56Sopenharmony_ci # more efficient than read(). 6317db96d56Sopenharmony_ci 6327db96d56Sopenharmony_ci # (It would be tempting to also provide an implementation of 6337db96d56Sopenharmony_ci # readinto() in terms of read(), in case the latter is a more suitable 6347db96d56Sopenharmony_ci # primitive operation, but that would lead to nasty recursion in case 6357db96d56Sopenharmony_ci # a subclass doesn't implement either.) 6367db96d56Sopenharmony_ci 6377db96d56Sopenharmony_ci def read(self, size=-1): 6387db96d56Sopenharmony_ci """Read and return up to size bytes, where size is an int. 6397db96d56Sopenharmony_ci 6407db96d56Sopenharmony_ci Returns an empty bytes object on EOF, or None if the object is 6417db96d56Sopenharmony_ci set not to block and has no data to read. 6427db96d56Sopenharmony_ci """ 6437db96d56Sopenharmony_ci if size is None: 6447db96d56Sopenharmony_ci size = -1 6457db96d56Sopenharmony_ci if size < 0: 6467db96d56Sopenharmony_ci return self.readall() 6477db96d56Sopenharmony_ci b = bytearray(size.__index__()) 6487db96d56Sopenharmony_ci n = self.readinto(b) 6497db96d56Sopenharmony_ci if n is None: 6507db96d56Sopenharmony_ci return None 6517db96d56Sopenharmony_ci del b[n:] 6527db96d56Sopenharmony_ci return bytes(b) 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci def readall(self): 6557db96d56Sopenharmony_ci """Read until EOF, using multiple read() call.""" 6567db96d56Sopenharmony_ci res = bytearray() 6577db96d56Sopenharmony_ci while True: 6587db96d56Sopenharmony_ci data = self.read(DEFAULT_BUFFER_SIZE) 6597db96d56Sopenharmony_ci if not data: 6607db96d56Sopenharmony_ci break 6617db96d56Sopenharmony_ci res += data 6627db96d56Sopenharmony_ci if res: 6637db96d56Sopenharmony_ci return bytes(res) 6647db96d56Sopenharmony_ci else: 6657db96d56Sopenharmony_ci # b'' or None 6667db96d56Sopenharmony_ci return data 6677db96d56Sopenharmony_ci 6687db96d56Sopenharmony_ci def readinto(self, b): 6697db96d56Sopenharmony_ci """Read bytes into a pre-allocated bytes-like object b. 6707db96d56Sopenharmony_ci 6717db96d56Sopenharmony_ci Returns an int representing the number of bytes read (0 for EOF), or 6727db96d56Sopenharmony_ci None if the object is set not to block and has no data to read. 6737db96d56Sopenharmony_ci """ 6747db96d56Sopenharmony_ci self._unsupported("readinto") 6757db96d56Sopenharmony_ci 6767db96d56Sopenharmony_ci def write(self, b): 6777db96d56Sopenharmony_ci """Write the given buffer to the IO stream. 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ci Returns the number of bytes written, which may be less than the 6807db96d56Sopenharmony_ci length of b in bytes. 6817db96d56Sopenharmony_ci """ 6827db96d56Sopenharmony_ci self._unsupported("write") 6837db96d56Sopenharmony_ci 6847db96d56Sopenharmony_ciio.RawIOBase.register(RawIOBase) 6857db96d56Sopenharmony_cifrom _io import FileIO 6867db96d56Sopenharmony_ciRawIOBase.register(FileIO) 6877db96d56Sopenharmony_ci 6887db96d56Sopenharmony_ci 6897db96d56Sopenharmony_ciclass BufferedIOBase(IOBase): 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ci """Base class for buffered IO objects. 6927db96d56Sopenharmony_ci 6937db96d56Sopenharmony_ci The main difference with RawIOBase is that the read() method 6947db96d56Sopenharmony_ci supports omitting the size argument, and does not have a default 6957db96d56Sopenharmony_ci implementation that defers to readinto(). 6967db96d56Sopenharmony_ci 6977db96d56Sopenharmony_ci In addition, read(), readinto() and write() may raise 6987db96d56Sopenharmony_ci BlockingIOError if the underlying raw stream is in non-blocking 6997db96d56Sopenharmony_ci mode and not ready; unlike their raw counterparts, they will never 7007db96d56Sopenharmony_ci return None. 7017db96d56Sopenharmony_ci 7027db96d56Sopenharmony_ci A typical implementation should not inherit from a RawIOBase 7037db96d56Sopenharmony_ci implementation, but wrap one. 7047db96d56Sopenharmony_ci """ 7057db96d56Sopenharmony_ci 7067db96d56Sopenharmony_ci def read(self, size=-1): 7077db96d56Sopenharmony_ci """Read and return up to size bytes, where size is an int. 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci If the argument is omitted, None, or negative, reads and 7107db96d56Sopenharmony_ci returns all data until EOF. 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci If the argument is positive, and the underlying raw stream is 7137db96d56Sopenharmony_ci not 'interactive', multiple raw reads may be issued to satisfy 7147db96d56Sopenharmony_ci the byte count (unless EOF is reached first). But for 7157db96d56Sopenharmony_ci interactive raw streams (XXX and for pipes?), at most one raw 7167db96d56Sopenharmony_ci read will be issued, and a short result does not imply that 7177db96d56Sopenharmony_ci EOF is imminent. 7187db96d56Sopenharmony_ci 7197db96d56Sopenharmony_ci Returns an empty bytes array on EOF. 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_ci Raises BlockingIOError if the underlying raw stream has no 7227db96d56Sopenharmony_ci data at the moment. 7237db96d56Sopenharmony_ci """ 7247db96d56Sopenharmony_ci self._unsupported("read") 7257db96d56Sopenharmony_ci 7267db96d56Sopenharmony_ci def read1(self, size=-1): 7277db96d56Sopenharmony_ci """Read up to size bytes with at most one read() system call, 7287db96d56Sopenharmony_ci where size is an int. 7297db96d56Sopenharmony_ci """ 7307db96d56Sopenharmony_ci self._unsupported("read1") 7317db96d56Sopenharmony_ci 7327db96d56Sopenharmony_ci def readinto(self, b): 7337db96d56Sopenharmony_ci """Read bytes into a pre-allocated bytes-like object b. 7347db96d56Sopenharmony_ci 7357db96d56Sopenharmony_ci Like read(), this may issue multiple reads to the underlying raw 7367db96d56Sopenharmony_ci stream, unless the latter is 'interactive'. 7377db96d56Sopenharmony_ci 7387db96d56Sopenharmony_ci Returns an int representing the number of bytes read (0 for EOF). 7397db96d56Sopenharmony_ci 7407db96d56Sopenharmony_ci Raises BlockingIOError if the underlying raw stream has no 7417db96d56Sopenharmony_ci data at the moment. 7427db96d56Sopenharmony_ci """ 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_ci return self._readinto(b, read1=False) 7457db96d56Sopenharmony_ci 7467db96d56Sopenharmony_ci def readinto1(self, b): 7477db96d56Sopenharmony_ci """Read bytes into buffer *b*, using at most one system call 7487db96d56Sopenharmony_ci 7497db96d56Sopenharmony_ci Returns an int representing the number of bytes read (0 for EOF). 7507db96d56Sopenharmony_ci 7517db96d56Sopenharmony_ci Raises BlockingIOError if the underlying raw stream has no 7527db96d56Sopenharmony_ci data at the moment. 7537db96d56Sopenharmony_ci """ 7547db96d56Sopenharmony_ci 7557db96d56Sopenharmony_ci return self._readinto(b, read1=True) 7567db96d56Sopenharmony_ci 7577db96d56Sopenharmony_ci def _readinto(self, b, read1): 7587db96d56Sopenharmony_ci if not isinstance(b, memoryview): 7597db96d56Sopenharmony_ci b = memoryview(b) 7607db96d56Sopenharmony_ci b = b.cast('B') 7617db96d56Sopenharmony_ci 7627db96d56Sopenharmony_ci if read1: 7637db96d56Sopenharmony_ci data = self.read1(len(b)) 7647db96d56Sopenharmony_ci else: 7657db96d56Sopenharmony_ci data = self.read(len(b)) 7667db96d56Sopenharmony_ci n = len(data) 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci b[:n] = data 7697db96d56Sopenharmony_ci 7707db96d56Sopenharmony_ci return n 7717db96d56Sopenharmony_ci 7727db96d56Sopenharmony_ci def write(self, b): 7737db96d56Sopenharmony_ci """Write the given bytes buffer to the IO stream. 7747db96d56Sopenharmony_ci 7757db96d56Sopenharmony_ci Return the number of bytes written, which is always the length of b 7767db96d56Sopenharmony_ci in bytes. 7777db96d56Sopenharmony_ci 7787db96d56Sopenharmony_ci Raises BlockingIOError if the buffer is full and the 7797db96d56Sopenharmony_ci underlying raw stream cannot accept more data at the moment. 7807db96d56Sopenharmony_ci """ 7817db96d56Sopenharmony_ci self._unsupported("write") 7827db96d56Sopenharmony_ci 7837db96d56Sopenharmony_ci def detach(self): 7847db96d56Sopenharmony_ci """ 7857db96d56Sopenharmony_ci Separate the underlying raw stream from the buffer and return it. 7867db96d56Sopenharmony_ci 7877db96d56Sopenharmony_ci After the raw stream has been detached, the buffer is in an unusable 7887db96d56Sopenharmony_ci state. 7897db96d56Sopenharmony_ci """ 7907db96d56Sopenharmony_ci self._unsupported("detach") 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ciio.BufferedIOBase.register(BufferedIOBase) 7937db96d56Sopenharmony_ci 7947db96d56Sopenharmony_ci 7957db96d56Sopenharmony_ciclass _BufferedIOMixin(BufferedIOBase): 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci """A mixin implementation of BufferedIOBase with an underlying raw stream. 7987db96d56Sopenharmony_ci 7997db96d56Sopenharmony_ci This passes most requests on to the underlying raw stream. It 8007db96d56Sopenharmony_ci does *not* provide implementations of read(), readinto() or 8017db96d56Sopenharmony_ci write(). 8027db96d56Sopenharmony_ci """ 8037db96d56Sopenharmony_ci 8047db96d56Sopenharmony_ci def __init__(self, raw): 8057db96d56Sopenharmony_ci self._raw = raw 8067db96d56Sopenharmony_ci 8077db96d56Sopenharmony_ci ### Positioning ### 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_ci def seek(self, pos, whence=0): 8107db96d56Sopenharmony_ci new_position = self.raw.seek(pos, whence) 8117db96d56Sopenharmony_ci if new_position < 0: 8127db96d56Sopenharmony_ci raise OSError("seek() returned an invalid position") 8137db96d56Sopenharmony_ci return new_position 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci def tell(self): 8167db96d56Sopenharmony_ci pos = self.raw.tell() 8177db96d56Sopenharmony_ci if pos < 0: 8187db96d56Sopenharmony_ci raise OSError("tell() returned an invalid position") 8197db96d56Sopenharmony_ci return pos 8207db96d56Sopenharmony_ci 8217db96d56Sopenharmony_ci def truncate(self, pos=None): 8227db96d56Sopenharmony_ci self._checkClosed() 8237db96d56Sopenharmony_ci self._checkWritable() 8247db96d56Sopenharmony_ci 8257db96d56Sopenharmony_ci # Flush the stream. We're mixing buffered I/O with lower-level I/O, 8267db96d56Sopenharmony_ci # and a flush may be necessary to synch both views of the current 8277db96d56Sopenharmony_ci # file state. 8287db96d56Sopenharmony_ci self.flush() 8297db96d56Sopenharmony_ci 8307db96d56Sopenharmony_ci if pos is None: 8317db96d56Sopenharmony_ci pos = self.tell() 8327db96d56Sopenharmony_ci # XXX: Should seek() be used, instead of passing the position 8337db96d56Sopenharmony_ci # XXX directly to truncate? 8347db96d56Sopenharmony_ci return self.raw.truncate(pos) 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci ### Flush and close ### 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ci def flush(self): 8397db96d56Sopenharmony_ci if self.closed: 8407db96d56Sopenharmony_ci raise ValueError("flush on closed file") 8417db96d56Sopenharmony_ci self.raw.flush() 8427db96d56Sopenharmony_ci 8437db96d56Sopenharmony_ci def close(self): 8447db96d56Sopenharmony_ci if self.raw is not None and not self.closed: 8457db96d56Sopenharmony_ci try: 8467db96d56Sopenharmony_ci # may raise BlockingIOError or BrokenPipeError etc 8477db96d56Sopenharmony_ci self.flush() 8487db96d56Sopenharmony_ci finally: 8497db96d56Sopenharmony_ci self.raw.close() 8507db96d56Sopenharmony_ci 8517db96d56Sopenharmony_ci def detach(self): 8527db96d56Sopenharmony_ci if self.raw is None: 8537db96d56Sopenharmony_ci raise ValueError("raw stream already detached") 8547db96d56Sopenharmony_ci self.flush() 8557db96d56Sopenharmony_ci raw = self._raw 8567db96d56Sopenharmony_ci self._raw = None 8577db96d56Sopenharmony_ci return raw 8587db96d56Sopenharmony_ci 8597db96d56Sopenharmony_ci ### Inquiries ### 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci def seekable(self): 8627db96d56Sopenharmony_ci return self.raw.seekable() 8637db96d56Sopenharmony_ci 8647db96d56Sopenharmony_ci @property 8657db96d56Sopenharmony_ci def raw(self): 8667db96d56Sopenharmony_ci return self._raw 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci @property 8697db96d56Sopenharmony_ci def closed(self): 8707db96d56Sopenharmony_ci return self.raw.closed 8717db96d56Sopenharmony_ci 8727db96d56Sopenharmony_ci @property 8737db96d56Sopenharmony_ci def name(self): 8747db96d56Sopenharmony_ci return self.raw.name 8757db96d56Sopenharmony_ci 8767db96d56Sopenharmony_ci @property 8777db96d56Sopenharmony_ci def mode(self): 8787db96d56Sopenharmony_ci return self.raw.mode 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_ci def __getstate__(self): 8817db96d56Sopenharmony_ci raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") 8827db96d56Sopenharmony_ci 8837db96d56Sopenharmony_ci def __repr__(self): 8847db96d56Sopenharmony_ci modname = self.__class__.__module__ 8857db96d56Sopenharmony_ci clsname = self.__class__.__qualname__ 8867db96d56Sopenharmony_ci try: 8877db96d56Sopenharmony_ci name = self.name 8887db96d56Sopenharmony_ci except AttributeError: 8897db96d56Sopenharmony_ci return "<{}.{}>".format(modname, clsname) 8907db96d56Sopenharmony_ci else: 8917db96d56Sopenharmony_ci return "<{}.{} name={!r}>".format(modname, clsname, name) 8927db96d56Sopenharmony_ci 8937db96d56Sopenharmony_ci ### Lower-level APIs ### 8947db96d56Sopenharmony_ci 8957db96d56Sopenharmony_ci def fileno(self): 8967db96d56Sopenharmony_ci return self.raw.fileno() 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci def isatty(self): 8997db96d56Sopenharmony_ci return self.raw.isatty() 9007db96d56Sopenharmony_ci 9017db96d56Sopenharmony_ci 9027db96d56Sopenharmony_ciclass BytesIO(BufferedIOBase): 9037db96d56Sopenharmony_ci 9047db96d56Sopenharmony_ci """Buffered I/O implementation using an in-memory bytes buffer.""" 9057db96d56Sopenharmony_ci 9067db96d56Sopenharmony_ci # Initialize _buffer as soon as possible since it's used by __del__() 9077db96d56Sopenharmony_ci # which calls close() 9087db96d56Sopenharmony_ci _buffer = None 9097db96d56Sopenharmony_ci 9107db96d56Sopenharmony_ci def __init__(self, initial_bytes=None): 9117db96d56Sopenharmony_ci buf = bytearray() 9127db96d56Sopenharmony_ci if initial_bytes is not None: 9137db96d56Sopenharmony_ci buf += initial_bytes 9147db96d56Sopenharmony_ci self._buffer = buf 9157db96d56Sopenharmony_ci self._pos = 0 9167db96d56Sopenharmony_ci 9177db96d56Sopenharmony_ci def __getstate__(self): 9187db96d56Sopenharmony_ci if self.closed: 9197db96d56Sopenharmony_ci raise ValueError("__getstate__ on closed file") 9207db96d56Sopenharmony_ci return self.__dict__.copy() 9217db96d56Sopenharmony_ci 9227db96d56Sopenharmony_ci def getvalue(self): 9237db96d56Sopenharmony_ci """Return the bytes value (contents) of the buffer 9247db96d56Sopenharmony_ci """ 9257db96d56Sopenharmony_ci if self.closed: 9267db96d56Sopenharmony_ci raise ValueError("getvalue on closed file") 9277db96d56Sopenharmony_ci return bytes(self._buffer) 9287db96d56Sopenharmony_ci 9297db96d56Sopenharmony_ci def getbuffer(self): 9307db96d56Sopenharmony_ci """Return a readable and writable view of the buffer. 9317db96d56Sopenharmony_ci """ 9327db96d56Sopenharmony_ci if self.closed: 9337db96d56Sopenharmony_ci raise ValueError("getbuffer on closed file") 9347db96d56Sopenharmony_ci return memoryview(self._buffer) 9357db96d56Sopenharmony_ci 9367db96d56Sopenharmony_ci def close(self): 9377db96d56Sopenharmony_ci if self._buffer is not None: 9387db96d56Sopenharmony_ci self._buffer.clear() 9397db96d56Sopenharmony_ci super().close() 9407db96d56Sopenharmony_ci 9417db96d56Sopenharmony_ci def read(self, size=-1): 9427db96d56Sopenharmony_ci if self.closed: 9437db96d56Sopenharmony_ci raise ValueError("read from closed file") 9447db96d56Sopenharmony_ci if size is None: 9457db96d56Sopenharmony_ci size = -1 9467db96d56Sopenharmony_ci else: 9477db96d56Sopenharmony_ci try: 9487db96d56Sopenharmony_ci size_index = size.__index__ 9497db96d56Sopenharmony_ci except AttributeError: 9507db96d56Sopenharmony_ci raise TypeError(f"{size!r} is not an integer") 9517db96d56Sopenharmony_ci else: 9527db96d56Sopenharmony_ci size = size_index() 9537db96d56Sopenharmony_ci if size < 0: 9547db96d56Sopenharmony_ci size = len(self._buffer) 9557db96d56Sopenharmony_ci if len(self._buffer) <= self._pos: 9567db96d56Sopenharmony_ci return b"" 9577db96d56Sopenharmony_ci newpos = min(len(self._buffer), self._pos + size) 9587db96d56Sopenharmony_ci b = self._buffer[self._pos : newpos] 9597db96d56Sopenharmony_ci self._pos = newpos 9607db96d56Sopenharmony_ci return bytes(b) 9617db96d56Sopenharmony_ci 9627db96d56Sopenharmony_ci def read1(self, size=-1): 9637db96d56Sopenharmony_ci """This is the same as read. 9647db96d56Sopenharmony_ci """ 9657db96d56Sopenharmony_ci return self.read(size) 9667db96d56Sopenharmony_ci 9677db96d56Sopenharmony_ci def write(self, b): 9687db96d56Sopenharmony_ci if self.closed: 9697db96d56Sopenharmony_ci raise ValueError("write to closed file") 9707db96d56Sopenharmony_ci if isinstance(b, str): 9717db96d56Sopenharmony_ci raise TypeError("can't write str to binary stream") 9727db96d56Sopenharmony_ci with memoryview(b) as view: 9737db96d56Sopenharmony_ci n = view.nbytes # Size of any bytes-like object 9747db96d56Sopenharmony_ci if n == 0: 9757db96d56Sopenharmony_ci return 0 9767db96d56Sopenharmony_ci pos = self._pos 9777db96d56Sopenharmony_ci if pos > len(self._buffer): 9787db96d56Sopenharmony_ci # Inserts null bytes between the current end of the file 9797db96d56Sopenharmony_ci # and the new write position. 9807db96d56Sopenharmony_ci padding = b'\x00' * (pos - len(self._buffer)) 9817db96d56Sopenharmony_ci self._buffer += padding 9827db96d56Sopenharmony_ci self._buffer[pos:pos + n] = b 9837db96d56Sopenharmony_ci self._pos += n 9847db96d56Sopenharmony_ci return n 9857db96d56Sopenharmony_ci 9867db96d56Sopenharmony_ci def seek(self, pos, whence=0): 9877db96d56Sopenharmony_ci if self.closed: 9887db96d56Sopenharmony_ci raise ValueError("seek on closed file") 9897db96d56Sopenharmony_ci try: 9907db96d56Sopenharmony_ci pos_index = pos.__index__ 9917db96d56Sopenharmony_ci except AttributeError: 9927db96d56Sopenharmony_ci raise TypeError(f"{pos!r} is not an integer") 9937db96d56Sopenharmony_ci else: 9947db96d56Sopenharmony_ci pos = pos_index() 9957db96d56Sopenharmony_ci if whence == 0: 9967db96d56Sopenharmony_ci if pos < 0: 9977db96d56Sopenharmony_ci raise ValueError("negative seek position %r" % (pos,)) 9987db96d56Sopenharmony_ci self._pos = pos 9997db96d56Sopenharmony_ci elif whence == 1: 10007db96d56Sopenharmony_ci self._pos = max(0, self._pos + pos) 10017db96d56Sopenharmony_ci elif whence == 2: 10027db96d56Sopenharmony_ci self._pos = max(0, len(self._buffer) + pos) 10037db96d56Sopenharmony_ci else: 10047db96d56Sopenharmony_ci raise ValueError("unsupported whence value") 10057db96d56Sopenharmony_ci return self._pos 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci def tell(self): 10087db96d56Sopenharmony_ci if self.closed: 10097db96d56Sopenharmony_ci raise ValueError("tell on closed file") 10107db96d56Sopenharmony_ci return self._pos 10117db96d56Sopenharmony_ci 10127db96d56Sopenharmony_ci def truncate(self, pos=None): 10137db96d56Sopenharmony_ci if self.closed: 10147db96d56Sopenharmony_ci raise ValueError("truncate on closed file") 10157db96d56Sopenharmony_ci if pos is None: 10167db96d56Sopenharmony_ci pos = self._pos 10177db96d56Sopenharmony_ci else: 10187db96d56Sopenharmony_ci try: 10197db96d56Sopenharmony_ci pos_index = pos.__index__ 10207db96d56Sopenharmony_ci except AttributeError: 10217db96d56Sopenharmony_ci raise TypeError(f"{pos!r} is not an integer") 10227db96d56Sopenharmony_ci else: 10237db96d56Sopenharmony_ci pos = pos_index() 10247db96d56Sopenharmony_ci if pos < 0: 10257db96d56Sopenharmony_ci raise ValueError("negative truncate position %r" % (pos,)) 10267db96d56Sopenharmony_ci del self._buffer[pos:] 10277db96d56Sopenharmony_ci return pos 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ci def readable(self): 10307db96d56Sopenharmony_ci if self.closed: 10317db96d56Sopenharmony_ci raise ValueError("I/O operation on closed file.") 10327db96d56Sopenharmony_ci return True 10337db96d56Sopenharmony_ci 10347db96d56Sopenharmony_ci def writable(self): 10357db96d56Sopenharmony_ci if self.closed: 10367db96d56Sopenharmony_ci raise ValueError("I/O operation on closed file.") 10377db96d56Sopenharmony_ci return True 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci def seekable(self): 10407db96d56Sopenharmony_ci if self.closed: 10417db96d56Sopenharmony_ci raise ValueError("I/O operation on closed file.") 10427db96d56Sopenharmony_ci return True 10437db96d56Sopenharmony_ci 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ciclass BufferedReader(_BufferedIOMixin): 10467db96d56Sopenharmony_ci 10477db96d56Sopenharmony_ci """BufferedReader(raw[, buffer_size]) 10487db96d56Sopenharmony_ci 10497db96d56Sopenharmony_ci A buffer for a readable, sequential BaseRawIO object. 10507db96d56Sopenharmony_ci 10517db96d56Sopenharmony_ci The constructor creates a BufferedReader for the given readable raw 10527db96d56Sopenharmony_ci stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE 10537db96d56Sopenharmony_ci is used. 10547db96d56Sopenharmony_ci """ 10557db96d56Sopenharmony_ci 10567db96d56Sopenharmony_ci def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 10577db96d56Sopenharmony_ci """Create a new buffered reader using the given readable raw IO object. 10587db96d56Sopenharmony_ci """ 10597db96d56Sopenharmony_ci if not raw.readable(): 10607db96d56Sopenharmony_ci raise OSError('"raw" argument must be readable.') 10617db96d56Sopenharmony_ci 10627db96d56Sopenharmony_ci _BufferedIOMixin.__init__(self, raw) 10637db96d56Sopenharmony_ci if buffer_size <= 0: 10647db96d56Sopenharmony_ci raise ValueError("invalid buffer size") 10657db96d56Sopenharmony_ci self.buffer_size = buffer_size 10667db96d56Sopenharmony_ci self._reset_read_buf() 10677db96d56Sopenharmony_ci self._read_lock = Lock() 10687db96d56Sopenharmony_ci 10697db96d56Sopenharmony_ci def readable(self): 10707db96d56Sopenharmony_ci return self.raw.readable() 10717db96d56Sopenharmony_ci 10727db96d56Sopenharmony_ci def _reset_read_buf(self): 10737db96d56Sopenharmony_ci self._read_buf = b"" 10747db96d56Sopenharmony_ci self._read_pos = 0 10757db96d56Sopenharmony_ci 10767db96d56Sopenharmony_ci def read(self, size=None): 10777db96d56Sopenharmony_ci """Read size bytes. 10787db96d56Sopenharmony_ci 10797db96d56Sopenharmony_ci Returns exactly size bytes of data unless the underlying raw IO 10807db96d56Sopenharmony_ci stream reaches EOF or if the call would block in non-blocking 10817db96d56Sopenharmony_ci mode. If size is negative, read until EOF or until read() would 10827db96d56Sopenharmony_ci block. 10837db96d56Sopenharmony_ci """ 10847db96d56Sopenharmony_ci if size is not None and size < -1: 10857db96d56Sopenharmony_ci raise ValueError("invalid number of bytes to read") 10867db96d56Sopenharmony_ci with self._read_lock: 10877db96d56Sopenharmony_ci return self._read_unlocked(size) 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_ci def _read_unlocked(self, n=None): 10907db96d56Sopenharmony_ci nodata_val = b"" 10917db96d56Sopenharmony_ci empty_values = (b"", None) 10927db96d56Sopenharmony_ci buf = self._read_buf 10937db96d56Sopenharmony_ci pos = self._read_pos 10947db96d56Sopenharmony_ci 10957db96d56Sopenharmony_ci # Special case for when the number of bytes to read is unspecified. 10967db96d56Sopenharmony_ci if n is None or n == -1: 10977db96d56Sopenharmony_ci self._reset_read_buf() 10987db96d56Sopenharmony_ci if hasattr(self.raw, 'readall'): 10997db96d56Sopenharmony_ci chunk = self.raw.readall() 11007db96d56Sopenharmony_ci if chunk is None: 11017db96d56Sopenharmony_ci return buf[pos:] or None 11027db96d56Sopenharmony_ci else: 11037db96d56Sopenharmony_ci return buf[pos:] + chunk 11047db96d56Sopenharmony_ci chunks = [buf[pos:]] # Strip the consumed bytes. 11057db96d56Sopenharmony_ci current_size = 0 11067db96d56Sopenharmony_ci while True: 11077db96d56Sopenharmony_ci # Read until EOF or until read() would block. 11087db96d56Sopenharmony_ci chunk = self.raw.read() 11097db96d56Sopenharmony_ci if chunk in empty_values: 11107db96d56Sopenharmony_ci nodata_val = chunk 11117db96d56Sopenharmony_ci break 11127db96d56Sopenharmony_ci current_size += len(chunk) 11137db96d56Sopenharmony_ci chunks.append(chunk) 11147db96d56Sopenharmony_ci return b"".join(chunks) or nodata_val 11157db96d56Sopenharmony_ci 11167db96d56Sopenharmony_ci # The number of bytes to read is specified, return at most n bytes. 11177db96d56Sopenharmony_ci avail = len(buf) - pos # Length of the available buffered data. 11187db96d56Sopenharmony_ci if n <= avail: 11197db96d56Sopenharmony_ci # Fast path: the data to read is fully buffered. 11207db96d56Sopenharmony_ci self._read_pos += n 11217db96d56Sopenharmony_ci return buf[pos:pos+n] 11227db96d56Sopenharmony_ci # Slow path: read from the stream until enough bytes are read, 11237db96d56Sopenharmony_ci # or until an EOF occurs or until read() would block. 11247db96d56Sopenharmony_ci chunks = [buf[pos:]] 11257db96d56Sopenharmony_ci wanted = max(self.buffer_size, n) 11267db96d56Sopenharmony_ci while avail < n: 11277db96d56Sopenharmony_ci chunk = self.raw.read(wanted) 11287db96d56Sopenharmony_ci if chunk in empty_values: 11297db96d56Sopenharmony_ci nodata_val = chunk 11307db96d56Sopenharmony_ci break 11317db96d56Sopenharmony_ci avail += len(chunk) 11327db96d56Sopenharmony_ci chunks.append(chunk) 11337db96d56Sopenharmony_ci # n is more than avail only when an EOF occurred or when 11347db96d56Sopenharmony_ci # read() would have blocked. 11357db96d56Sopenharmony_ci n = min(n, avail) 11367db96d56Sopenharmony_ci out = b"".join(chunks) 11377db96d56Sopenharmony_ci self._read_buf = out[n:] # Save the extra data in the buffer. 11387db96d56Sopenharmony_ci self._read_pos = 0 11397db96d56Sopenharmony_ci return out[:n] if out else nodata_val 11407db96d56Sopenharmony_ci 11417db96d56Sopenharmony_ci def peek(self, size=0): 11427db96d56Sopenharmony_ci """Returns buffered bytes without advancing the position. 11437db96d56Sopenharmony_ci 11447db96d56Sopenharmony_ci The argument indicates a desired minimal number of bytes; we 11457db96d56Sopenharmony_ci do at most one raw read to satisfy it. We never return more 11467db96d56Sopenharmony_ci than self.buffer_size. 11477db96d56Sopenharmony_ci """ 11487db96d56Sopenharmony_ci with self._read_lock: 11497db96d56Sopenharmony_ci return self._peek_unlocked(size) 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_ci def _peek_unlocked(self, n=0): 11527db96d56Sopenharmony_ci want = min(n, self.buffer_size) 11537db96d56Sopenharmony_ci have = len(self._read_buf) - self._read_pos 11547db96d56Sopenharmony_ci if have < want or have <= 0: 11557db96d56Sopenharmony_ci to_read = self.buffer_size - have 11567db96d56Sopenharmony_ci current = self.raw.read(to_read) 11577db96d56Sopenharmony_ci if current: 11587db96d56Sopenharmony_ci self._read_buf = self._read_buf[self._read_pos:] + current 11597db96d56Sopenharmony_ci self._read_pos = 0 11607db96d56Sopenharmony_ci return self._read_buf[self._read_pos:] 11617db96d56Sopenharmony_ci 11627db96d56Sopenharmony_ci def read1(self, size=-1): 11637db96d56Sopenharmony_ci """Reads up to size bytes, with at most one read() system call.""" 11647db96d56Sopenharmony_ci # Returns up to size bytes. If at least one byte is buffered, we 11657db96d56Sopenharmony_ci # only return buffered bytes. Otherwise, we do one raw read. 11667db96d56Sopenharmony_ci if size < 0: 11677db96d56Sopenharmony_ci size = self.buffer_size 11687db96d56Sopenharmony_ci if size == 0: 11697db96d56Sopenharmony_ci return b"" 11707db96d56Sopenharmony_ci with self._read_lock: 11717db96d56Sopenharmony_ci self._peek_unlocked(1) 11727db96d56Sopenharmony_ci return self._read_unlocked( 11737db96d56Sopenharmony_ci min(size, len(self._read_buf) - self._read_pos)) 11747db96d56Sopenharmony_ci 11757db96d56Sopenharmony_ci # Implementing readinto() and readinto1() is not strictly necessary (we 11767db96d56Sopenharmony_ci # could rely on the base class that provides an implementation in terms of 11777db96d56Sopenharmony_ci # read() and read1()). We do it anyway to keep the _pyio implementation 11787db96d56Sopenharmony_ci # similar to the io implementation (which implements the methods for 11797db96d56Sopenharmony_ci # performance reasons). 11807db96d56Sopenharmony_ci def _readinto(self, buf, read1): 11817db96d56Sopenharmony_ci """Read data into *buf* with at most one system call.""" 11827db96d56Sopenharmony_ci 11837db96d56Sopenharmony_ci # Need to create a memoryview object of type 'b', otherwise 11847db96d56Sopenharmony_ci # we may not be able to assign bytes to it, and slicing it 11857db96d56Sopenharmony_ci # would create a new object. 11867db96d56Sopenharmony_ci if not isinstance(buf, memoryview): 11877db96d56Sopenharmony_ci buf = memoryview(buf) 11887db96d56Sopenharmony_ci if buf.nbytes == 0: 11897db96d56Sopenharmony_ci return 0 11907db96d56Sopenharmony_ci buf = buf.cast('B') 11917db96d56Sopenharmony_ci 11927db96d56Sopenharmony_ci written = 0 11937db96d56Sopenharmony_ci with self._read_lock: 11947db96d56Sopenharmony_ci while written < len(buf): 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci # First try to read from internal buffer 11977db96d56Sopenharmony_ci avail = min(len(self._read_buf) - self._read_pos, len(buf)) 11987db96d56Sopenharmony_ci if avail: 11997db96d56Sopenharmony_ci buf[written:written+avail] = \ 12007db96d56Sopenharmony_ci self._read_buf[self._read_pos:self._read_pos+avail] 12017db96d56Sopenharmony_ci self._read_pos += avail 12027db96d56Sopenharmony_ci written += avail 12037db96d56Sopenharmony_ci if written == len(buf): 12047db96d56Sopenharmony_ci break 12057db96d56Sopenharmony_ci 12067db96d56Sopenharmony_ci # If remaining space in callers buffer is larger than 12077db96d56Sopenharmony_ci # internal buffer, read directly into callers buffer 12087db96d56Sopenharmony_ci if len(buf) - written > self.buffer_size: 12097db96d56Sopenharmony_ci n = self.raw.readinto(buf[written:]) 12107db96d56Sopenharmony_ci if not n: 12117db96d56Sopenharmony_ci break # eof 12127db96d56Sopenharmony_ci written += n 12137db96d56Sopenharmony_ci 12147db96d56Sopenharmony_ci # Otherwise refill internal buffer - unless we're 12157db96d56Sopenharmony_ci # in read1 mode and already got some data 12167db96d56Sopenharmony_ci elif not (read1 and written): 12177db96d56Sopenharmony_ci if not self._peek_unlocked(1): 12187db96d56Sopenharmony_ci break # eof 12197db96d56Sopenharmony_ci 12207db96d56Sopenharmony_ci # In readinto1 mode, return as soon as we have some data 12217db96d56Sopenharmony_ci if read1 and written: 12227db96d56Sopenharmony_ci break 12237db96d56Sopenharmony_ci 12247db96d56Sopenharmony_ci return written 12257db96d56Sopenharmony_ci 12267db96d56Sopenharmony_ci def tell(self): 12277db96d56Sopenharmony_ci return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos 12287db96d56Sopenharmony_ci 12297db96d56Sopenharmony_ci def seek(self, pos, whence=0): 12307db96d56Sopenharmony_ci if whence not in valid_seek_flags: 12317db96d56Sopenharmony_ci raise ValueError("invalid whence value") 12327db96d56Sopenharmony_ci with self._read_lock: 12337db96d56Sopenharmony_ci if whence == 1: 12347db96d56Sopenharmony_ci pos -= len(self._read_buf) - self._read_pos 12357db96d56Sopenharmony_ci pos = _BufferedIOMixin.seek(self, pos, whence) 12367db96d56Sopenharmony_ci self._reset_read_buf() 12377db96d56Sopenharmony_ci return pos 12387db96d56Sopenharmony_ci 12397db96d56Sopenharmony_ciclass BufferedWriter(_BufferedIOMixin): 12407db96d56Sopenharmony_ci 12417db96d56Sopenharmony_ci """A buffer for a writeable sequential RawIO object. 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_ci The constructor creates a BufferedWriter for the given writeable raw 12447db96d56Sopenharmony_ci stream. If the buffer_size is not given, it defaults to 12457db96d56Sopenharmony_ci DEFAULT_BUFFER_SIZE. 12467db96d56Sopenharmony_ci """ 12477db96d56Sopenharmony_ci 12487db96d56Sopenharmony_ci def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 12497db96d56Sopenharmony_ci if not raw.writable(): 12507db96d56Sopenharmony_ci raise OSError('"raw" argument must be writable.') 12517db96d56Sopenharmony_ci 12527db96d56Sopenharmony_ci _BufferedIOMixin.__init__(self, raw) 12537db96d56Sopenharmony_ci if buffer_size <= 0: 12547db96d56Sopenharmony_ci raise ValueError("invalid buffer size") 12557db96d56Sopenharmony_ci self.buffer_size = buffer_size 12567db96d56Sopenharmony_ci self._write_buf = bytearray() 12577db96d56Sopenharmony_ci self._write_lock = Lock() 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ci def writable(self): 12607db96d56Sopenharmony_ci return self.raw.writable() 12617db96d56Sopenharmony_ci 12627db96d56Sopenharmony_ci def write(self, b): 12637db96d56Sopenharmony_ci if isinstance(b, str): 12647db96d56Sopenharmony_ci raise TypeError("can't write str to binary stream") 12657db96d56Sopenharmony_ci with self._write_lock: 12667db96d56Sopenharmony_ci if self.closed: 12677db96d56Sopenharmony_ci raise ValueError("write to closed file") 12687db96d56Sopenharmony_ci # XXX we can implement some more tricks to try and avoid 12697db96d56Sopenharmony_ci # partial writes 12707db96d56Sopenharmony_ci if len(self._write_buf) > self.buffer_size: 12717db96d56Sopenharmony_ci # We're full, so let's pre-flush the buffer. (This may 12727db96d56Sopenharmony_ci # raise BlockingIOError with characters_written == 0.) 12737db96d56Sopenharmony_ci self._flush_unlocked() 12747db96d56Sopenharmony_ci before = len(self._write_buf) 12757db96d56Sopenharmony_ci self._write_buf.extend(b) 12767db96d56Sopenharmony_ci written = len(self._write_buf) - before 12777db96d56Sopenharmony_ci if len(self._write_buf) > self.buffer_size: 12787db96d56Sopenharmony_ci try: 12797db96d56Sopenharmony_ci self._flush_unlocked() 12807db96d56Sopenharmony_ci except BlockingIOError as e: 12817db96d56Sopenharmony_ci if len(self._write_buf) > self.buffer_size: 12827db96d56Sopenharmony_ci # We've hit the buffer_size. We have to accept a partial 12837db96d56Sopenharmony_ci # write and cut back our buffer. 12847db96d56Sopenharmony_ci overage = len(self._write_buf) - self.buffer_size 12857db96d56Sopenharmony_ci written -= overage 12867db96d56Sopenharmony_ci self._write_buf = self._write_buf[:self.buffer_size] 12877db96d56Sopenharmony_ci raise BlockingIOError(e.errno, e.strerror, written) 12887db96d56Sopenharmony_ci return written 12897db96d56Sopenharmony_ci 12907db96d56Sopenharmony_ci def truncate(self, pos=None): 12917db96d56Sopenharmony_ci with self._write_lock: 12927db96d56Sopenharmony_ci self._flush_unlocked() 12937db96d56Sopenharmony_ci if pos is None: 12947db96d56Sopenharmony_ci pos = self.raw.tell() 12957db96d56Sopenharmony_ci return self.raw.truncate(pos) 12967db96d56Sopenharmony_ci 12977db96d56Sopenharmony_ci def flush(self): 12987db96d56Sopenharmony_ci with self._write_lock: 12997db96d56Sopenharmony_ci self._flush_unlocked() 13007db96d56Sopenharmony_ci 13017db96d56Sopenharmony_ci def _flush_unlocked(self): 13027db96d56Sopenharmony_ci if self.closed: 13037db96d56Sopenharmony_ci raise ValueError("flush on closed file") 13047db96d56Sopenharmony_ci while self._write_buf: 13057db96d56Sopenharmony_ci try: 13067db96d56Sopenharmony_ci n = self.raw.write(self._write_buf) 13077db96d56Sopenharmony_ci except BlockingIOError: 13087db96d56Sopenharmony_ci raise RuntimeError("self.raw should implement RawIOBase: it " 13097db96d56Sopenharmony_ci "should not raise BlockingIOError") 13107db96d56Sopenharmony_ci if n is None: 13117db96d56Sopenharmony_ci raise BlockingIOError( 13127db96d56Sopenharmony_ci errno.EAGAIN, 13137db96d56Sopenharmony_ci "write could not complete without blocking", 0) 13147db96d56Sopenharmony_ci if n > len(self._write_buf) or n < 0: 13157db96d56Sopenharmony_ci raise OSError("write() returned incorrect number of bytes") 13167db96d56Sopenharmony_ci del self._write_buf[:n] 13177db96d56Sopenharmony_ci 13187db96d56Sopenharmony_ci def tell(self): 13197db96d56Sopenharmony_ci return _BufferedIOMixin.tell(self) + len(self._write_buf) 13207db96d56Sopenharmony_ci 13217db96d56Sopenharmony_ci def seek(self, pos, whence=0): 13227db96d56Sopenharmony_ci if whence not in valid_seek_flags: 13237db96d56Sopenharmony_ci raise ValueError("invalid whence value") 13247db96d56Sopenharmony_ci with self._write_lock: 13257db96d56Sopenharmony_ci self._flush_unlocked() 13267db96d56Sopenharmony_ci return _BufferedIOMixin.seek(self, pos, whence) 13277db96d56Sopenharmony_ci 13287db96d56Sopenharmony_ci def close(self): 13297db96d56Sopenharmony_ci with self._write_lock: 13307db96d56Sopenharmony_ci if self.raw is None or self.closed: 13317db96d56Sopenharmony_ci return 13327db96d56Sopenharmony_ci # We have to release the lock and call self.flush() (which will 13337db96d56Sopenharmony_ci # probably just re-take the lock) in case flush has been overridden in 13347db96d56Sopenharmony_ci # a subclass or the user set self.flush to something. This is the same 13357db96d56Sopenharmony_ci # behavior as the C implementation. 13367db96d56Sopenharmony_ci try: 13377db96d56Sopenharmony_ci # may raise BlockingIOError or BrokenPipeError etc 13387db96d56Sopenharmony_ci self.flush() 13397db96d56Sopenharmony_ci finally: 13407db96d56Sopenharmony_ci with self._write_lock: 13417db96d56Sopenharmony_ci self.raw.close() 13427db96d56Sopenharmony_ci 13437db96d56Sopenharmony_ci 13447db96d56Sopenharmony_ciclass BufferedRWPair(BufferedIOBase): 13457db96d56Sopenharmony_ci 13467db96d56Sopenharmony_ci """A buffered reader and writer object together. 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ci A buffered reader object and buffered writer object put together to 13497db96d56Sopenharmony_ci form a sequential IO object that can read and write. This is typically 13507db96d56Sopenharmony_ci used with a socket or two-way pipe. 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ci reader and writer are RawIOBase objects that are readable and 13537db96d56Sopenharmony_ci writeable respectively. If the buffer_size is omitted it defaults to 13547db96d56Sopenharmony_ci DEFAULT_BUFFER_SIZE. 13557db96d56Sopenharmony_ci """ 13567db96d56Sopenharmony_ci 13577db96d56Sopenharmony_ci # XXX The usefulness of this (compared to having two separate IO 13587db96d56Sopenharmony_ci # objects) is questionable. 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ci def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE): 13617db96d56Sopenharmony_ci """Constructor. 13627db96d56Sopenharmony_ci 13637db96d56Sopenharmony_ci The arguments are two RawIO instances. 13647db96d56Sopenharmony_ci """ 13657db96d56Sopenharmony_ci if not reader.readable(): 13667db96d56Sopenharmony_ci raise OSError('"reader" argument must be readable.') 13677db96d56Sopenharmony_ci 13687db96d56Sopenharmony_ci if not writer.writable(): 13697db96d56Sopenharmony_ci raise OSError('"writer" argument must be writable.') 13707db96d56Sopenharmony_ci 13717db96d56Sopenharmony_ci self.reader = BufferedReader(reader, buffer_size) 13727db96d56Sopenharmony_ci self.writer = BufferedWriter(writer, buffer_size) 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci def read(self, size=-1): 13757db96d56Sopenharmony_ci if size is None: 13767db96d56Sopenharmony_ci size = -1 13777db96d56Sopenharmony_ci return self.reader.read(size) 13787db96d56Sopenharmony_ci 13797db96d56Sopenharmony_ci def readinto(self, b): 13807db96d56Sopenharmony_ci return self.reader.readinto(b) 13817db96d56Sopenharmony_ci 13827db96d56Sopenharmony_ci def write(self, b): 13837db96d56Sopenharmony_ci return self.writer.write(b) 13847db96d56Sopenharmony_ci 13857db96d56Sopenharmony_ci def peek(self, size=0): 13867db96d56Sopenharmony_ci return self.reader.peek(size) 13877db96d56Sopenharmony_ci 13887db96d56Sopenharmony_ci def read1(self, size=-1): 13897db96d56Sopenharmony_ci return self.reader.read1(size) 13907db96d56Sopenharmony_ci 13917db96d56Sopenharmony_ci def readinto1(self, b): 13927db96d56Sopenharmony_ci return self.reader.readinto1(b) 13937db96d56Sopenharmony_ci 13947db96d56Sopenharmony_ci def readable(self): 13957db96d56Sopenharmony_ci return self.reader.readable() 13967db96d56Sopenharmony_ci 13977db96d56Sopenharmony_ci def writable(self): 13987db96d56Sopenharmony_ci return self.writer.writable() 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_ci def flush(self): 14017db96d56Sopenharmony_ci return self.writer.flush() 14027db96d56Sopenharmony_ci 14037db96d56Sopenharmony_ci def close(self): 14047db96d56Sopenharmony_ci try: 14057db96d56Sopenharmony_ci self.writer.close() 14067db96d56Sopenharmony_ci finally: 14077db96d56Sopenharmony_ci self.reader.close() 14087db96d56Sopenharmony_ci 14097db96d56Sopenharmony_ci def isatty(self): 14107db96d56Sopenharmony_ci return self.reader.isatty() or self.writer.isatty() 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci @property 14137db96d56Sopenharmony_ci def closed(self): 14147db96d56Sopenharmony_ci return self.writer.closed 14157db96d56Sopenharmony_ci 14167db96d56Sopenharmony_ci 14177db96d56Sopenharmony_ciclass BufferedRandom(BufferedWriter, BufferedReader): 14187db96d56Sopenharmony_ci 14197db96d56Sopenharmony_ci """A buffered interface to random access streams. 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci The constructor creates a reader and writer for a seekable stream, 14227db96d56Sopenharmony_ci raw, given in the first argument. If the buffer_size is omitted it 14237db96d56Sopenharmony_ci defaults to DEFAULT_BUFFER_SIZE. 14247db96d56Sopenharmony_ci """ 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): 14277db96d56Sopenharmony_ci raw._checkSeekable() 14287db96d56Sopenharmony_ci BufferedReader.__init__(self, raw, buffer_size) 14297db96d56Sopenharmony_ci BufferedWriter.__init__(self, raw, buffer_size) 14307db96d56Sopenharmony_ci 14317db96d56Sopenharmony_ci def seek(self, pos, whence=0): 14327db96d56Sopenharmony_ci if whence not in valid_seek_flags: 14337db96d56Sopenharmony_ci raise ValueError("invalid whence value") 14347db96d56Sopenharmony_ci self.flush() 14357db96d56Sopenharmony_ci if self._read_buf: 14367db96d56Sopenharmony_ci # Undo read ahead. 14377db96d56Sopenharmony_ci with self._read_lock: 14387db96d56Sopenharmony_ci self.raw.seek(self._read_pos - len(self._read_buf), 1) 14397db96d56Sopenharmony_ci # First do the raw seek, then empty the read buffer, so that 14407db96d56Sopenharmony_ci # if the raw seek fails, we don't lose buffered data forever. 14417db96d56Sopenharmony_ci pos = self.raw.seek(pos, whence) 14427db96d56Sopenharmony_ci with self._read_lock: 14437db96d56Sopenharmony_ci self._reset_read_buf() 14447db96d56Sopenharmony_ci if pos < 0: 14457db96d56Sopenharmony_ci raise OSError("seek() returned invalid position") 14467db96d56Sopenharmony_ci return pos 14477db96d56Sopenharmony_ci 14487db96d56Sopenharmony_ci def tell(self): 14497db96d56Sopenharmony_ci if self._write_buf: 14507db96d56Sopenharmony_ci return BufferedWriter.tell(self) 14517db96d56Sopenharmony_ci else: 14527db96d56Sopenharmony_ci return BufferedReader.tell(self) 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci def truncate(self, pos=None): 14557db96d56Sopenharmony_ci if pos is None: 14567db96d56Sopenharmony_ci pos = self.tell() 14577db96d56Sopenharmony_ci # Use seek to flush the read buffer. 14587db96d56Sopenharmony_ci return BufferedWriter.truncate(self, pos) 14597db96d56Sopenharmony_ci 14607db96d56Sopenharmony_ci def read(self, size=None): 14617db96d56Sopenharmony_ci if size is None: 14627db96d56Sopenharmony_ci size = -1 14637db96d56Sopenharmony_ci self.flush() 14647db96d56Sopenharmony_ci return BufferedReader.read(self, size) 14657db96d56Sopenharmony_ci 14667db96d56Sopenharmony_ci def readinto(self, b): 14677db96d56Sopenharmony_ci self.flush() 14687db96d56Sopenharmony_ci return BufferedReader.readinto(self, b) 14697db96d56Sopenharmony_ci 14707db96d56Sopenharmony_ci def peek(self, size=0): 14717db96d56Sopenharmony_ci self.flush() 14727db96d56Sopenharmony_ci return BufferedReader.peek(self, size) 14737db96d56Sopenharmony_ci 14747db96d56Sopenharmony_ci def read1(self, size=-1): 14757db96d56Sopenharmony_ci self.flush() 14767db96d56Sopenharmony_ci return BufferedReader.read1(self, size) 14777db96d56Sopenharmony_ci 14787db96d56Sopenharmony_ci def readinto1(self, b): 14797db96d56Sopenharmony_ci self.flush() 14807db96d56Sopenharmony_ci return BufferedReader.readinto1(self, b) 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci def write(self, b): 14837db96d56Sopenharmony_ci if self._read_buf: 14847db96d56Sopenharmony_ci # Undo readahead 14857db96d56Sopenharmony_ci with self._read_lock: 14867db96d56Sopenharmony_ci self.raw.seek(self._read_pos - len(self._read_buf), 1) 14877db96d56Sopenharmony_ci self._reset_read_buf() 14887db96d56Sopenharmony_ci return BufferedWriter.write(self, b) 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_ci 14917db96d56Sopenharmony_ciclass FileIO(RawIOBase): 14927db96d56Sopenharmony_ci _fd = -1 14937db96d56Sopenharmony_ci _created = False 14947db96d56Sopenharmony_ci _readable = False 14957db96d56Sopenharmony_ci _writable = False 14967db96d56Sopenharmony_ci _appending = False 14977db96d56Sopenharmony_ci _seekable = None 14987db96d56Sopenharmony_ci _closefd = True 14997db96d56Sopenharmony_ci 15007db96d56Sopenharmony_ci def __init__(self, file, mode='r', closefd=True, opener=None): 15017db96d56Sopenharmony_ci """Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading, 15027db96d56Sopenharmony_ci writing, exclusive creation or appending. The file will be created if it 15037db96d56Sopenharmony_ci doesn't exist when opened for writing or appending; it will be truncated 15047db96d56Sopenharmony_ci when opened for writing. A FileExistsError will be raised if it already 15057db96d56Sopenharmony_ci exists when opened for creating. Opening a file for creating implies 15067db96d56Sopenharmony_ci writing so this mode behaves in a similar way to 'w'. Add a '+' to the mode 15077db96d56Sopenharmony_ci to allow simultaneous reading and writing. A custom opener can be used by 15087db96d56Sopenharmony_ci passing a callable as *opener*. The underlying file descriptor for the file 15097db96d56Sopenharmony_ci object is then obtained by calling opener with (*name*, *flags*). 15107db96d56Sopenharmony_ci *opener* must return an open file descriptor (passing os.open as *opener* 15117db96d56Sopenharmony_ci results in functionality similar to passing None). 15127db96d56Sopenharmony_ci """ 15137db96d56Sopenharmony_ci if self._fd >= 0: 15147db96d56Sopenharmony_ci # Have to close the existing file first. 15157db96d56Sopenharmony_ci try: 15167db96d56Sopenharmony_ci if self._closefd: 15177db96d56Sopenharmony_ci os.close(self._fd) 15187db96d56Sopenharmony_ci finally: 15197db96d56Sopenharmony_ci self._fd = -1 15207db96d56Sopenharmony_ci 15217db96d56Sopenharmony_ci if isinstance(file, float): 15227db96d56Sopenharmony_ci raise TypeError('integer argument expected, got float') 15237db96d56Sopenharmony_ci if isinstance(file, int): 15247db96d56Sopenharmony_ci fd = file 15257db96d56Sopenharmony_ci if fd < 0: 15267db96d56Sopenharmony_ci raise ValueError('negative file descriptor') 15277db96d56Sopenharmony_ci else: 15287db96d56Sopenharmony_ci fd = -1 15297db96d56Sopenharmony_ci 15307db96d56Sopenharmony_ci if not isinstance(mode, str): 15317db96d56Sopenharmony_ci raise TypeError('invalid mode: %s' % (mode,)) 15327db96d56Sopenharmony_ci if not set(mode) <= set('xrwab+'): 15337db96d56Sopenharmony_ci raise ValueError('invalid mode: %s' % (mode,)) 15347db96d56Sopenharmony_ci if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1: 15357db96d56Sopenharmony_ci raise ValueError('Must have exactly one of create/read/write/append ' 15367db96d56Sopenharmony_ci 'mode and at most one plus') 15377db96d56Sopenharmony_ci 15387db96d56Sopenharmony_ci if 'x' in mode: 15397db96d56Sopenharmony_ci self._created = True 15407db96d56Sopenharmony_ci self._writable = True 15417db96d56Sopenharmony_ci flags = os.O_EXCL | os.O_CREAT 15427db96d56Sopenharmony_ci elif 'r' in mode: 15437db96d56Sopenharmony_ci self._readable = True 15447db96d56Sopenharmony_ci flags = 0 15457db96d56Sopenharmony_ci elif 'w' in mode: 15467db96d56Sopenharmony_ci self._writable = True 15477db96d56Sopenharmony_ci flags = os.O_CREAT | os.O_TRUNC 15487db96d56Sopenharmony_ci elif 'a' in mode: 15497db96d56Sopenharmony_ci self._writable = True 15507db96d56Sopenharmony_ci self._appending = True 15517db96d56Sopenharmony_ci flags = os.O_APPEND | os.O_CREAT 15527db96d56Sopenharmony_ci 15537db96d56Sopenharmony_ci if '+' in mode: 15547db96d56Sopenharmony_ci self._readable = True 15557db96d56Sopenharmony_ci self._writable = True 15567db96d56Sopenharmony_ci 15577db96d56Sopenharmony_ci if self._readable and self._writable: 15587db96d56Sopenharmony_ci flags |= os.O_RDWR 15597db96d56Sopenharmony_ci elif self._readable: 15607db96d56Sopenharmony_ci flags |= os.O_RDONLY 15617db96d56Sopenharmony_ci else: 15627db96d56Sopenharmony_ci flags |= os.O_WRONLY 15637db96d56Sopenharmony_ci 15647db96d56Sopenharmony_ci flags |= getattr(os, 'O_BINARY', 0) 15657db96d56Sopenharmony_ci 15667db96d56Sopenharmony_ci noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or 15677db96d56Sopenharmony_ci getattr(os, 'O_CLOEXEC', 0)) 15687db96d56Sopenharmony_ci flags |= noinherit_flag 15697db96d56Sopenharmony_ci 15707db96d56Sopenharmony_ci owned_fd = None 15717db96d56Sopenharmony_ci try: 15727db96d56Sopenharmony_ci if fd < 0: 15737db96d56Sopenharmony_ci if not closefd: 15747db96d56Sopenharmony_ci raise ValueError('Cannot use closefd=False with file name') 15757db96d56Sopenharmony_ci if opener is None: 15767db96d56Sopenharmony_ci fd = os.open(file, flags, 0o666) 15777db96d56Sopenharmony_ci else: 15787db96d56Sopenharmony_ci fd = opener(file, flags) 15797db96d56Sopenharmony_ci if not isinstance(fd, int): 15807db96d56Sopenharmony_ci raise TypeError('expected integer from opener') 15817db96d56Sopenharmony_ci if fd < 0: 15827db96d56Sopenharmony_ci raise OSError('Negative file descriptor') 15837db96d56Sopenharmony_ci owned_fd = fd 15847db96d56Sopenharmony_ci if not noinherit_flag: 15857db96d56Sopenharmony_ci os.set_inheritable(fd, False) 15867db96d56Sopenharmony_ci 15877db96d56Sopenharmony_ci self._closefd = closefd 15887db96d56Sopenharmony_ci fdfstat = os.fstat(fd) 15897db96d56Sopenharmony_ci try: 15907db96d56Sopenharmony_ci if stat.S_ISDIR(fdfstat.st_mode): 15917db96d56Sopenharmony_ci raise IsADirectoryError(errno.EISDIR, 15927db96d56Sopenharmony_ci os.strerror(errno.EISDIR), file) 15937db96d56Sopenharmony_ci except AttributeError: 15947db96d56Sopenharmony_ci # Ignore the AttributeError if stat.S_ISDIR or errno.EISDIR 15957db96d56Sopenharmony_ci # don't exist. 15967db96d56Sopenharmony_ci pass 15977db96d56Sopenharmony_ci self._blksize = getattr(fdfstat, 'st_blksize', 0) 15987db96d56Sopenharmony_ci if self._blksize <= 1: 15997db96d56Sopenharmony_ci self._blksize = DEFAULT_BUFFER_SIZE 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_ci if _setmode: 16027db96d56Sopenharmony_ci # don't translate newlines (\r\n <=> \n) 16037db96d56Sopenharmony_ci _setmode(fd, os.O_BINARY) 16047db96d56Sopenharmony_ci 16057db96d56Sopenharmony_ci self.name = file 16067db96d56Sopenharmony_ci if self._appending: 16077db96d56Sopenharmony_ci # For consistent behaviour, we explicitly seek to the 16087db96d56Sopenharmony_ci # end of file (otherwise, it might be done only on the 16097db96d56Sopenharmony_ci # first write()). 16107db96d56Sopenharmony_ci try: 16117db96d56Sopenharmony_ci os.lseek(fd, 0, SEEK_END) 16127db96d56Sopenharmony_ci except OSError as e: 16137db96d56Sopenharmony_ci if e.errno != errno.ESPIPE: 16147db96d56Sopenharmony_ci raise 16157db96d56Sopenharmony_ci except: 16167db96d56Sopenharmony_ci if owned_fd is not None: 16177db96d56Sopenharmony_ci os.close(owned_fd) 16187db96d56Sopenharmony_ci raise 16197db96d56Sopenharmony_ci self._fd = fd 16207db96d56Sopenharmony_ci 16217db96d56Sopenharmony_ci def __del__(self): 16227db96d56Sopenharmony_ci if self._fd >= 0 and self._closefd and not self.closed: 16237db96d56Sopenharmony_ci import warnings 16247db96d56Sopenharmony_ci warnings.warn('unclosed file %r' % (self,), ResourceWarning, 16257db96d56Sopenharmony_ci stacklevel=2, source=self) 16267db96d56Sopenharmony_ci self.close() 16277db96d56Sopenharmony_ci 16287db96d56Sopenharmony_ci def __getstate__(self): 16297db96d56Sopenharmony_ci raise TypeError(f"cannot pickle {self.__class__.__name__!r} object") 16307db96d56Sopenharmony_ci 16317db96d56Sopenharmony_ci def __repr__(self): 16327db96d56Sopenharmony_ci class_name = '%s.%s' % (self.__class__.__module__, 16337db96d56Sopenharmony_ci self.__class__.__qualname__) 16347db96d56Sopenharmony_ci if self.closed: 16357db96d56Sopenharmony_ci return '<%s [closed]>' % class_name 16367db96d56Sopenharmony_ci try: 16377db96d56Sopenharmony_ci name = self.name 16387db96d56Sopenharmony_ci except AttributeError: 16397db96d56Sopenharmony_ci return ('<%s fd=%d mode=%r closefd=%r>' % 16407db96d56Sopenharmony_ci (class_name, self._fd, self.mode, self._closefd)) 16417db96d56Sopenharmony_ci else: 16427db96d56Sopenharmony_ci return ('<%s name=%r mode=%r closefd=%r>' % 16437db96d56Sopenharmony_ci (class_name, name, self.mode, self._closefd)) 16447db96d56Sopenharmony_ci 16457db96d56Sopenharmony_ci def _checkReadable(self): 16467db96d56Sopenharmony_ci if not self._readable: 16477db96d56Sopenharmony_ci raise UnsupportedOperation('File not open for reading') 16487db96d56Sopenharmony_ci 16497db96d56Sopenharmony_ci def _checkWritable(self, msg=None): 16507db96d56Sopenharmony_ci if not self._writable: 16517db96d56Sopenharmony_ci raise UnsupportedOperation('File not open for writing') 16527db96d56Sopenharmony_ci 16537db96d56Sopenharmony_ci def read(self, size=None): 16547db96d56Sopenharmony_ci """Read at most size bytes, returned as bytes. 16557db96d56Sopenharmony_ci 16567db96d56Sopenharmony_ci Only makes one system call, so less data may be returned than requested 16577db96d56Sopenharmony_ci In non-blocking mode, returns None if no data is available. 16587db96d56Sopenharmony_ci Return an empty bytes object at EOF. 16597db96d56Sopenharmony_ci """ 16607db96d56Sopenharmony_ci self._checkClosed() 16617db96d56Sopenharmony_ci self._checkReadable() 16627db96d56Sopenharmony_ci if size is None or size < 0: 16637db96d56Sopenharmony_ci return self.readall() 16647db96d56Sopenharmony_ci try: 16657db96d56Sopenharmony_ci return os.read(self._fd, size) 16667db96d56Sopenharmony_ci except BlockingIOError: 16677db96d56Sopenharmony_ci return None 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_ci def readall(self): 16707db96d56Sopenharmony_ci """Read all data from the file, returned as bytes. 16717db96d56Sopenharmony_ci 16727db96d56Sopenharmony_ci In non-blocking mode, returns as much as is immediately available, 16737db96d56Sopenharmony_ci or None if no data is available. Return an empty bytes object at EOF. 16747db96d56Sopenharmony_ci """ 16757db96d56Sopenharmony_ci self._checkClosed() 16767db96d56Sopenharmony_ci self._checkReadable() 16777db96d56Sopenharmony_ci bufsize = DEFAULT_BUFFER_SIZE 16787db96d56Sopenharmony_ci try: 16797db96d56Sopenharmony_ci pos = os.lseek(self._fd, 0, SEEK_CUR) 16807db96d56Sopenharmony_ci end = os.fstat(self._fd).st_size 16817db96d56Sopenharmony_ci if end >= pos: 16827db96d56Sopenharmony_ci bufsize = end - pos + 1 16837db96d56Sopenharmony_ci except OSError: 16847db96d56Sopenharmony_ci pass 16857db96d56Sopenharmony_ci 16867db96d56Sopenharmony_ci result = bytearray() 16877db96d56Sopenharmony_ci while True: 16887db96d56Sopenharmony_ci if len(result) >= bufsize: 16897db96d56Sopenharmony_ci bufsize = len(result) 16907db96d56Sopenharmony_ci bufsize += max(bufsize, DEFAULT_BUFFER_SIZE) 16917db96d56Sopenharmony_ci n = bufsize - len(result) 16927db96d56Sopenharmony_ci try: 16937db96d56Sopenharmony_ci chunk = os.read(self._fd, n) 16947db96d56Sopenharmony_ci except BlockingIOError: 16957db96d56Sopenharmony_ci if result: 16967db96d56Sopenharmony_ci break 16977db96d56Sopenharmony_ci return None 16987db96d56Sopenharmony_ci if not chunk: # reached the end of the file 16997db96d56Sopenharmony_ci break 17007db96d56Sopenharmony_ci result += chunk 17017db96d56Sopenharmony_ci 17027db96d56Sopenharmony_ci return bytes(result) 17037db96d56Sopenharmony_ci 17047db96d56Sopenharmony_ci def readinto(self, b): 17057db96d56Sopenharmony_ci """Same as RawIOBase.readinto().""" 17067db96d56Sopenharmony_ci m = memoryview(b).cast('B') 17077db96d56Sopenharmony_ci data = self.read(len(m)) 17087db96d56Sopenharmony_ci n = len(data) 17097db96d56Sopenharmony_ci m[:n] = data 17107db96d56Sopenharmony_ci return n 17117db96d56Sopenharmony_ci 17127db96d56Sopenharmony_ci def write(self, b): 17137db96d56Sopenharmony_ci """Write bytes b to file, return number written. 17147db96d56Sopenharmony_ci 17157db96d56Sopenharmony_ci Only makes one system call, so not all of the data may be written. 17167db96d56Sopenharmony_ci The number of bytes actually written is returned. In non-blocking mode, 17177db96d56Sopenharmony_ci returns None if the write would block. 17187db96d56Sopenharmony_ci """ 17197db96d56Sopenharmony_ci self._checkClosed() 17207db96d56Sopenharmony_ci self._checkWritable() 17217db96d56Sopenharmony_ci try: 17227db96d56Sopenharmony_ci return os.write(self._fd, b) 17237db96d56Sopenharmony_ci except BlockingIOError: 17247db96d56Sopenharmony_ci return None 17257db96d56Sopenharmony_ci 17267db96d56Sopenharmony_ci def seek(self, pos, whence=SEEK_SET): 17277db96d56Sopenharmony_ci """Move to new file position. 17287db96d56Sopenharmony_ci 17297db96d56Sopenharmony_ci Argument offset is a byte count. Optional argument whence defaults to 17307db96d56Sopenharmony_ci SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values 17317db96d56Sopenharmony_ci are SEEK_CUR or 1 (move relative to current position, positive or negative), 17327db96d56Sopenharmony_ci and SEEK_END or 2 (move relative to end of file, usually negative, although 17337db96d56Sopenharmony_ci many platforms allow seeking beyond the end of a file). 17347db96d56Sopenharmony_ci 17357db96d56Sopenharmony_ci Note that not all file objects are seekable. 17367db96d56Sopenharmony_ci """ 17377db96d56Sopenharmony_ci if isinstance(pos, float): 17387db96d56Sopenharmony_ci raise TypeError('an integer is required') 17397db96d56Sopenharmony_ci self._checkClosed() 17407db96d56Sopenharmony_ci return os.lseek(self._fd, pos, whence) 17417db96d56Sopenharmony_ci 17427db96d56Sopenharmony_ci def tell(self): 17437db96d56Sopenharmony_ci """tell() -> int. Current file position. 17447db96d56Sopenharmony_ci 17457db96d56Sopenharmony_ci Can raise OSError for non seekable files.""" 17467db96d56Sopenharmony_ci self._checkClosed() 17477db96d56Sopenharmony_ci return os.lseek(self._fd, 0, SEEK_CUR) 17487db96d56Sopenharmony_ci 17497db96d56Sopenharmony_ci def truncate(self, size=None): 17507db96d56Sopenharmony_ci """Truncate the file to at most size bytes. 17517db96d56Sopenharmony_ci 17527db96d56Sopenharmony_ci Size defaults to the current file position, as returned by tell(). 17537db96d56Sopenharmony_ci The current file position is changed to the value of size. 17547db96d56Sopenharmony_ci """ 17557db96d56Sopenharmony_ci self._checkClosed() 17567db96d56Sopenharmony_ci self._checkWritable() 17577db96d56Sopenharmony_ci if size is None: 17587db96d56Sopenharmony_ci size = self.tell() 17597db96d56Sopenharmony_ci os.ftruncate(self._fd, size) 17607db96d56Sopenharmony_ci return size 17617db96d56Sopenharmony_ci 17627db96d56Sopenharmony_ci def close(self): 17637db96d56Sopenharmony_ci """Close the file. 17647db96d56Sopenharmony_ci 17657db96d56Sopenharmony_ci A closed file cannot be used for further I/O operations. close() may be 17667db96d56Sopenharmony_ci called more than once without error. 17677db96d56Sopenharmony_ci """ 17687db96d56Sopenharmony_ci if not self.closed: 17697db96d56Sopenharmony_ci try: 17707db96d56Sopenharmony_ci if self._closefd: 17717db96d56Sopenharmony_ci os.close(self._fd) 17727db96d56Sopenharmony_ci finally: 17737db96d56Sopenharmony_ci super().close() 17747db96d56Sopenharmony_ci 17757db96d56Sopenharmony_ci def seekable(self): 17767db96d56Sopenharmony_ci """True if file supports random-access.""" 17777db96d56Sopenharmony_ci self._checkClosed() 17787db96d56Sopenharmony_ci if self._seekable is None: 17797db96d56Sopenharmony_ci try: 17807db96d56Sopenharmony_ci self.tell() 17817db96d56Sopenharmony_ci except OSError: 17827db96d56Sopenharmony_ci self._seekable = False 17837db96d56Sopenharmony_ci else: 17847db96d56Sopenharmony_ci self._seekable = True 17857db96d56Sopenharmony_ci return self._seekable 17867db96d56Sopenharmony_ci 17877db96d56Sopenharmony_ci def readable(self): 17887db96d56Sopenharmony_ci """True if file was opened in a read mode.""" 17897db96d56Sopenharmony_ci self._checkClosed() 17907db96d56Sopenharmony_ci return self._readable 17917db96d56Sopenharmony_ci 17927db96d56Sopenharmony_ci def writable(self): 17937db96d56Sopenharmony_ci """True if file was opened in a write mode.""" 17947db96d56Sopenharmony_ci self._checkClosed() 17957db96d56Sopenharmony_ci return self._writable 17967db96d56Sopenharmony_ci 17977db96d56Sopenharmony_ci def fileno(self): 17987db96d56Sopenharmony_ci """Return the underlying file descriptor (an integer).""" 17997db96d56Sopenharmony_ci self._checkClosed() 18007db96d56Sopenharmony_ci return self._fd 18017db96d56Sopenharmony_ci 18027db96d56Sopenharmony_ci def isatty(self): 18037db96d56Sopenharmony_ci """True if the file is connected to a TTY device.""" 18047db96d56Sopenharmony_ci self._checkClosed() 18057db96d56Sopenharmony_ci return os.isatty(self._fd) 18067db96d56Sopenharmony_ci 18077db96d56Sopenharmony_ci @property 18087db96d56Sopenharmony_ci def closefd(self): 18097db96d56Sopenharmony_ci """True if the file descriptor will be closed by close().""" 18107db96d56Sopenharmony_ci return self._closefd 18117db96d56Sopenharmony_ci 18127db96d56Sopenharmony_ci @property 18137db96d56Sopenharmony_ci def mode(self): 18147db96d56Sopenharmony_ci """String giving the file mode""" 18157db96d56Sopenharmony_ci if self._created: 18167db96d56Sopenharmony_ci if self._readable: 18177db96d56Sopenharmony_ci return 'xb+' 18187db96d56Sopenharmony_ci else: 18197db96d56Sopenharmony_ci return 'xb' 18207db96d56Sopenharmony_ci elif self._appending: 18217db96d56Sopenharmony_ci if self._readable: 18227db96d56Sopenharmony_ci return 'ab+' 18237db96d56Sopenharmony_ci else: 18247db96d56Sopenharmony_ci return 'ab' 18257db96d56Sopenharmony_ci elif self._readable: 18267db96d56Sopenharmony_ci if self._writable: 18277db96d56Sopenharmony_ci return 'rb+' 18287db96d56Sopenharmony_ci else: 18297db96d56Sopenharmony_ci return 'rb' 18307db96d56Sopenharmony_ci else: 18317db96d56Sopenharmony_ci return 'wb' 18327db96d56Sopenharmony_ci 18337db96d56Sopenharmony_ci 18347db96d56Sopenharmony_ciclass TextIOBase(IOBase): 18357db96d56Sopenharmony_ci 18367db96d56Sopenharmony_ci """Base class for text I/O. 18377db96d56Sopenharmony_ci 18387db96d56Sopenharmony_ci This class provides a character and line based interface to stream 18397db96d56Sopenharmony_ci I/O. 18407db96d56Sopenharmony_ci """ 18417db96d56Sopenharmony_ci 18427db96d56Sopenharmony_ci def read(self, size=-1): 18437db96d56Sopenharmony_ci """Read at most size characters from stream, where size is an int. 18447db96d56Sopenharmony_ci 18457db96d56Sopenharmony_ci Read from underlying buffer until we have size characters or we hit EOF. 18467db96d56Sopenharmony_ci If size is negative or omitted, read until EOF. 18477db96d56Sopenharmony_ci 18487db96d56Sopenharmony_ci Returns a string. 18497db96d56Sopenharmony_ci """ 18507db96d56Sopenharmony_ci self._unsupported("read") 18517db96d56Sopenharmony_ci 18527db96d56Sopenharmony_ci def write(self, s): 18537db96d56Sopenharmony_ci """Write string s to stream and returning an int.""" 18547db96d56Sopenharmony_ci self._unsupported("write") 18557db96d56Sopenharmony_ci 18567db96d56Sopenharmony_ci def truncate(self, pos=None): 18577db96d56Sopenharmony_ci """Truncate size to pos, where pos is an int.""" 18587db96d56Sopenharmony_ci self._unsupported("truncate") 18597db96d56Sopenharmony_ci 18607db96d56Sopenharmony_ci def readline(self): 18617db96d56Sopenharmony_ci """Read until newline or EOF. 18627db96d56Sopenharmony_ci 18637db96d56Sopenharmony_ci Returns an empty string if EOF is hit immediately. 18647db96d56Sopenharmony_ci """ 18657db96d56Sopenharmony_ci self._unsupported("readline") 18667db96d56Sopenharmony_ci 18677db96d56Sopenharmony_ci def detach(self): 18687db96d56Sopenharmony_ci """ 18697db96d56Sopenharmony_ci Separate the underlying buffer from the TextIOBase and return it. 18707db96d56Sopenharmony_ci 18717db96d56Sopenharmony_ci After the underlying buffer has been detached, the TextIO is in an 18727db96d56Sopenharmony_ci unusable state. 18737db96d56Sopenharmony_ci """ 18747db96d56Sopenharmony_ci self._unsupported("detach") 18757db96d56Sopenharmony_ci 18767db96d56Sopenharmony_ci @property 18777db96d56Sopenharmony_ci def encoding(self): 18787db96d56Sopenharmony_ci """Subclasses should override.""" 18797db96d56Sopenharmony_ci return None 18807db96d56Sopenharmony_ci 18817db96d56Sopenharmony_ci @property 18827db96d56Sopenharmony_ci def newlines(self): 18837db96d56Sopenharmony_ci """Line endings translated so far. 18847db96d56Sopenharmony_ci 18857db96d56Sopenharmony_ci Only line endings translated during reading are considered. 18867db96d56Sopenharmony_ci 18877db96d56Sopenharmony_ci Subclasses should override. 18887db96d56Sopenharmony_ci """ 18897db96d56Sopenharmony_ci return None 18907db96d56Sopenharmony_ci 18917db96d56Sopenharmony_ci @property 18927db96d56Sopenharmony_ci def errors(self): 18937db96d56Sopenharmony_ci """Error setting of the decoder or encoder. 18947db96d56Sopenharmony_ci 18957db96d56Sopenharmony_ci Subclasses should override.""" 18967db96d56Sopenharmony_ci return None 18977db96d56Sopenharmony_ci 18987db96d56Sopenharmony_ciio.TextIOBase.register(TextIOBase) 18997db96d56Sopenharmony_ci 19007db96d56Sopenharmony_ci 19017db96d56Sopenharmony_ciclass IncrementalNewlineDecoder(codecs.IncrementalDecoder): 19027db96d56Sopenharmony_ci r"""Codec used when reading a file in universal newlines mode. It wraps 19037db96d56Sopenharmony_ci another incremental decoder, translating \r\n and \r into \n. It also 19047db96d56Sopenharmony_ci records the types of newlines encountered. When used with 19057db96d56Sopenharmony_ci translate=False, it ensures that the newline sequence is returned in 19067db96d56Sopenharmony_ci one piece. 19077db96d56Sopenharmony_ci """ 19087db96d56Sopenharmony_ci def __init__(self, decoder, translate, errors='strict'): 19097db96d56Sopenharmony_ci codecs.IncrementalDecoder.__init__(self, errors=errors) 19107db96d56Sopenharmony_ci self.translate = translate 19117db96d56Sopenharmony_ci self.decoder = decoder 19127db96d56Sopenharmony_ci self.seennl = 0 19137db96d56Sopenharmony_ci self.pendingcr = False 19147db96d56Sopenharmony_ci 19157db96d56Sopenharmony_ci def decode(self, input, final=False): 19167db96d56Sopenharmony_ci # decode input (with the eventual \r from a previous pass) 19177db96d56Sopenharmony_ci if self.decoder is None: 19187db96d56Sopenharmony_ci output = input 19197db96d56Sopenharmony_ci else: 19207db96d56Sopenharmony_ci output = self.decoder.decode(input, final=final) 19217db96d56Sopenharmony_ci if self.pendingcr and (output or final): 19227db96d56Sopenharmony_ci output = "\r" + output 19237db96d56Sopenharmony_ci self.pendingcr = False 19247db96d56Sopenharmony_ci 19257db96d56Sopenharmony_ci # retain last \r even when not translating data: 19267db96d56Sopenharmony_ci # then readline() is sure to get \r\n in one pass 19277db96d56Sopenharmony_ci if output.endswith("\r") and not final: 19287db96d56Sopenharmony_ci output = output[:-1] 19297db96d56Sopenharmony_ci self.pendingcr = True 19307db96d56Sopenharmony_ci 19317db96d56Sopenharmony_ci # Record which newlines are read 19327db96d56Sopenharmony_ci crlf = output.count('\r\n') 19337db96d56Sopenharmony_ci cr = output.count('\r') - crlf 19347db96d56Sopenharmony_ci lf = output.count('\n') - crlf 19357db96d56Sopenharmony_ci self.seennl |= (lf and self._LF) | (cr and self._CR) \ 19367db96d56Sopenharmony_ci | (crlf and self._CRLF) 19377db96d56Sopenharmony_ci 19387db96d56Sopenharmony_ci if self.translate: 19397db96d56Sopenharmony_ci if crlf: 19407db96d56Sopenharmony_ci output = output.replace("\r\n", "\n") 19417db96d56Sopenharmony_ci if cr: 19427db96d56Sopenharmony_ci output = output.replace("\r", "\n") 19437db96d56Sopenharmony_ci 19447db96d56Sopenharmony_ci return output 19457db96d56Sopenharmony_ci 19467db96d56Sopenharmony_ci def getstate(self): 19477db96d56Sopenharmony_ci if self.decoder is None: 19487db96d56Sopenharmony_ci buf = b"" 19497db96d56Sopenharmony_ci flag = 0 19507db96d56Sopenharmony_ci else: 19517db96d56Sopenharmony_ci buf, flag = self.decoder.getstate() 19527db96d56Sopenharmony_ci flag <<= 1 19537db96d56Sopenharmony_ci if self.pendingcr: 19547db96d56Sopenharmony_ci flag |= 1 19557db96d56Sopenharmony_ci return buf, flag 19567db96d56Sopenharmony_ci 19577db96d56Sopenharmony_ci def setstate(self, state): 19587db96d56Sopenharmony_ci buf, flag = state 19597db96d56Sopenharmony_ci self.pendingcr = bool(flag & 1) 19607db96d56Sopenharmony_ci if self.decoder is not None: 19617db96d56Sopenharmony_ci self.decoder.setstate((buf, flag >> 1)) 19627db96d56Sopenharmony_ci 19637db96d56Sopenharmony_ci def reset(self): 19647db96d56Sopenharmony_ci self.seennl = 0 19657db96d56Sopenharmony_ci self.pendingcr = False 19667db96d56Sopenharmony_ci if self.decoder is not None: 19677db96d56Sopenharmony_ci self.decoder.reset() 19687db96d56Sopenharmony_ci 19697db96d56Sopenharmony_ci _LF = 1 19707db96d56Sopenharmony_ci _CR = 2 19717db96d56Sopenharmony_ci _CRLF = 4 19727db96d56Sopenharmony_ci 19737db96d56Sopenharmony_ci @property 19747db96d56Sopenharmony_ci def newlines(self): 19757db96d56Sopenharmony_ci return (None, 19767db96d56Sopenharmony_ci "\n", 19777db96d56Sopenharmony_ci "\r", 19787db96d56Sopenharmony_ci ("\r", "\n"), 19797db96d56Sopenharmony_ci "\r\n", 19807db96d56Sopenharmony_ci ("\n", "\r\n"), 19817db96d56Sopenharmony_ci ("\r", "\r\n"), 19827db96d56Sopenharmony_ci ("\r", "\n", "\r\n") 19837db96d56Sopenharmony_ci )[self.seennl] 19847db96d56Sopenharmony_ci 19857db96d56Sopenharmony_ci 19867db96d56Sopenharmony_ciclass TextIOWrapper(TextIOBase): 19877db96d56Sopenharmony_ci 19887db96d56Sopenharmony_ci r"""Character and line based layer over a BufferedIOBase object, buffer. 19897db96d56Sopenharmony_ci 19907db96d56Sopenharmony_ci encoding gives the name of the encoding that the stream will be 19917db96d56Sopenharmony_ci decoded or encoded with. It defaults to locale.getencoding(). 19927db96d56Sopenharmony_ci 19937db96d56Sopenharmony_ci errors determines the strictness of encoding and decoding (see the 19947db96d56Sopenharmony_ci codecs.register) and defaults to "strict". 19957db96d56Sopenharmony_ci 19967db96d56Sopenharmony_ci newline can be None, '', '\n', '\r', or '\r\n'. It controls the 19977db96d56Sopenharmony_ci handling of line endings. If it is None, universal newlines is 19987db96d56Sopenharmony_ci enabled. With this enabled, on input, the lines endings '\n', '\r', 19997db96d56Sopenharmony_ci or '\r\n' are translated to '\n' before being returned to the 20007db96d56Sopenharmony_ci caller. Conversely, on output, '\n' is translated to the system 20017db96d56Sopenharmony_ci default line separator, os.linesep. If newline is any other of its 20027db96d56Sopenharmony_ci legal values, that newline becomes the newline when the file is read 20037db96d56Sopenharmony_ci and it is returned untranslated. On output, '\n' is converted to the 20047db96d56Sopenharmony_ci newline. 20057db96d56Sopenharmony_ci 20067db96d56Sopenharmony_ci If line_buffering is True, a call to flush is implied when a call to 20077db96d56Sopenharmony_ci write contains a newline character. 20087db96d56Sopenharmony_ci """ 20097db96d56Sopenharmony_ci 20107db96d56Sopenharmony_ci _CHUNK_SIZE = 2048 20117db96d56Sopenharmony_ci 20127db96d56Sopenharmony_ci # Initialize _buffer as soon as possible since it's used by __del__() 20137db96d56Sopenharmony_ci # which calls close() 20147db96d56Sopenharmony_ci _buffer = None 20157db96d56Sopenharmony_ci 20167db96d56Sopenharmony_ci # The write_through argument has no effect here since this 20177db96d56Sopenharmony_ci # implementation always writes through. The argument is present only 20187db96d56Sopenharmony_ci # so that the signature can match the signature of the C version. 20197db96d56Sopenharmony_ci def __init__(self, buffer, encoding=None, errors=None, newline=None, 20207db96d56Sopenharmony_ci line_buffering=False, write_through=False): 20217db96d56Sopenharmony_ci self._check_newline(newline) 20227db96d56Sopenharmony_ci encoding = text_encoding(encoding) 20237db96d56Sopenharmony_ci 20247db96d56Sopenharmony_ci if encoding == "locale": 20257db96d56Sopenharmony_ci encoding = self._get_locale_encoding() 20267db96d56Sopenharmony_ci 20277db96d56Sopenharmony_ci if not isinstance(encoding, str): 20287db96d56Sopenharmony_ci raise ValueError("invalid encoding: %r" % encoding) 20297db96d56Sopenharmony_ci 20307db96d56Sopenharmony_ci if not codecs.lookup(encoding)._is_text_encoding: 20317db96d56Sopenharmony_ci msg = ("%r is not a text encoding; " 20327db96d56Sopenharmony_ci "use codecs.open() to handle arbitrary codecs") 20337db96d56Sopenharmony_ci raise LookupError(msg % encoding) 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_ci if errors is None: 20367db96d56Sopenharmony_ci errors = "strict" 20377db96d56Sopenharmony_ci else: 20387db96d56Sopenharmony_ci if not isinstance(errors, str): 20397db96d56Sopenharmony_ci raise ValueError("invalid errors: %r" % errors) 20407db96d56Sopenharmony_ci if _CHECK_ERRORS: 20417db96d56Sopenharmony_ci codecs.lookup_error(errors) 20427db96d56Sopenharmony_ci 20437db96d56Sopenharmony_ci self._buffer = buffer 20447db96d56Sopenharmony_ci self._decoded_chars = '' # buffer for text returned from decoder 20457db96d56Sopenharmony_ci self._decoded_chars_used = 0 # offset into _decoded_chars for read() 20467db96d56Sopenharmony_ci self._snapshot = None # info for reconstructing decoder state 20477db96d56Sopenharmony_ci self._seekable = self._telling = self.buffer.seekable() 20487db96d56Sopenharmony_ci self._has_read1 = hasattr(self.buffer, 'read1') 20497db96d56Sopenharmony_ci self._configure(encoding, errors, newline, 20507db96d56Sopenharmony_ci line_buffering, write_through) 20517db96d56Sopenharmony_ci 20527db96d56Sopenharmony_ci def _check_newline(self, newline): 20537db96d56Sopenharmony_ci if newline is not None and not isinstance(newline, str): 20547db96d56Sopenharmony_ci raise TypeError("illegal newline type: %r" % (type(newline),)) 20557db96d56Sopenharmony_ci if newline not in (None, "", "\n", "\r", "\r\n"): 20567db96d56Sopenharmony_ci raise ValueError("illegal newline value: %r" % (newline,)) 20577db96d56Sopenharmony_ci 20587db96d56Sopenharmony_ci def _configure(self, encoding=None, errors=None, newline=None, 20597db96d56Sopenharmony_ci line_buffering=False, write_through=False): 20607db96d56Sopenharmony_ci self._encoding = encoding 20617db96d56Sopenharmony_ci self._errors = errors 20627db96d56Sopenharmony_ci self._encoder = None 20637db96d56Sopenharmony_ci self._decoder = None 20647db96d56Sopenharmony_ci self._b2cratio = 0.0 20657db96d56Sopenharmony_ci 20667db96d56Sopenharmony_ci self._readuniversal = not newline 20677db96d56Sopenharmony_ci self._readtranslate = newline is None 20687db96d56Sopenharmony_ci self._readnl = newline 20697db96d56Sopenharmony_ci self._writetranslate = newline != '' 20707db96d56Sopenharmony_ci self._writenl = newline or os.linesep 20717db96d56Sopenharmony_ci 20727db96d56Sopenharmony_ci self._line_buffering = line_buffering 20737db96d56Sopenharmony_ci self._write_through = write_through 20747db96d56Sopenharmony_ci 20757db96d56Sopenharmony_ci # don't write a BOM in the middle of a file 20767db96d56Sopenharmony_ci if self._seekable and self.writable(): 20777db96d56Sopenharmony_ci position = self.buffer.tell() 20787db96d56Sopenharmony_ci if position != 0: 20797db96d56Sopenharmony_ci try: 20807db96d56Sopenharmony_ci self._get_encoder().setstate(0) 20817db96d56Sopenharmony_ci except LookupError: 20827db96d56Sopenharmony_ci # Sometimes the encoder doesn't exist 20837db96d56Sopenharmony_ci pass 20847db96d56Sopenharmony_ci 20857db96d56Sopenharmony_ci # self._snapshot is either None, or a tuple (dec_flags, next_input) 20867db96d56Sopenharmony_ci # where dec_flags is the second (integer) item of the decoder state 20877db96d56Sopenharmony_ci # and next_input is the chunk of input bytes that comes next after the 20887db96d56Sopenharmony_ci # snapshot point. We use this to reconstruct decoder states in tell(). 20897db96d56Sopenharmony_ci 20907db96d56Sopenharmony_ci # Naming convention: 20917db96d56Sopenharmony_ci # - "bytes_..." for integer variables that count input bytes 20927db96d56Sopenharmony_ci # - "chars_..." for integer variables that count decoded characters 20937db96d56Sopenharmony_ci 20947db96d56Sopenharmony_ci def __repr__(self): 20957db96d56Sopenharmony_ci result = "<{}.{}".format(self.__class__.__module__, 20967db96d56Sopenharmony_ci self.__class__.__qualname__) 20977db96d56Sopenharmony_ci try: 20987db96d56Sopenharmony_ci name = self.name 20997db96d56Sopenharmony_ci except AttributeError: 21007db96d56Sopenharmony_ci pass 21017db96d56Sopenharmony_ci else: 21027db96d56Sopenharmony_ci result += " name={0!r}".format(name) 21037db96d56Sopenharmony_ci try: 21047db96d56Sopenharmony_ci mode = self.mode 21057db96d56Sopenharmony_ci except AttributeError: 21067db96d56Sopenharmony_ci pass 21077db96d56Sopenharmony_ci else: 21087db96d56Sopenharmony_ci result += " mode={0!r}".format(mode) 21097db96d56Sopenharmony_ci return result + " encoding={0!r}>".format(self.encoding) 21107db96d56Sopenharmony_ci 21117db96d56Sopenharmony_ci @property 21127db96d56Sopenharmony_ci def encoding(self): 21137db96d56Sopenharmony_ci return self._encoding 21147db96d56Sopenharmony_ci 21157db96d56Sopenharmony_ci @property 21167db96d56Sopenharmony_ci def errors(self): 21177db96d56Sopenharmony_ci return self._errors 21187db96d56Sopenharmony_ci 21197db96d56Sopenharmony_ci @property 21207db96d56Sopenharmony_ci def line_buffering(self): 21217db96d56Sopenharmony_ci return self._line_buffering 21227db96d56Sopenharmony_ci 21237db96d56Sopenharmony_ci @property 21247db96d56Sopenharmony_ci def write_through(self): 21257db96d56Sopenharmony_ci return self._write_through 21267db96d56Sopenharmony_ci 21277db96d56Sopenharmony_ci @property 21287db96d56Sopenharmony_ci def buffer(self): 21297db96d56Sopenharmony_ci return self._buffer 21307db96d56Sopenharmony_ci 21317db96d56Sopenharmony_ci def reconfigure(self, *, 21327db96d56Sopenharmony_ci encoding=None, errors=None, newline=Ellipsis, 21337db96d56Sopenharmony_ci line_buffering=None, write_through=None): 21347db96d56Sopenharmony_ci """Reconfigure the text stream with new parameters. 21357db96d56Sopenharmony_ci 21367db96d56Sopenharmony_ci This also flushes the stream. 21377db96d56Sopenharmony_ci """ 21387db96d56Sopenharmony_ci if (self._decoder is not None 21397db96d56Sopenharmony_ci and (encoding is not None or errors is not None 21407db96d56Sopenharmony_ci or newline is not Ellipsis)): 21417db96d56Sopenharmony_ci raise UnsupportedOperation( 21427db96d56Sopenharmony_ci "It is not possible to set the encoding or newline of stream " 21437db96d56Sopenharmony_ci "after the first read") 21447db96d56Sopenharmony_ci 21457db96d56Sopenharmony_ci if errors is None: 21467db96d56Sopenharmony_ci if encoding is None: 21477db96d56Sopenharmony_ci errors = self._errors 21487db96d56Sopenharmony_ci else: 21497db96d56Sopenharmony_ci errors = 'strict' 21507db96d56Sopenharmony_ci elif not isinstance(errors, str): 21517db96d56Sopenharmony_ci raise TypeError("invalid errors: %r" % errors) 21527db96d56Sopenharmony_ci 21537db96d56Sopenharmony_ci if encoding is None: 21547db96d56Sopenharmony_ci encoding = self._encoding 21557db96d56Sopenharmony_ci else: 21567db96d56Sopenharmony_ci if not isinstance(encoding, str): 21577db96d56Sopenharmony_ci raise TypeError("invalid encoding: %r" % encoding) 21587db96d56Sopenharmony_ci if encoding == "locale": 21597db96d56Sopenharmony_ci encoding = self._get_locale_encoding() 21607db96d56Sopenharmony_ci 21617db96d56Sopenharmony_ci if newline is Ellipsis: 21627db96d56Sopenharmony_ci newline = self._readnl 21637db96d56Sopenharmony_ci self._check_newline(newline) 21647db96d56Sopenharmony_ci 21657db96d56Sopenharmony_ci if line_buffering is None: 21667db96d56Sopenharmony_ci line_buffering = self.line_buffering 21677db96d56Sopenharmony_ci if write_through is None: 21687db96d56Sopenharmony_ci write_through = self.write_through 21697db96d56Sopenharmony_ci 21707db96d56Sopenharmony_ci self.flush() 21717db96d56Sopenharmony_ci self._configure(encoding, errors, newline, 21727db96d56Sopenharmony_ci line_buffering, write_through) 21737db96d56Sopenharmony_ci 21747db96d56Sopenharmony_ci def seekable(self): 21757db96d56Sopenharmony_ci if self.closed: 21767db96d56Sopenharmony_ci raise ValueError("I/O operation on closed file.") 21777db96d56Sopenharmony_ci return self._seekable 21787db96d56Sopenharmony_ci 21797db96d56Sopenharmony_ci def readable(self): 21807db96d56Sopenharmony_ci return self.buffer.readable() 21817db96d56Sopenharmony_ci 21827db96d56Sopenharmony_ci def writable(self): 21837db96d56Sopenharmony_ci return self.buffer.writable() 21847db96d56Sopenharmony_ci 21857db96d56Sopenharmony_ci def flush(self): 21867db96d56Sopenharmony_ci self.buffer.flush() 21877db96d56Sopenharmony_ci self._telling = self._seekable 21887db96d56Sopenharmony_ci 21897db96d56Sopenharmony_ci def close(self): 21907db96d56Sopenharmony_ci if self.buffer is not None and not self.closed: 21917db96d56Sopenharmony_ci try: 21927db96d56Sopenharmony_ci self.flush() 21937db96d56Sopenharmony_ci finally: 21947db96d56Sopenharmony_ci self.buffer.close() 21957db96d56Sopenharmony_ci 21967db96d56Sopenharmony_ci @property 21977db96d56Sopenharmony_ci def closed(self): 21987db96d56Sopenharmony_ci return self.buffer.closed 21997db96d56Sopenharmony_ci 22007db96d56Sopenharmony_ci @property 22017db96d56Sopenharmony_ci def name(self): 22027db96d56Sopenharmony_ci return self.buffer.name 22037db96d56Sopenharmony_ci 22047db96d56Sopenharmony_ci def fileno(self): 22057db96d56Sopenharmony_ci return self.buffer.fileno() 22067db96d56Sopenharmony_ci 22077db96d56Sopenharmony_ci def isatty(self): 22087db96d56Sopenharmony_ci return self.buffer.isatty() 22097db96d56Sopenharmony_ci 22107db96d56Sopenharmony_ci def write(self, s): 22117db96d56Sopenharmony_ci 'Write data, where s is a str' 22127db96d56Sopenharmony_ci if self.closed: 22137db96d56Sopenharmony_ci raise ValueError("write to closed file") 22147db96d56Sopenharmony_ci if not isinstance(s, str): 22157db96d56Sopenharmony_ci raise TypeError("can't write %s to text stream" % 22167db96d56Sopenharmony_ci s.__class__.__name__) 22177db96d56Sopenharmony_ci length = len(s) 22187db96d56Sopenharmony_ci haslf = (self._writetranslate or self._line_buffering) and "\n" in s 22197db96d56Sopenharmony_ci if haslf and self._writetranslate and self._writenl != "\n": 22207db96d56Sopenharmony_ci s = s.replace("\n", self._writenl) 22217db96d56Sopenharmony_ci encoder = self._encoder or self._get_encoder() 22227db96d56Sopenharmony_ci # XXX What if we were just reading? 22237db96d56Sopenharmony_ci b = encoder.encode(s) 22247db96d56Sopenharmony_ci self.buffer.write(b) 22257db96d56Sopenharmony_ci if self._line_buffering and (haslf or "\r" in s): 22267db96d56Sopenharmony_ci self.flush() 22277db96d56Sopenharmony_ci self._set_decoded_chars('') 22287db96d56Sopenharmony_ci self._snapshot = None 22297db96d56Sopenharmony_ci if self._decoder: 22307db96d56Sopenharmony_ci self._decoder.reset() 22317db96d56Sopenharmony_ci return length 22327db96d56Sopenharmony_ci 22337db96d56Sopenharmony_ci def _get_encoder(self): 22347db96d56Sopenharmony_ci make_encoder = codecs.getincrementalencoder(self._encoding) 22357db96d56Sopenharmony_ci self._encoder = make_encoder(self._errors) 22367db96d56Sopenharmony_ci return self._encoder 22377db96d56Sopenharmony_ci 22387db96d56Sopenharmony_ci def _get_decoder(self): 22397db96d56Sopenharmony_ci make_decoder = codecs.getincrementaldecoder(self._encoding) 22407db96d56Sopenharmony_ci decoder = make_decoder(self._errors) 22417db96d56Sopenharmony_ci if self._readuniversal: 22427db96d56Sopenharmony_ci decoder = IncrementalNewlineDecoder(decoder, self._readtranslate) 22437db96d56Sopenharmony_ci self._decoder = decoder 22447db96d56Sopenharmony_ci return decoder 22457db96d56Sopenharmony_ci 22467db96d56Sopenharmony_ci # The following three methods implement an ADT for _decoded_chars. 22477db96d56Sopenharmony_ci # Text returned from the decoder is buffered here until the client 22487db96d56Sopenharmony_ci # requests it by calling our read() or readline() method. 22497db96d56Sopenharmony_ci def _set_decoded_chars(self, chars): 22507db96d56Sopenharmony_ci """Set the _decoded_chars buffer.""" 22517db96d56Sopenharmony_ci self._decoded_chars = chars 22527db96d56Sopenharmony_ci self._decoded_chars_used = 0 22537db96d56Sopenharmony_ci 22547db96d56Sopenharmony_ci def _get_decoded_chars(self, n=None): 22557db96d56Sopenharmony_ci """Advance into the _decoded_chars buffer.""" 22567db96d56Sopenharmony_ci offset = self._decoded_chars_used 22577db96d56Sopenharmony_ci if n is None: 22587db96d56Sopenharmony_ci chars = self._decoded_chars[offset:] 22597db96d56Sopenharmony_ci else: 22607db96d56Sopenharmony_ci chars = self._decoded_chars[offset:offset + n] 22617db96d56Sopenharmony_ci self._decoded_chars_used += len(chars) 22627db96d56Sopenharmony_ci return chars 22637db96d56Sopenharmony_ci 22647db96d56Sopenharmony_ci def _get_locale_encoding(self): 22657db96d56Sopenharmony_ci try: 22667db96d56Sopenharmony_ci import locale 22677db96d56Sopenharmony_ci except ImportError: 22687db96d56Sopenharmony_ci # Importing locale may fail if Python is being built 22697db96d56Sopenharmony_ci return "utf-8" 22707db96d56Sopenharmony_ci else: 22717db96d56Sopenharmony_ci return locale.getencoding() 22727db96d56Sopenharmony_ci 22737db96d56Sopenharmony_ci def _rewind_decoded_chars(self, n): 22747db96d56Sopenharmony_ci """Rewind the _decoded_chars buffer.""" 22757db96d56Sopenharmony_ci if self._decoded_chars_used < n: 22767db96d56Sopenharmony_ci raise AssertionError("rewind decoded_chars out of bounds") 22777db96d56Sopenharmony_ci self._decoded_chars_used -= n 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_ci def _read_chunk(self): 22807db96d56Sopenharmony_ci """ 22817db96d56Sopenharmony_ci Read and decode the next chunk of data from the BufferedReader. 22827db96d56Sopenharmony_ci """ 22837db96d56Sopenharmony_ci 22847db96d56Sopenharmony_ci # The return value is True unless EOF was reached. The decoded 22857db96d56Sopenharmony_ci # string is placed in self._decoded_chars (replacing its previous 22867db96d56Sopenharmony_ci # value). The entire input chunk is sent to the decoder, though 22877db96d56Sopenharmony_ci # some of it may remain buffered in the decoder, yet to be 22887db96d56Sopenharmony_ci # converted. 22897db96d56Sopenharmony_ci 22907db96d56Sopenharmony_ci if self._decoder is None: 22917db96d56Sopenharmony_ci raise ValueError("no decoder") 22927db96d56Sopenharmony_ci 22937db96d56Sopenharmony_ci if self._telling: 22947db96d56Sopenharmony_ci # To prepare for tell(), we need to snapshot a point in the 22957db96d56Sopenharmony_ci # file where the decoder's input buffer is empty. 22967db96d56Sopenharmony_ci 22977db96d56Sopenharmony_ci dec_buffer, dec_flags = self._decoder.getstate() 22987db96d56Sopenharmony_ci # Given this, we know there was a valid snapshot point 22997db96d56Sopenharmony_ci # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_ci # Read a chunk, decode it, and put the result in self._decoded_chars. 23027db96d56Sopenharmony_ci if self._has_read1: 23037db96d56Sopenharmony_ci input_chunk = self.buffer.read1(self._CHUNK_SIZE) 23047db96d56Sopenharmony_ci else: 23057db96d56Sopenharmony_ci input_chunk = self.buffer.read(self._CHUNK_SIZE) 23067db96d56Sopenharmony_ci eof = not input_chunk 23077db96d56Sopenharmony_ci decoded_chars = self._decoder.decode(input_chunk, eof) 23087db96d56Sopenharmony_ci self._set_decoded_chars(decoded_chars) 23097db96d56Sopenharmony_ci if decoded_chars: 23107db96d56Sopenharmony_ci self._b2cratio = len(input_chunk) / len(self._decoded_chars) 23117db96d56Sopenharmony_ci else: 23127db96d56Sopenharmony_ci self._b2cratio = 0.0 23137db96d56Sopenharmony_ci 23147db96d56Sopenharmony_ci if self._telling: 23157db96d56Sopenharmony_ci # At the snapshot point, len(dec_buffer) bytes before the read, 23167db96d56Sopenharmony_ci # the next input to be decoded is dec_buffer + input_chunk. 23177db96d56Sopenharmony_ci self._snapshot = (dec_flags, dec_buffer + input_chunk) 23187db96d56Sopenharmony_ci 23197db96d56Sopenharmony_ci return not eof 23207db96d56Sopenharmony_ci 23217db96d56Sopenharmony_ci def _pack_cookie(self, position, dec_flags=0, 23227db96d56Sopenharmony_ci bytes_to_feed=0, need_eof=False, chars_to_skip=0): 23237db96d56Sopenharmony_ci # The meaning of a tell() cookie is: seek to position, set the 23247db96d56Sopenharmony_ci # decoder flags to dec_flags, read bytes_to_feed bytes, feed them 23257db96d56Sopenharmony_ci # into the decoder with need_eof as the EOF flag, then skip 23267db96d56Sopenharmony_ci # chars_to_skip characters of the decoded result. For most simple 23277db96d56Sopenharmony_ci # decoders, tell() will often just give a byte offset in the file. 23287db96d56Sopenharmony_ci return (position | (dec_flags<<64) | (bytes_to_feed<<128) | 23297db96d56Sopenharmony_ci (chars_to_skip<<192) | bool(need_eof)<<256) 23307db96d56Sopenharmony_ci 23317db96d56Sopenharmony_ci def _unpack_cookie(self, bigint): 23327db96d56Sopenharmony_ci rest, position = divmod(bigint, 1<<64) 23337db96d56Sopenharmony_ci rest, dec_flags = divmod(rest, 1<<64) 23347db96d56Sopenharmony_ci rest, bytes_to_feed = divmod(rest, 1<<64) 23357db96d56Sopenharmony_ci need_eof, chars_to_skip = divmod(rest, 1<<64) 23367db96d56Sopenharmony_ci return position, dec_flags, bytes_to_feed, bool(need_eof), chars_to_skip 23377db96d56Sopenharmony_ci 23387db96d56Sopenharmony_ci def tell(self): 23397db96d56Sopenharmony_ci if not self._seekable: 23407db96d56Sopenharmony_ci raise UnsupportedOperation("underlying stream is not seekable") 23417db96d56Sopenharmony_ci if not self._telling: 23427db96d56Sopenharmony_ci raise OSError("telling position disabled by next() call") 23437db96d56Sopenharmony_ci self.flush() 23447db96d56Sopenharmony_ci position = self.buffer.tell() 23457db96d56Sopenharmony_ci decoder = self._decoder 23467db96d56Sopenharmony_ci if decoder is None or self._snapshot is None: 23477db96d56Sopenharmony_ci if self._decoded_chars: 23487db96d56Sopenharmony_ci # This should never happen. 23497db96d56Sopenharmony_ci raise AssertionError("pending decoded text") 23507db96d56Sopenharmony_ci return position 23517db96d56Sopenharmony_ci 23527db96d56Sopenharmony_ci # Skip backward to the snapshot point (see _read_chunk). 23537db96d56Sopenharmony_ci dec_flags, next_input = self._snapshot 23547db96d56Sopenharmony_ci position -= len(next_input) 23557db96d56Sopenharmony_ci 23567db96d56Sopenharmony_ci # How many decoded characters have been used up since the snapshot? 23577db96d56Sopenharmony_ci chars_to_skip = self._decoded_chars_used 23587db96d56Sopenharmony_ci if chars_to_skip == 0: 23597db96d56Sopenharmony_ci # We haven't moved from the snapshot point. 23607db96d56Sopenharmony_ci return self._pack_cookie(position, dec_flags) 23617db96d56Sopenharmony_ci 23627db96d56Sopenharmony_ci # Starting from the snapshot position, we will walk the decoder 23637db96d56Sopenharmony_ci # forward until it gives us enough decoded characters. 23647db96d56Sopenharmony_ci saved_state = decoder.getstate() 23657db96d56Sopenharmony_ci try: 23667db96d56Sopenharmony_ci # Fast search for an acceptable start point, close to our 23677db96d56Sopenharmony_ci # current pos. 23687db96d56Sopenharmony_ci # Rationale: calling decoder.decode() has a large overhead 23697db96d56Sopenharmony_ci # regardless of chunk size; we want the number of such calls to 23707db96d56Sopenharmony_ci # be O(1) in most situations (common decoders, sensible input). 23717db96d56Sopenharmony_ci # Actually, it will be exactly 1 for fixed-size codecs (all 23727db96d56Sopenharmony_ci # 8-bit codecs, also UTF-16 and UTF-32). 23737db96d56Sopenharmony_ci skip_bytes = int(self._b2cratio * chars_to_skip) 23747db96d56Sopenharmony_ci skip_back = 1 23757db96d56Sopenharmony_ci assert skip_bytes <= len(next_input) 23767db96d56Sopenharmony_ci while skip_bytes > 0: 23777db96d56Sopenharmony_ci decoder.setstate((b'', dec_flags)) 23787db96d56Sopenharmony_ci # Decode up to temptative start point 23797db96d56Sopenharmony_ci n = len(decoder.decode(next_input[:skip_bytes])) 23807db96d56Sopenharmony_ci if n <= chars_to_skip: 23817db96d56Sopenharmony_ci b, d = decoder.getstate() 23827db96d56Sopenharmony_ci if not b: 23837db96d56Sopenharmony_ci # Before pos and no bytes buffered in decoder => OK 23847db96d56Sopenharmony_ci dec_flags = d 23857db96d56Sopenharmony_ci chars_to_skip -= n 23867db96d56Sopenharmony_ci break 23877db96d56Sopenharmony_ci # Skip back by buffered amount and reset heuristic 23887db96d56Sopenharmony_ci skip_bytes -= len(b) 23897db96d56Sopenharmony_ci skip_back = 1 23907db96d56Sopenharmony_ci else: 23917db96d56Sopenharmony_ci # We're too far ahead, skip back a bit 23927db96d56Sopenharmony_ci skip_bytes -= skip_back 23937db96d56Sopenharmony_ci skip_back = skip_back * 2 23947db96d56Sopenharmony_ci else: 23957db96d56Sopenharmony_ci skip_bytes = 0 23967db96d56Sopenharmony_ci decoder.setstate((b'', dec_flags)) 23977db96d56Sopenharmony_ci 23987db96d56Sopenharmony_ci # Note our initial start point. 23997db96d56Sopenharmony_ci start_pos = position + skip_bytes 24007db96d56Sopenharmony_ci start_flags = dec_flags 24017db96d56Sopenharmony_ci if chars_to_skip == 0: 24027db96d56Sopenharmony_ci # We haven't moved from the start point. 24037db96d56Sopenharmony_ci return self._pack_cookie(start_pos, start_flags) 24047db96d56Sopenharmony_ci 24057db96d56Sopenharmony_ci # Feed the decoder one byte at a time. As we go, note the 24067db96d56Sopenharmony_ci # nearest "safe start point" before the current location 24077db96d56Sopenharmony_ci # (a point where the decoder has nothing buffered, so seek() 24087db96d56Sopenharmony_ci # can safely start from there and advance to this location). 24097db96d56Sopenharmony_ci bytes_fed = 0 24107db96d56Sopenharmony_ci need_eof = False 24117db96d56Sopenharmony_ci # Chars decoded since `start_pos` 24127db96d56Sopenharmony_ci chars_decoded = 0 24137db96d56Sopenharmony_ci for i in range(skip_bytes, len(next_input)): 24147db96d56Sopenharmony_ci bytes_fed += 1 24157db96d56Sopenharmony_ci chars_decoded += len(decoder.decode(next_input[i:i+1])) 24167db96d56Sopenharmony_ci dec_buffer, dec_flags = decoder.getstate() 24177db96d56Sopenharmony_ci if not dec_buffer and chars_decoded <= chars_to_skip: 24187db96d56Sopenharmony_ci # Decoder buffer is empty, so this is a safe start point. 24197db96d56Sopenharmony_ci start_pos += bytes_fed 24207db96d56Sopenharmony_ci chars_to_skip -= chars_decoded 24217db96d56Sopenharmony_ci start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 24227db96d56Sopenharmony_ci if chars_decoded >= chars_to_skip: 24237db96d56Sopenharmony_ci break 24247db96d56Sopenharmony_ci else: 24257db96d56Sopenharmony_ci # We didn't get enough decoded data; signal EOF to get more. 24267db96d56Sopenharmony_ci chars_decoded += len(decoder.decode(b'', final=True)) 24277db96d56Sopenharmony_ci need_eof = True 24287db96d56Sopenharmony_ci if chars_decoded < chars_to_skip: 24297db96d56Sopenharmony_ci raise OSError("can't reconstruct logical file position") 24307db96d56Sopenharmony_ci 24317db96d56Sopenharmony_ci # The returned cookie corresponds to the last safe start point. 24327db96d56Sopenharmony_ci return self._pack_cookie( 24337db96d56Sopenharmony_ci start_pos, start_flags, bytes_fed, need_eof, chars_to_skip) 24347db96d56Sopenharmony_ci finally: 24357db96d56Sopenharmony_ci decoder.setstate(saved_state) 24367db96d56Sopenharmony_ci 24377db96d56Sopenharmony_ci def truncate(self, pos=None): 24387db96d56Sopenharmony_ci self.flush() 24397db96d56Sopenharmony_ci if pos is None: 24407db96d56Sopenharmony_ci pos = self.tell() 24417db96d56Sopenharmony_ci return self.buffer.truncate(pos) 24427db96d56Sopenharmony_ci 24437db96d56Sopenharmony_ci def detach(self): 24447db96d56Sopenharmony_ci if self.buffer is None: 24457db96d56Sopenharmony_ci raise ValueError("buffer is already detached") 24467db96d56Sopenharmony_ci self.flush() 24477db96d56Sopenharmony_ci buffer = self._buffer 24487db96d56Sopenharmony_ci self._buffer = None 24497db96d56Sopenharmony_ci return buffer 24507db96d56Sopenharmony_ci 24517db96d56Sopenharmony_ci def seek(self, cookie, whence=0): 24527db96d56Sopenharmony_ci def _reset_encoder(position): 24537db96d56Sopenharmony_ci """Reset the encoder (merely useful for proper BOM handling)""" 24547db96d56Sopenharmony_ci try: 24557db96d56Sopenharmony_ci encoder = self._encoder or self._get_encoder() 24567db96d56Sopenharmony_ci except LookupError: 24577db96d56Sopenharmony_ci # Sometimes the encoder doesn't exist 24587db96d56Sopenharmony_ci pass 24597db96d56Sopenharmony_ci else: 24607db96d56Sopenharmony_ci if position != 0: 24617db96d56Sopenharmony_ci encoder.setstate(0) 24627db96d56Sopenharmony_ci else: 24637db96d56Sopenharmony_ci encoder.reset() 24647db96d56Sopenharmony_ci 24657db96d56Sopenharmony_ci if self.closed: 24667db96d56Sopenharmony_ci raise ValueError("tell on closed file") 24677db96d56Sopenharmony_ci if not self._seekable: 24687db96d56Sopenharmony_ci raise UnsupportedOperation("underlying stream is not seekable") 24697db96d56Sopenharmony_ci if whence == SEEK_CUR: 24707db96d56Sopenharmony_ci if cookie != 0: 24717db96d56Sopenharmony_ci raise UnsupportedOperation("can't do nonzero cur-relative seeks") 24727db96d56Sopenharmony_ci # Seeking to the current position should attempt to 24737db96d56Sopenharmony_ci # sync the underlying buffer with the current position. 24747db96d56Sopenharmony_ci whence = 0 24757db96d56Sopenharmony_ci cookie = self.tell() 24767db96d56Sopenharmony_ci elif whence == SEEK_END: 24777db96d56Sopenharmony_ci if cookie != 0: 24787db96d56Sopenharmony_ci raise UnsupportedOperation("can't do nonzero end-relative seeks") 24797db96d56Sopenharmony_ci self.flush() 24807db96d56Sopenharmony_ci position = self.buffer.seek(0, whence) 24817db96d56Sopenharmony_ci self._set_decoded_chars('') 24827db96d56Sopenharmony_ci self._snapshot = None 24837db96d56Sopenharmony_ci if self._decoder: 24847db96d56Sopenharmony_ci self._decoder.reset() 24857db96d56Sopenharmony_ci _reset_encoder(position) 24867db96d56Sopenharmony_ci return position 24877db96d56Sopenharmony_ci if whence != 0: 24887db96d56Sopenharmony_ci raise ValueError("unsupported whence (%r)" % (whence,)) 24897db96d56Sopenharmony_ci if cookie < 0: 24907db96d56Sopenharmony_ci raise ValueError("negative seek position %r" % (cookie,)) 24917db96d56Sopenharmony_ci self.flush() 24927db96d56Sopenharmony_ci 24937db96d56Sopenharmony_ci # The strategy of seek() is to go back to the safe start point 24947db96d56Sopenharmony_ci # and replay the effect of read(chars_to_skip) from there. 24957db96d56Sopenharmony_ci start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \ 24967db96d56Sopenharmony_ci self._unpack_cookie(cookie) 24977db96d56Sopenharmony_ci 24987db96d56Sopenharmony_ci # Seek back to the safe start point. 24997db96d56Sopenharmony_ci self.buffer.seek(start_pos) 25007db96d56Sopenharmony_ci self._set_decoded_chars('') 25017db96d56Sopenharmony_ci self._snapshot = None 25027db96d56Sopenharmony_ci 25037db96d56Sopenharmony_ci # Restore the decoder to its state from the safe start point. 25047db96d56Sopenharmony_ci if cookie == 0 and self._decoder: 25057db96d56Sopenharmony_ci self._decoder.reset() 25067db96d56Sopenharmony_ci elif self._decoder or dec_flags or chars_to_skip: 25077db96d56Sopenharmony_ci self._decoder = self._decoder or self._get_decoder() 25087db96d56Sopenharmony_ci self._decoder.setstate((b'', dec_flags)) 25097db96d56Sopenharmony_ci self._snapshot = (dec_flags, b'') 25107db96d56Sopenharmony_ci 25117db96d56Sopenharmony_ci if chars_to_skip: 25127db96d56Sopenharmony_ci # Just like _read_chunk, feed the decoder and save a snapshot. 25137db96d56Sopenharmony_ci input_chunk = self.buffer.read(bytes_to_feed) 25147db96d56Sopenharmony_ci self._set_decoded_chars( 25157db96d56Sopenharmony_ci self._decoder.decode(input_chunk, need_eof)) 25167db96d56Sopenharmony_ci self._snapshot = (dec_flags, input_chunk) 25177db96d56Sopenharmony_ci 25187db96d56Sopenharmony_ci # Skip chars_to_skip of the decoded characters. 25197db96d56Sopenharmony_ci if len(self._decoded_chars) < chars_to_skip: 25207db96d56Sopenharmony_ci raise OSError("can't restore logical file position") 25217db96d56Sopenharmony_ci self._decoded_chars_used = chars_to_skip 25227db96d56Sopenharmony_ci 25237db96d56Sopenharmony_ci _reset_encoder(cookie) 25247db96d56Sopenharmony_ci return cookie 25257db96d56Sopenharmony_ci 25267db96d56Sopenharmony_ci def read(self, size=None): 25277db96d56Sopenharmony_ci self._checkReadable() 25287db96d56Sopenharmony_ci if size is None: 25297db96d56Sopenharmony_ci size = -1 25307db96d56Sopenharmony_ci else: 25317db96d56Sopenharmony_ci try: 25327db96d56Sopenharmony_ci size_index = size.__index__ 25337db96d56Sopenharmony_ci except AttributeError: 25347db96d56Sopenharmony_ci raise TypeError(f"{size!r} is not an integer") 25357db96d56Sopenharmony_ci else: 25367db96d56Sopenharmony_ci size = size_index() 25377db96d56Sopenharmony_ci decoder = self._decoder or self._get_decoder() 25387db96d56Sopenharmony_ci if size < 0: 25397db96d56Sopenharmony_ci # Read everything. 25407db96d56Sopenharmony_ci result = (self._get_decoded_chars() + 25417db96d56Sopenharmony_ci decoder.decode(self.buffer.read(), final=True)) 25427db96d56Sopenharmony_ci self._set_decoded_chars('') 25437db96d56Sopenharmony_ci self._snapshot = None 25447db96d56Sopenharmony_ci return result 25457db96d56Sopenharmony_ci else: 25467db96d56Sopenharmony_ci # Keep reading chunks until we have size characters to return. 25477db96d56Sopenharmony_ci eof = False 25487db96d56Sopenharmony_ci result = self._get_decoded_chars(size) 25497db96d56Sopenharmony_ci while len(result) < size and not eof: 25507db96d56Sopenharmony_ci eof = not self._read_chunk() 25517db96d56Sopenharmony_ci result += self._get_decoded_chars(size - len(result)) 25527db96d56Sopenharmony_ci return result 25537db96d56Sopenharmony_ci 25547db96d56Sopenharmony_ci def __next__(self): 25557db96d56Sopenharmony_ci self._telling = False 25567db96d56Sopenharmony_ci line = self.readline() 25577db96d56Sopenharmony_ci if not line: 25587db96d56Sopenharmony_ci self._snapshot = None 25597db96d56Sopenharmony_ci self._telling = self._seekable 25607db96d56Sopenharmony_ci raise StopIteration 25617db96d56Sopenharmony_ci return line 25627db96d56Sopenharmony_ci 25637db96d56Sopenharmony_ci def readline(self, size=None): 25647db96d56Sopenharmony_ci if self.closed: 25657db96d56Sopenharmony_ci raise ValueError("read from closed file") 25667db96d56Sopenharmony_ci if size is None: 25677db96d56Sopenharmony_ci size = -1 25687db96d56Sopenharmony_ci else: 25697db96d56Sopenharmony_ci try: 25707db96d56Sopenharmony_ci size_index = size.__index__ 25717db96d56Sopenharmony_ci except AttributeError: 25727db96d56Sopenharmony_ci raise TypeError(f"{size!r} is not an integer") 25737db96d56Sopenharmony_ci else: 25747db96d56Sopenharmony_ci size = size_index() 25757db96d56Sopenharmony_ci 25767db96d56Sopenharmony_ci # Grab all the decoded text (we will rewind any extra bits later). 25777db96d56Sopenharmony_ci line = self._get_decoded_chars() 25787db96d56Sopenharmony_ci 25797db96d56Sopenharmony_ci start = 0 25807db96d56Sopenharmony_ci # Make the decoder if it doesn't already exist. 25817db96d56Sopenharmony_ci if not self._decoder: 25827db96d56Sopenharmony_ci self._get_decoder() 25837db96d56Sopenharmony_ci 25847db96d56Sopenharmony_ci pos = endpos = None 25857db96d56Sopenharmony_ci while True: 25867db96d56Sopenharmony_ci if self._readtranslate: 25877db96d56Sopenharmony_ci # Newlines are already translated, only search for \n 25887db96d56Sopenharmony_ci pos = line.find('\n', start) 25897db96d56Sopenharmony_ci if pos >= 0: 25907db96d56Sopenharmony_ci endpos = pos + 1 25917db96d56Sopenharmony_ci break 25927db96d56Sopenharmony_ci else: 25937db96d56Sopenharmony_ci start = len(line) 25947db96d56Sopenharmony_ci 25957db96d56Sopenharmony_ci elif self._readuniversal: 25967db96d56Sopenharmony_ci # Universal newline search. Find any of \r, \r\n, \n 25977db96d56Sopenharmony_ci # The decoder ensures that \r\n are not split in two pieces 25987db96d56Sopenharmony_ci 25997db96d56Sopenharmony_ci # In C we'd look for these in parallel of course. 26007db96d56Sopenharmony_ci nlpos = line.find("\n", start) 26017db96d56Sopenharmony_ci crpos = line.find("\r", start) 26027db96d56Sopenharmony_ci if crpos == -1: 26037db96d56Sopenharmony_ci if nlpos == -1: 26047db96d56Sopenharmony_ci # Nothing found 26057db96d56Sopenharmony_ci start = len(line) 26067db96d56Sopenharmony_ci else: 26077db96d56Sopenharmony_ci # Found \n 26087db96d56Sopenharmony_ci endpos = nlpos + 1 26097db96d56Sopenharmony_ci break 26107db96d56Sopenharmony_ci elif nlpos == -1: 26117db96d56Sopenharmony_ci # Found lone \r 26127db96d56Sopenharmony_ci endpos = crpos + 1 26137db96d56Sopenharmony_ci break 26147db96d56Sopenharmony_ci elif nlpos < crpos: 26157db96d56Sopenharmony_ci # Found \n 26167db96d56Sopenharmony_ci endpos = nlpos + 1 26177db96d56Sopenharmony_ci break 26187db96d56Sopenharmony_ci elif nlpos == crpos + 1: 26197db96d56Sopenharmony_ci # Found \r\n 26207db96d56Sopenharmony_ci endpos = crpos + 2 26217db96d56Sopenharmony_ci break 26227db96d56Sopenharmony_ci else: 26237db96d56Sopenharmony_ci # Found \r 26247db96d56Sopenharmony_ci endpos = crpos + 1 26257db96d56Sopenharmony_ci break 26267db96d56Sopenharmony_ci else: 26277db96d56Sopenharmony_ci # non-universal 26287db96d56Sopenharmony_ci pos = line.find(self._readnl) 26297db96d56Sopenharmony_ci if pos >= 0: 26307db96d56Sopenharmony_ci endpos = pos + len(self._readnl) 26317db96d56Sopenharmony_ci break 26327db96d56Sopenharmony_ci 26337db96d56Sopenharmony_ci if size >= 0 and len(line) >= size: 26347db96d56Sopenharmony_ci endpos = size # reached length size 26357db96d56Sopenharmony_ci break 26367db96d56Sopenharmony_ci 26377db96d56Sopenharmony_ci # No line ending seen yet - get more data' 26387db96d56Sopenharmony_ci while self._read_chunk(): 26397db96d56Sopenharmony_ci if self._decoded_chars: 26407db96d56Sopenharmony_ci break 26417db96d56Sopenharmony_ci if self._decoded_chars: 26427db96d56Sopenharmony_ci line += self._get_decoded_chars() 26437db96d56Sopenharmony_ci else: 26447db96d56Sopenharmony_ci # end of file 26457db96d56Sopenharmony_ci self._set_decoded_chars('') 26467db96d56Sopenharmony_ci self._snapshot = None 26477db96d56Sopenharmony_ci return line 26487db96d56Sopenharmony_ci 26497db96d56Sopenharmony_ci if size >= 0 and endpos > size: 26507db96d56Sopenharmony_ci endpos = size # don't exceed size 26517db96d56Sopenharmony_ci 26527db96d56Sopenharmony_ci # Rewind _decoded_chars to just after the line ending we found. 26537db96d56Sopenharmony_ci self._rewind_decoded_chars(len(line) - endpos) 26547db96d56Sopenharmony_ci return line[:endpos] 26557db96d56Sopenharmony_ci 26567db96d56Sopenharmony_ci @property 26577db96d56Sopenharmony_ci def newlines(self): 26587db96d56Sopenharmony_ci return self._decoder.newlines if self._decoder else None 26597db96d56Sopenharmony_ci 26607db96d56Sopenharmony_ci 26617db96d56Sopenharmony_ciclass StringIO(TextIOWrapper): 26627db96d56Sopenharmony_ci """Text I/O implementation using an in-memory buffer. 26637db96d56Sopenharmony_ci 26647db96d56Sopenharmony_ci The initial_value argument sets the value of object. The newline 26657db96d56Sopenharmony_ci argument is like the one of TextIOWrapper's constructor. 26667db96d56Sopenharmony_ci """ 26677db96d56Sopenharmony_ci 26687db96d56Sopenharmony_ci def __init__(self, initial_value="", newline="\n"): 26697db96d56Sopenharmony_ci super(StringIO, self).__init__(BytesIO(), 26707db96d56Sopenharmony_ci encoding="utf-8", 26717db96d56Sopenharmony_ci errors="surrogatepass", 26727db96d56Sopenharmony_ci newline=newline) 26737db96d56Sopenharmony_ci # Issue #5645: make universal newlines semantics the same as in the 26747db96d56Sopenharmony_ci # C version, even under Windows. 26757db96d56Sopenharmony_ci if newline is None: 26767db96d56Sopenharmony_ci self._writetranslate = False 26777db96d56Sopenharmony_ci if initial_value is not None: 26787db96d56Sopenharmony_ci if not isinstance(initial_value, str): 26797db96d56Sopenharmony_ci raise TypeError("initial_value must be str or None, not {0}" 26807db96d56Sopenharmony_ci .format(type(initial_value).__name__)) 26817db96d56Sopenharmony_ci self.write(initial_value) 26827db96d56Sopenharmony_ci self.seek(0) 26837db96d56Sopenharmony_ci 26847db96d56Sopenharmony_ci def getvalue(self): 26857db96d56Sopenharmony_ci self.flush() 26867db96d56Sopenharmony_ci decoder = self._decoder or self._get_decoder() 26877db96d56Sopenharmony_ci old_state = decoder.getstate() 26887db96d56Sopenharmony_ci decoder.reset() 26897db96d56Sopenharmony_ci try: 26907db96d56Sopenharmony_ci return decoder.decode(self.buffer.getvalue(), final=True) 26917db96d56Sopenharmony_ci finally: 26927db96d56Sopenharmony_ci decoder.setstate(old_state) 26937db96d56Sopenharmony_ci 26947db96d56Sopenharmony_ci def __repr__(self): 26957db96d56Sopenharmony_ci # TextIOWrapper tells the encoding in its repr. In StringIO, 26967db96d56Sopenharmony_ci # that's an implementation detail. 26977db96d56Sopenharmony_ci return object.__repr__(self) 26987db96d56Sopenharmony_ci 26997db96d56Sopenharmony_ci @property 27007db96d56Sopenharmony_ci def errors(self): 27017db96d56Sopenharmony_ci return None 27027db96d56Sopenharmony_ci 27037db96d56Sopenharmony_ci @property 27047db96d56Sopenharmony_ci def encoding(self): 27057db96d56Sopenharmony_ci return None 27067db96d56Sopenharmony_ci 27077db96d56Sopenharmony_ci def detach(self): 27087db96d56Sopenharmony_ci # This doesn't make sense on StringIO. 27097db96d56Sopenharmony_ci self._unsupported("detach") 2710