From 17f03ae3d3dc53fe973f37fe4dea4a831b4f97d7 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 24 Dec 2022 16:06:16 +0100 Subject: ReaderChain and image reader --- bsie/reader/chain.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 bsie/reader/chain.py (limited to 'bsie/reader/chain.py') diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py new file mode 100644 index 0000000..8e900e1 --- /dev/null +++ b/bsie/reader/chain.py @@ -0,0 +1,85 @@ +""" + +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.Any, + ): + 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: + for child in self._children: + try: + return child(path) + except errors.ReaderError: + # child cannot read the file, skip. + pass + + raise errors.ReaderError(path) + +## EOF ## -- cgit v1.2.3 From afd165000c1661a9cca117a4844ad3f89d926fdb Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Mon, 16 Jan 2023 20:53:39 +0100 Subject: unsupported file format exception --- bsie/reader/chain.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'bsie/reader/chain.py') diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py index 8e900e1..db7c2d5 100644 --- a/bsie/reader/chain.py +++ b/bsie/reader/chain.py @@ -73,13 +73,16 @@ class ReaderChain(base.Reader, typing.Generic[T_CONTENT]): 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. - pass + raise_error = errors.ReaderError # type: ignore [assignment] # mypy is confused - raise errors.ReaderError(path) + raise raise_error(path) ## EOF ## -- cgit v1.2.3 From 8439089807bbad92e95ad9062dc74c3d71f5d7eb Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Mon, 16 Jan 2023 21:35:19 +0100 Subject: ReaderBuilder optional config --- bsie/reader/chain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bsie/reader/chain.py') diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py index db7c2d5..5e9e0d5 100644 --- a/bsie/reader/chain.py +++ b/bsie/reader/chain.py @@ -37,7 +37,7 @@ class ReaderChain(base.Reader, typing.Generic[T_CONTENT]): def __init__( self, subreader_names: typing.Iterable[str], - cfg: typing.Any, + cfg: typing.Optional[typing.Any] = None, ): rbuild = builder.ReaderBuilder(cfg) children = [] -- cgit v1.2.3 From 0d0144466919cfb168e75c2af26d5cb74e10bfa0 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 8 Feb 2023 19:24:37 +0100 Subject: minor cleanup --- bsie/reader/chain.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'bsie/reader/chain.py') diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py index 5e9e0d5..1dbc52b 100644 --- a/bsie/reader/chain.py +++ b/bsie/reader/chain.py @@ -73,16 +73,19 @@ class ReaderChain(base.Reader, typing.Generic[T_CONTENT]): return hash((super().__hash__(), self._children)) def __call__(self, path: str) -> T_CONTENT: - raise_error = errors.UnsupportedFileFormatError + raise_error = False for child in self._children: try: return child(path) except errors.UnsupportedFileFormatError: + # child cannot read the file, skip. pass except errors.ReaderError: - # child cannot read the file, skip. - raise_error = errors.ReaderError # type: ignore [assignment] # mypy is confused + # child failed to read the file, skip. + raise_error = True - raise raise_error(path) + if raise_error: + raise errors.ReaderError(path) + raise errors.UnsupportedFileFormatError(path) ## EOF ## -- cgit v1.2.3 From 4b5c4d486bb4f0f4da2e25ad464e8336a781cdcb Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 1 Mar 2023 22:31:03 +0100 Subject: removed module header stubs --- bsie/reader/chain.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'bsie/reader/chain.py') diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py index 1dbc52b..79b44b4 100644 --- a/bsie/reader/chain.py +++ b/bsie/reader/chain.py @@ -1,9 +1,4 @@ -""" -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 -- cgit v1.2.3