python implementation of the io module import thread instead of threading to reduce startup cost open uses stblksize whenever we can note base classes defined here are registered with the official abcs defined in io py we don t use real inheritance though because we don t want to inherit the c implementations rebind for compatibility does open check its errors argument a helper function to choose the text encoding when encoding is not none this function returns it otherwise this function returns the default text encoding i e locale or utf8 depends on utf8 mode this function emits an encodingwarning if encoding is none and sys flags warndefaultencoding is true this can be used in apis with an encodingnone parameter that pass it to textiowrapper or open however please consider using encodingutf8 for new apis wrapper for builtins open trick so that open won t become a bound method when stored as a class variable as dbm dumb does see initsetbuiltinsopen in pythonpylifecycle c if not isinstancefile int file os fspathfile if not isinstancefile str bytes int raise typeerrorinvalid file r file if not isinstancemode str raise typeerrorinvalid mode r mode if not isinstancebuffering int raise typeerrorinvalid buffering r buffering if encoding is not none and not isinstanceencoding str raise typeerrorinvalid encoding r encoding if errors is not none and not isinstanceerrors str raise typeerrorinvalid errors r errors modes setmode if modes setaxrwbt or lenmode lenmodes raise valueerrorinvalid mode r mode creating x in modes reading r in modes writing w in modes appending a in modes updating in modes text t in modes binary b in modes if text and binary raise valueerrorcan t have text and binary mode at once if creating reading writing appending 1 raise valueerrorcan t have readwriteappend mode at once if not creating or reading or writing or appending raise valueerrormust have exactly one of readwriteappend mode if binary and encoding is not none raise valueerrorbinary mode doesn t take an encoding argument if binary and errors is not none raise valueerrorbinary mode doesn t take an errors argument if binary and newline is not none raise valueerrorbinary mode doesn t take a newline argument if binary and buffering 1 import warnings warnings warnline buffering buffering1 isn t supported in binary mode the default buffer size will be used runtimewarning 2 raw fileiofile creating and x or reading and r or writing and w or appending and a or updating and or closefd openeropener result raw try linebuffering false if buffering 1 or buffering 0 and raw isatty buffering 1 linebuffering true if buffering 0 buffering defaultbuffersize try bs os fstatraw fileno stblksize except oserror attributeerror pass else if bs 1 buffering bs if buffering 0 raise valueerrorinvalid buffering size if buffering 0 if binary return result raise valueerrorcan t have unbuffered text io if updating buffer bufferedrandomraw buffering elif creating or writing or appending buffer bufferedwriterraw buffering elif reading buffer bufferedreaderraw buffering else raise valueerrorunknown mode r mode result buffer if binary return result encoding textencodingencoding text textiowrapperbuffer encoding errors newline linebuffering result text text mode mode return result except result close raise define a default purepython implementation for opencode that does not allow hooks warn on first use defined for tests def opencodewithwarningpath import warnings warnings warnpyio opencode may not be using hooks runtimewarning 2 return openpath rb try opencode io opencode except attributeerror opencode opencodewithwarning in normal operation both unsupportedoperations should be bound to the same object try unsupportedoperation io unsupportedoperation except attributeerror class unsupportedoperationoserror valueerror pass class iobasemetaclassabc abcmeta internal def unsupportedself name positioning change stream position change the stream position to byte offset pos argument pos is interpreted relative to the position indicated by whence values for whence are ints 0 start of stream the default offset should be zero or positive 1 current stream position offset may be negative 2 end of stream offset is usually negative some operating systems file systems could provide additional values return an int indicating the new absolute position return an int indicating the current stream position return self seek0 1 def truncateself posnone self unsupportedtruncate flush and close def flushself self checkclosed xxx should this return the number of bytes written closed false def closeself if not self closed try self flush finally self closed true def delself if getting closed fails then the object is probably in an unusable state so ignore if close fails the caller logs the exception with sys unraisablehook close must be called at the end at del inquiries return a bool indicating whether object supports random access if false seek tell and truncate will raise oserror this method may need to do a test seek internal raise unsupportedoperation if file is not seekable return a bool indicating whether object was opened for reading if false read will raise oserror internal raise unsupportedoperation if file is not readable return a bool indicating whether object was opened for writing if false write and truncate will raise oserror internal raise unsupportedoperation if file is not writable closed bool true iff the file has been closed for backwards compatibility this is a property not a predicate internal raise a valueerror if file is closed context manager context management protocol returns self an instance of iobase self checkclosed return self def exitself args lowerlevel apis xxx should these be present even if unimplemented returns underlying file descriptor an int if one exists an oserror is raised if the io object does not use a file descriptor return a bool indicating whether this is an interactive stream return false if it can t be determined readlines and writelines for backwards compatibility a slowish readline if hasattrself peek def nreadahead readahead self peek1 if not readahead return 1 n readahead findbn 1 or lenreadahead if size 0 n minn size return n else def nreadahead return 1 if size is none size 1 else try sizeindex size index except attributeerror raise typeerrorfsize r is not an integer else size sizeindex res bytearray while size 0 or lenres size b self readnreadahead if not b break res b if res endswithbn break return bytesres def iterself self checkclosed return self def nextself line self readline if not line raise stopiteration return line def readlinesself hintnone if hint is none or hint 0 return listself n 0 lines for line in self lines appendline n lenline if n hint break return lines def writelinesself lines self checkclosed for line in lines self writeline io iobase registeriobase class rawiobaseiobase the read method is implemented by calling readinto derived classes that want to support read only need to implement readinto as a primitive operation in general readinto can be more efficient than read it would be tempting to also provide an implementation of readinto in terms of read in case the latter is a more suitable primitive operation but that would lead to nasty recursion in case a subclass doesn t implement either read and return up to size bytes where size is an int returns an empty bytes object on eof or none if the object is set not to block and has no data to read read until eof using multiple read call res bytearray while data self readdefaultbuffersize res data if res return bytesres else b or none return data def readintoself b self unsupportedreadinto def writeself b self unsupportedwrite io rawiobase registerrawiobase from io import fileio rawiobase registerfileio class bufferediobaseiobase def readself size1 self unsupportedread def read1self size1 self unsupportedread1 def readintoself b return self readintob read1false def readinto1self b return self readintob read1true def readintoself b read1 if not isinstanceb memoryview b memoryviewb b b cast b if read1 data self read1lenb else data self readlenb n lendata b n data return n def writeself b self unsupportedwrite def detachself self unsupporteddetach io bufferediobase registerbufferediobase class bufferediomixinbufferediobase def initself raw self raw raw positioning def seekself pos whence0 newposition self raw seekpos whence if newposition 0 raise oserrorseek returned an invalid position return newposition def tellself pos self raw tell if pos 0 raise oserrortell returned an invalid position return pos def truncateself posnone self checkclosed self checkwritable flush the stream we re mixing buffered io with lowerlevel io and a flush may be necessary to synch both views of the current file state self flush if pos is none pos self tell xxx should seek be used instead of passing the position xxx directly to truncate return self raw truncatepos flush and close def flushself if self closed raise valueerrorflush on closed file self raw flush def closeself if self raw is not none and not self closed try may raise blockingioerror or brokenpipeerror etc self flush finally self raw close def detachself if self raw is none raise valueerrorraw stream already detached self flush raw self raw self raw none return raw inquiries def seekableself return self raw seekable property def rawself return self raw property def closedself return self raw closed property def nameself return self raw name property def modeself return self raw mode def getstateself raise typeerrorfcannot pickle self class name r object def reprself modname self class module clsname self class qualname try name self name except attributeerror return formatmodname clsname else return name r formatmodname clsname name lowerlevel apis def filenoself return self raw fileno def isattyself return self raw isatty class bytesiobufferediobase initialize buffer as soon as possible since it s used by del which calls close return the bytes value contents of the buffer return a readable and writable view of the buffer this is the same as read inserts null bytes between the current end of the file and the new write position bufferedreaderraw buffersize a buffer for a readable sequential baserawio object the constructor creates a bufferedreader for the given readable raw stream and buffersize if buffersize is omitted defaultbuffersize is used create a new buffered reader using the given readable raw io object read size bytes returns exactly size bytes of data unless the underlying raw io stream reaches eof or if the call would block in nonblocking mode if size is negative read until eof or until read would block special case for when the number of bytes to read is unspecified read until eof or until read would block the number of bytes to read is specified return at most n bytes fast path the data to read is fully buffered slow path read from the stream until enough bytes are read or until an eof occurs or until read would block n is more than avail only when an eof occurred or when read would have blocked returns buffered bytes without advancing the position the argument indicates a desired minimal number of bytes we do at most one raw read to satisfy it we never return more than self buffersize reads up to size bytes with at most one read system call returns up to size bytes if at least one byte is buffered we only return buffered bytes otherwise we do one raw read self checkclosedread of closed file if size 0 size self buffersize if size 0 return b with self readlock self peekunlocked1 return self readunlocked minsize lenself readbuf self readpos implementing readinto and readinto1 is not strictly necessary we could rely on the base class that provides an implementation in terms of read and read1 we do it anyway to keep the pyio implementation similar to the io implementation which implements the methods for performance reasons def readintoself buf read1 need to create a memoryview object of type b otherwise we may not be able to assign bytes to it and slicing it would create a new object first try to read from internal buffer if remaining space in callers buffer is larger than internal buffer read directly into callers buffer otherwise refill internal buffer unless we re in read1 mode and already got some data in readinto1 mode return as soon as we have some data a buffer for a writeable sequential rawio object the constructor creates a bufferedwriter for the given writeable raw stream if the buffersize is not given it defaults to defaultbuffersize xxx we can implement some more tricks to try and avoid partial writes we re full so let s preflush the buffer this may raise blockingioerror with characterswritten 0 we ve hit the buffersize we have to accept a partial write and cut back our buffer we have to release the lock and call self flush which will probably just retake the lock in case flush has been overridden in a subclass or the user set self flush to something this is the same behavior as the c implementation may raise blockingioerror or brokenpipeerror etc a buffered reader and writer object together a buffered reader object and buffered writer object put together to form a sequential io object that can read and write this is typically used with a socket or twoway pipe reader and writer are rawiobase objects that are readable and writeable respectively if the buffersize is omitted it defaults to defaultbuffersize xxx the usefulness of this compared to having two separate io objects is questionable constructor the arguments are two rawio instances a buffered interface to random access streams the constructor creates a reader and writer for a seekable stream raw given in the first argument if the buffersize is omitted it defaults to defaultbuffersize undo read ahead first do the raw seek then empty the read buffer so that if the raw seek fails we don t lose buffered data forever use seek to flush the read buffer undo readahead open a file the mode can be r default w x or a for reading writing exclusive creation or appending the file will be created if it doesn t exist when opened for writing or appending it will be truncated when opened for writing a fileexistserror will be raised if it already exists when opened for creating opening a file for creating implies writing so this mode behaves in a similar way to w add a to the mode to allow simultaneous reading and writing a custom opener can be used by passing a callable as opener the underlying file descriptor for the file object is then obtained by calling opener with name flags opener must return an open file descriptor passing os open as opener results in functionality similar to passing none have to close the existing file first ignore the attributeerror if stat sisdir or errno eisdir don t exist don t translate newlines rn n for consistent behaviour we explicitly seek to the end of file otherwise it might be done only on the first write read at most size bytes returned as bytes only makes one system call so less data may be returned than requested in nonblocking mode returns none if no data is available return an empty bytes object at eof read all data from the file returned as bytes in nonblocking mode returns as much as is immediately available or none if no data is available return an empty bytes object at eof same as rawiobase readinto m memoryviewb cast b data self readlenm n lendata m n data return n def writeself b self checkclosed self checkwritable try return os writeself fd b except blockingioerror return none def seekself pos whenceseekset if isinstancepos float raise typeerror an integer is required self checkclosed return os lseekself fd pos whence def tellself truncate the file to at most size bytes size defaults to the current file position as returned by tell the current file position is changed to the value of size close the file a closed file cannot be used for further io operations close may be called more than once without error true if file supports randomaccess self checkclosed if self seekable is none try self tell except oserror self seekable false else self seekable true return self seekable def readableself true if file was opened in a write mode self checkclosed return self writable def filenoself true if the file is connected to a tty device self checkclosed return os isattyself fd property def closefdself string giving the file mode if self created if self readable return xb else return xb elif self appending if self readable return ab else return ab elif self readable if self writable return rb else return rb else return wb class textiobaseiobase def readself size1 self unsupportedread def writeself s truncate size to pos where pos is an int self unsupportedtruncate def readlineself self unsupportedreadline def detachself self unsupporteddetach property def encodingself line endings translated so far only line endings translated during reading are considered subclasses should override error setting of the decoder or encoder subclasses should override return none io textiobase registertextiobase class incrementalnewlinedecodercodecs incrementaldecoder rcodec used when reading a file in universal newlines mode it wraps another incremental decoder translating rn and r into n it also records the types of newlines encountered when used with translatefalse it ensures that the newline sequence is returned in one piece decode input with the eventual r from a previous pass retain last r even when not translating data then readline is sure to get rn in one pass record which newlines are read chunksize 2048 initialize buffer as soon as possible since it s used by del which calls close buffer none the writethrough argument has no effect here since this implementation always writes through the argument is present only so that the signature can match the signature of the c version def initself buffer encodingnone errorsnone newlinenone linebufferingfalse writethroughfalse self checknewlinenewline encoding textencodingencoding if encoding locale encoding self getlocaleencoding if not isinstanceencoding str raise valueerrorinvalid encoding r encoding if not codecs lookupencoding istextencoding msg r is not a text encoding use codecs open to handle arbitrary codecs raise lookuperrormsg encoding if errors is none errors strict else if not isinstanceerrors str raise valueerrorinvalid errors r errors if checkerrors codecs lookuperrorerrors self buffer buffer self decodedchars buffer for text returned from decoder self decodedcharsused 0 offset into decodedchars for read self snapshot none info for reconstructing decoder state self seekable self telling self buffer seekable self hasread1 hasattrself buffer read1 self configureencoding errors newline linebuffering writethrough def checknewlineself newline if newline is not none and not isinstancenewline str raise typeerrorillegal newline type r typenewline if newline not in none n r rn raise valueerrorillegal newline value r newline def configureself encodingnone errorsnone newlinenone linebufferingfalse writethroughfalse self encoding encoding self errors errors self encoder none self decoder none self b2cratio 0 0 self readuniversal not newline self readtranslate newline is none self readnl newline self writetranslate newline self writenl newline or os linesep self linebuffering linebuffering self writethrough writethrough don t write a bom in the middle of a file if self seekable and self writable position self buffer tell if position 0 try self getencoder setstate0 except lookuperror sometimes the encoder doesn t exist pass self snapshot is either none or a tuple decflags nextinput where decflags is the second integer item of the decoder state and nextinput is the chunk of input bytes that comes next after the snapshot point we use this to reconstruct decoder states in tell naming convention bytes for integer variables that count input bytes chars for integer variables that count decoded characters def reprself result formatself class module self class qualname try name self name except attributeerror pass else result name0 r formatname try mode self mode except attributeerror pass else result mode0 r formatmode return result encoding0 r formatself encoding property def encodingself return self encoding property def errorsself return self errors property def linebufferingself return self linebuffering property def writethroughself return self writethrough property def bufferself return self buffer def reconfigureself encodingnone errorsnone newlineellipsis linebufferingnone writethroughnone if self decoder is not none and encoding is not none or errors is not none or newline is not ellipsis raise unsupportedoperation it is not possible to set the encoding or newline of stream after the first read if errors is none if encoding is none errors self errors else errors strict elif not isinstanceerrors str raise typeerrorinvalid errors r errors if encoding is none encoding self encoding else if not isinstanceencoding str raise typeerrorinvalid encoding r encoding if encoding locale encoding self getlocaleencoding if newline is ellipsis newline self readnl self checknewlinenewline if linebuffering is none linebuffering self linebuffering if writethrough is none writethrough self writethrough self flush self configureencoding errors newline linebuffering writethrough def seekableself if self closed raise valueerrorio operation on closed file return self seekable def readableself return self buffer readable def writableself return self buffer writable def flushself self buffer flush self telling self seekable def closeself if self buffer is not none and not self closed try self flush finally self buffer close property def closedself return self buffer closed property def nameself return self buffer name def filenoself return self buffer fileno def isattyself return self buffer isatty def writeself s write data where s is a str if self closed raise valueerrorwrite to closed file if not isinstances str raise typeerrorcan t write s to text stream s class name length lens haslf self writetranslate or self linebuffering and n in s if haslf and self writetranslate and self writenl n s s replacen self writenl encoder self encoder or self getencoder xxx what if we were just reading b encoder encodes self buffer writeb if self linebuffering and haslf or r in s self flush self setdecodedchars self snapshot none if self decoder self decoder reset return length def getencoderself makeencoder codecs getincrementalencoderself encoding self encoder makeencoderself errors return self encoder def getdecoderself makedecoder codecs getincrementaldecoderself encoding decoder makedecoderself errors if self readuniversal decoder incrementalnewlinedecoderdecoder self readtranslate self decoder decoder return decoder the following three methods implement an adt for decodedchars text returned from the decoder is buffered here until the client requests it by calling our read or readline method def setdecodedcharsself chars advance into the decodedchars buffer offset self decodedcharsused if n is none chars self decodedcharsoffset else chars self decodedcharsoffset offset n self decodedcharsused lenchars return chars def getlocaleencodingself try import locale except importerror importing locale may fail if python is being built return utf8 else return locale getencoding def rewinddecodedcharsself n read and decode the next chunk of data from the bufferedreader the return value is true unless eof was reached the decoded string is placed in self decodedchars replacing its previous value the entire input chunk is sent to the decoder though some of it may remain buffered in the decoder yet to be converted to prepare for tell we need to snapshot a point in the file where the decoder s input buffer is empty given this we know there was a valid snapshot point lendecbuffer bytes ago with decoder state b decflags read a chunk decode it and put the result in self decodedchars at the snapshot point lendecbuffer bytes before the read the next input to be decoded is decbuffer inputchunk the meaning of a tell cookie is seek to position set the decoder flags to decflags read bytestofeed bytes feed them into the decoder with needeof as the eof flag then skip charstoskip characters of the decoded result for most simple decoders tell will often just give a byte offset in the file this should never happen skip backward to the snapshot point see readchunk how many decoded characters have been used up since the snapshot we haven t moved from the snapshot point starting from the snapshot position we will walk the decoder forward until it gives us enough decoded characters fast search for an acceptable start point close to our current pos rationale calling decoder decode has a large overhead regardless of chunk size we want the number of such calls to be o1 in most situations common decoders sensible input actually it will be exactly 1 for fixedsize codecs all 8bit codecs also utf16 and utf32 decode up to temptative start point before pos and no bytes buffered in decoder ok skip back by buffered amount and reset heuristic we re too far ahead skip back a bit note our initial start point we haven t moved from the start point feed the decoder one byte at a time as we go note the nearest safe start point before the current location a point where the decoder has nothing buffered so seek can safely start from there and advance to this location chars decoded since startpos decoder buffer is empty so this is a safe start point we didn t get enough decoded data signal eof to get more the returned cookie corresponds to the last safe start point reset the encoder merely useful for proper bom handling try encoder self encoder or self getencoder except lookuperror sometimes the encoder doesn t exist pass else if position 0 encoder setstate0 else encoder reset if self closed raise valueerrortell on closed file if not self seekable raise unsupportedoperationunderlying stream is not seekable if whence seekcur if cookie 0 raise unsupportedoperationcan t do nonzero currelative seeks seeking to the current position should attempt to sync the underlying buffer with the current position whence 0 cookie self tell elif whence seekend if cookie 0 raise unsupportedoperationcan t do nonzero endrelative seeks self flush position self buffer seek0 whence self setdecodedchars self snapshot none if self decoder self decoder reset resetencoderposition return position if whence 0 raise valueerrorunsupported whence r whence if cookie 0 raise valueerrornegative seek position r cookie self flush the strategy of seek is to go back to the safe start point and replay the effect of readcharstoskip from there startpos decflags bytestofeed needeof charstoskip self unpackcookiecookie seek back to the safe start point self buffer seekstartpos self setdecodedchars self snapshot none restore the decoder to its state from the safe start point if cookie 0 and self decoder self decoder reset elif self decoder or decflags or charstoskip self decoder self decoder or self getdecoder self decoder setstateb decflags self snapshot decflags b if charstoskip just like readchunk feed the decoder and save a snapshot inputchunk self buffer readbytestofeed self setdecodedchars self decoder decodeinputchunk needeof self snapshot decflags inputchunk skip charstoskip of the decoded characters if lenself decodedchars charstoskip raise oserrorcan t restore logical file position self decodedcharsused charstoskip resetencodercookie return cookie def readself sizenone self checkreadable if size is none size 1 else try sizeindex size index except attributeerror raise typeerrorfsize r is not an integer else size sizeindex decoder self decoder or self getdecoder if size 0 read everything result self getdecodedchars decoder decodeself buffer read finaltrue self setdecodedchars self snapshot none return result else keep reading chunks until we have size characters to return eof false result self getdecodedcharssize while lenresult size and not eof eof not self readchunk result self getdecodedcharssize lenresult return result def nextself self telling false line self readline if not line self snapshot none self telling self seekable raise stopiteration return line def readlineself sizenone if self closed raise valueerrorread from closed file if size is none size 1 else try sizeindex size index except attributeerror raise typeerrorfsize r is not an integer else size sizeindex grab all the decoded text we will rewind any extra bits later line self getdecodedchars start 0 make the decoder if it doesn t already exist if not self decoder self getdecoder pos endpos none while true if self readtranslate newlines are already translated only search for n pos line find n start if pos 0 endpos pos 1 break else start lenline elif self readuniversal universal newline search find any of r rn n the decoder ensures that rn are not split in two pieces in c we d look for these in parallel of course nlpos line findn start crpos line findr start if crpos 1 if nlpos 1 nothing found start lenline else found n endpos nlpos 1 break elif nlpos 1 found lone r endpos crpos 1 break elif nlpos crpos found n endpos nlpos 1 break elif nlpos crpos 1 found rn endpos crpos 2 break else found r endpos crpos 1 break else nonuniversal pos line findself readnl if pos 0 endpos pos lenself readnl break if size 0 and lenline size endpos size reached length size break no line ending seen yet get more data while self readchunk if self decodedchars break if self decodedchars line self getdecodedchars else end of file self setdecodedchars self snapshot none return line if size 0 and endpos size endpos size don t exceed size rewind decodedchars to just after the line ending we found self rewinddecodedcharslenline endpos return line endpos property def newlinesself return self decoder newlines if self decoder else none class stringiotextiowrapper def initself initialvalue newlinen superstringio self initbytesio encodingutf8 errorssurrogatepass newlinenewline issue 5645 make universal newlines semantics the same as in the c version even under windows if newline is none self writetranslate false if initialvalue is not none if not isinstanceinitialvalue str raise typeerrorinitialvalue must be str or none not 0 formattypeinitialvalue name self writeinitialvalue self seek0 def getvalueself self flush decoder self decoder or self getdecoder oldstate decoder getstate decoder reset try return decoder decodeself buffer getvalue finaltrue finally decoder setstateoldstate def reprself textiowrapper tells the encoding in its repr in stringio that s an implementation detail return object reprself property def errorsself return none property def encodingself return none def detachself this doesn t make sense on stringio self unsupporteddetach import _thread instead of threading to reduce startup cost hardwired values open uses st_blksize whenever we can bytes note base classes defined here are registered with the official abcs defined in io py we don t use real inheritance though because we don t want to inherit the c implementations rebind for compatibility does open check its errors argument a helper function to choose the text encoding when encoding is not none this function returns it otherwise this function returns the default text encoding i e locale or utf 8 depends on utf 8 mode this function emits an encodingwarning if encoding is none and sys flags warn_default_encoding is true this can be used in apis with an encoding none parameter that pass it to textiowrapper or open however please consider using encoding utf 8 for new apis wrapper for builtins open trick so that open won t become a bound method when stored as a class variable as dbm dumb does see init_set_builtins_open in python pylifecycle c open file and return a stream raise oserror upon failure file is either a text or byte string giving the name and the path if the file isn t in the current working directory of the file to be opened or an integer file descriptor of the file to be wrapped if a file descriptor is given it is closed when the returned i o object is closed unless closefd is set to false mode is an optional string that specifies the mode in which the file is opened it defaults to r which means open for reading in text mode other common values are w for writing truncating the file if it already exists x for exclusive creation of a new file and a for appending which on some unix systems means that all writes append to the end of the file regardless of the current seek position in text mode if encoding is not specified the encoding used is platform dependent for reading and writing raw bytes use binary mode and leave encoding unspecified the available modes are character meaning r open for reading default w open for writing truncating the file first x create a new file and open it for writing a open for writing appending to the end of the file if it exists b binary mode t text mode default open a disk file for updating reading and writing the default mode is rt open for reading text for binary random access the mode w b opens and truncates the file to 0 bytes while r b opens the file without truncation the x mode implies w and raises an fileexistserror if the file already exists python distinguishes between files opened in binary and text modes even when the underlying operating system doesn t files opened in binary mode appending b to the mode argument return contents as bytes objects without any decoding in text mode the default or when t is appended to the mode argument the contents of the file are returned as strings the bytes having been first decoded using a platform dependent encoding or using the specified encoding if given buffering is an optional integer used to set the buffering policy pass 0 to switch buffering off only allowed in binary mode 1 to select line buffering only usable in text mode and an integer 1 to indicate the size of a fixed size chunk buffer when no buffering argument is given the default buffering policy works as follows binary files are buffered in fixed size chunks the size of the buffer is chosen using a heuristic trying to determine the underlying device s block size and falling back on io default_buffer_size on many systems the buffer will typically be 4096 or 8192 bytes long interactive text files files for which isatty returns true use line buffering other text files use the policy described above for binary files encoding is the str name of the encoding used to decode or encode the file this should only be used in text mode the default encoding is platform dependent but any encoding supported by python can be passed see the codecs module for the list of supported encodings errors is an optional string that specifies how encoding errors are to be handled this argument should not be used in binary mode pass strict to raise a valueerror exception if there is an encoding error the default of none has the same effect or pass ignore to ignore errors note that ignoring encoding errors can lead to data loss see the documentation for codecs register for a list of the permitted encoding error strings newline is a string controlling how universal newlines works it only applies to text mode it can be none n r and r n it works as follows on input if newline is none universal newlines mode is enabled lines in the input can end in n r or r n and these are translated into n before being returned to the caller if it is universal newline mode is enabled but line endings are returned to the caller untranslated if it has any of the other legal values input lines are only terminated by the given string and the line ending is returned to the caller untranslated on output if newline is none any n characters written are translated to the system default line separator os linesep if newline is no translation takes place if newline is any of the other legal values any n characters written are translated to the given string closedfd is a bool if closefd is false the underlying file descriptor will be kept open when the file is closed this does not work when a file name is given and must be true in that case the newly created file is non inheritable a custom opener can be used by passing a callable as opener the underlying file descriptor for the file object is then obtained by calling opener with file flags opener must return an open file descriptor passing os open as opener results in functionality similar to passing none open returns a file object whose type depends on the mode and through which the standard file operations such as reading and writing are performed when open is used to open a file in a text mode w r wt rt etc it returns a textiowrapper when used to open a file in a binary mode the returned class varies in read binary mode it returns a bufferedreader in write binary and append binary modes it returns a bufferedwriter and in read write mode it returns a bufferedrandom it is also possible to use a string or bytearray as a file for both reading and writing for strings stringio can be used like a file opened in a text mode and for bytes a bytesio can be used like a file opened in a binary mode define a default pure python implementation for open_code that does not allow hooks warn on first use defined for tests opens the provided file with mode rb this function should be used when the intent is to treat the contents as executable code path should be an absolute path when supported by the runtime this function can be hooked in order to allow embedders more control over code files this functionality is not supported on the current runtime in normal operation both unsupportedoperation s should be bound to the same object the abstract base class for all i o classes this class provides dummy implementations for many methods that derived classes can override selectively the default implementations represent a file that cannot be read written or seeked even though iobase does not declare read or write because their signatures will vary implementations and clients should consider those methods part of the interface also implementations may raise unsupportedoperation when operations they do not support are called the basic type used for binary data read from or written to a file is bytes other bytes like objects are accepted as method arguments too text i o classes work with str data note that calling any method even inquiries on a closed stream is undefined implementations may raise oserror in this case iobase and its subclasses support the iterator protocol meaning that an iobase object can be iterated over yielding the lines in a stream iobase also supports the keyword with statement in this example fp is closed after the suite of the with statement is complete with open spam txt r as fp fp write spam and eggs internal internal raise an oserror exception for unsupported operations positioning change stream position change the stream position to byte offset pos argument pos is interpreted relative to the position indicated by whence values for whence are ints 0 start of stream the default offset should be zero or positive 1 current stream position offset may be negative 2 end of stream offset is usually negative some operating systems file systems could provide additional values return an int indicating the new absolute position return an int indicating the current stream position truncate file to size bytes size defaults to the current io position as reported by tell return the new size flush and close flush write buffers if applicable this is not implemented for read only and non blocking streams xxx should this return the number of bytes written flush and close the io object this method has no effect if the file is already closed destructor calls close if getting closed fails then the object is probably in an unusable state so ignore if close fails the caller logs the exception with sys unraisablehook close must be called at the end at __del__ inquiries return a bool indicating whether object supports random access if false seek tell and truncate will raise oserror this method may need to do a test seek internal raise unsupportedoperation if file is not seekable return a bool indicating whether object was opened for reading if false read will raise oserror internal raise unsupportedoperation if file is not readable return a bool indicating whether object was opened for writing if false write and truncate will raise oserror internal raise unsupportedoperation if file is not writable closed bool true iff the file has been closed for backwards compatibility this is a property not a predicate internal raise a valueerror if file is closed context manager that s a forward reference context management protocol returns self an instance of iobase context management protocol calls close lower level apis xxx should these be present even if unimplemented returns underlying file descriptor an int if one exists an oserror is raised if the io object does not use a file descriptor return a bool indicating whether this is an interactive stream return false if it can t be determined readline s and writelines read and return a line of bytes from the stream if size is specified at most size bytes will be read size should be an int the line terminator is always b n for binary files for text files the newlines argument to open can be used to select the line terminator s recognized for backwards compatibility a slowish readline return a list of lines from the stream hint can be specified to control the number of lines read no more lines will be read if the total size in bytes characters of all lines so far exceeds hint write a list of lines to the stream line separators are not added so it is usual for each of the lines provided to have a line separator at the end base class for raw binary i o the read method is implemented by calling readinto derived classes that want to support read only need to implement readinto as a primitive operation in general readinto can be more efficient than read it would be tempting to also provide an implementation of readinto in terms of read in case the latter is a more suitable primitive operation but that would lead to nasty recursion in case a subclass doesn t implement either read and return up to size bytes where size is an int returns an empty bytes object on eof or none if the object is set not to block and has no data to read read until eof using multiple read call b or none read bytes into a pre allocated bytes like object b returns an int representing the number of bytes read 0 for eof or none if the object is set not to block and has no data to read write the given buffer to the io stream returns the number of bytes written which may be less than the length of b in bytes base class for buffered io objects the main difference with rawiobase is that the read method supports omitting the size argument and does not have a default implementation that defers to readinto in addition read readinto and write may raise blockingioerror if the underlying raw stream is in non blocking mode and not ready unlike their raw counterparts they will never return none a typical implementation should not inherit from a rawiobase implementation but wrap one read and return up to size bytes where size is an int if the argument is omitted none or negative reads and returns all data until eof if the argument is positive and the underlying raw stream is not interactive multiple raw reads may be issued to satisfy the byte count unless eof is reached first but for interactive raw streams xxx and for pipes at most one raw read will be issued and a short result does not imply that eof is imminent returns an empty bytes array on eof raises blockingioerror if the underlying raw stream has no data at the moment read up to size bytes with at most one read system call where size is an int read bytes into a pre allocated bytes like object b like read this may issue multiple reads to the underlying raw stream unless the latter is interactive returns an int representing the number of bytes read 0 for eof raises blockingioerror if the underlying raw stream has no data at the moment read bytes into buffer b using at most one system call returns an int representing the number of bytes read 0 for eof raises blockingioerror if the underlying raw stream has no data at the moment write the given bytes buffer to the io stream return the number of bytes written which is always the length of b in bytes raises blockingioerror if the buffer is full and the underlying raw stream cannot accept more data at the moment separate the underlying raw stream from the buffer and return it after the raw stream has been detached the buffer is in an unusable state a mixin implementation of bufferediobase with an underlying raw stream this passes most requests on to the underlying raw stream it does not provide implementations of read readinto or write positioning flush the stream we re mixing buffered i o with lower level i o and a flush may be necessary to synch both views of the current file state xxx should seek be used instead of passing the position xxx directly to truncate flush and close may raise blockingioerror or brokenpipeerror etc inquiries lower level apis buffered i o implementation using an in memory bytes buffer initialize _buffer as soon as possible since it s used by __del__ which calls close return the bytes value contents of the buffer return a readable and writable view of the buffer this is the same as read size of any bytes like object inserts null bytes between the current end of the file and the new write position bufferedreader raw buffer_size a buffer for a readable sequential baserawio object the constructor creates a bufferedreader for the given readable raw stream and buffer_size if buffer_size is omitted default_buffer_size is used create a new buffered reader using the given readable raw io object read size bytes returns exactly size bytes of data unless the underlying raw io stream reaches eof or if the call would block in non blocking mode if size is negative read until eof or until read would block special case for when the number of bytes to read is unspecified strip the consumed bytes read until eof or until read would block the number of bytes to read is specified return at most n bytes length of the available buffered data fast path the data to read is fully buffered slow path read from the stream until enough bytes are read or until an eof occurs or until read would block n is more than avail only when an eof occurred or when read would have blocked save the extra data in the buffer returns buffered bytes without advancing the position the argument indicates a desired minimal number of bytes we do at most one raw read to satisfy it we never return more than self buffer_size reads up to size bytes with at most one read system call returns up to size bytes if at least one byte is buffered we only return buffered bytes otherwise we do one raw read implementing readinto and readinto1 is not strictly necessary we could rely on the base class that provides an implementation in terms of read and read1 we do it anyway to keep the _pyio implementation similar to the io implementation which implements the methods for performance reasons read data into buf with at most one system call need to create a memoryview object of type b otherwise we may not be able to assign bytes to it and slicing it would create a new object first try to read from internal buffer if remaining space in callers buffer is larger than internal buffer read directly into callers buffer eof otherwise refill internal buffer unless we re in read1 mode and already got some data eof in readinto1 mode return as soon as we have some data a buffer for a writeable sequential rawio object the constructor creates a bufferedwriter for the given writeable raw stream if the buffer_size is not given it defaults to default_buffer_size xxx we can implement some more tricks to try and avoid partial writes we re full so let s pre flush the buffer this may raise blockingioerror with characters_written 0 we ve hit the buffer_size we have to accept a partial write and cut back our buffer we have to release the lock and call self flush which will probably just re take the lock in case flush has been overridden in a subclass or the user set self flush to something this is the same behavior as the c implementation may raise blockingioerror or brokenpipeerror etc a buffered reader and writer object together a buffered reader object and buffered writer object put together to form a sequential io object that can read and write this is typically used with a socket or two way pipe reader and writer are rawiobase objects that are readable and writeable respectively if the buffer_size is omitted it defaults to default_buffer_size xxx the usefulness of this compared to having two separate io objects is questionable constructor the arguments are two rawio instances a buffered interface to random access streams the constructor creates a reader and writer for a seekable stream raw given in the first argument if the buffer_size is omitted it defaults to default_buffer_size undo read ahead first do the raw seek then empty the read buffer so that if the raw seek fails we don t lose buffered data forever use seek to flush the read buffer undo readahead open a file the mode can be r default w x or a for reading writing exclusive creation or appending the file will be created if it doesn t exist when opened for writing or appending it will be truncated when opened for writing a fileexistserror will be raised if it already exists when opened for creating opening a file for creating implies writing so this mode behaves in a similar way to w add a to the mode to allow simultaneous reading and writing a custom opener can be used by passing a callable as opener the underlying file descriptor for the file object is then obtained by calling opener with name flags opener must return an open file descriptor passing os open as opener results in functionality similar to passing none have to close the existing file first ignore the attributeerror if stat s_isdir or errno eisdir don t exist don t translate newlines r n n for consistent behaviour we explicitly seek to the end of file otherwise it might be done only on the first write read at most size bytes returned as bytes only makes one system call so less data may be returned than requested in non blocking mode returns none if no data is available return an empty bytes object at eof read all data from the file returned as bytes in non blocking mode returns as much as is immediately available or none if no data is available return an empty bytes object at eof reached the end of the file same as rawiobase readinto write bytes b to file return number written only makes one system call so not all of the data may be written the number of bytes actually written is returned in non blocking mode returns none if the write would block move to new file position argument offset is a byte count optional argument whence defaults to seek_set or 0 offset from start of file offset should be 0 other values are seek_cur or 1 move relative to current position positive or negative and seek_end or 2 move relative to end of file usually negative although many platforms allow seeking beyond the end of a file note that not all file objects are seekable tell int current file position can raise oserror for non seekable files truncate the file to at most size bytes size defaults to the current file position as returned by tell the current file position is changed to the value of size close the file a closed file cannot be used for further i o operations close may be called more than once without error true if file supports random access true if file was opened in a read mode true if file was opened in a write mode return the underlying file descriptor an integer true if the file is connected to a tty device true if the file descriptor will be closed by close string giving the file mode base class for text i o this class provides a character and line based interface to stream i o read at most size characters from stream where size is an int read from underlying buffer until we have size characters or we hit eof if size is negative or omitted read until eof returns a string write string s to stream and returning an int truncate size to pos where pos is an int read until newline or eof returns an empty string if eof is hit immediately separate the underlying buffer from the textiobase and return it after the underlying buffer has been detached the textio is in an unusable state subclasses should override line endings translated so far only line endings translated during reading are considered subclasses should override error setting of the decoder or encoder subclasses should override codec used when reading a file in universal newlines mode it wraps another incremental decoder translating r n and r into n it also records the types of newlines encountered when used with translate false it ensures that the newline sequence is returned in one piece decode input with the eventual r from a previous pass retain last r even when not translating data then readline is sure to get r n in one pass record which newlines are read character and line based layer over a bufferediobase object buffer encoding gives the name of the encoding that the stream will be decoded or encoded with it defaults to locale getencoding errors determines the strictness of encoding and decoding see the codecs register and defaults to strict newline can be none n r or r n it controls the handling of line endings if it is none universal newlines is enabled with this enabled on input the lines endings n r or r n are translated to n before being returned to the caller conversely on output n is translated to the system default line separator os linesep if newline is any other of its legal values that newline becomes the newline when the file is read and it is returned untranslated on output n is converted to the newline if line_buffering is true a call to flush is implied when a call to write contains a newline character initialize _buffer as soon as possible since it s used by __del__ which calls close the write_through argument has no effect here since this implementation always writes through the argument is present only so that the signature can match the signature of the c version buffer for text returned from decoder offset into _decoded_chars for read info for reconstructing decoder state don t write a bom in the middle of a file sometimes the encoder doesn t exist self _snapshot is either none or a tuple dec_flags next_input where dec_flags is the second integer item of the decoder state and next_input is the chunk of input bytes that comes next after the snapshot point we use this to reconstruct decoder states in tell naming convention bytes_ for integer variables that count input bytes chars_ for integer variables that count decoded characters reconfigure the text stream with new parameters this also flushes the stream xxx what if we were just reading the following three methods implement an adt for _decoded_chars text returned from the decoder is buffered here until the client requests it by calling our read or readline method set the _decoded_chars buffer advance into the _decoded_chars buffer importing locale may fail if python is being built rewind the _decoded_chars buffer read and decode the next chunk of data from the bufferedreader the return value is true unless eof was reached the decoded string is placed in self _decoded_chars replacing its previous value the entire input chunk is sent to the decoder though some of it may remain buffered in the decoder yet to be converted to prepare for tell we need to snapshot a point in the file where the decoder s input buffer is empty given this we know there was a valid snapshot point len dec_buffer bytes ago with decoder state b dec_flags read a chunk decode it and put the result in self _decoded_chars at the snapshot point len dec_buffer bytes before the read the next input to be decoded is dec_buffer input_chunk the meaning of a tell cookie is seek to position set the decoder flags to dec_flags read bytes_to_feed bytes feed them into the decoder with need_eof as the eof flag then skip chars_to_skip characters of the decoded result for most simple decoders tell will often just give a byte offset in the file this should never happen skip backward to the snapshot point see _read_chunk how many decoded characters have been used up since the snapshot we haven t moved from the snapshot point starting from the snapshot position we will walk the decoder forward until it gives us enough decoded characters fast search for an acceptable start point close to our current pos rationale calling decoder decode has a large overhead regardless of chunk size we want the number of such calls to be o 1 in most situations common decoders sensible input actually it will be exactly 1 for fixed size codecs all 8 bit codecs also utf 16 and utf 32 decode up to temptative start point before pos and no bytes buffered in decoder ok skip back by buffered amount and reset heuristic we re too far ahead skip back a bit note our initial start point we haven t moved from the start point feed the decoder one byte at a time as we go note the nearest safe start point before the current location a point where the decoder has nothing buffered so seek can safely start from there and advance to this location chars decoded since start_pos decoder buffer is empty so this is a safe start point we didn t get enough decoded data signal eof to get more the returned cookie corresponds to the last safe start point reset the encoder merely useful for proper bom handling sometimes the encoder doesn t exist seeking to the current position should attempt to sync the underlying buffer with the current position the strategy of seek is to go back to the safe start point and replay the effect of read chars_to_skip from there seek back to the safe start point restore the decoder to its state from the safe start point just like _read_chunk feed the decoder and save a snapshot skip chars_to_skip of the decoded characters read everything keep reading chunks until we have size characters to return grab all the decoded text we will rewind any extra bits later make the decoder if it doesn t already exist newlines are already translated only search for n universal newline search find any of r r n n the decoder ensures that r n are not split in two pieces in c we d look for these in parallel of course nothing found found n found lone r found n found r n found r non universal reached length size no line ending seen yet get more data end of file don t exceed size rewind _decoded_chars to just after the line ending we found text i o implementation using an in memory buffer the initial_value argument sets the value of object the newline argument is like the one of textiowrapper s constructor issue 5645 make universal newlines semantics the same as in the c version even under windows textiowrapper tells the encoding in its repr in stringio that s an implementation detail this doesn t make sense on stringio
import os
import abc
import codecs
import errno
import stat
import sys

