fix pep8 E302

Signed-off-by: Mattia Rizzolo's avatarMattia Rizzolo <mattia@debian.org>
parent 2a014b5a
......@@ -145,6 +145,7 @@ class ApkContainer(Archive):
differences.extend(super().compare(other, *args, **kwargs))
return differences
class ApkFile(File):
FILE_TYPE_HEADER_PREFIX = b"PK\x03\x04"
FILE_TYPE_RE = re.compile(r'^(Java|Zip) archive data.*\b')
......
......@@ -49,11 +49,13 @@ class ArContainer(LibarchiveContainer):
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]
class ArSymbolTableDumper(Command):
@tool_required('nm')
def cmdline(self):
return ['nm', '-s', self.path]
class ArFile(File):
CONTAINER_CLASS = ArContainer
FILE_TYPE_RE = re.compile(r'\bar archive\b')
......
......@@ -89,6 +89,7 @@ CBFS_HEADER_SIZE = 8 * 4 # 8 * uint32_t
# On 2015-12-15, the largest image produced by coreboot is 16 MiB
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)
return magic == CBFS_HEADER_MAGIC and \
......
......@@ -159,6 +159,7 @@ class DebControlFile(File):
return differences
class DotChangesFile(DebControlFile):
FILE_EXTENSION_SUFFIX = '.changes'
......@@ -232,6 +233,7 @@ class DotDscFile(DebControlFile):
return True
class DotBuildinfoContainer(DebControlContainer):
def get_member_names(self):
result = super(DotBuildinfoContainer, self).get_member_names()
......@@ -250,6 +252,7 @@ class DotBuildinfoContainer(DebControlContainer):
return [x for x in result if x not in ignore]
class DotBuildinfoFile(DebControlFile):
CONTAINER_CLASS = DotBuildinfoContainer
FILE_EXTENSION_SUFFIX = '.buildinfo'
......
......@@ -30,6 +30,7 @@ class DotChangesFile(TextFile):
difference.add_comment('Unable to find Python debian module. Falling back to text comparison.')
return difference
class DotDscFile(TextFile):
FILE_EXTENSION_SUFFIX = '.dsc'
......@@ -40,6 +41,7 @@ class DotDscFile(TextFile):
difference.add_comment('Unable to find Python debian module. Falling back to text comparison.')
return difference
class DotBuildinfoFile(TextFile):
FILE_EXTENSION_SUFFIX = '.buildinfo'
......
......@@ -72,6 +72,7 @@ class Device(File):
open(other.path) as other_content:
return Difference.from_text_readers(my_content, other_content, self.name, other.name, source=source, comment="device")
def format_device(mode, major, minor):
if stat.S_ISCHR(mode):
kind = 'character'
......
......@@ -52,6 +52,7 @@ class DexContainer(Archive):
shell=False, stderr=None, stdout=subprocess.PIPE)
return dest_path
class DexFile(File):
FILE_TYPE_RE = re.compile(r'^Dalvik dex file .*\b')
CONTAINER_CLASS = DexContainer
......@@ -32,6 +32,7 @@ class DeviceTreeContents(Command):
def cmdline(self):
return ['fdtdump', self.path]
class DeviceTreeFile(File):
FILE_TYPE_RE = re.compile(r'^Device Tree Blob')
......
......@@ -191,10 +191,12 @@ class ReadElfSection(Readelf):
def readelf_options(self):
return ReadElfSection.base_options() + ['--hex-dump={}'.format(self.section_name)]
class ReadelfStringSection(ReadElfSection):
def readelf_options(self):
return ReadElfSection.base_options() + ['--string-dump={}'.format(self.section_name)]
class ObjdumpSection(Command):
def __init__(self, path, section_name, *args, **kwargs):
self._path = path
......@@ -223,6 +225,7 @@ class ObjdumpSection(Command):
return line
class ObjdumpDisassembleSection(ObjdumpSection):
RE_SYMBOL_COMMENT = re.compile(rb'^( +[0-9a-f]+:[^#]+)# [0-9a-f]+ <[^>]+>$')
......@@ -249,6 +252,7 @@ READELF_COMMANDS = (
RedaelfVersionInfo,
)
def _compare_elf_data(path1, path2):
return [
Difference.from_command(x, path1, path2)
......@@ -321,6 +325,7 @@ class ElfSection(File):
command_args=[self._name],
)
class ElfCodeSection(ElfSection):
def compare(self, other, source=None):
return Difference.from_command(
......@@ -330,6 +335,7 @@ class ElfCodeSection(ElfSection):
command_args=[self._name],
)
class ElfStringSection(ElfSection):
def compare(self, other, source=None):
return Difference.from_command(
......@@ -529,6 +535,7 @@ class ElfContainer(Container):
def get_member(self, member_name):
return self._sections[member_name]
class ElfFile(File):
CONTAINER_CLASS = ElfContainer
FILE_TYPE_RE = re.compile(r'^ELF ')
......@@ -536,6 +543,7 @@ class ElfFile(File):
def compare_details(self, other, source=None):
return _compare_elf_data(self.path, other.path)
class StaticLibFile(File):
CONTAINER_CLASS = ElfContainer
FILE_TYPE_RE = re.compile(r'\bar archive\b')
......
......@@ -38,6 +38,7 @@ class GitIndexFile(File):
other.path,
)]
def parse_index(f):
_, version = struct.unpack('>LL', f.read(4 * 2))
......@@ -46,6 +47,7 @@ def parse_index(f):
'entries': list(parse_entries(f)),
}
def parse_entries(f):
num_entries = struct.unpack('>L', f.read(4))[0]
......@@ -65,6 +67,7 @@ def parse_entries(f):
yield x
def describe_index(filename):
with open(filename, 'rb') as f:
index = parse_index(f)
......@@ -79,6 +82,7 @@ Entries:
**index
)
def describe_entry(x):
return """
Path: {x[path]}
......
......@@ -46,6 +46,7 @@ class ShowIface(Command):
def cmdline(self):
return ['ghc', '--show-iface', self.path]
class HiFile(File):
"""
Here is how an example .hi file starts:
......
......@@ -29,6 +29,7 @@ class JavaScriptBeautify(Command):
def cmdline(self):
return ['js-beautify', self.path]
class JavaScriptFile(File):
FILE_EXTENSION_SUFFIX = '.js'
......
......@@ -32,6 +32,7 @@ class LlvmBcAnalyzer(Command):
def cmdline(self):
return ['llvm-bcanalyzer', '-dump', self.path]
class LlvmBcDisassembler(Command):
@tool_required('llvm-dis')
def cmdline(self):
......@@ -40,6 +41,7 @@ class LlvmBcDisassembler(Command):
# this makes it easier to generate reproducible diffs for our tests.
return ['find', self.path, '-execdir', 'llvm-dis', '-o', '-', '{}', ';']
class LlvmBitCodeFile(File):
FILE_TYPE_RE = re.compile(r'^LLVM IR bitcode')
......
......@@ -31,6 +31,7 @@ class SSHKeyList(Command):
def cmdline(self):
return ['ssh-keygen', '-l', '-f', self.path]
class PublicKeyFile(File):
FILE_TYPE_RE = re.compile(r'^OpenSSH \S+ public key')
......
......@@ -39,6 +39,7 @@ DUMP_RDB = """lazyLoad(commandArgs(TRUE)); for (obj in ls()) { print(obj); for (
def check_rds_extension(f):
return f.name.endswith(".rds") or f.name.endswith(".rdx")
def ensure_archive_rdx(f):
if not f.container or f.path.endswith(".rdb"):
return f.path
......@@ -56,6 +57,7 @@ def ensure_archive_rdx(f):
shutil.copy(rdx_path, f.path + ".rdx")
return f.path + ".rdb"
class RdsReader(Command):
@tool_required('Rscript')
def cmdline(self):
......@@ -64,6 +66,7 @@ class RdsReader(Command):
self.path
]
class RdsFile(File):
@staticmethod
def recognizes(file):
......@@ -76,11 +79,13 @@ class RdsFile(File):
def compare_details(self, other, source=None):
return [Difference.from_command(RdsReader, self.path, other.path)]
class RdbReader(Command):
@tool_required('Rscript')
def cmdline(self):
return ['Rscript', '-e', DUMP_RDB, self.path[:-4]]
class RdbFile(File):
FILE_EXTENSION_SUFFIX = '.rdb'
......
......@@ -25,6 +25,7 @@ from .utils.file import File
class AbstractRpmFile(File):
FILE_TYPE_RE = re.compile('^RPM\s')
class RpmFile(AbstractRpmFile):
def compare(self, other, source=None):
difference = self.compare_bytes(other)
......
......@@ -24,6 +24,7 @@ from diffoscope.difference import Difference
from .utils.file import File
from .utils.libarchive import LibarchiveContainer, list_libarchive
class TarContainer(LibarchiveContainer):
pass
......
......@@ -48,6 +48,7 @@ class Xxd(Command):
def cmdline(self):
return ['xxd', self.path]
def compare_root_paths(path1, path2):
from ..directory import FilesystemDirectory, FilesystemFile, compare_directories
......@@ -63,6 +64,7 @@ def compare_root_paths(path1, path2):
file2 = specialize(FilesystemFile(path2, container=container2))
return compare_files(file1, file2)
def compare_files(file1, file2, source=None, diff_content_only=False):
logger.debug(
"Comparing %s (%s) and %s (%s)",
......@@ -94,6 +96,7 @@ def compare_files(file1, file2, source=None, diff_content_only=False):
with profile('compare_files (cumulative)', file1):
return file1.compare(file2, source)
def bail_if_non_existing(*paths):
if not all(map(os.path.lexists, paths)):
for path in paths:
......@@ -101,6 +104,7 @@ def bail_if_non_existing(*paths):
sys.stderr.write('%s: %s: No such file or directory\n' % (sys.argv[0], path))
sys.exit(2)
def compare_binary_files(file1, file2, source=None):
try:
if source is None:
......@@ -114,6 +118,7 @@ def compare_binary_files(file1, file2, source=None):
comment = 'xxd not available in path. Falling back to Python hexlify.\n'
return Difference.from_text(hexdump1, hexdump2, file1.name, file2.name, source, comment)
def hexdump_fallback(path):
hexdump = io.StringIO()
with open(path, 'rb') as f:
......
......@@ -343,6 +343,8 @@ class File(object, metaclass=abc.ABCMeta):
return self.compare_bytes(other, source)
# helper function to convert to bytes if necessary
def maybe_decode(s):
if type(s) is bytes:
return s.decode('utf-8')
......
......@@ -28,6 +28,7 @@ try:
except ImportError:
from xml.dom import minidom
def _format(node):
"""
Removes *inplace* spaces from minidom.Document
......
......@@ -296,10 +296,12 @@ DIFFON = "\x01"
DIFFOFF = "\x02"
MAX_WF_SIZE = 1024 # any higher, and linediff takes >1 second and >200MB RAM
def _linediff_sane(x):
# turn non-printable chars into "."
return "." if ord(x) < 32 and x not in '\t\n' else x
def diffinput_truncate(s, sz):
# Truncate, preserving uniqueness
if len(s) > sz:
......@@ -307,6 +309,7 @@ def diffinput_truncate(s, sz):
len(s[sz:]), hashlib.sha1(s[sz:].encode('utf-8')).hexdigest())
return s
def linediff(s, t, diffon, diffoff):
# calculate common prefix/suffix, easy optimisation to WF
prefix = os.path.commonprefix((s, t))
......@@ -330,6 +333,7 @@ def linediff(s, t, diffon, diffoff):
t1 = ''.join(to_string(*p) for p in l2)
return prefix + s1 + suffix, prefix + t1 + suffix
def linediff_wagnerfischer(s, t):
'''
Line diff algorithm, originally from diff2html.
......@@ -385,6 +389,7 @@ def linediff_wagnerfischer(s, t):
assert s[fx] == t[fy]
yield (False, s[fx]), (False, t[fy])
def linediff_simplify(g):
"""Simplify the output of WF."""
current = None
......@@ -399,6 +404,7 @@ def linediff_simplify(g):
if current:
yield current
class SideBySideDiff(object):
"""Calculates a side-by-side diff from a unified diff."""
......
......@@ -26,6 +26,7 @@ class OutputParsingError(Exception):
self.command = command
self.object_class = object.__class__
class RequiredToolNotFound(Exception):
def __init__(self, command):
self.command = get_tool_name(command)
......@@ -33,6 +34,7 @@ class RequiredToolNotFound(Exception):
def get_package(self):
return get_package_provider(self.command)
class ContainerExtractionError(Exception):
def __init__(self, pathname, wrapped_exc):
self.pathname = pathname
......
......@@ -33,6 +33,7 @@ def command_excluded(command):
return True
return False
def filter_excludes(filenames):
for x in filenames:
for y in Config().excludes:
......@@ -42,6 +43,7 @@ def filter_excludes(filenames):
else:
yield x
def any_excluded(*filenames):
for x in filenames:
for y in Config().excludes:
......
......@@ -264,6 +264,7 @@ class RangeCompleter(object):
def __call__(self, prefix, **kwargs):
return (str(i) for i in self.choices if str(i).startswith(prefix))
class ListToolsAction(argparse.Action):
def __call__(self, parser, namespace, os_override, option_string=None):
# Ensure all comparators are imported so tool_required.all is
......@@ -288,6 +289,7 @@ class ListToolsAction(argparse.Action):
print(', '.join(sorted(tools)))
sys.exit(0)
class ListDebianSubstvarsAction(argparse._StoreTrueAction):
def __call__(self, *args, **kwargs):
# Ensure all comparators are imported so tool_required.all is
......@@ -315,6 +317,7 @@ class ListDebianSubstvarsAction(argparse._StoreTrueAction):
print('diffoscope:Recommends={}'.format(', '.join(sorted(tools))))
sys.exit(0)
def maybe_set_limit(config, parsed_args, key):
# apply limits affected by "no-default-limits"
v = getattr(parsed_args, key)
......@@ -323,6 +326,7 @@ def maybe_set_limit(config, parsed_args, key):
elif parsed_args.no_default_limits:
setattr(config, key, float("inf"))
def run_diffoscope(parsed_args):
ProfileManager().setup(parsed_args)
PresenterManager().configure(parsed_args)
......@@ -383,6 +387,7 @@ def sigterm_handler(signo, stack_frame):
clean_all_temp_files()
os._exit(2)
def main(args=None):
if args is None:
args = sys.argv[1:]
......
......@@ -85,9 +85,11 @@ def send_and_exhaust(iterator, arg, default):
pass
return output
def md5(s):
return hashlib.md5(s.encode('utf-8')).hexdigest()
def escape_anchor(val):
"""
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed
......@@ -103,12 +105,15 @@ def escape_anchor(val):
return val
def output_diff_path(path):
return '/'.join(n.source1 for n in path[1:])
def output_anchor(path):
return escape_anchor(output_diff_path(path))
def convert(s, ponct=0, tag=''):
i = 0
t = io.StringIO()
......@@ -146,6 +151,7 @@ def convert(s, ponct=0, tag=''):
return t.getvalue()
def output_visual(visual, path, indentstr, indentnum):
logger.debug('including image for %s', visual.source)
indent = tuple(indentstr * (indentnum + x) for x in range(3))
......@@ -160,6 +166,7 @@ def output_visual(visual, path, indentstr, indentnum):
{0[1]}<div class="difference"><img src=\"data:{3},{4}\" alt=\"compared images\" /></div>
{0[0]}</div>""".format(indent, html.escape(visual.source), anchor, visual.data_type, visual.content)
def output_node_frame(difference, path, indentstr, indentnum, body):
indent = tuple(indentstr * (indentnum + x) for x in range(3))
anchor = output_anchor(path)
......@@ -187,6 +194,7 @@ def output_node_frame(difference, path, indentstr, indentnum, body):
{1}{0[1]}</div>
{2}""", 3).pformatl(indent, header, body)
def output_node(ctx, difference, path, indentstr, indentnum):
"""Returns a tuple (parent, continuation) where
......@@ -241,6 +249,7 @@ def output_node(ctx, difference, path, indentstr, indentnum):
assert len(t.holes) >= len(difference.details) + 1 # there might be extra holes for the unified diff continuation
return cont(t, u""), ud_cont
def output_header(css_url, our_css_url=False, icon_url=None):
if css_url:
css_link = u' <link href="%s" type="text/css" rel="stylesheet" />\n' % css_url
......@@ -261,17 +270,20 @@ def output_header(css_url, our_css_url=False, icon_url=None):
'css_style': css_style
}
def output_footer(jquery_url=None):
footer = templates.FOOTER % {'version': VERSION}
if jquery_url:
return templates.SCRIPTS % {'jquery_url': html.escape(jquery_url)} + footer
return footer
@contextlib.contextmanager
def file_printer(directory, filename):
with codecs.open(os.path.join(directory, filename), 'w', encoding='utf-8') as f:
yield f.write
@contextlib.contextmanager
def spl_file_printer(directory, filename, accum):
with codecs.open(os.path.join(directory, filename), 'w', encoding='utf-8') as f:
......
......@@ -33,6 +33,7 @@ def profile(namespace, key):
if _ENABLED:
ProfileManager().increment(start, namespace, key)
class ProfileManager(object):
_singleton = {}
......
......@@ -47,12 +47,14 @@ OS_NAMES = collections.OrderedDict([
def get_tool_name(tool):
return REMAPPED_TOOL_NAMES.get(tool, tool)
def tool_prepend_prefix(prefix, *tools):
if not prefix:
return
for tool in tools:
REMAPPED_TOOL_NAMES[tool] = prefix + tool
def tool_required(command):
"""
Decorator that checks if the specified tool is installed
......@@ -88,13 +90,16 @@ def tool_required(command):
return tool_check
return wrapper
def tool_is_gnu(command):
return command in GNU_TOOL_NAMES
def os_is_gnu():
system = platform.system()
return system in ("Linux", "GNU") or system.startswith("GNU/")
def get_current_os():
system = platform.system()
if system == "Linux":
......@@ -102,12 +107,14 @@ def get_current_os():
return distro.id()
return system # noqa
def get_current_distro_like():
if distro:
return distro.like().split()
else:
return []
def get_package_provider(tool, os=None):
try:
providers = EXTERNAL_TOOLS[tool]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment