Source code for fgen_runtime.exceptions

"""
Exception classes for wrapper-specific errors
"""
from __future__ import annotations

from typing import Any, Callable, Optional

from numpy.typing import NDArray


[docs]class WrapperError(ValueError): """ Base exception for errors that arise from wrapper """
[docs]class WrapperErrorUnknownCause(WrapperError): """ Raised when there is an error with the wrapper, but we have nothing to help debug """ def __init__(self, msg: str): suffix = "Underlying reason unknown" error_msg = f"{msg}. {suffix}." super().__init__(error_msg)
[docs]class InitialisationError(WrapperError): """ Raised when the wrapper around the Fortran module hasn't been initialised yet """ def __init__(self, instance: Any, method: Optional[Callable[..., Any]] = None): if method: error_msg = f"{instance} must be initialised before {method} is called" else: error_msg = f"instance ({instance:r}) is not initialized yet" super().__init__(error_msg)
[docs]class CompiledExtensionNotFoundError(ImportError): """ Raised when a compiled extension can't be import i.e. found """ def __init__(self, compiled_extension_name: str): error_msg = f"Could not find compiled extension {compiled_extension_name!r}" super().__init__(error_msg)
[docs]class BadPointerError(ValueError): """ Raised when a pointer has a value we know is wrong """ def __init__(self, pointer_value: Any, extra_info: str): error_msg = ( f"The array pointer value is wrong ({pointer_value=}). " f"{extra_info}. " "Further underlying reason for the error is unknown." ) super().__init__(error_msg)
[docs]class PointerArrayConversionError(ValueError): """ Raised when we know a pointer has been incorrectly converted to an array """ def __init__( self, array: NDArray[Any], ptr: int, expected_array_interface_data: tuple[int, bool], ): error_msg = ( "The array pointer has been incorrectly converted to an numpy array. " f"We received {array.__array_interface__['data']=}. " f"The expected value is {expected_array_interface_data}. " f"Full context: {ptr=} {array.__array_interface__=}" ) super().__init__(error_msg)
[docs]class UnallocatedMemoryError(ValueError): """ Raised when we try to allocate memory that has not yet been allocated We can't always catch this error, but this is what we raise when we can. """ def __init__(self, variable_name: str): error_msg = ( f"The memory required to access ``{variable_name}`` is unallocated. " "You must allocate it before trying to access its value. " "Unfortunately, we cannot provide more information " "about why this memory is not yet allocated." ) super().__init__(error_msg)
[docs]class RelativePythonModuleNotFoundError(ImportError): """ Raised when a Python import configured by fgen fails """ def __init__( self, requesting_python_module: str, requested: str, requested_from_python_module: str, ): """ Initialise Parameters ---------- requesting_python_module The Python module in which the ``import`` statement appears requested The thing that is being requested e.g. ``HelpfulType`` requested_from_python_module The Python module from which ``requested`` is being imported e.g. ``source_module`` in ``from source_module import HelpfulType`` """ error_msg = ( "There is something wrong with your fgen configuration for " f"{requesting_python_module!r}. " "Somewhere (likely in the `.yaml` file which is used to generate " f"{requesting_python_module!r} with fgen) you are specifying that " f"{requested!r} can be imported from " f"{requested_from_python_module!r}, but this is failing." ) super().__init__(error_msg)
[docs]class SolveError(ValueError): """ Exception raised when an solver can't solve For example, because the integration has a runaway effect in it """