from _thread import allocate_lock as Lock
if sys.platform in {'win32', 'cygwin'}:
    from msvcrt import setmode as _setmode
else:
    _setmode = None

import io
from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)

valid_seek_flags = {0, 1, 2}  
if hasattr(os, 'SEEK_HOLE') :
    valid_seek_flags.add(os.SEEK_HOLE)
    valid_seek_flags.add(os.SEEK_DATA)


DEFAULT_BUFFER_SIZE = 8 * 1024  






BlockingIOError = BlockingIOError


_CHECK_ERRORS = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)


def text_encoding(encoding, stacklevel=2):
    
    if encoding is None:
        if sys.flags.utf8_mode:
            encoding = "utf-8"
        else:
            encoding = "locale"
        if sys.flags.warn_default_encoding:
            import warnings
            warnings.warn("'encoding' argument not specified.",
                          EncodingWarning, stacklevel + 1)
    return encoding








@staticmethod
def open(file, mode="r", buffering=-1, encoding=None, errors=None,
         newline=None, closefd=True, opener=None):

    r
    if not isinstance(file, int):
        file = os.fspath(file)
    if not isinstance(file, (str, bytes, int)):
        raise TypeError("invalid file: %r" % file)
    if not isinstance(mode, str):
        raise TypeError("invalid mode: %r" % mode)
    if not isinstance(buffering, int):
        raise TypeError("invalid buffering: %r" % buffering)
    if encoding is not None and not isinstance(encoding, str):
        raise TypeError("invalid encoding: %r" % encoding)
    if errors is not None and not isinstance(errors, str):
        raise TypeError("invalid errors: %r" % errors)
    modes = set(mode)
    if modes - set("axrwb+t") or len(mode) > len(modes):
        raise ValueError("invalid mode: %r" % mode)
    creating = "x" in modes
    reading = "r" in modes
    writing = "w" in modes
    appending = "a" in modes
    updating = "+" in modes
    text = "t" in modes
    binary = "b" in modes
    if text and binary:
        raise ValueError("can't have text and binary mode at once")
    if creating + reading + writing + appending > 1:
        raise ValueError("can't have read/write/append mode at once")
    if not (creating or reading or writing or appending):
        raise ValueError("must have exactly one of read/write/append mode")
    if binary and encoding is not None:
        raise ValueError("binary mode doesn't take an encoding argument")
    if binary and errors is not None:
        raise ValueError("binary mode doesn't take an errors argument")
    if binary and newline is not None:
        raise ValueError("binary mode doesn't take a newline argument")
    if binary and buffering == 1:
        import warnings
        warnings.warn("line buffering (buffering=1) isn't supported in binary "
                      "mode, the default buffer size will be used",
                      RuntimeWarning, 2)
    raw = FileIO(file,
                 (creating and "x" or "") +
                 (reading and "r" or "") +
                 (writing and "w" or "") +
                 (appending and "a" or "") +
                 (updating and "+" or ""),
                 closefd, opener=opener)
    result = raw
    try:
        line_buffering = False
        if buffering == 1 or buffering < 0 and raw.isatty():
            buffering = -1
            line_buffering = True
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE
            try:
                bs = os.fstat(raw.fileno()).st_blksize
            except (OSError, AttributeError):
                pass
            else:
                if bs > 1:
                    buffering = bs
        if buffering < 0:
            raise ValueError("invalid buffering size")
        if buffering == 0:
            if binary:
                return result
            raise ValueError("can't have unbuffered text I/O")
        if updating:
            buffer = BufferedRandom(raw, buffering)
        elif creating or writing or appending:
            buffer = BufferedWriter(raw, buffering)
        elif reading:
            buffer = BufferedReader(raw, buffering)
        else:
            raise ValueError("unknown mode: %r" % mode)
        result = buffer
        if binary:
            return result
        encoding = text_encoding(encoding)
        text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
        result = text
        text.mode = mode
        return result
    except:
        result.close()
        raise



