diff --git a/cognite/neat/_session/_base.py b/cognite/neat/_session/_base.py index bdc62522e..3f2fa086a 100644 --- a/cognite/neat/_session/_base.py +++ b/cognite/neat/_session/_base.py @@ -16,8 +16,10 @@ from ._read import ReadAPI from ._state import SessionState from ._to import ToAPI +from .exceptions import intercept_session_exceptions +@intercept_session_exceptions class NeatSession: def __init__( self, diff --git a/cognite/neat/_session/_state.py b/cognite/neat/_session/_state.py index af4799c23..5f68ab8a3 100644 --- a/cognite/neat/_session/_state.py +++ b/cognite/neat/_session/_state.py @@ -7,6 +7,8 @@ from cognite.neat._rules.models.information._rules_input import InformationInputRules from cognite.neat._store import NeatGraphStore +from .exceptions import NeatSessionError + @dataclass class SessionState: @@ -27,7 +29,7 @@ def store(self) -> NeatGraphStore: @property def input_rule(self) -> ReadRules: if not self.input_rules: - raise ValueError("No input rules provided") + raise NeatSessionError("No input data model available. Try using [bold].read[/bold] to load a data model.") return self.input_rules[-1] @property @@ -41,7 +43,9 @@ def information_input_rule(self) -> ReadRules | None: @property def last_verified_rule(self) -> VerifiedRules: if not self.verified_rules: - raise ValueError("No verified rules provided") + raise NeatSessionError( + "No data model available to verify. Try using [bold].read[/bold] to load a data model." + ) return self.verified_rules[-1] @property diff --git a/cognite/neat/_session/exceptions.py b/cognite/neat/_session/exceptions.py new file mode 100644 index 000000000..fecfba45e --- /dev/null +++ b/cognite/neat/_session/exceptions.py @@ -0,0 +1,42 @@ +import functools +from collections.abc import Callable +from typing import Any + +try: + from rich import print + + _PREFIX = "[bold red][ERROR][/bold red]" +except ImportError: + _PREFIX = "[ERROR]" + + +class NeatSessionError(Exception): + """Base class for all exceptions raised by the NeatSession class.""" + + ... + + +def _intercept_session_exceptions(func: Callable): + @functools.wraps(func) + def wrapper(*args: Any, **kwargs: Any): + try: + return func(*args, **kwargs) + except NeatSessionError as e: + action = func.__name__ + print(f"{_PREFIX} Cannot {action}: {e}") + + return wrapper + + +def intercept_session_exceptions(cls: type): + to_check = [cls] + while to_check: + cls = to_check.pop() + for attr_name in dir(cls): + if not attr_name.startswith("_"): + attr = getattr(cls, attr_name) + if callable(attr): + setattr(cls, attr_name, _intercept_session_exceptions(attr)) + elif isinstance(attr, type): + to_check.append(attr) + return cls diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9984cb2a6..a568a7e44 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -29,6 +29,7 @@ Changes are grouped as follows: - Transformation is now generated for every RDF based rules importer ### Added +- Added `NeatSession` - Rules exporter that produces a spreadsheet template for instance creation based on definition of classes in the rules - Rules transformer which converts information rules entities to be DMS compliant - Rules transformer `RuleMapping` that maps rules from one data model to another @@ -43,7 +44,7 @@ Changes are grouped as follows: - Required `env_file_name` explicitly set in the `get_cognite_client` function. This is to avoid loading the wrong environment file by accident when running the function in a notebook. - `NeatIssue` are no longer immutable. This is to comply with the expectation of Exceptions in Python. - +- [BREAKING] All `NEAT` former public methods are now private. Only `NeatSession` is public. ## [0.92.3] - 17-09-24 ### Fixed