From 6095c54b64928e76f99bda9d0ed13fa6631b6048 Mon Sep 17 00:00:00 2001 From: dgw Date: Wed, 9 Aug 2023 01:33:21 -0700 Subject: [PATCH] tools.calculation: more refined handling of unsupported node types Co-authored-by: SnoopJ --- sopel/tools/calculation.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/sopel/tools/calculation.py b/sopel/tools/calculation.py index b82225712..d59e5aebb 100644 --- a/sopel/tools/calculation.py +++ b/sopel/tools/calculation.py @@ -57,14 +57,24 @@ def _eval_node(self, node, timeout): A subclass could overwrite this to handle more nodes, calling it only for nodes it does not implement itself. """ - if ( - isinstance(node, ast.Constant) and - isinstance(node.value, (int, float)) - ): + if isinstance(node, ast.Constant): + if not isinstance(node.value, (int, float)): + raise ExpressionEvaluator.Error( + "'{}' values are not supported".format( + type(node.value).__name__, + ) + ) + return node.value - elif (isinstance(node, ast.BinOp) and - type(node.op) in self.binary_ops): + elif isinstance(node, ast.BinOp): + if type(node.op) not in self.binary_ops: + raise ExpressionEvaluator.Error( + "Unsupported binary operator '{}'".format( + type(node.op).__name__, + ) + ) + left = self._eval_node(node.left, timeout) right = self._eval_node(node.right, timeout) if time.time() > timeout: @@ -72,8 +82,14 @@ def _eval_node(self, node, timeout): "Time for evaluating expression ran out.") return self.binary_ops[type(node.op)](left, right) - elif (isinstance(node, ast.UnaryOp) and - type(node.op) in self.unary_ops): + elif isinstance(node, ast.UnaryOp): + if type(node.op) not in self.unary_ops: + raise ExpressionEvaluator.Error( + "Unsupported unary operator '{}'".format( + type(node.op).__name__, + ) + ) + operand = self._eval_node(node.operand, timeout) if time.time() > timeout: raise ExpressionEvaluator.Error( @@ -81,7 +97,10 @@ def _eval_node(self, node, timeout): return self.unary_ops[type(node.op)](operand) raise ExpressionEvaluator.Error( - "ast.Node '%s' not implemented." % (type(node).__name__,)) + "Node type '{}' is not supported.".format( + type(node).__name__, + ) + ) def guarded_mul(left, right):