1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
# Copyright (C) 2010-2023 Bastian Kleineidam
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""A lot of these tests need an external compression program.
See https://salsa.debian.org/debian/patool/-/blob/master/debian/control
at the "Suggests:" for a list of packages with supported compression
programs.
The file type detection uses the file(1) program which uses a library
of "magic" patterns. The contents of the magic pattern library can vary
between distributions so the tests might not run on all systems.
"""
import os
import patoolib
import pytest
import importlib
basedir = os.path.dirname(__file__)
datadir = os.path.join(basedir, 'data')
# Python 3.x function name attribute
fnameattr = '__name__'
def _need_func(testfunc, name, description):
"""Decorator skipping test if given testfunc returns False."""
def check_func(func):
def newfunc(*args, **kwargs):
if not testfunc(name):
pytest.skip(f"{description} {name!r} is not available")
return func(*args, **kwargs)
setattr(newfunc, fnameattr, getattr(func, fnameattr))
return newfunc
return check_func
def needs_os(name):
"""Decorator skipping test if given operating system is not available."""
return _need_func(lambda x: os.name == x, name, 'operating system')
def needs_program(name):
"""Decorator skipping test if given program is not available."""
return _need_func(lambda x: patoolib.util.find_program(x), name, 'program')
def needs_one_program(programs):
"""Decorator skipping test if not one of given programs are available."""
return _need_func(
lambda x: any(map(patoolib.util.find_program, x)), programs, 'programs'
)
def needs_module(name):
"""Decorator skipping test if given module is not available."""
def has_module(module):
try:
importlib.import_module(module)
return True
except ImportError:
return False
return _need_func(has_module, name, 'Python module')
def needs_codec(program, codec, commands=patoolib.ArchiveCommands):
"""Decorator skipping test if given program codec is not available."""
def check_prog(f):
def newfunc(*args, **kwargs):
exe = patoolib.util.find_program(program)
if not exe:
pytest.skip(f"program `{program}' not available")
for command in commands:
if not has_codec(command, program, exe, codec):
pytest.skip(
f"codec `{codec}' for program `{program}' and command `{command}' not available"
)
return f(*args, **kwargs)
setattr(newfunc, fnameattr, getattr(f, fnameattr))
return newfunc
return check_prog
def has_codec(command, program, exe, codec):
"""Test if program supports given codec with given command."""
if program in ('7z', '7zz', '7zzs', '7za'):
if codec == 'rar':
# 7zip can be optionally built without rar support
# Notably on Debian, the non-free p7zip-rar package must be installed to support RAR for 7z
return patoolib.util.p7zip_supports_rar(program)
if codec == 'compress':
return patoolib.util.p7zip_supports_compress(program)
elif program == 'arc':
return patoolib.util.get_arc_format(exe) == codec
return patoolib.program_supports_compression(command, program, exe, codec)
|