summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMikhail Efimov <efimov.mikhail@gmail.com>2024-10-22 16:00:25 (GMT)
committerGitHub <noreply@github.com>2024-10-22 16:00:25 (GMT)
commit079875e39589eb0628b5883f7ffa387e7476ec06 (patch)
treea1cdeca4fa197debfaed79c2a8f309572d644b93 /Lib
parent91ddde4af0c3031c84a967bcf59f6fb4f8a48c0d (diff)
downloadcpython-079875e39589eb0628b5883f7ffa387e7476ec06.zip
cpython-079875e39589eb0628b5883f7ffa387e7476ec06.tar.gz
cpython-079875e39589eb0628b5883f7ffa387e7476ec06.tar.bz2
gh-125038: Fix crash after genexpr.gi_frame.f_locals manipulations (#125178)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_dis.py1
-rw-r--r--Lib/test/test_generators.py73
2 files changed, 74 insertions, 0 deletions
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 1ee0fbe..1f9c04c 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -810,6 +810,7 @@ Disassembly of <code object <genexpr> at 0x..., file "%s", line %d>:
POP_TOP
L1: RESUME 0
LOAD_FAST 0 (.0)
+ GET_ITER
L2: FOR_ITER 10 (to L3)
STORE_FAST 1 (z)
LOAD_DEREF 2 (x)
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 03a31ec..bf2cb11 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -268,6 +268,79 @@ class GeneratorTest(unittest.TestCase):
#This should not raise
loop()
+
+class ModifyUnderlyingIterableTest(unittest.TestCase):
+ iterables = [
+ range(0),
+ range(20),
+ [1, 2, 3],
+ (2,),
+ {13, 48, 211},
+ frozenset((15, 8, 6)),
+ {1: 2, 3: 4},
+ ]
+
+ non_iterables = [
+ None,
+ 42,
+ 3.0,
+ 2j,
+ ]
+
+ def genexpr(self):
+ return (x for x in range(10))
+
+ def genfunc(self):
+ def gen(it):
+ for x in it:
+ yield x
+ return gen(range(10))
+
+ def process_tests(self, get_generator):
+ for obj in self.iterables:
+ g_obj = get_generator(obj)
+ with self.subTest(g_obj=g_obj, obj=obj):
+ self.assertListEqual(list(g_obj), list(obj))
+
+ g_iter = get_generator(iter(obj))
+ with self.subTest(g_iter=g_iter, obj=obj):
+ self.assertListEqual(list(g_iter), list(obj))
+
+ err_regex = "'.*' object is not iterable"
+ for obj in self.non_iterables:
+ g_obj = get_generator(obj)
+ with self.subTest(g_obj=g_obj):
+ self.assertRaisesRegex(TypeError, err_regex, list, g_obj)
+
+ def test_modify_f_locals(self):
+ def modify_f_locals(g, local, obj):
+ g.gi_frame.f_locals[local] = obj
+ return g
+
+ def get_generator_genexpr(obj):
+ return modify_f_locals(self.genexpr(), '.0', obj)
+
+ def get_generator_genfunc(obj):
+ return modify_f_locals(self.genfunc(), 'it', obj)
+
+ self.process_tests(get_generator_genexpr)
+ self.process_tests(get_generator_genfunc)
+
+ def test_new_gen_from_gi_code(self):
+ def new_gen_from_gi_code(g, obj):
+ generator_func = types.FunctionType(g.gi_code, {})
+ return generator_func(obj)
+
+ def get_generator_genexpr(obj):
+ return new_gen_from_gi_code(self.genexpr(), obj)
+
+ def get_generator_genfunc(obj):
+ return new_gen_from_gi_code(self.genfunc(), obj)
+
+ self.process_tests(get_generator_genexpr)
+ self.process_tests(get_generator_genfunc)
+
+
class ExceptionTest(unittest.TestCase):
# Tests for the issue #23353: check that the currently handled exception
# is correctly saved/restored in PyEval_EvalFrameEx().