From 4288ae36ef6fd1ed62df56ab73ae90c7c51d174d Mon Sep 17 00:00:00 2001 From: Jeremy Kubica <104161096+jeremykubica@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:19:09 -0500 Subject: [PATCH 1/3] Add some basic logging for errors in math node --- src/tdastro/math_nodes/basic_math_node.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/tdastro/math_nodes/basic_math_node.py b/src/tdastro/math_nodes/basic_math_node.py index 55c40e8..5fe9059 100644 --- a/src/tdastro/math_nodes/basic_math_node.py +++ b/src/tdastro/math_nodes/basic_math_node.py @@ -5,6 +5,7 @@ """ import ast +import logging # Disable unused import because we need all of these imported # so they can be used during evaluation of the node. @@ -15,6 +16,8 @@ from tdastro.base_models import FunctionNode +logger = logging.getLogger(__name__) + class BasicMathNode(FunctionNode): """A node that evaluates basic mathematical functions. @@ -125,7 +128,16 @@ def __init__(self, expression, backend="numpy", node_label=None, **kwargs): # Create a function from the expression. Note the expression has # already been sanitized and validated via _prepare(). def eval_func(**kwargs): - return eval(self.expression, globals(), kwargs) + try: + return eval(self.expression, globals(), kwargs) + except Exception as problem: + # Provide more detailed logging, including the expression and parameters + # used, when we encounter a math error like divide by zero. + logger.error( + f"{type(problem)} encountered during operation: {self.expression}\n" + f"with arguments={kwargs}" + ) + raise problem super().__init__(eval_func, node_label=node_label, **kwargs) From 0ef5212885be356e8d6cbb93fa4e228763d8f5da Mon Sep 17 00:00:00 2001 From: Jeremy Kubica <104161096+jeremykubica@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:06:43 -0500 Subject: [PATCH 2/3] Add the debugging information to the exception --- src/tdastro/math_nodes/basic_math_node.py | 7 ++----- tests/tdastro/math_nodes/test_basic_math_node.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/tdastro/math_nodes/basic_math_node.py b/src/tdastro/math_nodes/basic_math_node.py index 5fe9059..899b2d0 100644 --- a/src/tdastro/math_nodes/basic_math_node.py +++ b/src/tdastro/math_nodes/basic_math_node.py @@ -133,11 +133,8 @@ def eval_func(**kwargs): except Exception as problem: # Provide more detailed logging, including the expression and parameters # used, when we encounter a math error like divide by zero. - logger.error( - f"{type(problem)} encountered during operation: {self.expression}\n" - f"with arguments={kwargs}" - ) - raise problem + new_message = f"Error during math operation '{self.expression}' with args={kwargs}" + raise type(problem)(new_message) from problem super().__init__(eval_func, node_label=node_label, **kwargs) diff --git a/tests/tdastro/math_nodes/test_basic_math_node.py b/tests/tdastro/math_nodes/test_basic_math_node.py index 8e5b36e..c753a0a 100644 --- a/tests/tdastro/math_nodes/test_basic_math_node.py +++ b/tests/tdastro/math_nodes/test_basic_math_node.py @@ -63,6 +63,22 @@ def test_basic_math_node_fail(): _ = BasicMathNode("x + y", x=1.0) +@pytest.mark.filterwarnings("ignore::RuntimeWarning") +def test_basic_math_node_error(): + """Test that we augment the error with information about the expression and parameters.""" + node = BasicMathNode("y / x", x=0.0, y=1.0) + try: + node.sample_parameters() + except ZeroDivisionError as err: + assert str(err) == "Error during math operation 'y / x' with args={'x': 0.0, 'y': 1.0}" + + node = BasicMathNode("sqrt(x)", x=-10.0) + try: + node.sample_parameters() + except ValueError as err: + assert str(err) == "Error during math operation 'np.sqrt(x)' with args={'x': -10.0}" + + def test_basic_math_node_numpy(): """Test that we can perform computations via a BasicMathNode.""" node_a = SingleVariableNode("a", 10.0) From 901a97fbe2f7c00066c0fcf19be71f7a5e20d522 Mon Sep 17 00:00:00 2001 From: Jeremy Kubica <104161096+jeremykubica@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:08:11 -0500 Subject: [PATCH 3/3] Remove unneeded logger --- src/tdastro/math_nodes/basic_math_node.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tdastro/math_nodes/basic_math_node.py b/src/tdastro/math_nodes/basic_math_node.py index 899b2d0..f05b0d9 100644 --- a/src/tdastro/math_nodes/basic_math_node.py +++ b/src/tdastro/math_nodes/basic_math_node.py @@ -5,7 +5,6 @@ """ import ast -import logging # Disable unused import because we need all of these imported # so they can be used during evaluation of the node. @@ -16,8 +15,6 @@ from tdastro.base_models import FunctionNode -logger = logging.getLogger(__name__) - class BasicMathNode(FunctionNode): """A node that evaluates basic mathematical functions.