def _open_code_with_warning(path):
    
    import warnings
    warnings.warn("_pyio.open_code() may not be using hooks",
                  RuntimeWarning, 2)
    return open(path, "rb")

try:
    open_code = io.open_code
except AttributeError:
    open_code = _open_code_with_warning




try:
    UnsupportedOperation = io.UnsupportedOperation
except AttributeError:
    class UnsupportedOperation(OSError, ValueError):
        pass


class IOBase(metaclass=abc.ABCMeta):

    

    

    def _unsupported(self, name):
        
        raise UnsupportedOperation("%s.%s() not supported" %
                                   (self.__class__.__name__, name))

    

    def seek(self, pos, whence=0):
        
        self._unsupported("seek")

    def tell(self):
        
        return self.seek(0, 1)

    def truncate(self, pos=None):
        
        self._unsupported("truncate")

    

    def flush(self):
        
        self._checkClosed()
        

    __closed = False

    def close(self):
        
        if not self.__closed:
            try:
                self.flush()
            finally:
                self.__closed = True

    def __del__(self):
        
        try:
            closed = self.closed
        except AttributeError:
            
            
            return

        if closed:
            return

        
        
        self.close()

    

    def seekable(self):
        
        return False

    def _checkSeekable(self, msg=None):
        
        if not self.seekable():
            raise UnsupportedOperation("File or stream is not seekable."
                                       if msg is None else msg)

    def readable(self):
        
        return False

    def _checkReadable(self, msg=None):
        
        if not self.readable():
            raise UnsupportedOperation("File or stream is not readable."
                                       if msg is None else msg)

    def writable(self):
        
        return False

    def _checkWritable(self, msg=None):
        
        if not self.writable():
            raise UnsupportedOperation("File or stream is not writable."
                                       if msg is None else msg)

    @property
    def closed(self):
        
        return self.__closed

    def _checkClosed(self, msg=None):
        
        if self.closed:
            raise ValueError("I/O operation on closed file."
                             if msg is None else msg)

    

    def __enter__(self):  
        
        self._checkClosed()
        return self

    def __exit__(self, *args):
        
        self.close()

    

    

    def fileno(self):
        
        self._unsupported("fileno")

    def isatty(self):
        
        self._checkClosed()
        return False

    

    def readline(self, size=-1):
        r
        
        if hasattr(self, "peek"):
            def nreadahead():
                readahead = self.peek(1)
                if not readahead:
                    return 1
                n = (readahead.find(b"\n") + 1) or len(readahead)
                if size >= 0:
                    n = min(n, size)
                return n
        else:
            def nreadahead():
                return 1
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        res = bytearray()
        while size < 0 or len(res) < size:
            b = self.read(nreadahead())
            if not b:
                break
            res += b
            if res.endswith(b"\n"):
                break
        return bytes(res)

    def __iter__(self):
        self._checkClosed()
        return self

    def __next__(self):
        line = self.readline()
        if not line:
            raise StopIteration
        return line

    def readlines(self, hint=None):
        
        if hint is None or hint <= 0:
            return list(self)
        n = 0
        lines = []
        for line in self:
            lines.append(line)
            n += len(line)
            if n >= hint:
                break
        return lines

    def writelines(self, lines):
        
        self._checkClosed()
        for line in lines:
            self.write(line)

