aboutsummaryrefslogtreecommitdiffstats
path: root/src/bbss/lists.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/bbss/lists.py')
-rw-r--r--src/bbss/lists.py73
1 files changed, 41 insertions, 32 deletions
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"]