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.
This commit is contained in:
Charles LeDoux 2017-12-27 18:15:20 -06:00 committed by Yaroslav Halchenko
parent cadeb1ca9f
commit 03018b4e5b
4 changed files with 22 additions and 13 deletions

View File

@ -25,7 +25,7 @@ import importlib
from .configuration import App, Version as __version__ from .configuration import App, Version as __version__
__all__ = ['list_formats', 'list_archive', 'extract_archive', 'test_archive', __all__ = ['list_formats', 'list_archive', 'extract_archive', 'test_archive',
'create_archive', 'diff_archives', 'search_archive', 'repack_archive', 'create_archive', 'diff_archives', 'search_archive', 'repack_archive',
'recompress_archive'] 'recompress_archive', 'program_supports_compression']
# Supported archive commands # 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 from . import util
def get_archive_format (filename): 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))) 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 (): def list_formats ():
"""Print information about available archive formats to stdout.""" """Print information about available archive formats to stdout."""
print("Archive programs of", App) print("Archive programs of", App)

View File

@ -24,7 +24,7 @@ import tempfile
import time import time
import traceback import traceback
import locale import locale
from . import configuration, ArchiveMimetypes, ArchiveCompressions from . import configuration, ArchiveMimetypes, ArchiveCompressions, program_supports_compression
try: try:
from shutil import which from shutil import which
except ImportError: except ImportError:
@ -314,7 +314,12 @@ def guess_mime_file (filename):
elif mime2 in ArchiveMimetypes: elif mime2 in ArchiveMimetypes:
mime = mime2 mime = mime2
encoding = get_file_mime_encoding(outparts) 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): def guess_mime_file_mime (file_prog, filename):

View File

@ -69,6 +69,7 @@ class TestTar (ArchiveTest):
self.archive_commands('t.tgz.foo', skip_create=True) self.archive_commands('t.tgz.foo', skip_create=True)
@needs_program('file') @needs_program('file')
@needs_program('compress')
@needs_codec(program, 'compress') @needs_codec(program, 'compress')
def test_tar_z_file (self): def test_tar_z_file (self):
self.archive_commands('t.tar.Z.foo', skip_create=True) self.archive_commands('t.tar.Z.foo', skip_create=True)

View File

@ -138,6 +138,7 @@ class TestMime (unittest.TestCase):
self.mime_test_file("t.zpaq", "application/zpaq") self.mime_test_file("t.zpaq", "application/zpaq")
self.mime_test_file("t.zpaq.foo", "application/zpaq") self.mime_test_file("t.zpaq.foo", "application/zpaq")
@needs_program('file') @needs_program('file')
@needs_program('lzip') @needs_program('lzip')
def test_mime_file_lzip (self): def test_mime_file_lzip (self):