]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-29435: Allow is_tarfile to take a filelike obj (GH-18090)
authorWilliam Woodruff <william@yossarian.net>
Thu, 23 Jan 2020 02:24:16 +0000 (21:24 -0500)
committerEthan Furman <ethan@stoneleaf.us>
Thu, 23 Jan 2020 02:24:16 +0000 (18:24 -0800)
`is_tarfile()` now supports `name` being a file or file-like object.

Doc/library/tarfile.rst
Lib/tarfile.py
Lib/test/test_tarfile.py
Misc/ACKS
Misc/NEWS.d/next/Library/2020-01-20-18-48-00.bpo-29435.qqJ2Ax.rst [new file with mode: 0644]

index c34f2c4a570246893247a96e70dd3e62c7ef9e36..459e4ad991d9dcf2ac818b4044a90f9e2965ca01 100644 (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:
index 2c06f9160c658a745d7de251e9e928f74a4c6d5a..d0b748cea17231457cd06cd3e724703b9c523d51 100755 (executable)
@@ -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:
index 15324a4e48819ef67b8c3dd2916bef455c62af0f..6a901089611cd8b799624b6c2875f8ac25a3b045 100644 (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
index 3e45d5d0f7f29d5d5a426bee47a1c6accfa357f1..7e4b81bfdee62db2c55fe8c686c064c61dc02dd0 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1856,6 +1856,7 @@ Klaus-Juergen Wolf
 Dan Wolfe
 Richard Wolff
 Adam Woodbeck
+William Woodruff
 Steven Work
 Gordon Worley
 Darren Worrall
diff --git a/Misc/NEWS.d/next/Library/2020-01-20-18-48-00.bpo-29435.qqJ2Ax.rst b/Misc/NEWS.d/next/Library/2020-01-20-18-48-00.bpo-29435.qqJ2Ax.rst
new file mode 100644 (file)
index 0000000..eabc942
--- /dev/null
@@ -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.