io.IOBase.register(IOBase)


class RawIOBase(IOBase):

    

    
    
    
    

    
    
    
    

    def read(self, size=-1):
        
        if size is None:
            size = -1
        if size < 0:
            return self.readall()
        b = bytearray(size.__index__())
        n = self.readinto(b)
        if n is None:
            return None
        del b[n:]
        return bytes(b)

    def readall(self):
        
        res = bytearray()
        while data := self.read(DEFAULT_BUFFER_SIZE):
            res += data
        if res:
            return bytes(res)
        else:
            
            return data

    def readinto(self, b):
        
        self._unsupported("readinto")

    def write(self, b):
        
        self._unsupported("write")

io.RawIOBase.register(RawIOBase)
from _io import FileIO
RawIOBase.register(FileIO)


class BufferedIOBase(IOBase):

    

    def read(self, size=-1):
        
        self._unsupported("read")

    def read1(self, size=-1):
        
        self._unsupported("read1")

    def readinto(self, b):
        

        return self._readinto(b, read1=False)

    def readinto1(self, b):
        

        return self._readinto(b, read1=True)

    def _readinto(self, b, read1):
        if not isinstance(b, memoryview):
            b = memoryview(b)
        b = b.cast('B')

        if read1:
            data = self.read1(len(b))
        else:
            data = self.read(len(b))
        n = len(data)

        b[:n] = data

        return n

    def write(self, b):
        
        self._unsupported("write")

    def detach(self):
        
        self._unsupported("detach")

