From fef0fd7e14e889e498eab9cf3b70001abf8531c8 Mon Sep 17 00:00:00 2001 From: Roger Leigh Date: Wed, 11 Nov 2020 19:48:44 +0000 Subject: [PATCH 1/4] astutil: visit_Subscript can handle visiting arbitrary node types --- genshi/template/astutil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genshi/template/astutil.py b/genshi/template/astutil.py index 9c6ff29f..8af29742 100644 --- a/genshi/template/astutil.py +++ b/genshi/template/astutil.py @@ -744,7 +744,7 @@ def _process_slice(node): self._write(', ') self.visit(dim) else: - raise NotImplementedError('Slice type not implemented') + self.visit(node) _process_slice(node.slice) self._write(']') From b3b3d6463260c5c280faaa65cd0063cc99cee368 Mon Sep 17 00:00:00 2001 From: Simon Cross Date: Fri, 13 Nov 2020 13:45:19 +0200 Subject: [PATCH 2/4] Add tests for additional slice expressions. --- genshi/template/tests/eval.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py index e8910189..c8eb80f6 100644 --- a/genshi/template/tests/eval.py +++ b/genshi/template/tests/eval.py @@ -360,6 +360,31 @@ def test_slice_negative_end(self): res = expr.evaluate({'numbers': list(range(5))}) self.assertEqual([0, 1, 2, 3], res) + def test_slice_constant(self): + expr = Expression("numbers[1]") + res = expr.evaluate({"numbers": list(range(5))}) + self.assertEqual(res, 1) + + def test_slice_call(self): + def f(): + return 2 + expr = Expression("numbers[f()]") + res = expr.evaluate({"numbers": list(range(5)), "f": f}) + self.assertEqual(res, 2) + + def test_slice_name(self): + expr = Expression("numbers[v]") + res = expr.evaluate({"numbers": list(range(5)), "v": 2}) + self.assertEqual(res, 2) + + def test_slice_attribute(self): + class ValueHolder: + def __init__(self): + self.value = 3 + expr = Expression("numbers[obj.value]") + res = expr.evaluate({"numbers": list(range(5)), "obj": ValueHolder()}) + self.assertEqual(res, 3) + def test_access_undefined(self): expr = Expression("nothing", filename='index.html', lineno=50, lookup='lenient') From 61aad8adedba2c8449947fb939ac6e4492ca3b01 Mon Sep 17 00:00:00 2001 From: Simon Cross Date: Fri, 13 Nov 2020 13:49:09 +0200 Subject: [PATCH 3/4] Remove some unnecessary cases from slice processing. --- genshi/template/astutil.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/genshi/template/astutil.py b/genshi/template/astutil.py index 8af29742..d5b33bdf 100644 --- a/genshi/template/astutil.py +++ b/genshi/template/astutil.py @@ -734,10 +734,6 @@ def _process_slice(node): self.visit(node.step) elif isinstance(node, _ast.Index): self.visit(node.value) - elif isinstance(node, _ast_Constant): - self.visit_Constant(node) - elif isinstance(node, _ast.UnaryOp): - self.visit_UnaryOp(node) elif isinstance(node, _ast.ExtSlice): self.visit(node.dims[0]) for dim in node.dims[1:]: From 3a0c0360b08b46f543a9ef8d170a86574542af92 Mon Sep 17 00:00:00 2001 From: Simon Cross Date: Wed, 18 Nov 2020 00:32:46 +0200 Subject: [PATCH 4/4] Add tests for the use of various kinds of slicing inside suites. --- genshi/template/tests/eval.py | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py index c8eb80f6..a8dcd844 100644 --- a/genshi/template/tests/eval.py +++ b/genshi/template/tests/eval.py @@ -966,6 +966,71 @@ def test_with_statement_with_multiple_items(self): finally: os.remove(path) + def test_slice(self): + suite = Suite("x = numbers[0:2]") + data = {"numbers": [0, 1, 2, 3]} + suite.execute(data) + self.assertEqual([0, 1], data["x"]) + + def test_slice_with_vars(self): + suite = Suite("x = numbers[start:end]") + data = {"numbers": [0, 1, 2, 3], "start": 0, "end": 2} + suite.execute(data) + self.assertEqual([0, 1], data["x"]) + + def test_slice_copy(self): + suite = Suite("x = numbers[:]") + data = {"numbers": [0, 1, 2, 3]} + suite.execute(data) + self.assertEqual([0, 1, 2, 3], data["x"]) + + def test_slice_stride(self): + suite = Suite("x = numbers[::stride]") + data = {"numbers": [0, 1, 2, 3, 4], "stride": 2} + suite.execute(data) + self.assertEqual([0, 2, 4], data["x"]) + + def test_slice_negative_start(self): + suite = Suite("x = numbers[-1:]") + data = {"numbers": [0, 1, 2, 3, 4], "stride": 2} + suite.execute(data) + self.assertEqual([4], data["x"]) + + def test_slice_negative_end(self): + suite = Suite("x = numbers[:-1]") + data = {"numbers": [0, 1, 2, 3, 4], "stride": 2} + suite.execute(data) + self.assertEqual([0, 1, 2, 3], data["x"]) + + def test_slice_constant(self): + suite = Suite("x = numbers[1]") + data = {"numbers": [0, 1, 2, 3, 4]} + suite.execute(data) + self.assertEqual(1, data["x"]) + + def test_slice_call(self): + def f(): + return 2 + suite = Suite("x = numbers[f()]") + data = {"numbers": [0, 1, 2, 3, 4], "f": f} + suite.execute(data) + self.assertEqual(2, data["x"]) + + def test_slice_name(self): + suite = Suite("x = numbers[v]") + data = {"numbers": [0, 1, 2, 3, 4], "v": 2} + suite.execute(data) + self.assertEqual(2, data["x"]) + + def test_slice_attribute(self): + class ValueHolder: + def __init__(self): + self.value = 3 + suite = Suite("x = numbers[obj.value]") + data = {"numbers": [0, 1, 2, 3, 4], "obj": ValueHolder()} + suite.execute(data) + self.assertEqual(3, data["x"]) + def suite(): suite = unittest.TestSuite()