Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error to warning #445

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/cript/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ def _init_logger(self, log_level=logging.INFO) -> None:

logger.setLevel(log_level)

# Activate Warning handling
logging.captureWarnings(True)

# Create a console handler
console_handler = logging.StreamHandler()

Expand Down
14 changes: 14 additions & 0 deletions src/cript/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,17 @@ class CRIPTException(Exception):
@abstractmethod
def __str__(self) -> str:
pass


class CRIPTWarning(Warning):
"""
Parent CRIPT warning.
All CRIPT warning inherit this class.
"""

@abstractmethod
def __str__(self) -> str:
pass

def __repr__(self):
return str(self)
32 changes: 16 additions & 16 deletions src/cript/nodes/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import List

from cript.exceptions import CRIPTException
from cript.exceptions import CRIPTException, CRIPTWarning


class CRIPTUUIDException(CRIPTException):
Expand Down Expand Up @@ -67,7 +67,7 @@ def __str__(self) -> str:
return error_message


class CRIPTMaterialIdentifierError(CRIPTException):
class CRIPTMaterialIdentifierWarning(CRIPTWarning):
"""Every material node needs to have at least one identifier set."""

def __init__(self, material_node):
Expand Down Expand Up @@ -281,14 +281,14 @@ def __str__(self):
)


class CRIPTOrphanedNodesError(CRIPTException, ABC):
class CRIPTOrphanedNodesWarning(CRIPTWarning, ABC):
"""
## Definition
This error is raised when a child node is not attached to the
appropriate parent node. For example, all material nodes used
within a project must belong to the project inventory or are explicitly listed as material of that project.
If there is a material node that is used within a project but not a part of the
inventory and the validation code finds it then it raises an `CRIPTOrphanedNodeError`
inventory and the validation code finds it then it raises an `CRIPTOrphanedNodeWarning`

## Troubleshooting
Fixing this is simple and easy, just take the node that CRIPT Python SDK
Expand All @@ -307,10 +307,10 @@ def __str__(self):
pass


class CRIPTOrphanedMaterialError(CRIPTOrphanedNodesError):
class CRIPTOrphanedMaterialWarning(CRIPTOrphanedNodesWarning):
"""
## Definition
CRIPTOrphanedNodesError, but specific for orphaned materials.
CRIPTOrphanedNodesWarning, but specific for orphaned materials.

## Troubleshooting
Handle this error by adding the orphaned materials into the parent project or its inventories.
Expand All @@ -327,10 +327,10 @@ def __str__(self):
return ret_string


class CRIPTOrphanedExperimentError(CRIPTOrphanedNodesError):
class CRIPTOrphanedExperimentWarning(CRIPTOrphanedNodesWarning):
"""
## Definition
CRIPTOrphanedNodesError, but specific for orphaned nodes that should be listed in one of the experiments.
CRIPTOrphanedNodesWarning, but specific for orphaned nodes that should be listed in one of the experiments.

## Troubleshooting
Handle this error by adding the orphaned node into one the parent project's experiments.
Expand All @@ -348,10 +348,10 @@ def __str__(self) -> str:
return ret_string


class CRIPTOrphanedDataError(CRIPTOrphanedExperimentError):
class CRIPTOrphanedDataWarning(CRIPTOrphanedExperimentWarning):
"""
## Definition
CRIPTOrphanedExperimentError, but specific for orphaned Data node that should be listed in one of the experiments.
CRIPTOrphanedExperimentWarning, but specific for orphaned Data node that should be listed in one of the experiments.

## Troubleshooting
Handle this error by adding the orphaned node into one the parent project's experiments `data` attribute.
Expand All @@ -361,10 +361,10 @@ def __init__(self, orphaned_node):
super().__init__(orphaned_node)


class CRIPTOrphanedProcessError(CRIPTOrphanedExperimentError):
class CRIPTOrphanedProcessWarning(CRIPTOrphanedExperimentWarning):
"""
## Definition
CRIPTOrphanedExperimentError, but specific for orphaned Process node that should be
CRIPTOrphanedExperimentWarning, but specific for orphaned Process node that should be
listed in one of the experiments.

## Troubleshooting
Expand All @@ -376,10 +376,10 @@ def __init__(self, orphaned_node):
super().__init__(orphaned_node)


class CRIPTOrphanedComputationError(CRIPTOrphanedExperimentError):
class CRIPTOrphanedComputationWarning(CRIPTOrphanedExperimentWarning):
"""
## Definition
CRIPTOrphanedExperimentError, but specific for orphaned Computation node that should be
CRIPTOrphanedExperimentWarning, but specific for orphaned Computation node that should be
listed in one of the experiments.

## Troubleshooting
Expand All @@ -391,10 +391,10 @@ def __init__(self, orphaned_node):
super().__init__(orphaned_node)