io.BufferedIOBase.register(BufferedIOBase)


class _BufferedIOMixin(BufferedIOBase):

    

    def __init__(self, raw):
        self._raw = raw

    

    def seek(self, pos, whence=0):
        new_position = self.raw.seek(pos, whence)
        if new_position < 0:
            raise OSError("seek() returned an invalid position")
        return new_position

    def tell(self):
        pos = self.raw.tell()
        if pos < 0:
            raise OSError("tell() returned an invalid position")
        return pos

    def truncate(self, pos=None):
        self._checkClosed()
        self._checkWritable()

        
        
        
        self.flush()

        if pos is None:
            pos = self.tell()
        
        
        return self.raw.truncate(pos)

    

    def flush(self):
        if self.closed:
            raise ValueError("flush on closed file")
        self.raw.flush()

    def close(self):
        if self.raw is not None and not self.closed:
            try:
                
                self.flush()
            finally:
                self.raw.close()

    def detach(self):
        if self.raw is None:
            raise ValueError("raw stream already detached")
        self.flush()
        raw = self._raw
        self._raw = None
        return raw

    

    def seekable(self):
        return self.raw.seekable()

    @property
    def raw(self):
        return self._raw

    @property
    def closed(self):
        return self.raw.closed

    @property
    def name(self):
        return self.raw.name

    @property
    def mode(self):
        return self.raw.mode

    def __getstate__(self):
        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")

    def __repr__(self):
        modname = self.__class__.__module__
        clsname = self.__class__.__qualname__
        try:
            name = self.name
        except AttributeError:
            return "<{}.{}>".format(modname, clsname)
        else:
            return "<{}.{} name={!r}>".format(modname, clsname, name)

    

    def fileno(self):
        return self.raw.fileno()

    def isatty(self):
        return self.raw.isatty()


class BytesIO(BufferedIOBase):

    

    
    
    _buffer = None

    def __init__(self, initial_bytes=None):
        buf = bytearray()
        if initial_bytes is not None:
            buf += initial_bytes
        self._buffer = buf
        self._pos = 0

    def __getstate__(self):
        if self.closed:
            raise ValueError("__getstate__ on closed file")
        return self.__dict__.copy()

    def getvalue(self):
        
        if self.closed:
            raise ValueError("getvalue on closed file")
        return bytes(self._buffer)

    def getbuffer(self):
        
        if self.closed:
            raise ValueError("getbuffer on closed file")
        return memoryview(self._buffer)

    def close(self):
        if self._buffer is not None:
            self._buffer.clear()
        super().close()

    def read(self, size=-1):
        if self.closed:
            raise ValueError("read from closed file")
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        if size < 0:
            size = len(self._buffer)
        if len(self._buffer) <= self._pos:
            return b""
        newpos = min(len(self._buffer), self._pos + size)
        b = self._buffer[self._pos : newpos]
        self._pos = newpos
        return bytes(b)

    def read1(self, size=-1):
        
        return self.read(size)

    def write(self, b):
        if self.closed:
            raise ValueError("write to closed file")
        if isinstance(b, str):
            raise TypeError("can't write str to binary stream")
        with memoryview(b) as view:
            n = view.nbytes  
        if n == 0:
            return 0
        pos = self._pos
        if pos > len(self._buffer):
            
            
            padding = b'\x00' * (pos - len(self._buffer))
            self._buffer += padding
        self._buffer[pos:pos + n] = b
        self._pos += n
        return n

    def seek(self, pos, whence=0):
        if self.closed:
            raise ValueError("seek on closed file")
        try:
            pos_index = pos.__index__
        except AttributeError:
            raise TypeError(f"{pos!r} is not an integer")
        else:
            pos = pos_index()
        if whence == 0:
            if pos < 0:
                raise ValueError("negative seek position %r" % (pos,))
            self._pos = pos
        elif whence == 1:
            self._pos = max(0, self._pos + pos)
        elif whence == 2:
            self._pos = max(0, len(self._buffer) + pos)
        else:
            raise ValueError("unsupported whence value")
        return self._pos

    def tell(self):
        if self.closed:
            raise ValueError("tell on closed file")
        return self._pos

    def truncate(self, pos=None):
        if self.closed:
            raise ValueError("truncate on closed file")
        if pos is None:
            pos = self._pos
        else:
            try:
                pos_index = pos.__index__
            except AttributeError:
                raise TypeError(f"{pos!r} is not an integer")
            else:
                pos = pos_index()
            if pos < 0:
                raise ValueError("negative truncate position %r" % (pos,))
        del self._buffer[pos:]
        return pos

    def readable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True

    def writable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True

    def seekable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True


