Skip to content

Commit

Permalink
🔀 Merge pull request #103 from davep/tweak-filtering
Browse files Browse the repository at this point in the history
Various filtering tweaks
  • Loading branch information
davep authored Jan 14, 2025
2 parents 54c5fa1 + af1c524 commit 6bb2246
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
17 changes: 12 additions & 5 deletions src/braindrop/app/data/raindrops.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
)
Expand Down
36 changes: 35 additions & 1 deletion tests/unit/test_raindrops.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -61,26 +62,43 @@ 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),
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)
assert len(raindrops) == len(haystack)
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."""
Expand Down Expand Up @@ -115,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

0 comments on commit 6bb2246

Please sign in to comment.