From 646d743dce4a3704febfa28be3abce405823baef Mon Sep 17 00:00:00 2001 From: alyx Date: Sat, 25 Nov 2023 13:25:26 -0500 Subject: Modelling, guts basically done. --- src/bbss/lists.py | 73 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'src/bbss/lists.py') diff --git a/src/bbss/lists.py b/src/bbss/lists.py index 234d0f8..ba6955a 100644 --- a/src/bbss/lists.py +++ b/src/bbss/lists.py @@ -1,45 +1,54 @@ from dataclasses import dataclass -from collections.abc import Iterable, Iterator -from typing import Optional +from collections.abc import Iterable, Iterator, Sequence +from typing import Optional, overload, List, Callable, TypeVar, Self import requests +T = TypeVar('T') +def parse_listfile(contents: str, ctor: Callable[[str, Optional[str]], T]) -> List[T]: + acc = [] + comment_acc = "" + for line in contents.splitlines(): + if line.startswith("#"): + continue + elif line.startswith("##"): + comment_acc += line[2:].strip() + else: + acc.append(ctor(line, comment_acc if comment_acc else None)) + return acc + @dataclass(frozen=True) class ListFileEntry: entry: str comment: Optional[str] -class ListFileIterator(Iterator[ListFileEntry]): - def __init__(self, entries: list[ListFileEntry]): - self._entries = entries - self.index = -1 - def __next__(self) -> ListFileEntry: - if self.index == len(self._entries): - raise StopIteration - self.index += 1 - return self._entries[self.index] - -@dataclass(frozen=True) -class ListFile(Iterable[ListFileEntry]): +L = TypeVar('L', bound=ListFileEntry) +class BaseListFile(Sequence[L]): def __init__(self, contents: str): - self._contents = contents - acc = [] - comment_acc = "" - for line in contents.splitlines(): - if line.startswith("#"): - continue - elif line.startswith("##"): - comment_acc += line[2:].strip() - else: - acc.append(ListFileEntry(comment = comment_acc if comment_acc else None, entry = line)) - - self._entries = acc + self._contents: str = contents + self._entries: List[L] = [] - def __iter__(self) -> ListFileIterator: - return ListFileIterator(self._entries) + @overload + def __getitem__(self, key: int) -> L: + pass + @overload + def __getitem__(self, key: slice) -> Sequence[L]: + pass + def __getitem__(self, key): + return self._entries[key] - def entries(self) -> list[ListFileEntry]: - return self._entries + def __len__(self) -> int: + return self._entries.__len__() @classmethod - def from_url(cls, url: str): - return cls(requests.get(url, stream = False).text) + def from_url(cls, url: str) -> Optional[Self]: + req = requests.get(url, stream = False) + if not req.ok: + return None + return cls(req.text) + +class ListFile(BaseListFile[ListFileEntry]): + def __init__(self, contents: str): + super().__init__(contents) + self._entries = parse_listfile(contents, ListFileEntry) + +__all__ = ["parse_listfile", "ListFileEntry", "BaseListFile", "ListFIle"] -- cgit v1.2.3-54-g00ecf