class BufferedReader(_BufferedIOMixin):

    

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        
        if not raw.readable():
            raise OSError('"raw" argument must be readable.')

        _BufferedIOMixin.__init__(self, raw)
        if buffer_size <= 0:
            raise ValueError("invalid buffer size")
        self.buffer_size = buffer_size
        self._reset_read_buf()
        self._read_lock = Lock()

    def readable(self):
        return self.raw.readable()

    def _reset_read_buf(self):
        self._read_buf = b""
        self._read_pos = 0

    def read(self, size=None):
        
        if size is not None and size < -1:
            raise ValueError("invalid number of bytes to read")
        with self._read_lock:
            return self._read_unlocked(size)

    def _read_unlocked(self, n=None):
        nodata_val = b""
        empty_values = (b"", None)
        buf = self._read_buf
        pos = self._read_pos

        
        if n is None or n == -1:
            self._reset_read_buf()
            if hasattr(self.raw, 'readall'):
                chunk = self.raw.readall()
                if chunk is None:
                    return buf[pos:] or None
                else:
                    return buf[pos:] + chunk
            chunks = [buf[pos:]]  
            current_size = 0
            while True:
                
                chunk = self.raw.read()
                if chunk in empty_values:
                    nodata_val = chunk
                    break
                current_size += len(chunk)
                chunks.append(chunk)
            return b"".join(chunks) or nodata_val

        
        avail = len(buf) - pos  
        if n <= avail:
            
            self._read_pos += n
            return buf[pos:pos+n]
        
        
        chunks = [buf[pos:]]
        wanted = max(self.buffer_size, n)
        while avail < n:
            chunk = self.raw.read(wanted)
            if chunk in empty_values:
                nodata_val = chunk
                break
            avail += len(chunk)
            chunks.append(chunk)
        
        
        n = min(n, avail)
        out = b"".join(chunks)
        self._read_buf = out[n:]  
        self._read_pos = 0
        return out[:n] if out else nodata_val

    def peek(self, size=0):
        
        self._checkClosed("peek of closed file")
        with self._read_lock:
            return self._peek_unlocked(size)

    def _peek_unlocked(self, n=0):
        want = min(n, self.buffer_size)
        have = len(self._read_buf) - self._read_pos
        if have < want or have <= 0:
            to_read = self.buffer_size - have
            current = self.raw.read(to_read)
            if current:
                self._read_buf = self._read_buf[self._read_pos:] + current
                self._read_pos = 0
        return self._read_buf[self._read_pos:]

    def read1(self, size=-1):
        
        
        
        self._checkClosed("read of closed file")
        if size < 0:
            size = self.buffer_size
        if size == 0:
            return b""
        with self._read_lock:
            self._peek_unlocked(1)
            return self._read_unlocked(
                min(size, len(self._read_buf) - self._read_pos))

    
    
    
    
    
    def _readinto(self, buf, read1):
        

        self._checkClosed("readinto of closed file")

        
        
        
        if not isinstance(buf, memoryview):
            buf = memoryview(buf)
        if buf.nbytes == 0:
            return 0
        buf = buf.cast('B')

        written = 0
        with self._read_lock:
            while written < len(buf):

                
                avail = min(len(self._read_buf) - self._read_pos, len(buf))
                if avail:
                    buf[written:written+avail] = \
                        self._read_buf[self._read_pos:self._read_pos+avail]
                    self._read_pos += avail
                    written += avail
                    if written == len(buf):
                        break

                
                
                if len(buf) - written > self.buffer_size:
                    n = self.raw.readinto(buf[written:])
                    if not n:
                        break 
                    written += n

                
                
                elif not (read1 and written):
                    if not self._peek_unlocked(1):
                        break 

                
                if read1 and written:
                    break

        return written

    def tell(self):
        return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        self._checkClosed("seek of closed file")
        with self._read_lock:
            if whence == 1:
                pos -= len(self._read_buf) - self._read_pos
            pos = _BufferedIOMixin.seek(self, pos, whence)
            self._reset_read_buf()
            return pos

class BufferedWriter(_BufferedIOMixin):

    

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        if not raw.writable():
            raise OSError('"raw" argument must be writable.')

        _BufferedIOMixin.__init__(self, raw)
        if buffer_size <= 0:
            raise ValueError("invalid buffer size")
        self.buffer_size = buffer_size
        self._write_buf = bytearray()
        self._write_lock = Lock()

    def writable(self):
        return self.raw.writable()

    def write(self, b):
        if isinstance(b, str):
            raise TypeError("can't write str to binary stream")
        with self._write_lock:
            if self.closed:
                raise ValueError("write to closed file")
            
            
            if len(self._write_buf) > self.buffer_size:
                
                
                self._flush_unlocked()
            before = len(self._write_buf)
            self._write_buf.extend(b)
            written = len(self._write_buf) - before
            if len(self._write_buf) > self.buffer_size:
                try:
                    self._flush_unlocked()
                except BlockingIOError as e:
                    if len(self._write_buf) > self.buffer_size:
                        
                        
                        overage = len(self._write_buf) - self.buffer_size
                        written -= overage
                        self._write_buf = self._write_buf[:self.buffer_size]
                        raise BlockingIOError(e.errno, e.strerror, written)
            return written

    def truncate(self, pos=None):
        with self._write_lock:
            self._flush_unlocked()
            if pos is None:
                pos = self.raw.tell()
            return self.raw.truncate(pos)

    def flush(self):
        with self._write_lock:
            self._flush_unlocked()

    def _flush_unlocked(self):
        if self.closed:
            raise ValueError("flush on closed file")
        while self._write_buf:
            try:
                n = self.raw.write(self._write_buf)
            except BlockingIOError:
                raise RuntimeError("self.raw should implement RawIOBase: it "
                                   "should not raise BlockingIOError")
            if n is None:
                raise BlockingIOError(
                    errno.EAGAIN,
                    "write could not complete without blocking", 0)
            if n > len(self._write_buf) or n < 0:
                raise OSError("write() returned incorrect number of bytes")
            del self._write_buf[:n]

    def tell(self):
        return _BufferedIOMixin.tell(self) + len(self._write_buf)

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        with self._write_lock:
            self._flush_unlocked()
            return _BufferedIOMixin.seek(self, pos, whence)

    def close(self):
        with self._write_lock:
            if self.raw is None or self.closed:
                return
        
        
        
        
        try:
            
            self.flush()
        finally:
            with self._write_lock:
                self.raw.close()


class BufferedRWPair(BufferedIOBase):

    

    
    

    def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE):
        
        if not reader.readable():
            raise OSError('"reader" argument must be readable.')

        if not writer.writable():
            raise OSError('"writer" argument must be writable.')

        self.reader = BufferedReader(reader, buffer_size)
        self.writer = BufferedWriter(writer, buffer_size)

    def read(self, size=-1):
        if size is None:
            size = -1
        return self.reader.read(size)

    def readinto(self, b):
        return self.reader.readinto(b)

    def write(self, b):
        return self.writer.write(b)

    def peek(self, size=0):
        return self.reader.peek(size)

    def read1(self, size=-1):
        return self.reader.read1(size)

    def readinto1(self, b):
        return self.reader.readinto1(b)

    def readable(self):
        return self.reader.readable()

    def writable(self):
        return self.writer.writable()

    def flush(self):
        return self.writer.flush()

    def close(self):
        try:
            self.writer.close()
        finally:
            self.reader.close()

    def isatty(self):
        return self.reader.isatty() or self.writer.isatty()

    @property
    def closed(self):
        return self.writer.closed


class BufferedRandom(BufferedWriter, BufferedReader):

    

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        raw._checkSeekable()
        BufferedReader.__init__(self, raw, buffer_size)
        BufferedWriter.__init__(self, raw, buffer_size)

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        self.flush()
        if self._read_buf:
            
            with self._read_lock:
                self.raw.seek(self._read_pos - len(self._read_buf), 1)
        
        
        pos = self.raw.seek(pos, whence)
        with self._read_lock:
            self._reset_read_buf()
        if pos < 0:
            raise OSError("seek() returned invalid position")
        return pos

    def tell(self):
        if self._write_buf:
            return BufferedWriter.tell(self)
        else:
            return BufferedReader.tell(self)

    def truncate(self, pos=None):
        if pos is None:
            pos = self.tell()
        
        return BufferedWriter.truncate(self, pos)

    def read(self, size=None):
        if size is None:
            size = -1
        self.flush()
        return BufferedReader.read(self, size)

    def readinto(self, b):
        self.flush()
        return BufferedReader.readinto(self, b)

    def peek(self, size=0):
        self.flush()
        return BufferedReader.peek(self, size)

    def read1(self, size=-1):
        self.flush()
        return BufferedReader.read1(self, size)

    def readinto1(self, b):
        self.flush()
        return BufferedReader.readinto1(self, b)

    def write(self, b):
        if self._read_buf:
            
            with self._read_lock:
                self.raw.seek(self._read_pos - len(self._read_buf), 1)
                self._reset_read_buf()
        return BufferedWriter.write(self, b)


