From 03018b4e5b1e8b1c5b76feec34b0e02edfdd8181 Mon Sep 17 00:00:00 2001 From: Charles LeDoux Date: Wed, 27 Dec 2017 18:15:20 -0600 Subject: [PATCH] Only return separate encoding if `program_supports_compression` Why: * To prevent archives such as archive.rar.gz from breaking patool. This change addresses the need by: * move program_supports_compression above the `import util` line * If we don't do this, we have a circular import. * Import program_supports_compression into util. * Only return separate mime and encoding if program_support_compression returns True. * Otherwise return the mime of the encoding and no encoding. * Add fixes so that current tests still pass. * In program_support_compression: - Test tar separately and check all supported tar wrappers. * In test_tar: - Add file requirement for compress in the compress check. - Otherwise tar tries and failes when compress isn't installed. --- patoolib/__init__.py | 24 +++++++++++++----------- patoolib/util.py | 9 +++++++-- tests/archives/test_tar.py | 1 + tests/test_mime.py | 1 + 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/patoolib/__init__.py b/patoolib/__init__.py index f50d887..25ee4b4 100644 --- a/patoolib/__init__.py +++ b/patoolib/__init__.py @@ -25,7 +25,7 @@ import importlib from .configuration import App, Version as __version__ __all__ = ['list_formats', 'list_archive', 'extract_archive', 'test_archive', 'create_archive', 'diff_archives', 'search_archive', 'repack_archive', - 'recompress_archive'] + 'recompress_archive', 'program_supports_compression'] # Supported archive commands @@ -284,6 +284,18 @@ ProgramModules = { } +def program_supports_compression (program, compression): + """Decide if the given program supports the compression natively. + @return: True iff the program supports the given compression format + natively, else False. + """ + if program in ('tar', ): + return compression in ('gzip', 'bzip2', 'xz', 'lzip', 'compress', 'lzma') + py_lzma + elif program in ('star', 'bsdtar', 'py_tarfile'): + return compression in ('gzip', 'bzip2') + py_lzma + return False + + from . import util def get_archive_format (filename): @@ -336,16 +348,6 @@ def find_archive_program (format, command, program=None): raise util.PatoolError("could not find an executable program to %s format %s; candidates are (%s)," % (command, format, ",".join(programs))) -def program_supports_compression (program, compression): - """Decide if the given program supports the compression natively. - @return: True iff the program supports the given compression format - natively, else False. - """ - if program in ('tar', 'star', 'bsdtar', 'py_tarfile'): - return compression in ('gzip', 'bzip2') + py_lzma - return False - - def list_formats (): """Print information about available archive formats to stdout.""" print("Archive programs of", App) diff --git a/patoolib/util.py b/patoolib/util.py index 5975e75..e0976bd 100644 --- a/patoolib/util.py +++ b/patoolib/util.py @@ -24,7 +24,7 @@ import tempfile import time import traceback import locale -from . import configuration, ArchiveMimetypes, ArchiveCompressions +from . import configuration, ArchiveMimetypes, ArchiveCompressions, program_supports_compression try: from shutil import which except ImportError: @@ -314,7 +314,12 @@ def guess_mime_file (filename): elif mime2 in ArchiveMimetypes: mime = mime2 encoding = get_file_mime_encoding(outparts) - return mime, encoding + # Only return mime and encoding if the given mime can natively support the encoding. + if program_supports_compression(ArchiveMimetypes.get(mime), encoding): + return mime, encoding + else: + # If encoding is None, default back to `mime`. + return Encoding2Mime.get(encoding, mime), None def guess_mime_file_mime (file_prog, filename): diff --git a/tests/archives/test_tar.py b/tests/archives/test_tar.py index 9de8d4b..7f31730 100644 --- a/tests/archives/test_tar.py +++ b/tests/archives/test_tar.py @@ -69,6 +69,7 @@ class TestTar (ArchiveTest): self.archive_commands('t.tgz.foo', skip_create=True) @needs_program('file') + @needs_program('compress') @needs_codec(program, 'compress') def test_tar_z_file (self): self.archive_commands('t.tar.Z.foo', skip_create=True) diff --git a/tests/test_mime.py b/tests/test_mime.py index c36d2d0..8b93ce0 100644 --- a/tests/test_mime.py +++ b/tests/test_mime.py @@ -138,6 +138,7 @@ class TestMime (unittest.TestCase): self.mime_test_file("t.zpaq", "application/zpaq") self.mime_test_file("t.zpaq.foo", "application/zpaq") + @needs_program('file') @needs_program('lzip') def test_mime_file_lzip (self):