https://github.com/python/cpython/commit/e75ef6a768a439ee86aa997cd3ecb1ff73e3c3da commit: e75ef6a768a439ee86aa997cd3ecb1ff73e3c3da branch: main author: Serhiy Storchaka <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-08-13T13:12:24+03:00 summary:
gh-155040: Support copy.replace() for tarfile.TarInfo (GH-155046) Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> files: A Misc/NEWS.d/next/Library/2026-08-01-19-01-00.gh-issue-155040.Tr1nFo.rst M Doc/library/tarfile.rst M Lib/tarfile.py M Lib/test/test_tarfile.py diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index fc352e901f31dc..f19038d837bb52 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -963,6 +963,11 @@ A ``TarInfo`` object has the following public data attributes: If *deep* is false, the copy is shallow, i.e. ``pax_headers`` and any custom attributes are shared with the original ``TarInfo`` object. + This method is also used by :func:`copy.replace`. + + .. versionchanged:: next + Added support for :func:`copy.replace`. + A :class:`TarInfo` object also provides some convenient query methods: diff --git a/Lib/tarfile.py b/Lib/tarfile.py index dc5c3a59744cbc..592c4638c52c9b 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1036,6 +1036,8 @@ def replace(self, *, result.gname = gname return result + __replace__ = replace + def get_info(self): """Return the TarInfo's attributes as a dictionary. """ diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 5fa97e2ac226c4..bd544dfea51da3 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1,3 +1,4 @@ +import copy import errno import sys import os @@ -3524,6 +3525,16 @@ def test_replace_internal(self): with self.assertRaises(TypeError): member.replace(offset=123456789) + def test_copy_replace(self): + member = self.tar.getmember('ustar/regtype') + replaced = copy.replace(member, name='misc/other', mode=0o644) + self.assertEqual(replaced.name, 'misc/other') + self.assertEqual(replaced.mode, 0o644) + self.assertEqual(replaced.size, member.size) + self.assertEqual(member.name, 'ustar/regtype') + with self.assertRaises(TypeError): + copy.replace(member, offset=123456789) + class NoneInfoExtractTests(ReadTest): # These mainly check that all kinds of members are extracted successfully diff --git a/Misc/NEWS.d/next/Library/2026-08-01-19-01-00.gh-issue-155040.Tr1nFo.rst b/Misc/NEWS.d/next/Library/2026-08-01-19-01-00.gh-issue-155040.Tr1nFo.rst new file mode 100644 index 00000000000000..d7875404202912 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-01-19-01-00.gh-issue-155040.Tr1nFo.rst @@ -0,0 +1 @@ +:class:`tarfile.TarInfo` objects now support :func:`copy.replace`. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
