]> git.rocketbowman.com Git - nom.git/commitdiff
continue abstracting list and listItem
authorKyle Bowman <kyle+github@rocketbowman.com>
Sun, 19 Jan 2025 20:34:11 +0000 (15:34 -0500)
committerKyle Bowman <kyle+github@rocketbowman.com>
Sun, 19 Jan 2025 20:34:11 +0000 (15:34 -0500)
src/nom/base.py
src/nom/entry.py
tests/data/entry.csv [new file with mode: 0644]

index 4f90a1ef153c98f7ff3d0c769f24329a98acec15..9b0ac0af4e01bb0ab07672d00a7984f5b55bf34d 100644 (file)
@@ -1,13 +1,17 @@
 from pathlib import Path
 from csv import DictReader, DictWriter, excel_tab
+from abc import abstractmethod
+from typing import Sequence
 
 from nom.utils import NomError
 
 
 class NomListItem:
     
+    @classmethod
+    def get_fieldnames(cls):
+        return cls.__dataclass_fields__.keys()
     
-    # TODO: This technically doesn't follow the __repr__ pattern.
     # TODO: What if there's a pipe in one of the fields? 
     def to_str(self, delimiter: str ='|'):
         return delimiter.join([v for v in self.__dict__.values()])
@@ -20,20 +24,49 @@ class NomListItem:
         return cls(**dct)
 
 
-# NOTE: Implementation requires self.delimiter.
 class NomList:
 
+    # TODO: 
+    def __init__(self, items=[], delimiter: str="|"):
+        self.delimiter=delimiter
+        self.items : list[NomListItem] = items
+
+    # 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:
+    # ```
+    # @classmethod
+    # def from_csv(cls, path):
+    #     return super().from_csv(path, EntryListItem)
+    # ````
     @classmethod
-    def from_csv(cls, file: Path):
-        pass
+    def from_csv(cls, file: Path, constructor: NomListItem, delimiter="|"):
+        items = []
+        dialect = excel_tab
+        dialect.delimiter=delimiter
+        with open(file, "r") as f:
+            reader = DictReader(f,dialect=dialect)
+            for row in reader:
+                item = constructor(**row)
+                items.append(item) 
+        return cls(items=items, delimiter=delimiter)
 
     def to_csv(self, file: Path):
-        if not self.dicts:
+        if not self.items:
             raise NomError("There are no entries to write.")
+        
+        fieldnames=self.items[0].get_fieldnames()
+        dialect = excel_tab
+        dialect.delimiter=self.delimiter
 
         with open(file, "w") as f:
-            dialect = excel_tab
-            dialect.delimiter=self.delimiter
-            writer = DictWriter(f, fieldnames=self.fieldnames, dialect=dialect) 
+            writer = DictWriter(f, fieldnames=fieldnames, dialect=dialect) 
             writer.writeheader()
-            writer.writerows(self.dicts)
\ No newline at end of file
+            for item in self.items:
+                writer.writerow(item.to_dict())
+    
+    def to_stdout(self):
+        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
index 4aead2754bf2b5278d5bb779b1fd10028b7c2a8e..0597a074360613c3d1bda7b60c627d88418d18c7 100644 (file)
@@ -19,17 +19,11 @@ class EntryListItem(NomListItem):
     summary: Optional[str] = "" # TODO: Add this when you feel like stripping HTML
 
 
-
 class EntryList(NomList):
 
-    def __init__(self, delimiter='|'):
-        self.entries : list[EntryListItem] = []
-        self.dicts   : list[dict] = []
-        self.delimiter = delimiter
-        self.fieldnames = EntryListItem("","").to_dict().keys()
-
-    def add_entry(self, entry):
-        self.entries.append(entry)
+    @classmethod
+    def from_csv(cls, path: Path):
+        return super().from_csv(path, EntryListItem)
 
     def update_from_feeds(self, feedlist):
         pass
@@ -40,18 +34,12 @@ class EntryList(NomList):
     def from_stdout(self):
         pass
 
-    # TODO: Fix this with command line option
-    def to_stdout(self):
-        for entry in self.entries:
-            if entry:
-                print(entry.to_str())
-
 
 if __name__ == "__main__":
     dct = dict(id_="1", title="Entry One", url="https://path/to/entry1.html")
     path=Path("/home/kyle/projects/nom/tests/data/entry.csv")
-    elist = EntryList()
-    entry = EntryListItem.from_dict(dct)
-    elist.add_entry(entry)
-    elist.dicts = [entry.__dict__ for entry in elist.entries]
-    elist.to_csv(path)
+    #elist = EntryList()
+    #entry = EntryListItem.from_dict(dct)
+    #elist.add(entry)
+    #elist.to_csv(path)
+    elist=EntryList.from_csv(path)
diff --git a/tests/data/entry.csv b/tests/data/entry.csv
new file mode 100644 (file)
index 0000000..92966eb
--- /dev/null
@@ -0,0 +1,3 @@
+id_|title|url|date|feed_url|feed_alias|viewed|summary\r
+1|Entry One|https://path/to/entry1.html|test|||False|\r
+2|Entry Two|https://path/to/entry2.html|test|||False|\r