Skip to content

Commit

Permalink
pythongh-66143: Allow copying and pickling of CodecInfo object (pytho…
Browse files Browse the repository at this point in the history
…nGH-109235)

Co-authored-by: Robert Lehmann <[email protected]>
  • Loading branch information
furkanonder and lehmannro authored Sep 29, 2023
1 parent 7d57288 commit 3439cb0
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Lib/codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ def __repr__(self):
(self.__class__.__module__, self.__class__.__qualname__,
self.name, id(self))

def __getnewargs__(self):
return tuple(self)

class Codec:

""" Defines the interface for stateless encoders/decoders.
Expand Down
70 changes: 70 additions & 0 deletions Lib/test/test_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,76 @@ def test_file_closes_if_lookup_error_raised(self):

file().close.assert_called()

def test_copy(self):
orig = codecs.lookup('utf-8')
dup = copy.copy(orig)
self.assertIsNot(dup, orig)
self.assertEqual(dup, orig)
self.assertTrue(orig._is_text_encoding)
self.assertEqual(dup.encode, orig.encode)
self.assertEqual(dup.name, orig.name)
self.assertEqual(dup.incrementalencoder, orig.incrementalencoder)

# Test a CodecInfo with _is_text_encoding equal to false.
orig = codecs.lookup("base64")
dup = copy.copy(orig)
self.assertIsNot(dup, orig)
self.assertEqual(dup, orig)
self.assertFalse(orig._is_text_encoding)
self.assertEqual(dup.encode, orig.encode)
self.assertEqual(dup.name, orig.name)
self.assertEqual(dup.incrementalencoder, orig.incrementalencoder)

def test_deepcopy(self):
orig = codecs.lookup('utf-8')
dup = copy.deepcopy(orig)
self.assertIsNot(dup, orig)
self.assertEqual(dup, orig)
self.assertTrue(orig._is_text_encoding)
self.assertEqual(dup.encode, orig.encode)
self.assertEqual(dup.name, orig.name)
self.assertEqual(dup.incrementalencoder, orig.incrementalencoder)

# Test a CodecInfo with _is_text_encoding equal to false.
orig = codecs.lookup("base64")
dup = copy.deepcopy(orig)
self.assertIsNot(dup, orig)
self.assertEqual(dup, orig)
self.assertFalse(orig._is_text_encoding)
self.assertEqual(dup.encode, orig.encode)
self.assertEqual(dup.name, orig.name)
self.assertEqual(dup.incrementalencoder, orig.incrementalencoder)

def test_pickle(self):
codec_info = codecs.lookup('utf-8')
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(protocol=proto):
pickled_codec_info = pickle.dumps(codec_info)
unpickled_codec_info = pickle.loads(pickled_codec_info)
self.assertIsNot(codec_info, unpickled_codec_info)
self.assertEqual(codec_info, unpickled_codec_info)
self.assertEqual(codec_info.name, unpickled_codec_info.name)
self.assertEqual(
codec_info.incrementalencoder,
unpickled_codec_info.incrementalencoder
)
self.assertTrue(unpickled_codec_info._is_text_encoding)

# Test a CodecInfo with _is_text_encoding equal to false.
codec_info = codecs.lookup('base64')
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(protocol=proto):
pickled_codec_info = pickle.dumps(codec_info)
unpickled_codec_info = pickle.loads(pickled_codec_info)
self.assertIsNot(codec_info, unpickled_codec_info)
self.assertEqual(codec_info, unpickled_codec_info)
self.assertEqual(codec_info.name, unpickled_codec_info.name)
self.assertEqual(
codec_info.incrementalencoder,
unpickled_codec_info.incrementalencoder
)
self.assertFalse(unpickled_codec_info._is_text_encoding)


class StreamReaderTest(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The :class:`codecs.CodecInfo` object has been made copyable and pickleable.
Patched by Robert Lehmann and Furkan Onder.

0 comments on commit 3439cb0

Please sign in to comment.