diff options
author | Matthias Baumgartner <dev@igsor.net> | 2023-01-06 12:20:22 +0100 |
---|---|---|
committer | Matthias Baumgartner <dev@igsor.net> | 2023-01-06 12:20:22 +0100 |
commit | 079b4da93ea336b5bcc801cfd64c310aa7f8ddee (patch) | |
tree | 9c9a1cf7cbb9d71ba8dcce395996a1af3db790e2 /tagit/utils | |
parent | 0ba7a15c124d3a738a45247e78381dd56f7f1fa9 (diff) | |
download | tagit-079b4da93ea336b5bcc801cfd64c310aa7f8ddee.tar.gz tagit-079b4da93ea336b5bcc801cfd64c310aa7f8ddee.tar.bz2 tagit-079b4da93ea336b5bcc801cfd64c310aa7f8ddee.zip |
config early port (test still fails)
Diffstat (limited to 'tagit/utils')
-rw-r--r-- | tagit/utils/__init__.py | 1 | ||||
-rw-r--r-- | tagit/utils/errors.py | 52 | ||||
-rw-r--r-- | tagit/utils/shared.py | 63 |
3 files changed, 116 insertions, 0 deletions
diff --git a/tagit/utils/__init__.py b/tagit/utils/__init__.py index d5a8efe..d143034 100644 --- a/tagit/utils/__init__.py +++ b/tagit/utils/__init__.py @@ -9,6 +9,7 @@ import typing # inner-module imports from . import bsfs +from .shared import * # FIXME: port properly # exports __all__: typing.Sequence[str] = ( diff --git a/tagit/utils/errors.py b/tagit/utils/errors.py new file mode 100644 index 0000000..1bed670 --- /dev/null +++ b/tagit/utils/errors.py @@ -0,0 +1,52 @@ +"""Module-wide errors. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2018 +""" +# exports +__all__ = ( + 'EmptyFileError', + 'LoaderError', + 'NotAFileError', + 'ProgrammingError', + 'UserError', + 'abstract', + ) + + +## code ## + +def abstract(): + """Marks that a method has to be implemented in a child class.""" + raise NotImplementedError('abstract method that must be implemented in a subclass') + +class ProgrammingError(Exception): + """Reached a program state that shouldn't be reachable.""" + pass + +class UserError(ValueError): + """Found an illegal value that was specified directly by the user.""" + pass + +class NotAFileError(OSError): + """A file-system object is not a regular file.""" + pass + +class EmptyFileError(OSError): + """A file is unexpectedly empty.""" + pass + +class LoaderError(Exception): + """Failed to load or initialize a critical data structure.""" + pass + +class ParserFrontendError(Exception): + """Generic parser frontend error.""" + pass + +class ParserBackendError(Exception): + """Generic parser backend error.""" + pass + +## EOF ## diff --git a/tagit/utils/shared.py b/tagit/utils/shared.py new file mode 100644 index 0000000..13ffd2a --- /dev/null +++ b/tagit/utils/shared.py @@ -0,0 +1,63 @@ +# FIXME: port properly! +"""Shared functionality. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import logging +import pkgutil +import re +import typing + +# exports +__all__ = ('import_all', ) + + +## code ## + +# exports +__all__: typing.Sequence[str] = ( + 'fst', + 'is_list', + 'import_all', + ) + + +## code ## + +logger = logging.getLogger(__name__) + +fst = lambda lst: lst[0] + +def is_list(cand): + """Return true if *cand* is a list, a set, or a tuple""" + return isinstance(cand, list) or isinstance(cand, set) or isinstance(cand, tuple) + +def import_all(module, exclude=None, verbose=False): + """Recursively import all submodules of *module*. + *exclude* is a set of submodule names which will + be omitted. With *verbose*, all imports are logged + with level info. Returns all imported modules. + + >>> import tagit + >>> import_all(tagit, exclude={'tagit.shared.external'}) + + """ + exclude = set([] if exclude is None else exclude) + imports = [] + for importer, name, ispkg in pkgutil.iter_modules(module.__path__, module.__name__ + '.'): + if ispkg and all(re.match(exl, name) is None for exl in exclude): + if verbose: + logger.info(f'importing: {name}') + try: + module = __import__(name, fromlist='dummy') + imports.append(module) + imports += import_all(module, exclude, verbose) + except Exception as e: + logger.error(f'importing: {name}') + + return imports + +## EOF ## |