From 502f40143cfa33b4fd66cb08735817f9270d3f04 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Tue, 14 Jan 2025 08:38:38 +0000 Subject: [PATCH 1/5] :hammer: Tidy up the filtering code --- src/braindrop/app/data/raindrops.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/braindrop/app/data/raindrops.py b/src/braindrop/app/data/raindrops.py index 6f6454d..7180efc 100644 --- a/src/braindrop/app/data/raindrops.py +++ b/src/braindrop/app/data/raindrops.py @@ -8,7 +8,7 @@ # Python imports. from dataclasses import dataclass from functools import total_ordering -from typing import Callable, Counter, Iterable, Iterator +from typing import Callable, Counter, Iterable, Iterator, TypeAlias ############################################################################## # Typing extension imports. @@ -84,14 +84,21 @@ def __eq__(self, value: object, /) -> bool: raise NotImplementedError +############################################################################## +Filters: TypeAlias = tuple["Filter", ...] +"""The type of a collection of filters.""" + + ############################################################################## class Filter: """Base class for the raindrop filters.""" - def __rand__(self, raindrop: Raindrop) -> bool: - del raindrop + def __rand__(self, _: Raindrop) -> bool: return False + def __radd__(self, filters: Filters) -> Filters: + return (*filters, self) + def __eq__(self, value: object) -> bool: if isinstance(value, Filter): return False @@ -175,7 +182,7 @@ def __init__( self, title: str = "", raindrops: Iterable[Raindrop] | None = None, - filters: tuple[Filter, ...] | None = None, + filters: Filters | None = None, source: Raindrops | None = None, root_collection: Collection | None = None, ) -> None: @@ -336,7 +343,7 @@ def __and__(self, new_filter: Filter) -> Raindrops: return Raindrops( self.title, (raindrop for raindrop in self if raindrop & new_filter), - (*self._filters, new_filter), + self._filters + new_filter, self._source, self._root_collection, ) From 1d6859c23a1e817ea0f2fdf84a2adc19e07d473d Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Tue, 14 Jan 2025 08:39:58 +0000 Subject: [PATCH 2/5] :pencil: Fix a typo --- tests/unit/test_raindrops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_raindrops.py b/tests/unit/test_raindrops.py index d9960a7..b552530 100644 --- a/tests/unit/test_raindrops.py +++ b/tests/unit/test_raindrops.py @@ -61,7 +61,7 @@ def test_filter_with_tags() -> None: ############################################################################## def test_filter_with_text() -> None: - """Applying a test filter should have the expected result.""" + """Applying a text filter should have the expected result.""" needle = "needle" find_these = [ Raindrop(title=needle), From 100ad5250a27ba6dba3e48c3e874d11c463c7d74 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Tue, 14 Jan 2025 08:43:08 +0000 Subject: [PATCH 3/5] :white_check_mark: Add some testing for filtering for raindrop type See #101. --- tests/unit/test_raindrops.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/unit/test_raindrops.py b/tests/unit/test_raindrops.py index b552530..ea83aee 100644 --- a/tests/unit/test_raindrops.py +++ b/tests/unit/test_raindrops.py @@ -81,6 +81,19 @@ def test_filter_with_text() -> None: assert list(raindrops.containing(needle)) == find_these +############################################################################## +def test_filter_with_type() -> None: + """Applying a type filter should have the expected result.""" + raindrop_a = Raindrop(type="article") + raindrop_b = Raindrop(type="link") + raindrops = Raindrops(raindrops=[raindrop_a, raindrop_b]) + assert len(raindrops) == 2 + assert len(raindrops.of_type("article")) == 1 + assert next(iter(raindrops.of_type("article"))) == raindrop_a + assert len(raindrops.of_type("link")) == 1 + assert next(iter(raindrops.of_type("link"))) == raindrop_b + + ############################################################################## def test_unfiltering() -> None: """We should be able to unfilter a Raidrops.""" From fdce085de163460004f4d1ec73c5a97c57cceda0 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Tue, 14 Jan 2025 08:45:18 +0000 Subject: [PATCH 4/5] :rotating_light: Add link and domain to the text filtering test --- tests/unit/test_raindrops.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/test_raindrops.py b/tests/unit/test_raindrops.py index ea83aee..4209a3c 100644 --- a/tests/unit/test_raindrops.py +++ b/tests/unit/test_raindrops.py @@ -68,12 +68,16 @@ def test_filter_with_text() -> None: Raindrop(excerpt=needle), Raindrop(note=needle), Raindrop(tags=[Tag(needle)]), + Raindrop(link=needle), + Raindrop(domain=needle), ] not_these = [ Raindrop(title="title"), Raindrop(excerpt="excerpt"), Raindrop(note="note"), Raindrop(tags=[Tag("tag")]), + Raindrop(link="link"), + Raindrop(domain="domain"), ] haystack = find_these + not_these raindrops = Raindrops(raindrops=haystack) From af1c5248c196c6b9adf23e7901fbc8e84fd43503 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Tue, 14 Jan 2025 08:54:32 +0000 Subject: [PATCH 5/5] :white_check_mark: Add a test for managing raindrops filters --- tests/unit/test_raindrops.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/test_raindrops.py b/tests/unit/test_raindrops.py index 4209a3c..b75c719 100644 --- a/tests/unit/test_raindrops.py +++ b/tests/unit/test_raindrops.py @@ -3,6 +3,7 @@ ############################################################################## # Local imports. from braindrop.app.data import Raindrops, TagCount +from braindrop.app.data.raindrops import Filters from braindrop.raindrop import Raindrop, Tag @@ -132,4 +133,20 @@ def test_raindrop_in_raindrops() -> None: assert raindrop not in is_not_in +############################################################################## +def test_filters() -> None: + """We should be able to create a collection of filters.""" + text_filter = Raindrops.Containing("test") + type_filter = Raindrops.IsOfType("link") + tag_filter = Raindrops.Tagged("tag") + filters: Filters = () + filters += text_filter + assert len(filters) == 1 + filters += type_filter + assert len(filters) == 2 + filters += tag_filter + assert len(filters) == 3 + assert filters == (text_filter, type_filter, tag_filter) + + ### test_raindrops.py ends here