class FileIO(RawIOBase):
    _fd = -1
    _created = False
    _readable = False
    _writable = False
    _appending = False
    _seekable = None
    _closefd = True

    def __init__(self, file, mode='r', closefd=True, opener=None):
        
        if self._fd >= 0:
            
            try:
                if self._closefd:
                    os.close(self._fd)
            finally:
                self._fd = -1

        if isinstance(file, float):
            raise TypeError('integer argument expected, got float')
        if isinstance(file, int):
            fd = file
            if fd < 0:
                raise ValueError('negative file descriptor')
        else:
            fd = -1

        if not isinstance(mode, str):
            raise TypeError('invalid mode: %s' % (mode,))
        if not set(mode) <= set('xrwab+'):
            raise ValueError('invalid mode: %s' % (mode,))
        if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:
            raise ValueError('Must have exactly one of create/read/write/append '
                             'mode and at most one plus')

        if 'x' in mode:
            self._created = True
            self._writable = True
            flags = os.O_EXCL | os.O_CREAT
        elif 'r' in mode:
            self._readable = True
            flags = 0
        elif 'w' in mode:
            self._writable = True
            flags = os.O_CREAT | os.O_TRUNC
        elif 'a' in mode:
            self._writable = True
            self._appending = True
            flags = os.O_APPEND | os.O_CREAT

        if '+' in mode:
            self._readable = True
            self._writable = True

        if self._readable and self._writable:
            flags |= os.O_RDWR
        elif self._readable:
            flags |= os.O_RDONLY
        else:
            flags |= os.O_WRONLY

        flags |= getattr(os, 'O_BINARY', 0)

        noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or
                          getattr(os, 'O_CLOEXEC', 0))
        flags |= noinherit_flag

        owned_fd = None
        try:
            if fd < 0:
                if not closefd:
                    raise ValueError('Cannot use closefd=False with file name')
                if opener is None:
                    fd = os.open(file, flags, 0o666)
                else:
                    fd = opener(file, flags)
                    if not isinstance(fd, int):
                        raise TypeError('expected integer from opener')
                    if fd < 0:
                        raise OSError('Negative file descriptor')
                owned_fd = fd
                if not noinherit_flag:
                    os.set_inheritable(fd, False)

            self._closefd = closefd
            fdfstat = os.fstat(fd)
            try:
                if stat.S_ISDIR(fdfstat.st_mode):
                    raise IsADirectoryError(errno.EISDIR,
                                            os.strerror(errno.EISDIR), file)
            except AttributeError:
                
                
                pass
            self._blksize = getattr(fdfstat, 'st_blksize', 0)
            if self._blksize <= 1:
                self._blksize = DEFAULT_BUFFER_SIZE

            if _setmode:
                
                _setmode(fd, os.O_BINARY)

            self.name = file
            if self._appending:
                
                
                
                try:
                    os.lseek(fd, 0, SEEK_END)
                except OSError as e:
                    if e.errno != errno.ESPIPE:
                        raise
        except:
            if owned_fd is not None:
                os.close(owned_fd)
            raise
        self._fd = fd

    def __del__(self):
        if self._fd >= 0 and self._closefd and not self.closed:
            import warnings
            warnings.warn('unclosed file %r' % (self,), ResourceWarning,
                          stacklevel=2, source=self)
            self.close()

    def __getstate__(self):
        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")

    def __repr__(self):
        class_name = '%s.%s' % (self.__class__.__module__,
                                self.__class__.__qualname__)
        if self.closed:
            return '<%s [closed]>' % class_name
        try:
            name = self.name
        except AttributeError:
            return ('<%s fd=%d mode=%r closefd=%r>' %
                    (class_name, self._fd, self.mode, self._closefd))
        else:
            return ('<%s name=%r mode=%r closefd=%r>' %
                    (class_name, name, self.mode, self._closefd))

    def _checkReadable(self):
        if not self._readable:
            raise UnsupportedOperation('File not open for reading')

    def _checkWritable(self, msg=None):
        if not self._writable:
            raise UnsupportedOperation('File not open for writing')

    def read(self, size=None):
        
        self._checkClosed()
        self._checkReadable()
        if size is None or size < 0:
            return self.readall()
        try:
            return os.read(self._fd, size)
        except BlockingIOError:
            return None

    def readall(self):
        
        self._checkClosed()
        self._checkReadable()
        bufsize = DEFAULT_BUFFER_SIZE
        try:
            pos = os.lseek(self._fd, 0, SEEK_CUR)
            end = os.fstat(self._fd).st_size
            if end >= pos:
                bufsize = end - pos + 1
        except OSError:
            pass

        result = bytearray()
        while True:
            if len(result) >= bufsize:
                bufsize = len(result)
                bufsize += max(bufsize, DEFAULT_BUFFER_SIZE)
            n = bufsize - len(result)
            try:
                chunk = os.read(self._fd, n)
            except BlockingIOError:
                if result:
                    break
                return None
            if not chunk: 
                break
            result += chunk

        return bytes(result)

    def readinto(self, b):
        
        m = memoryview(b).cast('B')
        data = self.read(len(m))
        n = len(data)
        m[:n] = data
        return n

    def write(self, b):
        
        self._checkClosed()
        self._checkWritable()
        try:
            return os.write(self._fd, b)
        except BlockingIOError:
            return None

    def seek(self, pos, whence=SEEK_SET):
        
        if isinstance(pos, float):
            raise TypeError('an integer is required')
        self._checkClosed()
        return os.lseek(self._fd, pos, whence)

    def tell(self):
        
        self._checkClosed()
        return os.lseek(self._fd, 0, SEEK_CUR)

    def truncate(self, size=None):
        
        self._checkClosed()
        self._checkWritable()
        if size is None:
            size = self.tell()
        os.ftruncate(self._fd, size)
        return size

    def close(self):
        
        if not self.closed:
            try:
                if self._closefd:
                    os.close(self._fd)
            finally:
                super().close()

    def seekable(self):
        
        self._checkClosed()
        if self._seekable is None:
            try:
                self.tell()
            except OSError:
                self._seekable = False
            else:
                self._seekable = True
        return self._seekable

    def readable(self):
        
        self._checkClosed()
        return self._readable

    def writable(self):
        
        self._checkClosed()
        return self._writable

    def fileno(self):
        
        self._checkClosed()
        return self._fd

    def isatty(self):
        
        self._checkClosed()
        return os.isatty(self._fd)

    @property
    def closefd(self):
        
        return self._closefd

    @property
    def mode(self):
        
        if self._created:
            if self._readable:
                return 'xb+'
            else:
                return 'xb'
        elif self._appending:
            if self._readable:
                return 'ab+'
            else:
                return 'ab'
        elif self._readable:
            if self._writable:
                return 'rb+'
            else:
                return 'rb'
        else:
            return 'wb'


class TextIOBase(IOBase):

    

    def read(self, size=-1):
        
        self._unsupported("read")

    def write(self, s):
        
        self._unsupported("write")

    def truncate(self, pos=None):
        
        self._unsupported("truncate")

    def readline(self):
        
        self._unsupported("readline")

    def detach(self):
        
        self._unsupported("detach")

    @property
    def encoding(self):
        
        return None

    @property
    def newlines(self):
        
        return None

    @property
    def errors(self):
        
        return None

io.TextIOBase.register(TextIOBase)


class IncrementalNewlineDecoder(codecs.IncrementalDecoder):
    r
    def __init__(self, decoder, translate, errors='strict'):
        codecs.IncrementalDecoder.__init__(self, errors=errors)
        self.translate = translate
        self.decoder = decoder
        self.seennl = 0
        self.pendingcr = False

    def decode(self, input, final=False):
        
        if self.decoder is None:
            output = input
        else:
            output = self.decoder.decode(input, final=final)
        if self.pendingcr and (output or final):
            output = "\r" + output
            self.pendingcr = False

        
        
        if output.endswith("\r") and not final:
            output = output[:-1]
            self.pendingcr = True

        
        crlf = output.count('\r\n')
        cr = output.count('\r') - crlf
        lf = output.count('\n') - crlf
        self.seennl |= (lf and self._LF) | (cr and self._CR) \
                    | (crlf and self._CRLF)

        if self.translate:
            if crlf:
                output = output.replace("\r\n", "\n")
            if cr:
                output = output.replace("\r", "\n")

        return output

    def getstate(self):
        if self.decoder is None:
            buf = b""
            flag = 0
        else:
            buf, flag = self.decoder.getstate()
        flag <<= 1
        if self.pendingcr:
            flag |= 1
        return buf, flag

    def setstate(self, state):
        buf, flag = state
        self.pendingcr = bool(flag & 1)
        if self.decoder is not None:
            self.decoder.setstate((buf, flag >> 1))

    def reset(self):
        self.seennl = 0
        self.pendingcr = False
        if self.decoder is not None:
            self.decoder.reset()

    _LF = 1
    _CR = 2
    _CRLF = 4

    @property
    def newlines(self):
        return (None,
                "\n",
                "\r",
                ("\r", "\n"),
                "\r\n",
                ("\n", "\r\n"),
                ("\r", "\r\n"),
                ("\r", "\n", "\r\n")
               )[self.seennl]


