From: Kyle Bowman Date: Tue, 21 Jan 2025 01:05:29 +0000 (-0500) Subject: add simple filter functionality X-Git-Url: https://git.rocketbowman.com/?a=commitdiff_plain;h=b138fc5c041cdba47660df6e72f83bd5cc9624c9;p=nom.git add simple filter functionality --- diff --git a/src/nom/base.py b/src/nom/base.py index 831a7bb..8b79976 100644 --- a/src/nom/base.py +++ b/src/nom/base.py @@ -3,9 +3,12 @@ from csv import DictReader, DictWriter, excel_tab from copy import copy from pathlib import Path from pydantic import BaseModel +from typing import Callable from nom.utils import NomError +Predicate = Callable[..., bool] + class NomListItem(BaseModel): @@ -62,23 +65,22 @@ class NomList: # NOTE: To get the interface that I want (i.e `from_csv(path)`) - # each subclass must override from_csv and pass in the constructor - # of the corresponding ListItem. For example, for EntryList: + # each subclass must override from_csv and pass in the NomListItem + # that has a to_dict() method. For example, for EntryList: # ``` # @classmethod # def from_csv(cls, path): # return super().from_csv(path, EntryListItem) # ```` @classmethod - def from_csv(cls, file: Path, constructor: NomListItem, delimiter="|"): + def from_csv(cls, file: Path, nlitem: NomListItem, delimiter="|"): items = [] dialect = excel_tab dialect.delimiter=delimiter with open(file, "r") as f: reader = DictReader(f,dialect=dialect) for row in reader: - # TODO: This should be from_dict() - item = constructor(**row) + item = nlitem.from_dict(row) items.append(item) return cls(items=set(items), delimiter=delimiter) @@ -100,4 +102,8 @@ class NomList: if not self.items: raise NomError("There are no entries to write.") for item in self.items: - print(item.to_str()) \ No newline at end of file + print(item.to_str()) + +def filter(nlist: NomList, predicate: Predicate): + items = {item for item in nlist.items if predicate(item)} + return nlist.__class__(items, delimiter=nlist.delimiter) \ No newline at end of file diff --git a/src/nom/entry.py b/src/nom/entry.py index 7116944..4fa8b94 100644 --- a/src/nom/entry.py +++ b/src/nom/entry.py @@ -12,9 +12,12 @@ class EntryListItem(NomListItem): date: str feed_url: Optional[str] = "" feed_alias: Optional[str] = "" - viewed: Optional[bool] = "False" + viewed: Optional[bool] = False summary: Optional[str] = "" # TODO: Add this when you feel like stripping HTML + def __eq__(self, other): + return self.url == other.url + def __hash__(self): return hash(self.url) diff --git a/src/nom/feed.py b/src/nom/feed.py index b4324d2..7868ba2 100644 --- a/src/nom/feed.py +++ b/src/nom/feed.py @@ -27,7 +27,7 @@ class Feed: date=e.updated, feed_url=self.url, feed_alias="no alias", - viewed="False", + #viewed=False, summary="no summary") items.append(entry) return EntryList(items=items) diff --git a/tests/test_entry.py b/tests/test_entry.py index 0317c04..97f8f5d 100644 --- a/tests/test_entry.py +++ b/tests/test_entry.py @@ -4,9 +4,11 @@ from copy import copy import pytest from nom.entry import EntryList, EntryListItem +from nom.filter import is_viewed from test_feed import feedlist + @pytest.fixture def elist_single(): path = Path(__file__).parent / "data" / "entry_single.csv" @@ -44,3 +46,9 @@ def test_elist_addition(elist_multi, elist_single): sum_ = elist_multi + elist_single assert len(sum_) == len(elist_multi) + len(elist_single) assert isinstance(sum_,EntryList) + +def test_elist_filter(elist_multi): + #viewed = filter(is_viewed, elist_multi) + from nom.base import filter + viewed=filter(elist_multi, lambda e: e.viewed) + assert len(viewed) < len(elist_multi)