Commit 8ea7501f authored by Chris Lamb's avatar Chris Lamb 💬

PEP8: E501 - Try to make lines fit to length.

parent 055cae5c
......@@ -46,7 +46,8 @@ class ArContainer(LibarchiveContainer):
filtered_out = [p for p in members if p[0] in known_ignores]
if filtered_out:
for k, v in filtered_out:
logger.debug("ignored ar member '%s' because %s", k, known_ignores[k])
logger.debug("ignored ar member '%s' because %s",
k, known_ignores[k])
return [p for p in members if p[0] not in known_ignores]
......
......@@ -37,7 +37,8 @@ logger = logging.getLogger(__name__)
class CbfsListing(Command):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._header_re = re.compile(r'^.*: ([^,]+, bootblocksize [0-9]+, romsize [0-9]+, offset 0x[0-9A-Fa-f]+)$')
self._header_re = re.compile(
r'^.*: ([^,]+, bootblocksize [0-9]+, romsize [0-9]+, offset 0x[0-9A-Fa-f]+)$')
@tool_required('cbfstool')
def cmdline(self):
......@@ -75,9 +76,11 @@ class CbfsContainer(Archive):
@tool_required('cbfstool')
def extract(self, member_name, dest_dir):
dest_path = os.path.join(dest_dir, os.path.basename(member_name))
cmd = ['cbfstool', self.source.path, 'extract', '-n', member_name, '-f', dest_path]
cmd = ['cbfstool', self.source.path, 'extract',
'-n', member_name, '-f', dest_path]
logger.debug("cbfstool extract %s to %s", member_name, dest_path)
subprocess.check_call(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
subprocess.check_call(
cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
return dest_path
......@@ -91,7 +94,8 @@ CBFS_MAXIMUM_FILE_SIZE = 24 * 2 ** 20 # 24 MiB
def is_header_valid(buf, size, offset=0):
magic, version, romsize, bootblocksize, align, cbfs_offset, architecture, pad = struct.unpack_from('!IIIIIIII', buf, offset)
magic, version, romsize, bootblocksize, align, cbfs_offset, architecture, pad = struct.unpack_from(
'!IIIIIIII', buf, offset)
return magic == CBFS_HEADER_MAGIC and \
(version == CBFS_HEADER_VERSION1 or version == CBFS_HEADER_VERSION2) and \
(romsize <= size) and \
......@@ -122,7 +126,8 @@ class CbfsFile(File):
elif not file.name.endswith('.rom'):
return False
else:
logger.debug('CBFS relative offset seems wrong, scanning whole image')
logger.debug(
'CBFS relative offset seems wrong, scanning whole image')
f.seek(0, io.SEEK_SET)
offset = 0
buf = f.read(CBFS_HEADER_SIZE)
......
......@@ -108,7 +108,8 @@ class DebFile(File):
def md5sums(self):
if not hasattr(self, '_md5sums'):
control_tar = self.as_container.control_tar
md5sums_file = control_tar.as_container.lookup_file('./md5sums') if control_tar else None
md5sums_file = control_tar.as_container.lookup_file(
'./md5sums') if control_tar else None
if md5sums_file:
self._md5sums = md5sums_file.parse()
else:
......@@ -122,7 +123,8 @@ class DebFile(File):
return None
if not hasattr(self, '_control'):
control_file = self.as_container.control_tar.as_container.lookup_file('./control')
control_file = self.as_container.control_tar.as_container.lookup_file(
'./control')
if control_file:
with open(control_file.path, 'rb') as f:
self._control = deb822.Deb822(f)
......@@ -143,7 +145,8 @@ class Md5sumsFile(File):
isinstance(file.container.source, ArchiveMember) and \
isinstance(file.container.source.container.source, ArchiveMember) and \
DebContainer.RE_CONTROL_TAR.match(file.container.source.container.source.name) and \
isinstance(file.container.source.container.source.container.source, DebFile)
isinstance(
file.container.source.container.source.container.source, DebFile)
def parse(self):
try:
......
......@@ -27,7 +27,8 @@ class DotChangesFile(TextFile):
difference = super().compare(other, *args, **kwargs)
if not difference:
return None
difference.add_comment('Unable to find Python debian module. Falling back to text comparison.')
difference.add_comment(
'Unable to find Python debian module. Falling back to text comparison.')
return difference
......@@ -38,7 +39,8 @@ class DotDscFile(TextFile):
difference = super().compare(other, *args, **kwargs)
if not difference:
return None
difference.add_comment('Unable to find Python debian module. Falling back to text comparison.')
difference.add_comment(
'Unable to find Python debian module. Falling back to text comparison.')
return difference
......@@ -49,5 +51,6 @@ class DotBuildinfoFile(TextFile):
difference = super().compare(other, *args, **kwargs)
if not difference:
return None
difference.add_comment('Unable to find Python debian module. Falling back to text comparison.')
difference.add_comment(
'Unable to find Python debian module. Falling back to text comparison.')
return difference
......@@ -41,8 +41,10 @@ def list_files(path):
path = os.path.realpath(path)
all_files = []
for root, dirs, names in os.walk(path):
all_files.extend([os.path.join(root[len(path) + 1:], dir) for dir in dirs])
all_files.extend([os.path.join(root[len(path) + 1:], name) for name in names])
all_files.extend([os.path.join(root[len(path) + 1:], dir)
for dir in dirs])
all_files.extend([os.path.join(root[len(path) + 1:], name)
for name in names])
all_files.sort()
return all_files
......@@ -135,7 +137,8 @@ def xattr(path1, path2):
def compare_meta(path1, path2):
if Config().exclude_directory_metadata:
logger.debug("Excluding directory metadata for paths (%s, %s)", path1, path2)
logger.debug(
"Excluding directory metadata for paths (%s, %s)", path1, path2)
return []
logger.debug('compare_meta(%s, %s)', path1, path2)
......@@ -154,7 +157,8 @@ def compare_meta(path1, path2):
try:
differences.append(Difference.from_command(Getfacl, path1, path2))
except RequiredToolNotFound:
logger.warning("Unable to find 'getfacl', some directory metadata differences might not be noticed.")
logger.warning(
"Unable to find 'getfacl', some directory metadata differences might not be noticed.")
try:
lsattr1 = lsattr(path1)
lsattr2 = lsattr(path2)
......@@ -166,10 +170,12 @@ def compare_meta(path1, path2):
source='lsattr',
))
except RequiredToolNotFound:
logger.info("Unable to find 'lsattr', some directory metadata differences might not be noticed.")
logger.info(
"Unable to find 'lsattr', some directory metadata differences might not be noticed.")
differences.append(xattr(path1, path2))
return [d for d in differences if d is not None]
def compare_directories(path1, path2, source=None):
return FilesystemDirectory(path1).compare(FilesystemDirectory(path2))
......@@ -255,8 +261,10 @@ class DirectoryContainer(Container):
def comparisons(self, other):
my_members = collections.OrderedDict(self.get_adjusted_members_sizes())
other_members = collections.OrderedDict(other.get_adjusted_members_sizes())
total_size = sum(x[1] for x in my_members.values()) + sum(x[1] for x in other_members.values())
other_members = collections.OrderedDict(
other.get_adjusted_members_sizes())
total_size = sum(x[1] for x in my_members.values()) + \
sum(x[1] for x in other_members.values())
to_compare = set(my_members.keys()).intersection(other_members.keys())
with Progress(total_size) as p:
......
......@@ -376,7 +376,8 @@ def get_build_id(path):
logger.debug("Unable to get Build ID for %s: %s", path, e)
return None
m = re.search(r'^\s+Build ID: ([0-9a-f]+)$', output.decode('utf-8'), flags=re.MULTILINE)
m = re.search(r'^\s+Build ID: ([0-9a-f]+)$',
output.decode('utf-8'), flags=re.MULTILINE)
if not m:
return None
......@@ -394,7 +395,8 @@ def get_debug_link(path):
logger.debug("Unable to get Build Id for %s: %s", path, e)
return None
m = re.search(r'^\s+\[\s+0\]\s+(\S+)$', output.decode('utf-8', errors='replace'), flags=re.MULTILINE)
m = re.search(r'^\s+\[\s+0\]\s+(\S+)$', output.decode('utf-8',
errors='replace'), flags=re.MULTILINE)
if not m:
return None
......@@ -415,8 +417,10 @@ class ElfContainer(Container):
super().__init__(*args, **kwargs)
logger.debug("Creating ElfContainer for %s", self.source.path)
cmd = [get_tool_name('readelf'), '--wide', '--section-headers', self.source.path]
output = subprocess.check_output(cmd, shell=False, stderr=subprocess.DEVNULL)
cmd = [get_tool_name('readelf'), '--wide',
'--section-headers', self.source.path]
output = subprocess.check_output(
cmd, shell=False, stderr=subprocess.DEVNULL)
has_debug_symbols = False
try:
......@@ -448,7 +452,8 @@ class ElfContainer(Container):
for x in flags if x in ElfContainer.SECTION_FLAG_MAPPING
][0]
logger.debug("Adding section %s (%s) as %s", name, type, elf_class)
logger.debug("Adding section %s (%s) as %s",
name, type, elf_class)
self._sections[name] = elf_class(self, name)
except Exception as e:
......@@ -492,7 +497,8 @@ class ElfContainer(Container):
deb.container.dbgsym_build_id_map = get_build_id_map(deb.container)
if build_id not in deb.container.dbgsym_build_id_map:
logger.debug('Unable to find a matching debug package for Build Id %s', build_id)
logger.debug(
'Unable to find a matching debug package for Build Id %s', build_id)
return
dbgsym_package = deb.container.dbgsym_build_id_map[build_id]
......@@ -500,9 +506,11 @@ class ElfContainer(Container):
build_id[:2],
build_id[2:],
)
debug_file = dbgsym_package.as_container.data_tar.as_container.lookup_file(debug_file_path)
debug_file = dbgsym_package.as_container.data_tar.as_container.lookup_file(
debug_file_path)
if not debug_file:
logger.debug('Unable to find the matching debug file %s in %s', debug_file_path, dbgsym_package)
logger.debug('Unable to find the matching debug file %s in %s',
debug_file_path, dbgsym_package)
return
# Create a .debug directory and link the debug symbols there with the
......@@ -529,7 +537,8 @@ class ElfContainer(Container):
prefix='{}.debuglink.'.format(self.source.path),
).name
objcopy('--only-section=.gnu_debuglink', self.source.path, debuglink_path)
objcopy('--only-section=.gnu_debuglink',
self.source.path, debuglink_path)
# 2. Monkey-patch the ElfSection object created for the .gnu_debuglink
# to change the path to point to this new file
......
......@@ -46,7 +46,8 @@ class Msgunfmt(Command):
if not self._encoding:
self._header.write(line)
if line == b'\n':
logger.debug("unable to determine PO encoding, let's hope it's utf-8")
logger.debug(
"unable to determine PO encoding, let's hope it's utf-8")
self._encoding = 'utf-8'
return self._header.getvalue()
found = Msgunfmt.CHARSET_RE.match(line)
......
......@@ -72,15 +72,18 @@ class OtoolDisassembleInternal(Otool):
class MachoFile(File):
DESCRIPTION = "MacOS binaries"
FILE_TYPE_RE = re.compile(r'^Mach-O ')
RE_EXTRACT_ARCHS = re.compile(r'^(?:Architectures in the fat file: .* are|Non-fat file: .* is architecture): (.*)$')
RE_EXTRACT_ARCHS = re.compile(
r'^(?:Architectures in the fat file: .* are|Non-fat file: .* is architecture): (.*)$')
@staticmethod
@tool_required('lipo')
def get_arch_from_macho(path):
lipo_output = subprocess.check_output(['lipo', '-info', path]).decode('utf-8')
lipo_output = subprocess.check_output(
['lipo', '-info', path]).decode('utf-8')
lipo_match = MachoFile.RE_EXTRACT_ARCHS.match(lipo_output)
if lipo_match is None:
raise ValueError('lipo -info on Mach-O file %s did not produce expected output. Output was: %s' % path, lipo_output)
raise ValueError(
'lipo -info on Mach-O file %s did not produce expected output. Output was: %s' % path, lipo_output)
return lipo_match.group(1).split()
def compare_details(self, other, source=None):
......
......@@ -46,7 +46,8 @@ class PngFile(File):
FILE_TYPE_RE = re.compile(r'^PNG image data\b')
def compare_details(self, other, source=None):
sng_diff = Difference.from_command(Sng, self.path, other.path, source='sng')
sng_diff = Difference.from_command(
Sng, self.path, other.path, source='sng')
differences = [sng_diff]
if sng_diff is not None and Config().compute_visual_diffs and \
......
......@@ -73,7 +73,8 @@ class PpuFile(File):
if not hasattr(PpuFile, 'ppu_version'):
try:
with profile('command', 'ppudump'):
subprocess.check_output(['ppudump', '-vh', file.path], shell=False, stderr=subprocess.STDOUT)
subprocess.check_output(
['ppudump', '-vh', file.path], shell=False, stderr=subprocess.STDOUT)
PpuFile.ppu_version = ppu_version
except subprocess.CalledProcessError as e:
error = e.output.decode('utf-8', errors='ignore')
......
......@@ -99,7 +99,8 @@ class RpmContainer(Archive):
dest_path = os.path.join(dest_dir, 'content')
cmd = ['rpm2cpio', self.source.path]
with open(dest_path, 'wb') as dest:
subprocess.check_call(cmd, shell=False, stdout=dest, stderr=subprocess.PIPE)
subprocess.check_call(
cmd, shell=False, stdout=dest, stderr=subprocess.PIPE)
return dest_path
......
......@@ -31,5 +31,6 @@ class RpmFile(AbstractRpmFile):
difference = self.compare_bytes(other)
if not difference:
return None
difference.add_comment('Unable to import Python rpm module. Falling back to binary comparison.')
difference.add_comment(
'Unable to import Python rpm module. Falling back to binary comparison.')
return difference
......@@ -51,7 +51,8 @@ class RustObjectContainer(Archive):
with open(dest_path, 'wb') as fpw, open(self.source.path, 'rb') as fpr:
raw_deflate = fpr.read()[RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET:]
# decompressobj() ignores the (non-existent) checksum; a zlib.decompress() would error
raw_inflate = zlib.decompressobj().decompress(ZLIB_DEFAULT_COMPRESSION + raw_deflate)
raw_inflate = zlib.decompressobj().decompress(
ZLIB_DEFAULT_COMPRESSION + raw_deflate)
fpw.write(raw_inflate)
return dest_path
......
......@@ -89,7 +89,8 @@ class SquashfsMember(ArchiveMember):
class SquashfsRegularFile(SquashfsMember):
# Example line:
# -rw-r--r-- user/group 446 2015-06-24 14:49 squashfs-root/text
LINE_RE = re.compile(r'^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(?P<member_name>.*)$')
LINE_RE = re.compile(
r'^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(?P<member_name>.*)$')
@staticmethod
def parse(line):
......@@ -105,7 +106,8 @@ class SquashfsRegularFile(SquashfsMember):
class SquashfsDirectory(Directory, SquashfsMember):
# Example line:
# drwxr-xr-x user/group 51 2015-06-24 14:47 squashfs-root
LINE_RE = re.compile(r'^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(?P<member_name>.*)$')
LINE_RE = re.compile(
r'^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(?P<member_name>.*)$')
@staticmethod
def parse(line):
......@@ -125,7 +127,8 @@ class SquashfsDirectory(Directory, SquashfsMember):
@property
def path(self):
raise NotImplementedError("SquashfsDirectory is not meant to be extracted.")
raise NotImplementedError(
"SquashfsDirectory is not meant to be extracted.")
def is_directory(self):
return True
......@@ -186,7 +189,8 @@ class SquashfsDevice(Device, SquashfsMember):
d['mode'] = SquashfsDevice.KIND_MAP[d['kind']]
del d['kind']
except KeyError:
raise SquashfsInvalidLineFormat("unknown device kind %s" % d['kind'])
raise SquashfsInvalidLineFormat(
"unknown device kind %s" % d['kind'])
try:
d['major'] = int(d['major'])
......
......@@ -51,14 +51,17 @@ class TextFile(File):
try:
with codecs.open(self.path, 'r', encoding=my_encoding) as my_content, \
codecs.open(other.path, 'r', encoding=other_encoding) as other_content:
difference = Difference.from_text_readers(my_content, other_content, self.name, other.name, source)
difference = Difference.from_text_readers(
my_content, other_content, self.name, other.name, source)
# Check if difference is only in line order.
if difference and order_only_difference(difference.unified_diff):
difference.add_comment("ordering differences only")
if my_encoding != other_encoding:
if difference is None:
difference = Difference(None, self.path, other.path, source)
difference.add_details([Difference.from_text(my_encoding, other_encoding, None, None, source='encoding')])
difference = Difference(
None, self.path, other.path, source)
difference.add_details([Difference.from_text(
my_encoding, other_encoding, None, None, source='encoding')])
return difference
except (LookupError, UnicodeDecodeError):
# unknown or misdetected encoding
......
......@@ -90,11 +90,13 @@ class ArchiveMember(File):
@property
def path(self):
if self._path is None:
logger.debug("Unpacking %s from %s", self._name, self.container.source.name)
logger.debug("Unpacking %s from %s", self._name,
self.container.source.name)
assert self._temp_dir is None
self._temp_dir = get_temporary_directory()
with profile('container_extract', self.container):
self._path = self.container.extract(self._name, self._temp_dir.name)
self._path = self.container.extract(
self._name, self._temp_dir.name)
return self._path
def cleanup(self):
......
......@@ -32,7 +32,8 @@ class Command(object, metaclass=abc.ABCMeta):
self._path = path
def start(self):
logger.debug("Executing %s", ' '.join([shlex.quote(x) for x in self.cmdline()]))
logger.debug("Executing %s", ' '.join(
[shlex.quote(x) for x in self.cmdline()]))
self._stdin = self.stdin()
# "stdin" used to be a feeder but we didn't need the functionality so
......
......@@ -96,7 +96,8 @@ def compare_files(file1, file2, source=None, diff_content_only=False):
if has_same_content:
if not force_details:
logger.debug("has_same_content_as returned True; skipping further comparisons")
logger.debug(
"has_same_content_as returned True; skipping further comparisons")
return None
if diff_content_only:
return None
......@@ -121,7 +122,8 @@ def bail_if_non_existing(*paths):
if not all(map(os.path.lexists, paths)):
for path in paths:
if not os.path.lexists(path):
sys.stderr.write('%s: %s: No such file or directory\n' % (sys.argv[0], path))
sys.stderr.write(
'%s: %s: No such file or directory\n' % (sys.argv[0], path))
sys.exit(2)
......
......@@ -130,7 +130,8 @@ class Container(object, metaclass=abc.ABCMeta):
def comparisons(self, other):
my_members = OrderedDict(self.get_adjusted_members_sizes())
other_members = OrderedDict(other.get_adjusted_members_sizes())
total_size = sum(x[1] for x in itertools.chain(my_members.values(), other_members.values()))
total_size = sum(x[1] for x in itertools.chain(
my_members.values(), other_members.values()))
# TODO: progress could be a bit more accurate here, give more weight to fuzzy-hashed files
# TODO: merge DirectoryContainer.comparisons() into this
......@@ -149,7 +150,8 @@ class Container(object, metaclass=abc.ABCMeta):
other_names = set(other_members.keys())
# keep it sorted like my_members
both_names = [name for name in my_members.keys() if name in other_names]
both_names = [name for name in my_members.keys()
if name in other_names]
for name in both_names:
yield prep_yield(name, name)
......@@ -171,7 +173,8 @@ class Container(object, metaclass=abc.ABCMeta):
from .compare import compare_files
def compare_pair(file1, file2, comment):
difference = compare_files(file1, file2, source=None, diff_content_only=no_recurse)
difference = compare_files(
file1, file2, source=None, diff_content_only=no_recurse)
if comment:
if difference is None:
difference = Difference(None, file1.name, file2.name)
......
......@@ -205,7 +205,8 @@ class File(object, metaclass=abc.ABCMeta):
return self._other_file.__class__.CONTAINER_CLASS(self)
return None
if not hasattr(self, '_as_container'):
logger.debug('instantiating %s for %s', self.__class__.CONTAINER_CLASS, self)
logger.debug('instantiating %s for %s',
self.__class__.CONTAINER_CLASS, self)
try:
self._as_container = self.__class__.CONTAINER_CLASS(self)
except RequiredToolNotFound:
......@@ -316,7 +317,8 @@ class File(object, metaclass=abc.ABCMeta):
msg = "Reached max container depth ({})".format(depth)
logger.debug(msg)
difference.add_comment(msg)
details.extend(self.as_container.compare(other.as_container, no_recurse=no_recurse))
details.extend(self.as_container.compare(
other.as_container, no_recurse=no_recurse))
details = [x for x in details if x]
if not details:
......@@ -392,7 +394,8 @@ class File(object, metaclass=abc.ABCMeta):
"'%s' not available in path. Falling back to binary comparison." % e.command)
package = e.get_package()
if package:
difference.add_comment("Install '%s' to get a better output." % package)
difference.add_comment(
"Install '%s' to get a better output." % package)
except OutputParsingError as e:
difference = self.compare_bytes(other, source=source)
if difference is None:
......
......@@ -44,11 +44,13 @@ def perform_fuzzy_matching(members1, members2):
for name2, (file2, _) in members2.items():
if name2 in already_compared or file2.is_directory() or not file2.fuzzy_hash:
continue
comparisons.append((tlsh.diff(file1.fuzzy_hash, file2.fuzzy_hash), name2))
comparisons.append(
(tlsh.diff(file1.fuzzy_hash, file2.fuzzy_hash), name2))
if comparisons:
comparisons.sort(key=operator.itemgetter(0))
score, name2 = comparisons[0]
logger.debug('fuzzy top match %s %s: %d difference score', name1, name2, score)
logger.debug(
'fuzzy top match %s %s: %d difference score', name1, name2, score)
if score < Config().fuzzy_threshold:
yield name1, name2, score
already_compared.add(name2)
......@@ -40,54 +40,76 @@ logger = logging.getLogger(__name__)
# Monkeypatch libarchive-c (<< 2.2)
if not hasattr(libarchive.ffi, 'entry_rdevmajor'):
libarchive.ffi.ffi('entry_rdevmajor', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.rdevmajor = property(lambda self: libarchive.ffi.entry_rdevmajor(self._entry_p))
libarchive.ffi.ffi('entry_rdevmajor', [
libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.rdevmajor = property(
lambda self: libarchive.ffi.entry_rdevmajor(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_rdevminor'):
libarchive.ffi.ffi('entry_rdevminor', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.rdevminor = property(lambda self: libarchive.ffi.entry_rdevminor(self._entry_p))
libarchive.ffi.ffi('entry_rdevminor', [
libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.rdevminor = property(
lambda self: libarchive.ffi.entry_rdevminor(self._entry_p))
# Monkeypatch libarchive-c (<< 2.3)
if not hasattr(libarchive.ffi, 'entry_nlink'):
libarchive.ffi.ffi('entry_nlink', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.nlink = property(lambda self: libarchive.ffi.entry_nlink(self._entry_p))
libarchive.ffi.ffi(
'entry_nlink', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint)
libarchive.ArchiveEntry.nlink = property(
lambda self: libarchive.ffi.entry_nlink(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_uid'):
libarchive.ffi.ffi('entry_uid', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint32)
libarchive.ArchiveEntry.uid = property(lambda self: libarchive.ffi.entry_uid(self._entry_p))
libarchive.ffi.ffi(
'entry_uid', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint32)
libarchive.ArchiveEntry.uid = property(
lambda self: libarchive.ffi.entry_uid(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_gid'):
libarchive.ffi.ffi('entry_gid', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint32)
libarchive.ArchiveEntry.gid = property(lambda self: libarchive.ffi.entry_uid(self._entry_p))
libarchive.ffi.ffi(
'entry_gid', [libarchive.ffi.c_archive_entry_p], ctypes.c_uint32)
libarchive.ArchiveEntry.gid = property(
lambda self: libarchive.ffi.entry_uid(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_mtime_nsec'):
libarchive.ffi.ffi('entry_mtime_nsec', [libarchive.ffi.c_archive_entry_p], ctypes.c_long)
libarchive.ArchiveEntry.mtime_nsec = property(lambda self: libarchive.ffi.entry_mtime_nsec(self._entry_p))
libarchive.ffi.ffi('entry_mtime_nsec', [
libarchive.ffi.c_archive_entry_p], ctypes.c_long)
libarchive.ArchiveEntry.mtime_nsec = property(
lambda self: libarchive.ffi.entry_mtime_nsec(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_uname'):
libarchive.ffi.ffi('entry_uname', [libarchive.ffi.c_archive_entry_p], ctypes.c_char_p)
libarchive.ArchiveEntry.uname = property(lambda self: libarchive.ffi.entry_uname(self._entry_p))
libarchive.ffi.ffi(
'entry_uname', [libarchive.ffi.c_archive_entry_p], ctypes.c_char_p)
libarchive.ArchiveEntry.uname = property(
lambda self: libarchive.ffi.entry_uname(self._entry_p))
if not hasattr(libarchive.ffi, 'entry_gname'):
libarchive.ffi.ffi('entry_gname', [libarchive.ffi.c_archive_entry_p], ctypes.c_char_p)
libarchive.ArchiveEntry.gname = property(lambda self: libarchive.ffi.entry_gname(self._entry_p))
libarchive.ffi.ffi(
'entry_gname', [libarchive.ffi.c_archive_entry_p], ctypes.c_char_p)
libarchive.ArchiveEntry.gname = property(
lambda self: libarchive.ffi.entry_gname(self._entry_p))
# Monkeypatch libarchive-c so we always get pathname as (Unicode) str
# Otherwise, we'll get sometimes str and sometimes bytes and always pain.
libarchive.ArchiveEntry.pathname = property(lambda self: libarchive.ffi.entry_pathname(self._entry_p).decode('utf-8', errors='surrogateescape'))
libarchive.ArchiveEntry.pathname = property(lambda self: libarchive.ffi.entry_pathname(
self._entry_p).decode('utf-8', errors='surrogateescape'))
def list_libarchive(path):
with libarchive.file_reader(path) as archive:
for entry in archive:
if entry.isblk or entry.ischr:
size_or_dev = '{major:>3},{minor:>3}'.format(major=entry.rdevmajor, minor=entry.rdevminor)
size_or_dev = '{major:>3},{minor:>3}'.format(
major=entry.rdevmajor, minor=entry.rdevminor)
else:
size_or_dev = entry.size
mtime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(entry.mtime)) + '.{:06d}'.format(entry.mtime_nsec // 1000)
mtime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(entry.mtime)
) + '.{:06d}'.format(entry.mtime_nsec // 1000)
if entry.issym:
name_and_link = '{entry.name} -> {entry.linkname}'.format(entry=entry)
name_and_link = '{entry.name} -> {entry.linkname}'.format(
entry=entry)
else:
name_and_link = entry.name
if entry.uname:
user = '{user:<8} {uid:>7}'.format(user=entry.uname.decode('utf-8', errors='surrogateescape'), uid='({})'.format(entry.uid))
user = '{user:<8} {uid:>7}'.format(user=entry.uname.decode(
'utf-8', errors='surrogateescape'), uid='({})'.format(entry.uid))
else:
user = entry.uid
if entry.gname:
group = '{group:<8} {gid:>7}'.format(group=entry.gname.decode('utf-8', errors='surrogateescape'), gid='({})'.format(entry.gid))
group = '{group:<8} {gid:>7}'.format(group=entry.gname.decode(
'utf-8', errors='surrogateescape'), gid='({})'.format(entry.gid))
else:
group = entry.gid
yield '{strmode} {entry.nlink:>3} {user:>8} {group:>8} {size_or_dev:>8} {mtime:>8} {name_and_link}\n'.format(strmode=entry.strmode.decode('us-ascii'), entry=entry, user=user, group=group, size_or_dev=size_or_dev, mtime=mtime, name_and_link=name_and_link)
......@@ -119,7 +141,8 @@ class LibarchiveDirectory(Directory, LibarchiveMember):
@property
def path(self):
raise NotImplementedError('LibarchiveDirectory is not meant to be extracted.')
raise NotImplementedError(
'LibarchiveDirectory is not meant to be extracted.')
def is_directory(self):
return True
......
......@@ -51,7 +51,8 @@ def specialize(file):
for cls in ComparatorManager().classes:
if try_recognize(file, cls, cls.fallback_recognizes):
logger.debug("File recognized by fallback. Magic says: %s", file.magic_file_type)
logger.debug(
"File recognized by fallback. Magic says: %s", file.magic_file_type)
return file
logger.debug(
......
......@@ -96,7 +96,8 @@ class ZipContainer(Archive):
# We don't really want to crash if the filename in the zip archive
# can't be encoded using the filesystem encoding. So let's replace
# any weird character so we can get to the bytes.
targetpath = os.path.join(dest_dir, os.path.basename(member_name)).encode(sys.getfilesystemencoding(), errors='replace')
targetpath = os.path.join(dest_dir, os.path.basename(member_name)).encode(
sys.getfilesystemencoding(), errors='replace')
with self.archive.open(member_name) as source, open(targetpath, 'wb') as target:
shutil.copyfileobj(source, target)
return targetpath.decode(sys.getfilesystemencoding())
......@@ -110,7 +111,8 @@ class ZipContainer(Archive):
class ZipFile(File):
CONTAINER_CLASS = ZipContainer
FILE_TYPE_RE = re.compile(r'^(Zip archive|Java archive|EPUB document|OpenDocument (Text|Spreadsheet|Presentation|Drawing|Formula|Template|Text Template))\b')
FILE_TYPE_RE = re.compile(
r'^(Zip archive|Java archive|EPUB document|OpenDocument (Text|Spreadsheet|Presentation|Drawing|Formula|Template|Text Template))\b')
def compare_details(self, other, source=None):
zipinfo_difference = Difference.from_command(Zipinfo, self.path, other.path) or \
......
......@@ -484,7 +484,8 @@ def linediff_simplify(g):
if not current:
current = l, r
elif current[0][0] == l[0] and current[1][0] == r[0]:
current = (l[0], current[0][1] + l[1]), (r[0], current[1][1] + r[1])
current = (l[0], current[0][1] + l[1]
), (r[0], current[1][1] + r[1])
else:
yield current
current = l, r
......@@ -620,9 +621,11 @@ class SideBySideDiff(object):
if re.match(r"^\\ No newline", l):
if self.hunk_size2 == 0:
self.buf[-1] = (self.buf[-1][0], self.buf[-1][1] + '\n' + l[2:])
self.buf[-1] = (self.buf[-1][0],
self.buf[-1][1] + '\n' + l[2:])