""" Part of the bsie module. A copy of the license is provided with the project. Author: Matthias Baumgartner, 2022 """ # standard imports import logging import typing # bsie imports from bsie.utils import bsfs, errors # inner-module imports from . import base from . import builder # exports __all__: typing.Sequence[str] = ( 'ReaderChain', ) ## code ## logger = logging.getLogger(__name__) # Content type. T_CONTENT = typing.TypeVar('T_CONTENT') # pylint: disable=invalid-name class ReaderChain(base.Reader, typing.Generic[T_CONTENT]): """Read an image.""" # sub-readers for specific file formats. _children: typing.Tuple[base.Reader, ...] def __init__( self, subreader_names: typing.Iterable[str], cfg: typing.Optional[typing.Any] = None, ): rbuild = builder.ReaderBuilder(cfg) children = [] for name in subreader_names: try: # build sub-reader children.append(rbuild.build(name)) except (ValueError, TypeError, errors.LoaderError, errors.BuilderError) as err: # failed to build a child; skip and notify logger.warning('failed to load reader: %s', err) if len(children) == 0: logger.warning('%s failed to load any sub-readers.', bsfs.typename(self)) # copy children to member self._children = tuple(children) def __str__(self) -> str: substr = ', '.join(str(child) for child in self._children) return f'{bsfs.typename(self)}({substr})' def __repr__(self) -> str: return f'{bsfs.typename(self)}({self._children})' def __eq__(self, other: typing.Any) -> bool: return super().__eq__(other) \ and self._children == other._children def __hash__(self) -> int: return hash((super().__hash__(), self._children)) def __call__(self, path: str) -> T_CONTENT: raise_error = errors.UnsupportedFileFormatError for child in self._children: try: return child(path) except errors.UnsupportedFileFormatError: pass except errors.ReaderError: # child cannot read the file, skip. raise_error = errors.ReaderError # type: ignore [assignment] # mypy is confused raise raise_error(path) ## EOF ##