Source code for f3dasm_optimize._src._imports

"""Classes that manage importing and exceptions of submodules with extension.
This code was adapted from Optuna
(https://github.com/optuna/optuna/blob/master/optuna/_imports.py)
and modified to fit the specific case of f3dasm.
"""

#                                                                       Modules
# =============================================================================

# Standard
from types import TracebackType
from typing import Optional, Tuple, Type

#                                                          Authorship & Credits
# =============================================================================
__author__ = 'Martin van der Schelling (M.P.vanderSchelling@tudelft.nl)'
__credits__ = ['Martin van der Schelling', 'Optuna']
__status__ = 'Stable'
# =============================================================================
#
# =============================================================================


class _DeferredImportExceptionContextManager:
    """Context manager to defer exceptions from imports.

    Catches :exc:`ImportError` and :exc:`SyntaxError`.
    If any exception is caught, this class raises an :exc:`ImportError`
    when being checked.

    """

    def __init__(self) -> None:
        self._deferred: Optional[Tuple[Exception, str]] = None

    def __enter__(self) -> "_DeferredImportExceptionContextManager":
        """Enter the context manager.

        Returns:
            Itself.

        """
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[Exception]],
        exc_value: Optional[Exception],
        traceback: Optional[TracebackType],
    ) -> Optional[bool]:
        """Exit the context manager.

        Args:
            exc_type:
                Raised exception type. :obj:`None` if nothing is raised.
            exc_value:
                Raised exception object. :obj:`None` if nothing is raised.
            traceback:
                Associated traceback. :obj:`None` if nothing is raised.

        Returns:
            :obj:`None` if nothing is deferred, otherwise :obj:`True`.
            :obj:`True` will suppress any exceptions avoiding
            them from propagating.

        """
        if isinstance(exc_value, (ImportError, SyntaxError)):
            if isinstance(exc_value, ImportError):
                message = (
                    f"Tried to import '{exc_value.name}' but failed. \
                        Please make sure that you have "
                    f"installed the required package correctly to use \
                        this optimizer. "
                    f"Actual error: {exc_value}."
                )
            elif isinstance(exc_value, SyntaxError):
                message = (
                    f"Tried to import a package but failed due to a \
                        syntax error in {exc_value.filename}. Please "
                    f"make sure that the Python version is correct \
                        to use this optimizer. Actual "
                    f"error: {exc_value}."
                )
            else:
                assert False

            self._deferred = (exc_value, message)
            return True
        return None

    def is_successful(self) -> bool:
        """Return whether the context manager has caught any exceptions.

        Returns:
            :obj:`True` if no exceptions are caught, :obj:`False` otherwise.

        """
        return self._deferred is None

    def check(self) -> None:
        """Check whether the context manager has caught any exceptions.

        Raises:
            :exc:`ImportError`:
                If any exception was caught from the caught exception.

        """
        if self._deferred is not None:
            exc_value, message = self._deferred
            raise ImportError(message) from exc_value


[docs]def try_import() -> _DeferredImportExceptionContextManager: """Create a context manager that can wrap imports of optional packages to defer exceptions. Args: Extension name for this particular context manager Returns: Deferred import context manager. """ return _DeferredImportExceptionContextManager()