from abc import abstractmethod from logging import Logger from pathlib import Path from typing import Any, Final, Iterable, Iterator, Protocol, Sequence, TypeVar, overload from numpy.typing import NDArray _T = TypeVar("_T") class ProgressHandler(Protocol): @overload def wrap(self, values: Sequence[_T]) -> Iterator[_T]: ... @overload def wrap(self, values: Iterable[_T], total: int) -> Iterator[_T]: ... class FileHandler: @abstractmethod def create(self, filename: str, content: bytes, text: bool = False): ... def image(self, filename: str, image: NDArray[Any]): from io import BytesIO import imageio.v3 as iio data = iio.imwrite("", image, extension=Path(filename).suffix) # type: ignore self.create(filename, data, False) class BaseSolver: def __init__( self, logger: Logger, verbose: bool, year: int, day: int, progress: ProgressHandler, files: FileHandler | None = None, ): self.logger: Final = logger self.verbose: Final = verbose self.year: Final = year self.day: Final = day self.progress: Final = progress self.files: Final = files @abstractmethod def solve(self, input: str) -> Iterator[Any] | None: ...