mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-03-09 21:24:36 +00:00
Remove flake8 E731 Errors
Note: black formatting is now applying correctly as well.
This commit is contained in:
parent
af19660c18
commit
9446f37fad
@ -17,7 +17,11 @@ from hscommon.util import flatten, multi_replace
|
||||
from hscommon.trans import tr
|
||||
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
|
||||
|
||||
@ -34,11 +38,9 @@ def getwords(s):
|
||||
# of their accents, etc.) are preserved as is. The arbitrary limit is
|
||||
# obtained from this one: ord("\u037e") GREEK QUESTION MARK
|
||||
s = "".join(
|
||||
c for c in s
|
||||
if (ord(c) <= 894
|
||||
and c in string.ascii_letters + string.digits + string.whitespace
|
||||
)
|
||||
or ord(c) > 894
|
||||
c
|
||||
for c in s
|
||||
if (ord(c) <= 894 and c in string.ascii_letters + string.digits + string.whitespace) or ord(c) > 894
|
||||
)
|
||||
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:
|
||||
second.remove(matched_field)
|
||||
else:
|
||||
results = [
|
||||
compare(field1, field2, flags) for field1, field2 in zip(first, second)
|
||||
]
|
||||
results = [compare(field1, field2, flags) for field1, field2 in zip(first, second)]
|
||||
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.
|
||||
"""
|
||||
result = defaultdict(set)
|
||||
for object in j.iter_with_progress(
|
||||
objects, "Prepared %d/%d files", JOB_REFRESH_RATE
|
||||
):
|
||||
for object in j.iter_with_progress(objects, "Prepared %d/%d files", JOB_REFRESH_RATE):
|
||||
for word in unpack_fields(object.words):
|
||||
result[word].add(object)
|
||||
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.
|
||||
Because if we remove them, we will miss some duplicates!
|
||||
"""
|
||||
uncommon_words = set(
|
||||
word for word, objects in word_dict.items() if len(objects) < threshold
|
||||
)
|
||||
uncommon_words = set(word for word, objects in word_dict.items() if len(objects) < threshold)
|
||||
for word, objects in list(word_dict.items()):
|
||||
if len(objects) < threshold:
|
||||
continue
|
||||
@ -275,10 +271,7 @@ def getmatches(
|
||||
# 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.
|
||||
del compared # This should give us enough room to call logging.
|
||||
logging.warning(
|
||||
"Memory Overflow. Matches: %d. Word dict: %d"
|
||||
% (len(result), len(word_dict))
|
||||
)
|
||||
logging.warning("Memory Overflow. Matches: %d. Word dict: %d" % (len(result), len(word_dict)))
|
||||
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.
|
||||
"""
|
||||
discarded = set(
|
||||
m
|
||||
for m in self.matches
|
||||
if not all(obj in self.unordered for obj in [m.first, m.second])
|
||||
)
|
||||
discarded = set(m for m in self.matches if not all(obj in self.unordered for obj in [m.first, m.second]))
|
||||
self.matches -= discarded
|
||||
self.candidates = defaultdict(set)
|
||||
return discarded
|
||||
|
||||
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:
|
||||
return
|
||||
for m in self._get_matches_for_ref():
|
||||
@ -435,8 +423,7 @@ class Group:
|
||||
"""
|
||||
# tie_breaker(ref, dupe) --> True if dupe should be ref
|
||||
# Returns True if anything changed during prioritization.
|
||||
master_key_func = lambda x: (-x.is_ref, key_func(x))
|
||||
new_order = sorted(self.ordered, key=master_key_func)
|
||||
new_order = sorted(self.ordered, key=lambda x: (-x.is_ref, key_func(x)))
|
||||
changed = new_order != self.ordered
|
||||
self.ordered = new_order
|
||||
if tie_breaker is None:
|
||||
@ -459,9 +446,7 @@ class Group:
|
||||
self.unordered.remove(item)
|
||||
self._percentage = None
|
||||
self._matches_for_ref = None
|
||||
if (len(self) > 1) and any(
|
||||
not getattr(item, "is_ref", False) for item in self
|
||||
):
|
||||
if (len(self) > 1) and any(not getattr(item, "is_ref", False) for item in self):
|
||||
if discard_matches:
|
||||
self.matches = set(m for m in self.matches if item not in m)
|
||||
else:
|
||||
@ -470,8 +455,7 @@ class Group:
|
||||
pass
|
||||
|
||||
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:
|
||||
return False
|
||||
try:
|
||||
@ -490,9 +474,7 @@ class Group:
|
||||
if self._percentage is None:
|
||||
if self.dupes:
|
||||
matches = self._get_matches_for_ref()
|
||||
self._percentage = sum(match.percentage for match in matches) // len(
|
||||
matches
|
||||
)
|
||||
self._percentage = sum(match.percentage for match in matches) // len(matches)
|
||||
else:
|
||||
self._percentage = 0
|
||||
return self._percentage
|
||||
@ -547,12 +529,8 @@ def get_groups(matches):
|
||||
orphan_matches = []
|
||||
for group in groups:
|
||||
orphan_matches += {
|
||||
m
|
||||
for m in group.discard_matches()
|
||||
if not any(obj in matched_files for obj in [m.first, m.second])
|
||||
m 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:
|
||||
groups += get_groups(
|
||||
orphan_matches
|
||||
) # no job, as it isn't supposed to take a long time
|
||||
groups += get_groups(orphan_matches) # no job, as it isn't supposed to take a long time
|
||||
return groups
|
||||
|
@ -106,9 +106,7 @@ class Results(Markable):
|
||||
self.groups,
|
||||
)
|
||||
if self.__filtered_dupes:
|
||||
self.__dupes = [
|
||||
dupe for dupe in self.__dupes if dupe in self.__filtered_dupes
|
||||
]
|
||||
self.__dupes = [dupe for dupe in self.__dupes if dupe in self.__filtered_dupes]
|
||||
sd = self.__dupes_sort_descriptor
|
||||
if sd:
|
||||
self.sort_dupes(sd[0], sd[1], sd[2])
|
||||
@ -127,18 +125,10 @@ class Results(Markable):
|
||||
total_count = self.__total_count
|
||||
total_size = self.__total_size
|
||||
else:
|
||||
mark_count = len(
|
||||
[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)]
|
||||
)
|
||||
total_size = sum(
|
||||
dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe)
|
||||
)
|
||||
mark_count = len([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)])
|
||||
total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe))
|
||||
if self.mark_inverted:
|
||||
marked_size = self.__total_size - marked_size
|
||||
result = tr("%d / %d (%s / %s) duplicates marked.") % (
|
||||
@ -201,11 +191,7 @@ class Results(Markable):
|
||||
self.__filters.append(filter_str)
|
||||
if self.__filtered_dupes is None:
|
||||
self.__filtered_dupes = flatten(g[:] for g in self.groups)
|
||||
self.__filtered_dupes = set(
|
||||
dupe
|
||||
for dupe in self.__filtered_dupes
|
||||
if filter_re.search(str(dupe.path))
|
||||
)
|
||||
self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(str(dupe.path)))
|
||||
filtered_groups = set()
|
||||
for dupe in self.__filtered_dupes:
|
||||
filtered_groups.add(self.get_group_of_duplicate(dupe))
|
||||
@ -217,8 +203,7 @@ class Results(Markable):
|
||||
self.__dupes = None
|
||||
|
||||
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:
|
||||
return self.__group_of_duplicate[dupe]
|
||||
except (TypeError, KeyError):
|
||||
@ -284,8 +269,7 @@ class Results(Markable):
|
||||
self.is_modified = False
|
||||
|
||||
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)
|
||||
r = g.ref
|
||||
if not g.switch_ref(dupe):
|
||||
@ -412,10 +396,10 @@ class Results(Markable):
|
||||
"""
|
||||
if not self.__dupes:
|
||||
self.__get_dupe_list()
|
||||
keyfunc = lambda d: self.app._get_dupe_sort_key(
|
||||
d, lambda: self.get_group_of_duplicate(d), key, delta
|
||||
self.__dupes.sort(
|
||||
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)
|
||||
|
||||
def sort_groups(self, key, asc=True):
|
||||
@ -426,8 +410,7 @@ class Results(Markable):
|
||||
:param str key: key attribute name to sort with.
|
||||
:param bool asc: If false, sorting is reversed.
|
||||
"""
|
||||
keyfunc = lambda g: self.app._get_group_sort_key(g, key)
|
||||
self.groups.sort(key=keyfunc, reverse=not asc)
|
||||
self.groups.sort(key=lambda g: self.app._get_group_sort_key(g, key), reverse=not asc)
|
||||
self.__groups_sort_descriptor = (key, asc)
|
||||
|
||||
# ---Properties
|
||||
|
@ -177,9 +177,7 @@ class TestCaseWordCompareWithFields:
|
||||
def test_simple(self):
|
||||
eq_(
|
||||
67,
|
||||
compare_fields(
|
||||
[["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]
|
||||
),
|
||||
compare_fields([["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]),
|
||||
)
|
||||
|
||||
def test_empty(self):
|
||||
@ -265,9 +263,7 @@ class TestCasebuild_word_dict:
|
||||
j = job.Job(1, do_progress)
|
||||
self.log = []
|
||||
s = "foo bar"
|
||||
build_word_dict(
|
||||
[NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j
|
||||
)
|
||||
build_word_dict([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
|
||||
eq_(0, self.log[0])
|
||||
eq_(100, self.log[1])
|
||||
@ -297,10 +293,7 @@ class TestCasereduce_common_words:
|
||||
|
||||
def test_dont_remove_objects_with_only_common_words(self):
|
||||
d = {
|
||||
"common": set(
|
||||
[NamedObject("common uncommon", True) for i in range(50)]
|
||||
+ [NamedObject("common", True)]
|
||||
),
|
||||
"common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
|
||||
"uncommon": set([NamedObject("common uncommon", True)]),
|
||||
}
|
||||
reduce_common_words(d, 50)
|
||||
@ -309,10 +302,7 @@ class TestCasereduce_common_words:
|
||||
|
||||
def test_values_still_are_set_instances(self):
|
||||
d = {
|
||||
"common": set(
|
||||
[NamedObject("common uncommon", True) for i in range(50)]
|
||||
+ [NamedObject("common", True)]
|
||||
),
|
||||
"common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
|
||||
"uncommon": set([NamedObject("common uncommon", True)]),
|
||||
}
|
||||
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.
|
||||
only_common = NamedObject("foo bar", True)
|
||||
d = {
|
||||
"foo": 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]
|
||||
),
|
||||
"foo": 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)]),
|
||||
}
|
||||
reduce_common_words(d, 50)
|
||||
@ -386,9 +372,7 @@ class TestCaseget_match:
|
||||
assert object() not in m
|
||||
|
||||
def test_word_weight(self):
|
||||
m = get_match(
|
||||
NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,)
|
||||
)
|
||||
m = get_match(NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,))
|
||||
eq_(m.percentage, int((6.0 / 13.0) * 100))
|
||||
|
||||
|
||||
@ -554,8 +538,12 @@ class TestCaseGetMatchesByContents:
|
||||
def test_big_file_partial_hashes(self):
|
||||
smallsize = 1
|
||||
bigsize = 100 * 1024 * 1024 # 100MB
|
||||
f = [no("bigfoo", size=bigsize), no("bigbar", size=bigsize),
|
||||
no("smallfoo", size=smallsize), no("smallbar", size=smallsize)]
|
||||
f = [
|
||||
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[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
|
||||
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
|
||||
g = get_test_group()
|
||||
o1, o2, o3 = g.ordered
|
||||
tie_breaker = lambda ref, dupe: dupe is o3
|
||||
g.prioritize(lambda x: 0, tie_breaker)
|
||||
g.prioritize(lambda x: 0, lambda ref, dupe: dupe is o3)
|
||||
assert g.ref is o3
|
||||
|
||||
def test_prioritize_with_tie_breaker_runs_on_all_dupes(self):
|
||||
@ -761,8 +748,7 @@ class TestCaseGroup:
|
||||
o1.foo = 1
|
||||
o2.foo = 2
|
||||
o3.foo = 3
|
||||
tie_breaker = lambda ref, dupe: dupe.foo > ref.foo
|
||||
g.prioritize(lambda x: 0, tie_breaker)
|
||||
g.prioritize(lambda x: 0, lambda ref, dupe: dupe.foo > ref.foo)
|
||||
assert g.ref is o3
|
||||
|
||||
def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self):
|
||||
@ -775,9 +761,7 @@ class TestCaseGroup:
|
||||
o1.bar = 1
|
||||
o2.bar = 2
|
||||
o3.bar = 3
|
||||
key_func = lambda x: -x.foo
|
||||
tie_breaker = lambda ref, dupe: dupe.bar > ref.bar
|
||||
g.prioritize(key_func, tie_breaker)
|
||||
g.prioritize(lambda x: -x.foo, lambda ref, dupe: dupe.bar > ref.bar)
|
||||
assert g.ref is o2
|
||||
|
||||
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
|
||||
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
|
||||
m4 = Match(
|
||||
C, D, 70
|
||||
) # However, because C and D match, they should have their own group.
|
||||
m4 = Match(C, D, 70) # However, because C and D match, they should have their own group.
|
||||
groups = get_groups([m1, m2, m3, m4])
|
||||
eq_(len(groups), 2)
|
||||
g1, g2 = groups
|
||||
|
@ -30,8 +30,7 @@ from .util import ensure_folder, delete_files_with_pattern
|
||||
|
||||
|
||||
def print_and_do(cmd):
|
||||
"""Prints ``cmd`` and executes it in the shell.
|
||||
"""
|
||||
"""Prints ``cmd`` and executes it in the shell."""
|
||||
print(cmd)
|
||||
p = Popen(cmd, shell=True)
|
||||
return p.wait()
|
||||
@ -91,16 +90,14 @@ def copy_all(pattern, dst):
|
||||
|
||||
|
||||
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):
|
||||
shutil.rmtree(path)
|
||||
os.mkdir(path)
|
||||
|
||||
|
||||
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:
|
||||
outfilename = filename
|
||||
fp = open(filename, "rt", encoding="utf-8")
|
||||
@ -152,9 +149,7 @@ def package_cocoa_app_in_dmg(app_path, destfolder, args):
|
||||
# a valid signature.
|
||||
if args.sign_identity:
|
||||
sign_identity = "Developer ID Application: {}".format(args.sign_identity)
|
||||
result = print_and_do(
|
||||
'codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path)
|
||||
)
|
||||
result = print_and_do('codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path))
|
||||
if result != 0:
|
||||
print("ERROR: Signing failed. Aborting packaging.")
|
||||
return
|
||||
@ -182,10 +177,7 @@ def build_dmg(app_path, destfolder):
|
||||
)
|
||||
print("Building %s" % dmgname)
|
||||
# UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less.
|
||||
print_and_do(
|
||||
'hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"'
|
||||
% (op.join(destfolder, dmgname), dmgpath)
|
||||
)
|
||||
print_and_do('hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"' % (op.join(destfolder, dmgname), dmgpath))
|
||||
print("Build Complete")
|
||||
|
||||
|
||||
@ -207,8 +199,7 @@ sysconfig.get_config_h_filename = lambda: op.join(op.dirname(__file__), 'pyconfi
|
||||
|
||||
|
||||
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)
|
||||
pythonpath = os.environ.get("PYTHONPATH", "")
|
||||
pathsep = ";" if ISWINDOWS else ":"
|
||||
@ -231,9 +222,7 @@ def copy_packages(packages_names, dest, create_links=False, extra_ignores=None):
|
||||
create_links = False
|
||||
if not extra_ignores:
|
||||
extra_ignores = []
|
||||
ignore = shutil.ignore_patterns(
|
||||
".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores
|
||||
)
|
||||
ignore = shutil.ignore_patterns(".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores)
|
||||
for package_name in packages_names:
|
||||
if op.exists(package_name):
|
||||
source_path = package_name
|
||||
@ -444,11 +433,10 @@ class OSXFrameworkStructure:
|
||||
|
||||
def create_symlinks(self):
|
||||
# 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(rel(self.executablepath), op.join(self.dest, self.executablename))
|
||||
os.symlink(rel(self.headers), op.join(self.dest, "Headers"))
|
||||
os.symlink(rel(self.resources), op.join(self.dest, "Resources"))
|
||||
os.symlink(op.relpath(self.executablepath, self.dest), op.join(self.dest, self.executablename))
|
||||
os.symlink(op.relpath(self.headers, self.dest), op.join(self.dest, "Headers"))
|
||||
os.symlink(op.relpath(self.resources, self.dest), op.join(self.dest, "Resources"))
|
||||
|
||||
def copy_executable(self, executable):
|
||||
copy(executable, self.executablepath)
|
||||
@ -481,9 +469,7 @@ def copy_embeddable_python_dylib(dst):
|
||||
def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
|
||||
sysprefix = sys.prefix # could be a virtualenv
|
||||
basesysprefix = sys.base_prefix # seems to be path to non-virtual sys
|
||||
real_lib_prefix = sysconfig.get_config_var(
|
||||
"LIBDEST"
|
||||
) # leaving this in case it is neede
|
||||
real_lib_prefix = sysconfig.get_config_var("LIBDEST") # leaving this in case it is neede
|
||||
|
||||
def is_stdlib_path(path):
|
||||
# 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
|
||||
if "site-package" in path:
|
||||
return False
|
||||
if not (
|
||||
path.startswith(sysprefix)
|
||||
or path.startswith(basesysprefix)
|
||||
or path.startswith(real_lib_prefix)
|
||||
):
|
||||
if not (path.startswith(sysprefix) or path.startswith(basesysprefix) or path.startswith(real_lib_prefix)):
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -511,9 +493,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
|
||||
relpath = op.relpath(p, real_lib_prefix)
|
||||
elif p.startswith(sysprefix):
|
||||
relpath = op.relpath(p, sysprefix)
|
||||
assert relpath.startswith(
|
||||
"lib/python3."
|
||||
) # we want to get rid of that lib/python3.x part
|
||||
assert relpath.startswith("lib/python3.") # we want to get rid of that lib/python3.x part
|
||||
relpath = relpath[len("lib/python3.X/") :]
|
||||
elif p.startswith(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/") :]
|
||||
else:
|
||||
raise AssertionError()
|
||||
if relpath.startswith(
|
||||
"lib-dynload"
|
||||
): # We copy .so files in lib-dynload directly in our dest
|
||||
if relpath.startswith("lib-dynload"): # We copy .so files in lib-dynload directly in our dest
|
||||
relpath = relpath[len("lib-dynload/") :]
|
||||
if relpath.startswith("encodings") or relpath.startswith("distutils"):
|
||||
# We force their inclusion later.
|
||||
@ -562,9 +540,7 @@ def fix_qt_resource_file(path):
|
||||
fp.write(b"\n".join(lines))
|
||||
|
||||
|
||||
def build_cocoa_ext(
|
||||
extname, dest, source_files, extra_frameworks=(), extra_includes=()
|
||||
):
|
||||
def build_cocoa_ext(extname, dest, source_files, extra_frameworks=(), extra_includes=()):
|
||||
extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"]
|
||||
for extra in extra_frameworks:
|
||||
extra_link_args += ["-framework", extra]
|
||||
|
@ -97,8 +97,7 @@ class Table(MutableSequence, Selectable):
|
||||
self._rows.pop(0)
|
||||
if self._footer is not None:
|
||||
self._rows.pop()
|
||||
key = lambda row: row.sort_key_for_column(column_name)
|
||||
self._rows.sort(key=key, reverse=desc)
|
||||
self._rows.sort(key=lambda row: row.sort_key_for_column(column_name), reverse=desc)
|
||||
if self._header is not None:
|
||||
self._rows.insert(0, self._header)
|
||||
if self._footer is not None:
|
||||
@ -277,8 +276,7 @@ class GUITable(Table, GUIObject):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _do_delete(self):
|
||||
"""(Virtual) Delete the selected rows.
|
||||
"""
|
||||
"""(Virtual) Delete the selected rows."""
|
||||
pass
|
||||
|
||||
def _fill(self):
|
||||
|
@ -76,14 +76,10 @@ class PreferencesDialogBase(QDialog):
|
||||
super().__init__(parent, flags, **kwargs)
|
||||
self.app = app
|
||||
all_languages = get_langnames()
|
||||
self.supportedLanguages = sorted(
|
||||
SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang]
|
||||
)
|
||||
self.supportedLanguages = sorted(SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang])
|
||||
self._setupUi()
|
||||
|
||||
self.filterHardnessSlider.valueChanged["int"].connect(
|
||||
self.filterHardnessLabel.setNum
|
||||
)
|
||||
self.filterHardnessSlider.valueChanged["int"].connect(self.filterHardnessLabel.setNum)
|
||||
self.buttonBox.clicked.connect(self.buttonClicked)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
@ -102,9 +98,7 @@ class PreferencesDialogBase(QDialog):
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.filterHardnessSlider.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth())
|
||||
self.filterHardnessSlider.setSizePolicy(sizePolicy)
|
||||
self.filterHardnessSlider.setMinimum(1)
|
||||
self.filterHardnessSlider.setMaximum(100)
|
||||
@ -140,9 +134,7 @@ class PreferencesDialogBase(QDialog):
|
||||
self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path"))
|
||||
self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox)
|
||||
self.customCommandLabel = QLabel(self)
|
||||
self.customCommandLabel.setText(
|
||||
tr("Custom Command (arguments: %d for dupe, %r for ref):")
|
||||
)
|
||||
self.customCommandLabel.setText(tr("Custom Command (arguments: %d for dupe, %r for ref):"))
|
||||
self.widgetsVLayout.addWidget(self.customCommandLabel)
|
||||
self.customCommandEdit = QLineEdit(self)
|
||||
self.widgetsVLayout.addWidget(self.customCommandEdit)
|
||||
@ -154,9 +146,7 @@ class PreferencesDialogBase(QDialog):
|
||||
self.languageComboBox = QComboBox(self)
|
||||
for lang in self.supportedLanguages:
|
||||
self.languageComboBox.addItem(get_langnames()[lang])
|
||||
layout.addLayout(
|
||||
horizontalWrap([self.languageLabel, self.languageComboBox, None])
|
||||
)
|
||||
layout.addLayout(horizontalWrap([self.languageLabel, self.languageComboBox, None]))
|
||||
self._setupAddCheckbox(
|
||||
"tabs_default_pos",
|
||||
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.setMinimum(5)
|
||||
formlayout.addRow(tr("Font size:"), self.fontSizeSpinBox)
|
||||
self._setupAddCheckbox(
|
||||
"reference_bold_font", tr("Use bold font for references")
|
||||
)
|
||||
self._setupAddCheckbox("reference_bold_font", tr("Use bold font for references"))
|
||||
formlayout.addRow(self.reference_bold_font)
|
||||
|
||||
self.result_table_ref_foreground_color = ColorPickerButton(self)
|
||||
formlayout.addRow(
|
||||
tr("Reference foreground color:"), self.result_table_ref_foreground_color
|
||||
)
|
||||
formlayout.addRow(tr("Reference foreground color:"), self.result_table_ref_foreground_color)
|
||||
self.result_table_ref_background_color = ColorPickerButton(self)
|
||||
formlayout.addRow(
|
||||
tr("Reference background color:"), self.result_table_ref_background_color
|
||||
)
|
||||
formlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color)
|
||||
self.result_table_delta_foreground_color = ColorPickerButton(self)
|
||||
formlayout.addRow(
|
||||
tr("Delta foreground color:"), self.result_table_delta_foreground_color
|
||||
)
|
||||
formlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color)
|
||||
formlayout.setLabelAlignment(Qt.AlignLeft)
|
||||
|
||||
# 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")
|
||||
)
|
||||
self.details_groupbox_layout.addWidget(self.details_dialog_titlebar_enabled)
|
||||
self._setupAddCheckbox(
|
||||
"details_dialog_vertical_titlebar", tr("Vertical title bar")
|
||||
)
|
||||
self._setupAddCheckbox("details_dialog_vertical_titlebar", tr("Vertical title bar"))
|
||||
self.details_dialog_vertical_titlebar.setToolTip(
|
||||
tr(
|
||||
"Change the title bar from horizontal on top, to vertical on the left side"
|
||||
)
|
||||
tr("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_dialog_vertical_titlebar.setEnabled(
|
||||
self.details_dialog_titlebar_enabled.isChecked()
|
||||
)
|
||||
self.details_dialog_titlebar_enabled.stateChanged.connect(
|
||||
self.details_dialog_vertical_titlebar.setEnabled
|
||||
)
|
||||
self.details_dialog_vertical_titlebar.setEnabled(self.details_dialog_titlebar_enabled.isChecked())
|
||||
self.details_dialog_titlebar_enabled.stateChanged.connect(self.details_dialog_vertical_titlebar.setEnabled)
|
||||
gridlayout = QGridLayout()
|
||||
formlayout = QFormLayout()
|
||||
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
|
||||
gridlayout.setColumnStretch(1, 1)
|
||||
formlayout.setHorizontalSpacing(50)
|
||||
formlayout.addRow(
|
||||
tr("Delta foreground color:"), self.details_table_delta_foreground_color
|
||||
)
|
||||
formlayout.addRow(tr("Delta foreground color:"), self.details_table_delta_foreground_color)
|
||||
gridlayout.addLayout(formlayout, 0, 0)
|
||||
self.details_groupbox_layout.addLayout(gridlayout)
|
||||
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.buttonBox = QDialogButtonBox(self)
|
||||
self.buttonBox.setStandardButtons(
|
||||
QDialogButtonBox.Cancel
|
||||
| QDialogButtonBox.Ok
|
||||
| QDialogButtonBox.RestoreDefaults
|
||||
QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults
|
||||
)
|
||||
self.mainVLayout.addWidget(self.tabwidget)
|
||||
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):
|
||||
if prefs is None:
|
||||
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:
|
||||
self.filterHardnessSlider.setValue(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,
|
||||
)
|
||||
self.fontSizeSpinBox.setValue(prefs.tableFontSize)
|
||||
self.details_table_delta_foreground_color.setColor(
|
||||
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_delta_foreground_color.setColor(
|
||||
prefs.result_table_delta_foreground_color
|
||||
)
|
||||
self.details_table_delta_foreground_color.setColor(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_delta_foreground_color.setColor(prefs.result_table_delta_foreground_color)
|
||||
try:
|
||||
langindex = self.supportedLanguages.index(self.app.prefs.language)
|
||||
except ValueError:
|
||||
@ -344,31 +309,22 @@ use the modifier key to drag the floating window around"
|
||||
def save(self):
|
||||
prefs = self.app.prefs
|
||||
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.use_regexp = ischecked(self.useRegexpBox)
|
||||
prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox)
|
||||
prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches)
|
||||
prefs.debug_mode = ischecked(self.debugModeBox)
|
||||
prefs.reference_bold_font = ischecked(self.reference_bold_font)
|
||||
prefs.details_dialog_titlebar_enabled = ischecked(
|
||||
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.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.details_dialog_titlebar_enabled = ischecked(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.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.custom_command = str(self.customCommandEdit.text())
|
||||
prefs.tableFontSize = self.fontSizeSpinBox.value()
|
||||
@ -411,9 +367,7 @@ class ColorPickerButton(QPushButton):
|
||||
|
||||
@pyqtSlot()
|
||||
def onClicked(self):
|
||||
color = QColorDialog.getColor(
|
||||
self.color if self.color is not None else Qt.white, self.parent
|
||||
)
|
||||
color = QColorDialog.getColor(self.color if self.color is not None else Qt.white, self.parent)
|
||||
self.setColor(color)
|
||||
|
||||
def setColor(self, color):
|
||||
|
Loading…
x
Reference in New Issue
Block a user