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.

19391939

def __init__(self, buffer, encoding=None, errors=None, newline=None,

19401940

line_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)

19451942

if encoding is None:

19461943

try:

19471944

encoding = os.device_encoding(buffer.fileno())

@@ -1971,22 +1968,38 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,

19711968

raise ValueError("invalid errors: %r" % errors)

1972196919731970

self._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):

19741987

self._encoding = encoding

19751988

self._errors = errors

1989+

self._encoder = None

1990+

self._decoder = None

1991+

self._b2cratio = 0.0

1992+19761993

self._readuniversal = not newline

19771994

self._readtranslate = newline is None

19781995

self._readnl = newline

19791996

self._writetranslate = newline != ''

19801997

self._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

19902003

if self._seekable and self.writable():

19912004

position = self.buffer.tell()

19922005

if position != 0:

@@ -1996,12 +2009,6 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,

19962009

# Sometimes the encoder doesn't exist

19972010

pass

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):

20482055

def buffer(self):

20492056

return 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+20562090

if line_buffering is None:

20572091

line_buffering = self.line_buffering

20582092

if write_through is None:

20592093

write_through = self.write_through

2094+20602095

self.flush()

2061-

self._configure(line_buffering, write_through)

2096+

self._configure(encoding, errors, newline,

2097+

line_buffering, write_through)

2062209820632099

def seekable(self):

20642100

if self.closed: