aboutsummaryrefslogtreecommitdiffstats
path: root/tagit/utils
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-01-06 12:20:22 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-01-06 12:20:22 +0100
commit079b4da93ea336b5bcc801cfd64c310aa7f8ddee (patch)
tree9c9a1cf7cbb9d71ba8dcce395996a1af3db790e2 /tagit/utils
parent0ba7a15c124d3a738a45247e78381dd56f7f1fa9 (diff)
downloadtagit-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__.py1
-rw-r--r--tagit/utils/errors.py52
-rw-r--r--tagit/utils/shared.py63
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 ##