Remove flake8 E731 Errors

Note: black formatting is now applying correctly as well.
This commit is contained in:
Andrew Senetar 2021-08-15 03:51:27 -05:00
parent af19660c18
commit 9446f37fad
Signed by: arsenetar
GPG Key ID: C63300DCE48AB2F1
6 changed files with 100 additions and 229 deletions

View File

@ -17,7 +17,11 @@ from hscommon.util import flatten, multi_replace
from hscommon.trans import tr from hscommon.trans import tr
from hscommon.jobprogress import job from hscommon.jobprogress import job
(WEIGHT_WORDS, MATCH_SIMILAR_WORDS, NO_FIELD_ORDER,) = range(3) (
WEIGHT_WORDS,
MATCH_SIMILAR_WORDS,
NO_FIELD_ORDER,
) = range(3)
JOB_REFRESH_RATE = 100 JOB_REFRESH_RATE = 100
@ -34,11 +38,9 @@ def getwords(s):
# of their accents, etc.) are preserved as is. The arbitrary limit is # of their accents, etc.) are preserved as is. The arbitrary limit is
# obtained from this one: ord("\u037e") GREEK QUESTION MARK # obtained from this one: ord("\u037e") GREEK QUESTION MARK
s = "".join( s = "".join(
c for c in s c
if (ord(c) <= 894 for c in s
and c in string.ascii_letters + string.digits + string.whitespace if (ord(c) <= 894 and c in string.ascii_letters + string.digits + string.whitespace) or ord(c) > 894
)
or ord(c) > 894
) )
return [_f for _f in s.split(" ") if _f] # remove empty elements return [_f for _f in s.split(" ") if _f] # remove empty elements
@ -115,9 +117,7 @@ def compare_fields(first, second, flags=()):
if matched_field: if matched_field:
second.remove(matched_field) second.remove(matched_field)
else: else:
results = [ results = [compare(field1, field2, flags) for field1, field2 in zip(first, second)]
compare(field1, field2, flags) for field1, field2 in zip(first, second)
]
return min(results) if results else 0 return min(results) if results else 0
@ -130,9 +130,7 @@ def build_word_dict(objects, j=job.nulljob):
The result will be a dict with words as keys, lists of objects as values. The result will be a dict with words as keys, lists of objects as values.
""" """
result = defaultdict(set) result = defaultdict(set)
for object in j.iter_with_progress( for object in j.iter_with_progress(objects, "Prepared %d/%d files", JOB_REFRESH_RATE):
objects, "Prepared %d/%d files", JOB_REFRESH_RATE
):
for word in unpack_fields(object.words): for word in unpack_fields(object.words):
result[word].add(object) result[word].add(object)
return result return result
@ -167,9 +165,7 @@ def reduce_common_words(word_dict, threshold):
The exception to this removal are the objects where all the words of the object are common. The exception to this removal are the objects where all the words of the object are common.
Because if we remove them, we will miss some duplicates! Because if we remove them, we will miss some duplicates!
""" """
uncommon_words = set( uncommon_words = set(word for word, objects in word_dict.items() if len(objects) < threshold)
word for word, objects in word_dict.items() if len(objects) < threshold
)
for word, objects in list(word_dict.items()): for word, objects in list(word_dict.items()):
if len(objects) < threshold: if len(objects) < threshold:
continue continue
@ -275,10 +271,7 @@ def getmatches(
# This is the place where the memory usage is at its peak during the scan. # This is the place where the memory usage is at its peak during the scan.
# Just continue the process with an incomplete list of matches. # Just continue the process with an incomplete list of matches.
del compared # This should give us enough room to call logging. del compared # This should give us enough room to call logging.
logging.warning( logging.warning("Memory Overflow. Matches: %d. Word dict: %d" % (len(result), len(word_dict)))
"Memory Overflow. Matches: %d. Word dict: %d"
% (len(result), len(word_dict))
)
return result return result
return result return result
@ -408,18 +401,13 @@ class Group:
You can call this after the duplicate scanning process to free a bit of memory. You can call this after the duplicate scanning process to free a bit of memory.
""" """
discarded = set( discarded = set(m for m in self.matches if not all(obj in self.unordered for obj in [m.first, m.second]))
m
for m in self.matches
if not all(obj in self.unordered for obj in [m.first, m.second])
)
self.matches -= discarded self.matches -= discarded
self.candidates = defaultdict(set) self.candidates = defaultdict(set)
return discarded return discarded
def get_match_of(self, item): def get_match_of(self, item):
"""Returns the match pair between ``item`` and :attr:`ref`. """Returns the match pair between ``item`` and :attr:`ref`."""
"""
if item is self.ref: if item is self.ref:
return return
for m in self._get_matches_for_ref(): for m in self._get_matches_for_ref():
@ -435,8 +423,7 @@ class Group:
""" """
# tie_breaker(ref, dupe) --> True if dupe should be ref # tie_breaker(ref, dupe) --> True if dupe should be ref
# Returns True if anything changed during prioritization. # Returns True if anything changed during prioritization.
master_key_func = lambda x: (-x.is_ref, key_func(x)) new_order = sorted(self.ordered, key=lambda x: (-x.is_ref, key_func(x)))
new_order = sorted(self.ordered, key=master_key_func)
changed = new_order != self.ordered changed = new_order != self.ordered
self.ordered = new_order self.ordered = new_order
if tie_breaker is None: if tie_breaker is None:
@ -459,9 +446,7 @@ class Group:
self.unordered.remove(item) self.unordered.remove(item)
self._percentage = None self._percentage = None
self._matches_for_ref = None self._matches_for_ref = None
if (len(self) > 1) and any( if (len(self) > 1) and any(not getattr(item, "is_ref", False) for item in self):
not getattr(item, "is_ref", False) for item in self
):
if discard_matches: if discard_matches:
self.matches = set(m for m in self.matches if item not in m) self.matches = set(m for m in self.matches if item not in m)
else: else:
@ -470,8 +455,7 @@ class Group:
pass pass
def switch_ref(self, with_dupe): def switch_ref(self, with_dupe):
"""Make the :attr:`ref` dupe of the group switch position with ``with_dupe``. """Make the :attr:`ref` dupe of the group switch position with ``with_dupe``."""
"""
if self.ref.is_ref: if self.ref.is_ref:
return False return False
try: try:
@ -490,9 +474,7 @@ class Group:
if self._percentage is None: if self._percentage is None:
if self.dupes: if self.dupes:
matches = self._get_matches_for_ref() matches = self._get_matches_for_ref()
self._percentage = sum(match.percentage for match in matches) // len( self._percentage = sum(match.percentage for match in matches) // len(matches)
matches
)
else: else:
self._percentage = 0 self._percentage = 0
return self._percentage return self._percentage
@ -547,12 +529,8 @@ def get_groups(matches):
orphan_matches = [] orphan_matches = []
for group in groups: for group in groups:
orphan_matches += { orphan_matches += {
m m for m in group.discard_matches() if not any(obj in matched_files for obj in [m.first, m.second])
for m in group.discard_matches()
if not any(obj in matched_files for obj in [m.first, m.second])
} }
if groups and orphan_matches: if groups and orphan_matches:
groups += get_groups( groups += get_groups(orphan_matches) # no job, as it isn't supposed to take a long time
orphan_matches
) # no job, as it isn't supposed to take a long time
return groups return groups