class TextIOWrapper(TextIOBase):

    r

    _CHUNK_SIZE = 2048

    
    
    _buffer = None

    
    
    
    def __init__(self, buffer, encoding=None, errors=None, newline=None,
                 line_buffering=False, write_through=False):
        self._check_newline(newline)
        encoding = text_encoding(encoding)

        if encoding == "locale":
            encoding = self._get_locale_encoding()

        if not isinstance(encoding, str):
            raise ValueError("invalid encoding: %r" % encoding)

        if not codecs.lookup(encoding)._is_text_encoding:
            msg = ("%r is not a text encoding; "
                   "use codecs.open() to handle arbitrary codecs")
            raise LookupError(msg % encoding)

        if errors is None:
            errors = "strict"
        else:
            if not isinstance(errors, str):
                raise ValueError("invalid errors: %r" % errors)
            if _CHECK_ERRORS:
                codecs.lookup_error(errors)

        self._buffer = buffer
        self._decoded_chars = ''  
        self._decoded_chars_used = 0  
        self._snapshot = None  
        self._seekable = self._telling = self.buffer.seekable()
        self._has_read1 = hasattr(self.buffer, 'read1')
        self._configure(encoding, errors, newline,
                        line_buffering, write_through)

    def _check_newline(self, newline):
        if newline is not None and not isinstance(newline, str):
            raise TypeError("illegal newline type: %r" % (type(newline),))
        if newline not in (None, "", "\n", "\r", "\r\n"):
            raise ValueError("illegal newline value: %r" % (newline,))

    def _configure(self, encoding=None, errors=None, newline=None,
                   line_buffering=False, write_through=False):
        self._encoding = encoding
        self._errors = errors
        self._encoder = None
        self._decoder = None
        self._b2cratio = 0.0

        self._readuniversal = not newline
        self._readtranslate = newline is None
        self._readnl = newline
        self._writetranslate = newline != ''
        self._writenl = newline or os.linesep

        self._line_buffering = line_buffering
        self._write_through = write_through

        
        if self._seekable and self.writable():
            position = self.buffer.tell()
            if position != 0:
                try:
                    self._get_encoder().setstate(0)
                except LookupError:
                    
                    pass

    
    
    
    

    
    
    

    def __repr__(self):
        result = "<{}.{}".format(self.__class__.__module__,
                                 self.__class__.__qualname__)
        try:
            name = self.name
        except AttributeError:
            pass
        else:
            result += " name={0!r}".format(name)
        try:
            mode = self.mode
        except AttributeError:
            pass
        else:
            result += " mode={0!r}".format(mode)
        return result + " encoding={0!r}>".format(self.encoding)

    @property
    def encoding(self):
        return self._encoding

    @property
    def errors(self):
        return self._errors

    @property
    def line_buffering(self):
        return self._line_buffering

    @property
    def write_through(self):
        return self._write_through

    @property
    def buffer(self):
        return self._buffer

    def reconfigure(self, *,
                    encoding=None, errors=None, newline=Ellipsis,
                    line_buffering=None, write_through=None):
        
        if (self._decoder is not None
                and (encoding is not None or errors is not None
                     or newline is not Ellipsis)):
            raise UnsupportedOperation(
                "It is not possible to set the encoding or newline of stream "
                "after the first read")

        if errors is None:
            if encoding is None:
                errors = self._errors
            else:
                errors = 'strict'
        elif not isinstance(errors, str):
            raise TypeError("invalid errors: %r" % errors)

        if encoding is None:
            encoding = self._encoding
        else:
            if not isinstance(encoding, str):
                raise TypeError("invalid encoding: %r" % encoding)
            if encoding == "locale":
                encoding = self._get_locale_encoding()

        if newline is Ellipsis:
            newline = self._readnl
        self._check_newline(newline)

        if line_buffering is None:
            line_buffering = self.line_buffering
        if write_through is None:
            write_through = self.write_through

        self.flush()
        self._configure(encoding, errors, newline,
                        line_buffering, write_through)

    def seekable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return self._seekable

    def readable(self):
        return self.buffer.readable()

    def writable(self):
        return self.buffer.writable()

    def flush(self):
        self.buffer.flush()
        self._telling = self._seekable

    def close(self):
        if self.buffer is not None and not self.closed:
            try:
                self.flush()
            finally:
                self.buffer.close()

    @property
    def closed(self):
        return self.buffer.closed

    @property
    def name(self):
        return self.buffer.name

    def fileno(self):
        return self.buffer.fileno()

    def isatty(self):
        return self.buffer.isatty()

    def write(self, s):
        'Write data, where s is a str'
        if self.closed:
            raise ValueError("write to closed file")
        if not isinstance(s, str):
            raise TypeError("can't write %s to text stream" %
                            s.__class__.__name__)
        length = len(s)
        haslf = (self._writetranslate or self._line_buffering) and "\n" in s
        if haslf and self._writetranslate and self._writenl != "\n":
            s = s.replace("\n", self._writenl)
        encoder = self._encoder or self._get_encoder()
        
        b = encoder.encode(s)
        self.buffer.write(b)
        if self._line_buffering and (haslf or "\r" in s):
            self.flush()
        self._set_decoded_chars('')
        self._snapshot = None
        if self._decoder:
            self._decoder.reset()
        return length

    def _get_encoder(self):
        make_encoder = codecs.getincrementalencoder(self._encoding)
        self._encoder = make_encoder(self._errors)
        return self._encoder

    def _get_decoder(self):
        make_decoder = codecs.getincrementaldecoder(self._encoding)
        decoder = make_decoder(self._errors)
        if self._readuniversal:
            decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
        self._decoder = decoder
        return decoder

    
    
    
    def _set_decoded_chars(self, chars):
        
        self._decoded_chars = chars
        self._decoded_chars_used = 0

    def _get_decoded_chars(self, n=None):
        
        offset = self._decoded_chars_used
        if n is None:
            chars = self._decoded_chars[offset:]
        else:
            chars = self._decoded_chars[offset:offset + n]
        self._decoded_chars_used += len(chars)
        return chars

    def _get_locale_encoding(self):
        try:
            import locale
        except ImportError:
            
            return "utf-8"
        else:
            return locale.getencoding()

    def _rewind_decoded_chars(self, n):
        
        if self._decoded_chars_used < n:
            raise AssertionError("rewind decoded_chars out of bounds")
        self._decoded_chars_used -= n

    def _read_chunk(self):
        

        
        
        
        
        

        if self._decoder is None:
            raise ValueError("no decoder")

        if self._telling:
            
            

            dec_buffer, dec_flags = self._decoder.getstate()
            
            

        
        if self._has_read1:
            input_chunk = self.buffer.read1(self._CHUNK_SIZE)
        else:
            input_chunk = self.buffer.read(self._CHUNK_SIZE)
        eof = not input_chunk
        decoded_chars = self._decoder.decode(input_chunk, eof)
        self._set_decoded_chars(decoded_chars)
        if decoded_chars:
            self._b2cratio = len(input_chunk) / len(self._decoded_chars)
        else:
            self._b2cratio = 0.0

        if self._telling:
            
            
            self._snapshot = (dec_flags, dec_buffer + input_chunk)

        return not eof

    def _pack_cookie(self, position, dec_flags=0,
                           bytes_to_feed=0, need_eof=False, chars_to_skip=0):
        
        
        
        
        
        return (position | (dec_flags<<64) | (bytes_to_feed<<128) |
               (chars_to_skip<<192) | bool(need_eof)<<256)

    def _unpack_cookie(self, bigint):
        rest, position = divmod(bigint, 1<<64)
        rest, dec_flags = divmod(rest, 1<<64)
        rest, bytes_to_feed = divmod(rest, 1<<64)
        need_eof, chars_to_skip = divmod(rest, 1<<64)
        return position, dec_flags, bytes_to_feed, bool(need_eof), chars_to_skip

    def tell(self):
        if not self._seekable:
            raise UnsupportedOperation("underlying stream is not seekable")
        if not self._telling:
            raise OSError("telling position disabled by next() call")
        self.flush()
        position = self.buffer.tell()
        decoder = self._decoder
        if decoder is None or self._snapshot is None:
            if self._decoded_chars:
                
                raise AssertionError("pending decoded text")
            return position

        
        dec_flags, next_input = self._snapshot
        position -= len(next_input)

        
        chars_to_skip = self._decoded_chars_used
        if chars_to_skip == 0:
            
            return self._pack_cookie(position, dec_flags)

        
        
        saved_state = decoder.getstate()
        try:
            
            
            
            
            
            
            
            skip_bytes = int(self._b2cratio * chars_to_skip)
            skip_back = 1
            assert skip_bytes <= len(next_input)
            while skip_bytes > 0:
                decoder.setstate((b'', dec_flags))
                
                n = len(decoder.decode(next_input[:skip_bytes]))
                if n <= chars_to_skip:
                    b, d = decoder.getstate()
                    if not b:
                        
                        dec_flags = d
                        chars_to_skip -= n
                        break
                    
                    skip_bytes -= len(b)
                    skip_back = 1
                else:
                    
                    skip_bytes -= skip_back
                    skip_back = skip_back * 2
            else:
                skip_bytes = 0
                decoder.setstate((b'', dec_flags))

            
            start_pos = position + skip_bytes
            start_flags = dec_flags
            if chars_to_skip == 0:
                
                return self._pack_cookie(start_pos, start_flags)

            
            
            
            
            bytes_fed = 0
            need_eof = False
            
            chars_decoded = 0
            for i in range(skip_bytes, len(next_input)):
                bytes_fed += 1
                chars_decoded += len(decoder.decode(next_input[i:i+1]))
                dec_buffer, dec_flags = decoder.getstate()
                if not dec_buffer and chars_decoded <= chars_to_skip:
                    
                    start_pos += bytes_fed
                    chars_to_skip -= chars_decoded
                    start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
                if chars_decoded >= chars_to_skip:
                    break
            else:
                
                chars_decoded += len(decoder.decode(b'', final=True))
                need_eof = True
                if chars_decoded < chars_to_skip:
                    raise OSError("can't reconstruct logical file position")

            
            return self._pack_cookie(
                start_pos, start_flags, bytes_fed, need_eof, chars_to_skip)
        finally:
            decoder.setstate(saved_state)

    def truncate(self, pos=None):
        self.flush()
        if pos is None:
            pos = self.tell()
        return self.buffer.truncate(pos)

    def detach(self):
        if self.buffer is None:
            raise ValueError("buffer is already detached")
        self.flush()
        buffer = self._buffer
        self._buffer = None
        return buffer

    def seek(self, cookie, whence=0):
        def _reset_encoder(position):
            
            try:
                encoder = self._encoder or self._get_encoder()
            except LookupError:
                
                pass
            else:
                if position != 0:
                    encoder.setstate(0)
                else:
                    encoder.reset()

        if self.closed:
            raise ValueError("tell on closed file")
        if not self._seekable:
            raise UnsupportedOperation("underlying stream is not seekable")
        if whence == SEEK_CUR:
            if cookie != 0:
                raise UnsupportedOperation("can't do nonzero cur-relative seeks")
            
            
            whence = 0
            cookie = self.tell()
        elif whence == SEEK_END:
            if cookie != 0:
                raise UnsupportedOperation("can't do nonzero end-relative seeks")
            self.flush()
            position = self.buffer.seek(0, whence)
            self._set_decoded_chars('')
            self._snapshot = None
            if self._decoder:
                self._decoder.reset()
            _reset_encoder(position)
            return position
        if whence != 0:
            raise ValueError("unsupported whence (%r)" % (whence,))
        if cookie < 0:
            raise ValueError("negative seek position %r" % (cookie,))
        self.flush()

        
        
        start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
            self._unpack_cookie(cookie)

        
        self.buffer.seek(start_pos)
        self._set_decoded_chars('')
        self._snapshot = None

        
        if cookie == 0 and self._decoder:
            self._decoder.reset()
        elif self._decoder or dec_flags or chars_to_skip:
            self._decoder = self._decoder or self._get_decoder()
            self._decoder.setstate((b'', dec_flags))
            self._snapshot = (dec_flags, b'')

        if chars_to_skip:
            
            input_chunk = self.buffer.read(bytes_to_feed)
            self._set_decoded_chars(
                self._decoder.decode(input_chunk, need_eof))
            self._snapshot = (dec_flags, input_chunk)

            
            if len(self._decoded_chars) < chars_to_skip:
                raise OSError("can't restore logical file position")
            self._decoded_chars_used = chars_to_skip

        _reset_encoder(cookie)
        return cookie

    def read(self, size=None):
        self._checkReadable()
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        decoder = self._decoder or self._get_decoder()
        if size < 0:
            
            result = (self._get_decoded_chars() +
                      decoder.decode(self.buffer.read(), final=True))
            self._set_decoded_chars('')
            self._snapshot = None
            return result
        else:
            
            eof = False
            result = self._get_decoded_chars(size)
            while len(result) < size and not eof:
                eof = not self._read_chunk()
                result += self._get_decoded_chars(size - len(result))
            return result

    def __next__(self):
        self._telling = False
        line = self.readline()
        if not line:
            self._snapshot = None
            self._telling = self._seekable
            raise StopIteration
        return line

    def readline(self, size=None):
        if self.closed:
            raise ValueError("read from closed file")
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()

        
        line = self._get_decoded_chars()

        start = 0
        
        if not self._decoder:
            self._get_decoder()

        pos = endpos = None
        while True:
            if self._readtranslate:
                
                pos = line.find('\n', start)
                if pos >= 0:
                    endpos = pos + 1
                    break
                else:
                    start = len(line)

            elif self._readuniversal:
                
                

                
                nlpos = line.find("\n", start)
                crpos = line.find("\r", start)
                if crpos == -1:
                    if nlpos == -1:
                        
                        start = len(line)
                    else:
                        
                        endpos = nlpos + 1
                        break
                elif nlpos == -1:
                    
                    endpos = crpos + 1
                    break
                elif nlpos < crpos:
                    
                    endpos = nlpos + 1
                    break
                elif nlpos == crpos + 1:
                    
                    endpos = crpos + 2
                    break
                else:
                    
                    endpos = crpos + 1
                    break
            else:
                
                pos = line.find(self._readnl)
                if pos >= 0:
                    endpos = pos + len(self._readnl)
                    break

            if size >= 0 and len(line) >= size:
                endpos = size  
                break

            
            while self._read_chunk():
                if self._decoded_chars:
                    break
            if self._decoded_chars:
                line += self._get_decoded_chars()
            else:
                
                self._set_decoded_chars('')
                self._snapshot = None
                return line

        if size >= 0 and endpos > size:
            endpos = size  

        
        self._rewind_decoded_chars(len(line) - endpos)
        return line[:endpos]

    @property
    def newlines(self):
        return self._decoder.newlines if self._decoder else None


class StringIO(TextIOWrapper):
    

    def __init__(self, initial_value="", newline="\n"):
        super(StringIO, self).__init__(BytesIO(),
                                       encoding="utf-8",
                                       errors="surrogatepass",
                                       newline=newline)
        
        
        if newline is None:
            self._writetranslate = False
        if initial_value is not None:
            if not isinstance(initial_value, str):
                raise TypeError("initial_value must be str or None, not {0}"
                                .format(type(initial_value).__name__))
            self.write(initial_value)
            self.seek(0)

    def getvalue(self):
        self.flush()
        decoder = self._decoder or self._get_decoder()
        old_state = decoder.getstate()
        decoder.reset()
        try:
            return decoder.decode(self.buffer.getvalue(), final=True)
        finally:
            decoder.setstate(old_state)

    def __repr__(self):
        
        
        return object.__repr__(self)

    @property
    def errors(self):
        return None

    @property
    def encoding(self):
        return None

    def detach(self):
        
        self._unsupported("detach")