From fc9d35b4c00d9c8659a25ff78ee4ccfae74fcc10 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Fri, 29 Dec 2023 14:11:17 +0200 Subject: [PATCH 1/2] Add InvalidAttribute exception subclass; add test for Nones --- leval/excs.py | 4 ++++ leval/utils.py | 9 +++++++-- leval_tests/test_leval.py | 4 +++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/leval/excs.py b/leval/excs.py index 2e13b38..9a0773b 100644 --- a/leval/excs.py +++ b/leval/excs.py @@ -29,6 +29,10 @@ class InvalidOperands(InvalidOperation): pass +class InvalidAttribute(InvalidOperation): + pass + + class NoSuchValue(NameError, EvaluatorError): pass diff --git a/leval/utils.py b/leval/utils.py index 8e94da4..94452a0 100644 --- a/leval/utils.py +++ b/leval/utils.py @@ -1,7 +1,7 @@ import ast from typing import Tuple -from leval.excs import InvalidOperation +from leval.excs import InvalidAttribute def expand_name(node: ast.Attribute) -> Tuple[str, ...]: @@ -18,8 +18,13 @@ def walk_attr(kid): walk_attr(kid.value) elif isinstance(kid, ast.Name): attr_bits.append(kid.id) + elif isinstance(kid, ast.Constant): + raise InvalidAttribute( + f"Accessing attributes of constants ({kid}) is not allowed", + node=node, + ) else: - raise InvalidOperation( # pragma: no cover + raise InvalidAttribute( # pragma: no cover f"Unsupported attribute structure in {node}", node=node, ) diff --git a/leval_tests/test_leval.py b/leval_tests/test_leval.py index 60f5ced..d071370 100644 --- a/leval_tests/test_leval.py +++ b/leval_tests/test_leval.py @@ -5,6 +5,7 @@ from leval.evaluator import Evaluator from leval.excs import ( + InvalidAttribute, InvalidOperands, InvalidOperation, NoSuchFunction, @@ -81,7 +82,8 @@ ), ("Can't access weird methods off valid names", "abs.__class__", NoSuchValue), ("Arbitrary Python code is not allowed", "if x > a:\n hello()", SyntaxError), - ("Can't access attributes off constants", "(3).__class__", InvalidOperation), + ("Can't access numeric constants' attributes", "(3).__class__", InvalidAttribute), + ("Can't access Nones' attributes", "None.__class__", InvalidAttribute), ( "Walruses aren't allowed", "(a := 3) + 8", From bf0a746794a009320f2a095d5e41e39fd5346c7a Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Fri, 29 Dec 2023 14:24:47 +0200 Subject: [PATCH 2/2] Note that False and True are implicitly allowed; add test --- leval/evaluator.py | 7 ++++++- leval_tests/test_leval.py | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/leval/evaluator.py b/leval/evaluator.py index 55ee2c3..2afcea6 100644 --- a/leval/evaluator.py +++ b/leval/evaluator.py @@ -22,7 +22,12 @@ DEFAULT_ALLOWED_CONTAINER_TYPES = frozenset((tuple, set)) DEFAULT_ALLOWED_CONSTANT_TYPES = frozenset( - (str, int, float, NoneType), + ( + str, + int, # NB: this implicitly includes bool + float, + NoneType, + ), ) diff --git a/leval_tests/test_leval.py b/leval_tests/test_leval.py index d071370..f95e8f0 100644 --- a/leval_tests/test_leval.py +++ b/leval_tests/test_leval.py @@ -84,6 +84,8 @@ ("Arbitrary Python code is not allowed", "if x > a:\n hello()", SyntaxError), ("Can't access numeric constants' attributes", "(3).__class__", InvalidAttribute), ("Can't access Nones' attributes", "None.__class__", InvalidAttribute), + ("Can't access Falses' attributes", "False.__class__", InvalidAttribute), + ("Can't access Trues' attributes", "True.__class__", InvalidAttribute), ( "Walruses aren't allowed", "(a := 3) + 8",