View File

@ -106,9 +106,7 @@ class Results(Markable):
self.groups, self.groups,
) )
if self.__filtered_dupes: if self.__filtered_dupes:
self.__dupes = [ self.__dupes = [dupe for dupe in self.__dupes if dupe in self.__filtered_dupes]
dupe for dupe in self.__dupes if dupe in self.__filtered_dupes
]
sd = self.__dupes_sort_descriptor sd = self.__dupes_sort_descriptor
if sd: if sd:
self.sort_dupes(sd[0], sd[1], sd[2]) self.sort_dupes(sd[0], sd[1], sd[2])
@ -127,18 +125,10 @@ class Results(Markable):
total_count = self.__total_count total_count = self.__total_count
total_size = self.__total_size total_size = self.__total_size
else: else:
mark_count = len( mark_count = len([dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)])
[dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)] marked_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe))
) total_count = len([dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)])
marked_size = sum( total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe))
dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe)
)
total_count = len(
[dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)]
)
total_size = sum(
dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe)
)
if self.mark_inverted: if self.mark_inverted:
marked_size = self.__total_size - marked_size marked_size = self.__total_size - marked_size
result = tr("%d / %d (%s / %s) duplicates marked.") % ( result = tr("%d / %d (%s / %s) duplicates marked.") % (
@ -201,11 +191,7 @@ class Results(Markable):
self.__filters.append(filter_str) self.__filters.append(filter_str)
if self.__filtered_dupes is None: if self.__filtered_dupes is None:
self.__filtered_dupes = flatten(g[:] for g in self.groups) self.__filtered_dupes = flatten(g[:] for g in self.groups)
self.__filtered_dupes = set( self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(str(dupe.path)))
dupe
for dupe in self.__filtered_dupes
if filter_re.search(str(dupe.path))
)
filtered_groups = set() filtered_groups = set()
for dupe in self.__filtered_dupes: for dupe in self.__filtered_dupes:
filtered_groups.add(self.get_group_of_duplicate(dupe)) filtered_groups.add(self.get_group_of_duplicate(dupe))
@ -217,8 +203,7 @@ class Results(Markable):
self.__dupes = None self.__dupes = None
def get_group_of_duplicate(self, dupe): def get_group_of_duplicate(self, dupe):
"""Returns :class:`~core.engine.Group` in which ``dupe`` belongs. """Returns :class:`~core.engine.Group` in which ``dupe`` belongs."""
"""
try: try:
return self.__group_of_duplicate[dupe] return self.__group_of_duplicate[dupe]
except (TypeError, KeyError): except (TypeError, KeyError):
@ -284,8 +269,7 @@ class Results(Markable):
self.is_modified = False self.is_modified = False
def make_ref(self, dupe): def make_ref(self, dupe):
"""Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group. """Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group."""
"""
g = self.get_group_of_duplicate(dupe) g = self.get_group_of_duplicate(dupe)
r = g.ref r = g.ref
if not g.switch_ref(dupe): if not g.switch_ref(dupe):
@ -412,10 +396,10 @@ class Results(Markable):
""" """
if not self.__dupes: if not self.__dupes:
self.__get_dupe_list() self.__get_dupe_list()
keyfunc = lambda d: self.app._get_dupe_sort_key( self.__dupes.sort(
d, lambda: self.get_group_of_duplicate(d), key, delta key=lambda d: self.app._get_dupe_sort_key(d, lambda: self.get_group_of_duplicate(d), key, delta),
reverse=not asc,
) )
self.__dupes.sort(key=keyfunc, reverse=not asc)
self.__dupes_sort_descriptor = (key, asc, delta) self.__dupes_sort_descriptor = (key, asc, delta)
def sort_groups(self, key, asc=True): def sort_groups(self, key, asc=True):
@ -426,8 +410,7 @@ class Results(Markable):
:param str key: key attribute name to sort with. :param str key: key attribute name to sort with.
:param bool asc: If false, sorting is reversed. :param bool asc: If false, sorting is reversed.
""" """
keyfunc = lambda g: self.app._get_group_sort_key(g, key) self.groups.sort(key=lambda g: self.app._get_group_sort_key(g, key), reverse=not asc)
self.groups.sort(key=keyfunc, reverse=not asc)
self.__groups_sort_descriptor = (key, asc) self.__groups_sort_descriptor = (key, asc)
# ---Properties # ---Properties

View File

@ -177,9 +177,7 @@ class TestCaseWordCompareWithFields:
def test_simple(self): def test_simple(self):
eq_( eq_(
67, 67,
compare_fields( compare_fields([["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]),
[["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]
),
) )
def test_empty(self): def test_empty(self):
@ -265,9 +263,7 @@ class TestCasebuild_word_dict:
j = job.Job(1, do_progress) j = job.Job(1, do_progress)
self.log = [] self.log = []
s = "foo bar" s = "foo bar"
build_word_dict( build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
[NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j
)
# We don't have intermediate log because iter_with_progress is called with every > 1 # We don't have intermediate log because iter_with_progress is called with every > 1
eq_(0, self.log[0]) eq_(0, self.log[0])
eq_(100, self.log[1]) eq_(100, self.log[1])
@ -297,10 +293,7 @@ class TestCasereduce_common_words:
def test_dont_remove_objects_with_only_common_words(self): def test_dont_remove_objects_with_only_common_words(self):
d = { d = {
"common": set( "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
[NamedObject("common uncommon", True) for i in range(50)]
+ [NamedObject("common", True)]
),
"uncommon": set([NamedObject("common uncommon", True)]), "uncommon": set([NamedObject("common uncommon", True)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@ -309,10 +302,7 @@ class TestCasereduce_common_words:
def test_values_still_are_set_instances(self): def test_values_still_are_set_instances(self):
d = { d = {
"common": set( "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
[NamedObject("common uncommon", True) for i in range(50)]
+ [NamedObject("common", True)]
),
"uncommon": set([NamedObject("common uncommon", True)]), "uncommon": set([NamedObject("common uncommon", True)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@ -352,12 +342,8 @@ class TestCasereduce_common_words:
# would not stay in 'bar' because 'foo' is not a common word anymore. # would not stay in 'bar' because 'foo' is not a common word anymore.
only_common = NamedObject("foo bar", True) only_common = NamedObject("foo bar", True)
d = { d = {
"foo": set( "foo": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]),
[NamedObject("foo bar baz", True) for i in range(49)] + [only_common] "bar": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]),
),
"bar": set(
[NamedObject("foo bar baz", True) for i in range(49)] + [only_common]
),
"baz": set([NamedObject("foo bar baz", True) for i in range(49)]), "baz": set([NamedObject("foo bar baz", True) for i in range(49)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@ -386,9 +372,7 @@ class TestCaseget_match:
assert object() not in m assert object() not in m
def test_word_weight(self): def test_word_weight(self):
m = get_match( m = get_match(NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,))
NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,)
)
eq_(m.percentage, int((6.0 / 13.0) * 100)) eq_(m.percentage, int((6.0 / 13.0) * 100))
@ -554,8 +538,12 @@ class TestCaseGetMatchesByContents:
def test_big_file_partial_hashes(self): def test_big_file_partial_hashes(self):
smallsize = 1 smallsize = 1
bigsize = 100 * 1024 * 1024 # 100MB bigsize = 100 * 1024 * 1024 # 100MB
f = [no("bigfoo", size=bigsize), no("bigbar", size=bigsize), f = [
no("smallfoo", size=smallsize), no("smallbar", size=smallsize)] no("bigfoo", size=bigsize),
no("bigbar", size=bigsize),
no("smallfoo", size=smallsize),
no("smallbar", size=smallsize),
]
f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar" f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar"
f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar" f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
f[2].md5 = f[2].md5partial = "bleh" f[2].md5 = f[2].md5partial = "bleh"
@ -749,8 +737,7 @@ class TestCaseGroup:
# if the ref has the same key as one or more of the dupe, run the tie_breaker func among them # if the ref has the same key as one or more of the dupe, run the tie_breaker func among them
g = get_test_group() g = get_test_group()
o1, o2, o3 = g.ordered o1, o2, o3 = g.ordered
tie_breaker = lambda ref, dupe: dupe is o3 g.prioritize(lambda x: 0, lambda ref, dupe: dupe is o3)
g.prioritize(lambda x: 0, tie_breaker)
assert g.ref is o3 assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_on_all_dupes(self): def test_prioritize_with_tie_breaker_runs_on_all_dupes(self):
@ -761,8 +748,7 @@ class TestCaseGroup:
o1.foo = 1 o1.foo = 1
o2.foo = 2 o2.foo = 2
o3.foo = 3 o3.foo = 3
tie_breaker = lambda ref, dupe: dupe.foo > ref.foo g.prioritize(lambda x: 0, lambda ref, dupe: dupe.foo > ref.foo)
g.prioritize(lambda x: 0, tie_breaker)
assert g.ref is o3 assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self): def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self):
@ -775,9 +761,7 @@ class TestCaseGroup:
o1.bar = 1 o1.bar = 1
o2.bar = 2 o2.bar = 2
o3.bar = 3 o3.bar = 3
key_func = lambda x: -x.foo g.prioritize(lambda x: -x.foo, lambda ref, dupe: dupe.bar > ref.bar)
tie_breaker = lambda ref, dupe: dupe.bar > ref.bar
g.prioritize(key_func, tie_breaker)
assert g.ref is o2 assert g.ref is o2
def test_prioritize_with_ref_dupe(self): def test_prioritize_with_ref_dupe(self):
@ -909,9 +893,7 @@ class TestCaseget_groups:
m1 = Match(A, B, 90) # This is the strongest "A" match m1 = Match(A, B, 90) # This is the strongest "A" match
m2 = Match(A, C, 80) # Because C doesn't match with B, it won't be in the group m2 = Match(A, C, 80) # Because C doesn't match with B, it won't be in the group
m3 = Match(A, D, 80) # Same thing for D m3 = Match(A, D, 80) # Same thing for D
m4 = Match( m4 = Match(C, D, 70) # However, because C and D match, they should have their own group.
C, D, 70
) # However, because C and D match, they should have their own group.
groups = get_groups([m1, m2, m3, m4]) groups = get_groups([m1, m2, m3, m4])
eq_(len(groups), 2) eq_(len(groups), 2)
g1, g2 = groups g1, g2 = groups

View File

@ -30,8 +30,7 @@ from .util import ensure_folder, delete_files_with_pattern
def print_and_do(cmd): def print_and_do(cmd):
"""Prints ``cmd`` and executes it in the shell. """Prints ``cmd`` and executes it in the shell."""
"""
print(cmd) print(cmd)
p = Popen(cmd, shell=True) p = Popen(cmd, shell=True)
return p.wait() return p.wait()
@ -91,16 +90,14 @@ def copy_all(pattern, dst):
def ensure_empty_folder(path): def ensure_empty_folder(path):
"""Make sure that the path exists and that it's an empty folder. """Make sure that the path exists and that it's an empty folder."""
"""
if op.exists(path): if op.exists(path):
shutil.rmtree(path) shutil.rmtree(path)
os.mkdir(path) os.mkdir(path)
def filereplace(filename, outfilename=None, **kwargs): def filereplace(filename, outfilename=None, **kwargs):
"""Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`. """Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`."""
"""
if outfilename is None: if outfilename is None:
outfilename = filename outfilename = filename
fp = open(filename, "rt", encoding="utf-8") fp = open(filename, "rt", encoding="utf-8")
@ -152,9 +149,7 @@ def package_cocoa_app_in_dmg(app_path, destfolder, args):
# a valid signature. # a valid signature.
if args.sign_identity: if args.sign_identity:
sign_identity = "Developer ID Application: {}".format(args.sign_identity) sign_identity = "Developer ID Application: {}".format(args.sign_identity)
result = print_and_do( result = print_and_do('codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path))
'codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path)
)
if result != 0: if result != 0:
print("ERROR: Signing failed. Aborting packaging.") print("ERROR: Signing failed. Aborting packaging.")
return return
@ -182,10 +177,7 @@ def build_dmg(app_path, destfolder):
) )
print("Building %s" % dmgname) print("Building %s" % dmgname)
# UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less. # UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less.
print_and_do( print_and_do('hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"' % (op.join(destfolder, dmgname), dmgpath))
'hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"'
% (op.join(destfolder, dmgname), dmgpath)
)
print("Build Complete") print("Build Complete")
@ -207,8 +199,7 @@ sysconfig.get_config_h_filename = lambda: op.join(op.dirname(__file__), 'pyconfi
def add_to_pythonpath(path): def add_to_pythonpath(path):
"""Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``. """Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``."""
"""
abspath = op.abspath(path) abspath = op.abspath(path)
pythonpath = os.environ.get("PYTHONPATH", "") pythonpath = os.environ.get("PYTHONPATH", "")
pathsep = ";" if ISWINDOWS else ":" pathsep = ";" if ISWINDOWS else ":"
@ -231,9 +222,7 @@ def copy_packages(packages_names, dest, create_links=False, extra_ignores=None):
create_links = False create_links = False
if not extra_ignores: if not extra_ignores:
extra_ignores = [] extra_ignores = []
ignore = shutil.ignore_patterns( ignore = shutil.ignore_patterns(".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores)
".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores
)
for package_name in packages_names: for package_name in packages_names:
if op.exists(package_name): if op.exists(package_name):
source_path = package_name source_path = package_name
@ -444,11 +433,10 @@ class OSXFrameworkStructure:
def create_symlinks(self): def create_symlinks(self):
# Only call this after create() and copy_executable() # Only call this after create() and copy_executable()
rel = lambda path: op.relpath(path, self.dest)
os.symlink("A", op.join(self.dest, "Versions", "Current")) os.symlink("A", op.join(self.dest, "Versions", "Current"))
os.symlink(rel(self.executablepath), op.join(self.dest, self.executablename)) os.symlink(op.relpath(self.executablepath, self.dest), op.join(self.dest, self.executablename))
os.symlink(rel(self.headers), op.join(self.dest, "Headers")) os.symlink(op.relpath(self.headers, self.dest), op.join(self.dest, "Headers"))
os.symlink(rel(self.resources), op.join(self.dest, "Resources")) os.symlink(op.relpath(self.resources, self.dest), op.join(self.dest, "Resources"))
def copy_executable(self, executable): def copy_executable(self, executable):
copy(executable, self.executablepath) copy(executable, self.executablepath)
@ -481,9 +469,7 @@ def copy_embeddable_python_dylib(dst):
def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
sysprefix = sys.prefix # could be a virtualenv sysprefix = sys.prefix # could be a virtualenv
basesysprefix = sys.base_prefix # seems to be path to non-virtual sys basesysprefix = sys.base_prefix # seems to be path to non-virtual sys
real_lib_prefix = sysconfig.get_config_var( real_lib_prefix = sysconfig.get_config_var("LIBDEST") # leaving this in case it is neede
"LIBDEST"
) # leaving this in case it is neede
def is_stdlib_path(path): def is_stdlib_path(path):
# A module path is only a stdlib path if it's in either sys.prefix or # A module path is only a stdlib path if it's in either sys.prefix or
@ -493,11 +479,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
return False return False
if "site-package" in path: if "site-package" in path:
return False return False
if not ( if not (path.startswith(sysprefix) or path.startswith(basesysprefix) or path.startswith(real_lib_prefix)):
path.startswith(sysprefix)
or path.startswith(basesysprefix)
or path.startswith(real_lib_prefix)
):
return False return False
return True return True
@ -511,9 +493,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
relpath = op.relpath(p, real_lib_prefix) relpath = op.relpath(p, real_lib_prefix)
elif p.startswith(sysprefix): elif p.startswith(sysprefix):
relpath = op.relpath(p, sysprefix) relpath = op.relpath(p, sysprefix)
assert relpath.startswith( assert relpath.startswith("lib/python3.") # we want to get rid of that lib/python3.x part
"lib/python3."
) # we want to get rid of that lib/python3.x part
relpath = relpath[len("lib/python3.X/") :] relpath = relpath[len("lib/python3.X/") :]
elif p.startswith(basesysprefix): elif p.startswith(basesysprefix):
relpath = op.relpath(p, basesysprefix) relpath = op.relpath(p, basesysprefix)
@ -521,9 +501,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
relpath = relpath[len("lib/python3.X/") :] relpath = relpath[len("lib/python3.X/") :]
else: else:
raise AssertionError() raise AssertionError()
if relpath.startswith( if relpath.startswith("lib-dynload"): # We copy .so files in lib-dynload directly in our dest
"lib-dynload"
): # We copy .so files in lib-dynload directly in our dest
relpath = relpath[len("lib-dynload/") :] relpath = relpath[len("lib-dynload/") :]
if relpath.startswith("encodings") or relpath.startswith("distutils"): if relpath.startswith("encodings") or relpath.startswith("distutils"):
# We force their inclusion later. # We force their inclusion later.
@ -562,9 +540,7 @@ def fix_qt_resource_file(path):
fp.write(b"\n".join(lines)) fp.write(b"\n".join(lines))
def build_cocoa_ext( def build_cocoa_ext(extname, dest, source_files, extra_frameworks=(), extra_includes=()):
extname, dest, source_files, extra_frameworks=(), extra_includes=()
):
extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"] extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"]
for extra in extra_frameworks: for extra in extra_frameworks:
extra_link_args += ["-framework", extra] extra_link_args += ["-framework", extra]

View File

@ -97,8 +97,7 @@ class Table(MutableSequence, Selectable):
self._rows.pop(0) self._rows.pop(0)
if self._footer is not None: if self._footer is not None:
self._rows.pop() self._rows.pop()
key = lambda row: row.sort_key_for_column(column_name) self._rows.sort(key=lambda row: row.sort_key_for_column(column_name), reverse=desc)
self._rows.sort(key=key, reverse=desc)
if self._header is not None: if self._header is not None:
self._rows.insert(0, self._header) self._rows.insert(0, self._header)
if self._footer is not None: if self._footer is not None:
@ -277,8 +276,7 @@ class GUITable(Table, GUIObject):
raise NotImplementedError() raise NotImplementedError()
def _do_delete(self): def _do_delete(self):
"""(Virtual) Delete the selected rows. """(Virtual) Delete the selected rows."""
"""
pass pass
def _fill(self): def _fill(self):

View File

@ -76,14 +76,10 @@ class PreferencesDialogBase(QDialog):
super().__init__(parent, flags, **kwargs) super().__init__(parent, flags, **kwargs)
self.app = app self.app = app
all_languages = get_langnames() all_languages = get_langnames()
self.supportedLanguages = sorted( self.supportedLanguages = sorted(SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang])
SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang]
)
self._setupUi() self._setupUi()
self.filterHardnessSlider.valueChanged["int"].connect( self.filterHardnessSlider.valueChanged["int"].connect(self.filterHardnessLabel.setNum)
self.filterHardnessLabel.setNum
)
self.buttonBox.clicked.connect(self.buttonClicked) self.buttonBox.clicked.connect(self.buttonClicked)
self.buttonBox.accepted.connect(self.accept) self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject) self.buttonBox.rejected.connect(self.reject)
@ -102,9 +98,7 @@ class PreferencesDialogBase(QDialog):
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth( sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth())
self.filterHardnessSlider.sizePolicy().hasHeightForWidth()
)
self.filterHardnessSlider.setSizePolicy(sizePolicy) self.filterHardnessSlider.setSizePolicy(sizePolicy)
self.filterHardnessSlider.setMinimum(1) self.filterHardnessSlider.setMinimum(1)
self.filterHardnessSlider.setMaximum(100) self.filterHardnessSlider.setMaximum(100)
@ -140,9 +134,7 @@ class PreferencesDialogBase(QDialog):
self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path")) self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path"))
self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox) self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox)
self.customCommandLabel = QLabel(self) self.customCommandLabel = QLabel(self)
self.customCommandLabel.setText( self.customCommandLabel.setText(tr("Custom Command (arguments: %d for dupe, %r for ref):"))
tr("Custom Command (arguments: %d for dupe, %r for ref):")
)
self.widgetsVLayout.addWidget(self.customCommandLabel) self.widgetsVLayout.addWidget(self.customCommandLabel)
self.customCommandEdit = QLineEdit(self) self.customCommandEdit = QLineEdit(self)
self.widgetsVLayout.addWidget(self.customCommandEdit) self.widgetsVLayout.addWidget(self.customCommandEdit)
@ -154,9 +146,7 @@ class PreferencesDialogBase(QDialog):
self.languageComboBox = QComboBox(self) self.languageComboBox = QComboBox(self)
for lang in self.supportedLanguages: for lang in self.supportedLanguages:
self.languageComboBox.addItem(get_langnames()[lang]) self.languageComboBox.addItem(get_langnames()[lang])
layout.addLayout( layout.addLayout(horizontalWrap([self.languageLabel, self.languageComboBox, None]))
horizontalWrap([self.languageLabel, self.languageComboBox, None])
)
self._setupAddCheckbox( self._setupAddCheckbox(
"tabs_default_pos", "tabs_default_pos",
tr("Use default position for tab bar (requires restart)"), tr("Use default position for tab bar (requires restart)"),
@ -178,23 +168,15 @@ On MacOS, the tab bar will fill up the window's width instead."
self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox = QSpinBox()
self.fontSizeSpinBox.setMinimum(5) self.fontSizeSpinBox.setMinimum(5)
formlayout.addRow(tr("Font size:"), self.fontSizeSpinBox) formlayout.addRow(tr("Font size:"), self.fontSizeSpinBox)
self._setupAddCheckbox( self._setupAddCheckbox("reference_bold_font", tr("Use bold font for references"))
"reference_bold_font", tr("Use bold font for references")
)
formlayout.addRow(self.reference_bold_font) formlayout.addRow(self.reference_bold_font)
self.result_table_ref_foreground_color = ColorPickerButton(self) self.result_table_ref_foreground_color = ColorPickerButton(self)
formlayout.addRow( formlayout.addRow(tr("Reference foreground color:"), self.result_table_ref_foreground_color)
tr("Reference foreground color:"), self.result_table_ref_foreground_color
)
self.result_table_ref_background_color = ColorPickerButton(self) self.result_table_ref_background_color = ColorPickerButton(self)
formlayout.addRow( formlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color)
tr("Reference background color:"), self.result_table_ref_background_color
)
self.result_table_delta_foreground_color = ColorPickerButton(self) self.result_table_delta_foreground_color = ColorPickerButton(self)
formlayout.addRow( formlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color)
tr("Delta foreground color:"), self.result_table_delta_foreground_color
)
formlayout.setLabelAlignment(Qt.AlignLeft) formlayout.setLabelAlignment(Qt.AlignLeft)
# Keep same vertical spacing as parent layout for consistency # Keep same vertical spacing as parent layout for consistency
@ -218,30 +200,20 @@ use the modifier key to drag the floating window around"
else tr("The title bar can only be disabled while the window is docked") else tr("The title bar can only be disabled while the window is docked")
) )
self.details_groupbox_layout.addWidget(self.details_dialog_titlebar_enabled) self.details_groupbox_layout.addWidget(self.details_dialog_titlebar_enabled)
self._setupAddCheckbox( self._setupAddCheckbox("details_dialog_vertical_titlebar", tr("Vertical title bar"))
"details_dialog_vertical_titlebar", tr("Vertical title bar")
)
self.details_dialog_vertical_titlebar.setToolTip( self.details_dialog_vertical_titlebar.setToolTip(
tr( tr("Change the title bar from horizontal on top, to vertical on the left side")
"Change the title bar from horizontal on top, to vertical on the left side"
)
) )
self.details_groupbox_layout.addWidget(self.details_dialog_vertical_titlebar) self.details_groupbox_layout.addWidget(self.details_dialog_vertical_titlebar)
self.details_dialog_vertical_titlebar.setEnabled( self.details_dialog_vertical_titlebar.setEnabled(self.details_dialog_titlebar_enabled.isChecked())
self.details_dialog_titlebar_enabled.isChecked() self.details_dialog_titlebar_enabled.stateChanged.connect(self.details_dialog_vertical_titlebar.setEnabled)
)
self.details_dialog_titlebar_enabled.stateChanged.connect(
self.details_dialog_vertical_titlebar.setEnabled
)
gridlayout = QGridLayout() gridlayout = QGridLayout()
formlayout = QFormLayout() formlayout = QFormLayout()
self.details_table_delta_foreground_color = ColorPickerButton(self) self.details_table_delta_foreground_color = ColorPickerButton(self)
# Padding on the right side and space between label and widget to keep it somewhat consistent across themes # Padding on the right side and space between label and widget to keep it somewhat consistent across themes
gridlayout.setColumnStretch(1, 1) gridlayout.setColumnStretch(1, 1)
formlayout.setHorizontalSpacing(50) formlayout.setHorizontalSpacing(50)
formlayout.addRow( formlayout.addRow(tr("Delta foreground color:"), self.details_table_delta_foreground_color)
tr("Delta foreground color:"), self.details_table_delta_foreground_color
)
gridlayout.addLayout(formlayout, 0, 0) gridlayout.addLayout(formlayout, 0, 0)
self.details_groupbox_layout.addLayout(gridlayout) self.details_groupbox_layout.addLayout(gridlayout)
details_groupbox.setLayout(self.details_groupbox_layout) details_groupbox.setLayout(self.details_groupbox_layout)
@ -276,9 +248,7 @@ use the modifier key to drag the floating window around"
# self.mainVLayout.addLayout(self.widgetsVLayout) # self.mainVLayout.addLayout(self.widgetsVLayout)
self.buttonBox = QDialogButtonBox(self) self.buttonBox = QDialogButtonBox(self)
self.buttonBox.setStandardButtons( self.buttonBox.setStandardButtons(
QDialogButtonBox.Cancel QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults
| QDialogButtonBox.Ok
| QDialogButtonBox.RestoreDefaults
) )
self.mainVLayout.addWidget(self.tabwidget) self.mainVLayout.addWidget(self.tabwidget)
self.mainVLayout.addWidget(self.buttonBox) self.mainVLayout.addWidget(self.buttonBox)
@ -299,7 +269,10 @@ use the modifier key to drag the floating window around"
def load(self, prefs=None, section=Sections.ALL): def load(self, prefs=None, section=Sections.ALL):
if prefs is None: if prefs is None:
prefs = self.app.prefs prefs = self.app.prefs
setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked)
def setchecked(cb, b):
cb.setCheckState(Qt.Checked if b else Qt.Unchecked)
if section & Sections.GENERAL: if section & Sections.GENERAL:
self.filterHardnessSlider.setValue(prefs.filter_hardness) self.filterHardnessSlider.setValue(prefs.filter_hardness)
self.filterHardnessLabel.setNum(prefs.filter_hardness) self.filterHardnessLabel.setNum(prefs.filter_hardness)
@ -322,18 +295,10 @@ use the modifier key to drag the floating window around"
prefs.details_dialog_vertical_titlebar, prefs.details_dialog_vertical_titlebar,
) )
self.fontSizeSpinBox.setValue(prefs.tableFontSize) self.fontSizeSpinBox.setValue(prefs.tableFontSize)
self.details_table_delta_foreground_color.setColor( self.details_table_delta_foreground_color.setColor(prefs.details_table_delta_foreground_color)
prefs.details_table_delta_foreground_color self.result_table_ref_foreground_color.setColor(prefs.result_table_ref_foreground_color)
) self.result_table_ref_background_color.setColor(prefs.result_table_ref_background_color)
self.result_table_ref_foreground_color.setColor( self.result_table_delta_foreground_color.setColor(prefs.result_table_delta_foreground_color)
prefs.result_table_ref_foreground_color
)
self.result_table_ref_background_color.setColor(
prefs.result_table_ref_background_color
)
self.result_table_delta_foreground_color.setColor(
prefs.result_table_delta_foreground_color
)
try: try:
langindex = self.supportedLanguages.index(self.app.prefs.language) langindex = self.supportedLanguages.index(self.app.prefs.language)
except ValueError: except ValueError:
@ -344,31 +309,22 @@ use the modifier key to drag the floating window around"
def save(self): def save(self):
prefs = self.app.prefs prefs = self.app.prefs
prefs.filter_hardness = self.filterHardnessSlider.value() prefs.filter_hardness = self.filterHardnessSlider.value()
ischecked = lambda cb: cb.checkState() == Qt.Checked
def ischecked(cb):
return cb.checkState() == Qt.Checked
prefs.mix_file_kind = ischecked(self.mixFileKindBox) prefs.mix_file_kind = ischecked(self.mixFileKindBox)
prefs.use_regexp = ischecked(self.useRegexpBox) prefs.use_regexp = ischecked(self.useRegexpBox)
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches)
prefs.debug_mode = ischecked(self.debugModeBox) prefs.debug_mode = ischecked(self.debugModeBox)
prefs.reference_bold_font = ischecked(self.reference_bold_font) prefs.reference_bold_font = ischecked(self.reference_bold_font)
prefs.details_dialog_titlebar_enabled = ischecked( prefs.details_dialog_titlebar_enabled = ischecked(self.details_dialog_titlebar_enabled)
self.details_dialog_titlebar_enabled prefs.details_dialog_vertical_titlebar = ischecked(self.details_dialog_vertical_titlebar)
) prefs.details_table_delta_foreground_color = self.details_table_delta_foreground_color.color
prefs.details_dialog_vertical_titlebar = ischecked( prefs.result_table_ref_foreground_color = self.result_table_ref_foreground_color.color
self.details_dialog_vertical_titlebar prefs.result_table_ref_background_color = self.result_table_ref_background_color.color
) prefs.result_table_delta_foreground_color = self.result_table_delta_foreground_color.color
prefs.details_table_delta_foreground_color = (
self.details_table_delta_foreground_color.color
)
prefs.result_table_ref_foreground_color = (
self.result_table_ref_foreground_color.color
)
prefs.result_table_ref_background_color = (
self.result_table_ref_background_color.color
)
prefs.result_table_delta_foreground_color = (
self.result_table_delta_foreground_color.color
)
prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex()
prefs.custom_command = str(self.customCommandEdit.text()) prefs.custom_command = str(self.customCommandEdit.text())
prefs.tableFontSize = self.fontSizeSpinBox.value() prefs.tableFontSize = self.fontSizeSpinBox.value()
@ -411,9 +367,7 @@ class ColorPickerButton(QPushButton):
@pyqtSlot() @pyqtSlot()
def onClicked(self): def onClicked(self):
color = QColorDialog.getColor( color = QColorDialog.getColor(self.color if self.color is not None else Qt.white, self.parent)
self.color if self.color is not None else Qt.white, self.parent
)
self.setColor(color) self.setColor(color)
def setColor(self, color): def setColor(self, color):