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()])
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
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
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)