Persisted List -------------- .. csv-table:: History :header: "Date", "Comment" :widths: 10 30 "2025-06-13", "New elements come first" "", "Copied from: `explain_java.py`_" .. _explain_java.py: explain_java.py.html#persisted-list :: from typing import List from pathlib import Path class PersistedList: """ A tiny helper that remembers a list of strings on disk. """ def __init__(self, filename: str) -> None: self.filename = Path(filename) self.names: List[str] = self._read_from_file() # ────────────────────────────────────────────────────────────── # Private helpers # ────────────────────────────────────────────────────────────── def _read_from_file(self) -> List[str]: """ Return the list stored on disk (empty if the file is missing). """ if self.filename.exists(): with self.filename.open("r", encoding="utf-8") as fh: return [line.strip() for line in fh if line.strip()] return [] def _write_to_file(self) -> None: """ Persist the current list to disk (one item per line). """ self.filename.parent.mkdir(parents=True, exist_ok=True) with self.filename.open("w", encoding="utf-8") as fh: fh.write("\n".join(self.names)) @staticmethod def _remove_strings(source: List[str], to_remove: List[str]) -> List[str]: """ Return a copy of *source* without any element that occurs in *to_remove*. """ removal_set = set(to_remove) return [s for s in source if s not in removal_set] # ────────────────────────────────────────────────────────────── # Public API # ────────────────────────────────────────────────────────────── def sort_by_pattern(self, all_names: List[str]) -> List[str]: """ Sort *all_names* so that previously‑stored names keep their old ordering, and every new name is appended alphabetically. The internal list is updated and re‑written to disk. """ priority = {name: idx for idx, name in enumerate(self.names)} sorted_names = sorted( all_names, key=lambda n: (1, priority[n]) if n in priority else (0, n) ) self.names = sorted_names self._write_to_file() return sorted_names def select(self, selected_name: str) -> None: """ Move *selected_name* to the top of the list (inserting it if it wasn’t present) and persist the change. """ self.names = self._remove_strings(self.names, [selected_name]) self.names.insert(0, selected_name) self._write_to_file() # ────────────────────────────────────────────────────────────── # Convenience # ────────────────────────────────────────────────────────────── def __iter__(self): return iter(self.names) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.filename!s}, {self.names})"