class CRIPTOrphanedComputationalProcessError(CRIPTOrphanedExperimentError):
class CRIPTOrphanedComputationalProcessWarning(CRIPTOrphanedExperimentWarning):
"""
## Definition
CRIPTOrphanedExperimentError, but specific for orphaned ComputationalProcess
CRIPTOrphanedExperimentWarning, but specific for orphaned ComputationalProcess
node that should be listed in one of the experiments.

## Troubleshooting
Expand Down
5 changes: 3 additions & 2 deletions src/cript/nodes/primary_nodes/material.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import warnings
from dataclasses import dataclass, field, replace
from typing import Any, List, Optional, Union

from beartype import beartype

from cript.nodes.exceptions import CRIPTMaterialIdentifierError
from cript.nodes.exceptions import CRIPTMaterialIdentifierWarning
from cript.nodes.primary_nodes.primary_base_node import PrimaryBaseNode
from cript.nodes.primary_nodes.process import Process
from cript.nodes.util.json import UIDProxy
Expand Down Expand Up @@ -218,7 +219,7 @@ def validate(self, api=None, is_patch: bool = False, force_validation: bool = Fa
and self.smiles is None
and self.vendor is None
):
raise CRIPTMaterialIdentifierError(self)
warnings.warn(CRIPTMaterialIdentifierWarning(self))

@property
@beartype
Expand Down
7 changes: 4 additions & 3 deletions src/cript/nodes/primary_nodes/project.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import warnings
from dataclasses import dataclass, field, replace
from typing import List, Optional, Union

Expand Down Expand Up @@ -106,7 +107,7 @@ def __init__(self, name: str, collection: Optional[List[Union[Collection, UIDPro
self._update_json_attrs_if_valid(new_json_attrs)

def validate(self, api=None, is_patch=False, force_validation: bool = False):
from cript.nodes.exceptions import CRIPTOrphanedMaterialError
from cript.nodes.exceptions import CRIPTOrphanedMaterialWarning
from cript.nodes.util.core import get_orphaned_experiment_exception

# First validate like other nodes
Expand All @@ -122,7 +123,7 @@ def validate(self, api=None, is_patch=False, force_validation: bool = False):
project_inventory_materials.append(material)
for material in project_graph_materials:
if material not in self.material and material not in project_inventory_materials:
raise CRIPTOrphanedMaterialError(material)
warnings.warn(CRIPTOrphanedMaterialWarning(material))

# Check graph for orphaned nodes, that should be listed in the experiments
project_experiments = self.find_children({"node": ["Experiment"]})
Expand All @@ -145,7 +146,7 @@ def validate(self, api=None, is_patch=False, force_validation: bool = False):
experiment_nodes.append(ex_node)
for node in project_graph_nodes:
if node not in experiment_nodes:
raise get_orphaned_experiment_exception(node)
warnings.warn(get_orphaned_experiment_exception(node))

@property
@beartype
Expand Down
64 changes: 34 additions & 30 deletions src/cript/nodes/util/core.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import uuid
import warnings

from cript.nodes.exceptions import (
CRIPTOrphanedComputationalProcessError,
CRIPTOrphanedComputationError,
CRIPTOrphanedDataError,
CRIPTOrphanedExperimentError,
CRIPTOrphanedMaterialError,
CRIPTOrphanedProcessError,
CRIPTOrphanedComputationalProcessWarning,
CRIPTOrphanedComputationWarning,
CRIPTOrphanedDataWarning,
CRIPTOrphanedExperimentWarning,
CRIPTOrphanedMaterialWarning,
CRIPTOrphanedProcessWarning,
)


Expand All @@ -27,25 +28,28 @@ def add_orphaned_nodes_to_project(project, active_experiment, max_iteration: int
raise RuntimeError(f"The provided active experiment {active_experiment} is not part of the project graph. Choose an active experiment that is part of a collection of this project.")

counter = 0
while True:
if counter > max_iteration >= 0:
break # Emergency stop
try:
project.validate()
except CRIPTOrphanedMaterialError as exc:
# because calling the setter calls `validate` we have to force add the material.
project._json_attrs.material.append(exc.orphaned_node)
except CRIPTOrphanedDataError as exc:
active_experiment.data += [exc.orphaned_node]
except CRIPTOrphanedProcessError as exc:
active_experiment.process += [exc.orphaned_node]
except CRIPTOrphanedComputationError as exc:
active_experiment.computation += [exc.orphaned_node]
except CRIPTOrphanedComputationalProcessError as exc:
active_experiment.computation_process += [exc.orphaned_node]
else:
break
counter += 1
# Convert Errors into exceptions, so we can catch and fix them
with warnings.catch_warnings():
warnings.simplefilter("error")
while True:
if counter > max_iteration >= 0:
break # Emergency stop
try:
project.validate()
except CRIPTOrphanedMaterialWarning as exc:
# because calling the setter calls `validate` we have to force add the material.
project._json_attrs.material.append(exc.orphaned_node)
except CRIPTOrphanedDataWarning as exc:
active_experiment.data += [exc.orphaned_node]
except CRIPTOrphanedProcessWarning as exc:
active_experiment.process += [exc.orphaned_node]
except CRIPTOrphanedComputationWarning as exc:
active_experiment.computation += [exc.orphaned_node]
except CRIPTOrphanedComputationalProcessWarning as exc:
active_experiment.computation_process += [exc.orphaned_node]
else:
break
counter += 1


def get_orphaned_experiment_exception(orphaned_node):
Expand All @@ -58,15 +62,15 @@ def get_orphaned_experiment_exception(orphaned_node):
from cript.nodes.primary_nodes.process import Process

if isinstance(orphaned_node, Data):
return CRIPTOrphanedDataError(orphaned_node)
return CRIPTOrphanedDataWarning(orphaned_node)
if isinstance(orphaned_node, Process):
return CRIPTOrphanedProcessError(orphaned_node)
return CRIPTOrphanedProcessWarning(orphaned_node)
if isinstance(orphaned_node, Computation):
return CRIPTOrphanedComputationError(orphaned_node)
return CRIPTOrphanedComputationWarning(orphaned_node)
if isinstance(orphaned_node, ComputationProcess):
return CRIPTOrphanedComputationalProcessError(orphaned_node)
return CRIPTOrphanedComputationalProcessWarning(orphaned_node)
# Base case raise the parent exception. TODO add bug warning.
return CRIPTOrphanedExperimentError(orphaned_node)
return CRIPTOrphanedExperimentWarning(orphaned_node)


def iterate_leaves(obj):
Expand Down
Loading
Loading