diff --git a/core/prioritize.py b/core/prioritize.py index b5be1a46..265cb284 100644 --- a/core/prioritize.py +++ b/core/prioritize.py @@ -24,19 +24,11 @@ class CriterionCategory: def format_criterion_value(self, value): return value - #--- Public def sort_key(self, dupe, crit_value): - # Use this sort key when the order in the list depends on whether or not the dupe meets the - # criteria. If it does, we return 0 (top of the list), if it doesn't, we return 1. - if self.extract_value(dupe) == crit_value: - return 0 - else: - return 1 + raise NotImplementedError() def criteria_list(self): - dupes = flatten(g[:] for g in self.results.groups) - values = dedupe(self.extract_value(d) for d in dupes) - return [Criterion(self, value) for value in values] + raise NotImplementedError() class Criterion: def __init__(self, category, value): @@ -52,13 +44,31 @@ class Criterion: return "{} ({})".format(self.category.NAME, self.display_value) -class KindCategory(CriterionCategory): +class ValueListCategory(CriterionCategory): + def sort_key(self, dupe, crit_value): + # Use this sort key when the order in the list depends on whether or not the dupe meets the + # criteria. If it does, we return 0 (top of the list), if it doesn't, we return 1. + if self.extract_value(dupe) == crit_value: + return 0 + else: + return 1 + + def criteria_list(self): + dupes = flatten(g[:] for g in self.results.groups) + values = sorted(dedupe(self.extract_value(d) for d in dupes)) + return [Criterion(self, value) for value in values] + + +class KindCategory(ValueListCategory): NAME = coltr("Kind") def extract_value(self, dupe): - return dupe.extension + value = dupe.extension + if not value: + value = tr("None") + return value -class FolderCategory(CriterionCategory): +class FolderCategory(ValueListCategory): NAME = coltr("Folder") def extract_value(self, dupe): @@ -66,6 +76,13 @@ class FolderCategory(CriterionCategory): def format_criterion_value(self, value): return str(value) + + def sort_key(self, dupe, crit_value): + value = self.extract_value(dupe) + if value[:len(crit_value)] == crit_value: + return 0 + else: + return 1 class FilenameCategory(CriterionCategory): NAME = coltr("Filename") diff --git a/core/tests/prioritize_test.py b/core/tests/prioritize_test.py index b421c36e..bfa4b64d 100644 --- a/core/tests/prioritize_test.py +++ b/core/tests/prioritize_test.py @@ -137,3 +137,39 @@ def test_filename_reprioritization(app): app.add_pri_criterion("Filename", 0) # Ends with a number app.pdialog.perform_reprioritization() eq_(app.rtable[0].data[0], 'foo1.ext') + +#--- +def app_with_subfolders(): + dupes = [ + [ + no('foo1', folder='baz'), + no('foo2', folder='foo/bar'), + ], + [ + no('foo3', folder='baz'), + no('foo4', folder='foo'), + ], + ] + return app_with_dupes(dupes) + +@with_app(app_with_subfolders) +def test_folder_crit_is_sorted(app): + # Folder subcriteria are sorted. + app.select_pri_criterion("Folder") + eq_(app.pdialog.criteria_list[:], ['baz', 'foo', 'foo/bar']) + +@with_app(app_with_subfolders) +def test_folder_crit_includes_subfolders(app): + # When selecting a folder crit, dupes in a subfolder are also considered as affected by that + # crit. + app.add_pri_criterion("Folder", 1) # foo + app.pdialog.perform_reprioritization() + # Both foo and foo/bar dupes will be prioritized + eq_(app.rtable[0].data[0], 'foo2') + eq_(app.rtable[2].data[0], 'foo4') + +@with_app(app_with_subfolders) +def test_display_something_on_empty_extensions(app): + # When there's no extension, display "None" instead of nothing at all. + app.select_pri_criterion("Kind") + eq_(app.pdialog.criteria_list[:], ['None'])