diff --git a/Lib/codecs.py b/Lib/codecs.py index 21c45a7d10a4c9..dc67ffc63d96b7 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -7,8 +7,10 @@ """ +import abc import builtins import sys +import _collections_abc ### Registry and builtin stateless codec functions @@ -251,7 +253,7 @@ def getstate(self): def setstate(self, state): self.buffer = state or "" -class IncrementalDecoder(object): +class IncrementalDecoder(abc.ABC): """ An IncrementalDecoder decodes an input in multiple steps. The input can be passed piece by piece to the decode() method. The IncrementalDecoder @@ -300,6 +302,13 @@ def setstate(self, state): setstate((b"", 0)) must be equivalent to reset(). """ + @classmethod + def __subclasshook__(cls, C): + if issubclass(C, _io.IncrementalNewlineDecoder): + return _collections_abc._check_methods(C, "decode", "reset", + "getstate", "setstate") + return NotImplemented + class BufferedIncrementalDecoder(IncrementalDecoder): """ This subclass of IncrementalDecoder can be used as the baseclass for an @@ -1110,6 +1119,11 @@ def make_encoding_map(decoding_map): if _false: import encodings +try: + import _io + IncrementalDecoder.register(_io.IncrementalNewlineDecoder) +except ImportError: + pass ### Tests if __name__ == '__main__': diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 1fe1cba5167fc6..bd209db6f0831a 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -4177,6 +4177,9 @@ def test_check_encoding_errors(self): proc = assert_python_failure('-X', 'dev', '-c', code) self.assertEqual(proc.rc, 10, proc) + def test_subclass_of_codecs_incremental_decoder(self): + self.assertTrue(self.io.IncrementalNewlineDecoder, + codecs.IncrementalDecoder) class CMiscIOTest(MiscIOTest): io = io diff --git a/Misc/NEWS.d/next/Library/2019-10-09-02-57-03.bpo-31722.r1mkRa.rst b/Misc/NEWS.d/next/Library/2019-10-09-02-57-03.bpo-31722.r1mkRa.rst new file mode 100644 index 00000000000000..4e506e75a838e7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-10-09-02-57-03.bpo-31722.r1mkRa.rst @@ -0,0 +1,2 @@ +Update :class:`codecs.IncrementalDecoder` to use :meth:`__subclasshook__` method. +(Contributed by Dong-hee Na in :issue:`31722`.)