bpo-15216: io: TextIOWrapper.reconfigure() accepts encoding, errors a… · python/cpython@507434f
@@ -1938,10 +1938,7 @@ class TextIOWrapper(TextIOBase):
19381938# so that the signature can match the signature of the C version.
19391939def __init__(self, buffer, encoding=None, errors=None, newline=None,
19401940line_buffering=False, write_through=False):
1941-if newline is not None and not isinstance(newline, str):
1942-raise TypeError("illegal newline type: %r" % (type(newline),))
1943-if newline not in (None, "", "\n", "\r", "\r\n"):
1944-raise ValueError("illegal newline value: %r" % (newline,))
1941+self._check_newline(newline)
19451942if encoding is None:
19461943try:
19471944encoding = os.device_encoding(buffer.fileno())
@@ -1971,22 +1968,38 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
19711968raise ValueError("invalid errors: %r" % errors)
1972196919731970self._buffer = buffer
1971+self._decoded_chars = '' # buffer for text returned from decoder
1972+self._decoded_chars_used = 0 # offset into _decoded_chars for read()
1973+self._snapshot = None # info for reconstructing decoder state
1974+self._seekable = self._telling = self.buffer.seekable()
1975+self._has_read1 = hasattr(self.buffer, 'read1')
1976+self._configure(encoding, errors, newline,
1977+line_buffering, write_through)
1978+1979+def _check_newline(self, newline):
1980+if newline is not None and not isinstance(newline, str):
1981+raise TypeError("illegal newline type: %r" % (type(newline),))
1982+if newline not in (None, "", "\n", "\r", "\r\n"):
1983+raise ValueError("illegal newline value: %r" % (newline,))
1984+1985+def _configure(self, encoding=None, errors=None, newline=None,
1986+line_buffering=False, write_through=False):
19741987self._encoding = encoding
19751988self._errors = errors
1989+self._encoder = None
1990+self._decoder = None
1991+self._b2cratio = 0.0
1992+19761993self._readuniversal = not newline
19771994self._readtranslate = newline is None
19781995self._readnl = newline
19791996self._writetranslate = newline != ''
19801997self._writenl = newline or os.linesep
1981-self._encoder = None
1982-self._decoder = None
1983-self._decoded_chars = '' # buffer for text returned from decoder
1984-self._decoded_chars_used = 0 # offset into _decoded_chars for read()
1985-self._snapshot = None # info for reconstructing decoder state
1986-self._seekable = self._telling = self.buffer.seekable()
1987-self._has_read1 = hasattr(self.buffer, 'read1')
1988-self._b2cratio = 0.0
198919981999+self._line_buffering = line_buffering
2000+self._write_through = write_through
2001+2002+# don't write a BOM in the middle of a file
19902003if self._seekable and self.writable():
19912004position = self.buffer.tell()
19922005if position != 0:
@@ -1996,12 +2009,6 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
19962009# Sometimes the encoder doesn't exist
19972010pass
199820111999-self._configure(line_buffering, write_through)
2000-2001-def _configure(self, line_buffering=False, write_through=False):
2002-self._line_buffering = line_buffering
2003-self._write_through = write_through
2004-20052012# self._snapshot is either None, or a tuple (dec_flags, next_input)
20062013# where dec_flags is the second (integer) item of the decoder state
20072014# and next_input is the chunk of input bytes that comes next after the
@@ -2048,17 +2055,46 @@ def write_through(self):
20482055def buffer(self):
20492056return self._buffer
205020572051-def reconfigure(self, *, line_buffering=None, write_through=None):
2058+def reconfigure(self, *,
2059+encoding=None, errors=None, newline=Ellipsis,
2060+line_buffering=None, write_through=None):
20522061"""Reconfigure the text stream with new parameters.
2053206220542063 This also flushes the stream.
20552064 """
2065+if (self._decoder is not None
2066+and (encoding is not None or errors is not None
2067+or newline is not Ellipsis)):
2068+raise UnsupportedOperation(
2069+"It is not possible to set the encoding or newline of stream "
2070+"after the first read")
2071+2072+if errors is None:
2073+if encoding is None:
2074+errors = self._errors
2075+else:
2076+errors = 'strict'
2077+elif not isinstance(errors, str):
2078+raise TypeError("invalid errors: %r" % errors)
2079+2080+if encoding is None:
2081+encoding = self._encoding
2082+else:
2083+if not isinstance(encoding, str):
2084+raise TypeError("invalid encoding: %r" % encoding)
2085+2086+if newline is Ellipsis:
2087+newline = self._readnl
2088+self._check_newline(newline)
2089+20562090if line_buffering is None:
20572091line_buffering = self.line_buffering
20582092if write_through is None:
20592093write_through = self.write_through
2094+20602095self.flush()
2061-self._configure(line_buffering, write_through)
2096+self._configure(encoding, errors, newline,
2097+line_buffering, write_through)
2062209820632099def seekable(self):
20642100if self.closed: