diff -r 9fcfdb53e8af Lib/codecs.py --- a/Lib/codecs.py Thu Nov 26 23:52:34 2015 +0200 +++ b/Lib/codecs.py Sat Nov 28 15:45:46 2015 +0200 @@ -335,6 +335,13 @@ class BufferedIncrementalDecoder(Increme # ignore additional state info self.buffer = state[0] + +def _getattr_proxy(self, name, _getattr=getattr): + # Public attribute lookups are delegated to the underlying stream + if name[:1] == '_': + raise AttributeError(name) + return _getattr(self.__dict__['stream'], name) + # # The StreamWriter and StreamReader class provide generic working # interfaces which can be used to implement new encoding submodules @@ -400,19 +407,15 @@ class StreamWriter(Codec): if whence == 0 and offset == 0: self.reset() - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - def __enter__(self): return self def __exit__(self, type, value, tb): self.stream.close() + # Inherit all other public methods from the underlying stream. + __getattr__ = _getattr_proxy + ### class StreamReader(Codec): @@ -440,8 +443,7 @@ class StreamReader(Codec): self.stream = stream self.errors = errors self.bytebuffer = b"" - self._empty_charbuffer = self.charbuffertype() - self.charbuffer = self._empty_charbuffer + self.charbuffer = self.charbuffertype() self.linebuffer = None def decode(self, input, errors='strict'): @@ -476,7 +478,7 @@ class StreamReader(Codec): """ # If we have lines cached, first merge them back into characters if self.linebuffer: - self.charbuffer = self._empty_charbuffer.join(self.linebuffer) + self.charbuffer = self.charbuffer[:0].join(self.linebuffer) self.linebuffer = None # read until we get the required number of characters (if available) @@ -518,7 +520,7 @@ class StreamReader(Codec): if chars < 0: # Return everything we've got result = self.charbuffer - self.charbuffer = self._empty_charbuffer + self.charbuffer = self.charbuffer[:0] else: # Return the first chars characters result = self.charbuffer[:chars] @@ -549,7 +551,7 @@ class StreamReader(Codec): return line readsize = size or 72 - line = self._empty_charbuffer + line = self.charbuffer[:0] # If size is given, we call read() only once while True: data = self.read(readsize, firstline=True) @@ -573,7 +575,7 @@ class StreamReader(Codec): # cache the remaining lines lines[-1] += self.charbuffer self.linebuffer = lines - self.charbuffer = None + self.charbuffer = self.charbuffer[:0] else: # only one remaining line, put it back into charbuffer self.charbuffer = lines[0] + self.charbuffer @@ -584,7 +586,7 @@ class StreamReader(Codec): line0withoutend = lines[0].splitlines(keepends=False)[0] if line0withend != line0withoutend: # We really have a line end # Put the rest back together and keep it until the next call - self.charbuffer = self._empty_charbuffer.join(lines[1:]) + \ + self.charbuffer = self.charbuffer[:0].join(lines[1:]) + \ self.charbuffer if keepends: line = line0withend @@ -625,7 +627,7 @@ class StreamReader(Codec): """ self.bytebuffer = b"" - self.charbuffer = self._empty_charbuffer + self.charbuffer = self.charbuffer[:0] self.linebuffer = None def seek(self, offset, whence=0): @@ -647,19 +649,15 @@ class StreamReader(Codec): def __iter__(self): return self - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - def __enter__(self): return self def __exit__(self, type, value, tb): self.stream.close() + # Inherit all other public methods from the underlying stream. + __getattr__ = _getattr_proxy + ### class StreamReaderWriter: @@ -732,13 +730,6 @@ class StreamReaderWriter: if whence == 0 and offset == 0: self.writer.reset() - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - # these are needed to make "with codecs.open(...)" work properly def __enter__(self): @@ -747,6 +738,9 @@ class StreamReaderWriter: def __exit__(self, type, value, tb): self.stream.close() + # Inherit all other public methods from the underlying stream. + __getattr__ = _getattr_proxy + ### class StreamRecoder: @@ -844,19 +838,15 @@ class StreamRecoder: self.reader.reset() self.writer.reset() - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - def __enter__(self): return self def __exit__(self, type, value, tb): self.stream.close() + # Inherit all other public methods from the underlying stream. + __getattr__ = _getattr_proxy + ### Shortcuts def open(filename, mode='r', encoding=None, errors='strict', buffering=1):