bpo-29435: Allow is_tarfile to take a filelike obj (GH-18090)

`is_tarfile()` now supports `name` being a file or file-like object.
This commit is contained in:
William Woodruff 2020-01-22 21:24:16 -05:00 committed by Ethan Furman
parent 41f0ef6abb
commit dd754caf14
5 changed files with 45 additions and 2 deletions

View File

@ -159,7 +159,10 @@ Some facts and figures:
.. function:: is_tarfile(name)
Return :const:`True` if *name* is a tar archive file, that the :mod:`tarfile`
module can read.
module can read. *name* may be a :class:`str`, file, or file-like object.
.. versionchanged:: 3.9
Support for file and file-like objects.
The :mod:`tarfile` module defines the following exceptions:

View File

@ -2461,9 +2461,14 @@ class TarFile(object):
def is_tarfile(name):
"""Return True if name points to a tar archive that we
are able to handle, else return False.
'name' should be a string, file, or file-like object.
"""
try:
t = open(name)
if hasattr(name, "read"):
t = open(fileobj=name)
else:
t = open(name)
t.close()
return True
except TarError:

View File

@ -319,6 +319,38 @@ class LzmaListTest(LzmaTest, ListTest):
class CommonReadTest(ReadTest):
def test_is_tarfile_erroneous(self):
with open(tmpname, "wb"):
pass
# is_tarfile works on filenames
self.assertFalse(tarfile.is_tarfile(tmpname))
# is_tarfile works on path-like objects
self.assertFalse(tarfile.is_tarfile(pathlib.Path(tmpname)))
# is_tarfile works on file objects
with open(tmpname, "rb") as fobj:
self.assertFalse(tarfile.is_tarfile(fobj))
# is_tarfile works on file-like objects
self.assertFalse(tarfile.is_tarfile(io.BytesIO(b"invalid")))
def test_is_tarfile_valid(self):
# is_tarfile works on filenames
self.assertTrue(tarfile.is_tarfile(self.tarname))
# is_tarfile works on path-like objects
self.assertTrue(tarfile.is_tarfile(pathlib.Path(self.tarname)))
# is_tarfile works on file objects
with open(self.tarname, "rb") as fobj:
self.assertTrue(tarfile.is_tarfile(fobj))
# is_tarfile works on file-like objects
with open(self.tarname, "rb") as fobj:
self.assertTrue(tarfile.is_tarfile(io.BytesIO(fobj.read())))
def test_empty_tarfile(self):
# Test for issue6123: Allow opening empty archives.
# This test checks if tarfile.open() is able to open an empty tar

View File

@ -1856,6 +1856,7 @@ Klaus-Juergen Wolf
Dan Wolfe
Richard Wolff
Adam Woodbeck
William Woodruff
Steven Work
Gordon Worley
Darren Worrall

View File

@ -0,0 +1,2 @@
Allow :func:`tarfile.is_tarfile` to be used with file and file-like
objects, like :func:`zipfile.is_zipfile`. Patch by William Woodruff.