Skip to content

Commit e3dd6df

Browse files
authored
Merge pull request #12 from aaron-sierra/fix-guess_format-popen-stdout
Handle file-like objects with integer name attribute
2 parents b839a05 + fcead6f commit e3dd6df

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

libarchive/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ def get_func(name, items, index):
117117

118118

119119
def guess_format(filename):
120-
filename, ext = os.path.splitext(filename)
120+
if isinstance(filename, int):
121+
filename = ext = ''
122+
else:
123+
filename, ext = os.path.splitext(filename)
121124
filter = FILTER_EXTENSIONS.get(ext)
122125
if filter:
123126
filename, ext = os.path.splitext(filename)
@@ -312,10 +315,11 @@ def from_archive(cls, archive, encoding=ENCODING):
312315
call_and_check(_libarchive.archive_read_next_header2, archive._a, archive._a, e)
313316
mode = _libarchive.archive_entry_filetype(e)
314317
mode |= _libarchive.archive_entry_perm(e)
318+
315319
if PY3:
316-
pathname=_libarchive.archive_entry_pathname(e)
320+
pathname = _libarchive.archive_entry_pathname(e)
317321
else:
318-
pathname=_libarchive.archive_entry_pathname(e).decode(encoding),
322+
pathname = _libarchive.archive_entry_pathname(e).decode(encoding)
319323

320324
entry = cls(
321325
pathname=pathname,
@@ -628,11 +632,7 @@ def reopen(self):
628632
def getentry(self, pathname):
629633
'''Take a name or entry object and returns an entry object.'''
630634
for entry in self:
631-
if PY3:
632-
entry_pathname = entry.pathname
633-
if not PY3:
634-
entry_pathname = entry.pathname[0]
635-
if entry_pathname == pathname:
635+
if entry.pathname == pathname:
636636
return entry
637637
raise KeyError(pathname)
638638

tests.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@
2626
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2727
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828

29-
import os, unittest, tempfile, random, string, subprocess, sys
29+
import os, unittest, tempfile, random, string, sys
30+
import zipfile
31+
import io
3032

31-
from libarchive import is_archive_name, is_archive
33+
from libarchive import Archive, is_archive_name, is_archive
3234
from libarchive.zip import is_zipfile, ZipFile, ZipEntry
3335

3436
PY3 = sys.version_info[0] == 3
3537

36-
TMPDIR = tempfile.mkdtemp()
37-
ZIPCMD = '/usr/bin/zip'
38+
TMPDIR = tempfile.mkdtemp(suffix='.python-libarchive')
3839
ZIPFILE = 'test.zip'
3940
ZIPPATH = os.path.join(TMPDIR, ZIPFILE)
4041

@@ -54,13 +55,10 @@ def make_temp_files():
5455

5556

5657
def make_temp_archive():
57-
if not os.access(ZIPCMD, os.X_OK):
58-
raise AssertionError('Cannot execute %s.' % ZIPCMD)
59-
cmd = [ZIPCMD, ZIPFILE]
6058
make_temp_files()
61-
cmd.extend(FILENAMES)
62-
os.chdir(TMPDIR)
63-
subprocess.call(cmd, stdout=subprocess.PIPE)
59+
with zipfile.ZipFile(ZIPPATH, mode="w") as z:
60+
for name in FILENAMES:
61+
z.write(os.path.join(TMPDIR, name), arcname=name)
6462

6563

6664
class TestIsArchiveName(unittest.TestCase):
@@ -152,10 +150,7 @@ def test_filenames(self):
152150
z = ZipFile(self.f, 'r')
153151
names = []
154152
for e in z:
155-
if PY3:
156-
names.append(e.filename)
157-
else:
158-
names.append(e.filename[0])
153+
names.append(e.filename)
159154
self.assertEqual(names, FILENAMES, 'File names differ in archive.')
160155

161156
#~ def test_non_ascii(self):
@@ -250,5 +245,35 @@ def test_deferred_close_by_archive(self):
250245
self.assertIsNone(z._stream)
251246
z.close()
252247

248+
249+
class TestHighLevelAPI(unittest.TestCase):
250+
def setUp(self):
251+
make_temp_archive()
252+
253+
def _test_listing_content(self, f):
254+
""" Test helper capturing file paths while iterating the archive. """
255+
found = []
256+
with Archive(f) as a:
257+
for entry in a:
258+
found.append(entry.pathname)
259+
260+
self.assertEqual(set(found), set(FILENAMES))
261+
262+
def test_open_by_name(self):
263+
""" Test an archive opened directly by name. """
264+
self._test_listing_content(ZIPPATH)
265+
266+
def test_open_by_named_fobj(self):
267+
""" Test an archive using a file-like object opened by name. """
268+
with open(ZIPPATH, 'rb') as f:
269+
self._test_listing_content(f)
270+
271+
def test_open_by_unnamed_fobj(self):
272+
""" Test an archive using file-like object opened by fileno(). """
273+
with open(ZIPPATH, 'rb') as zf:
274+
with io.FileIO(zf.fileno(), mode='r', closefd=False) as f:
275+
self._test_listing_content(f)
276+
277+
253278
if __name__ == '__main__':
254279
unittest.main()

0 commit comments

Comments
 (0)