Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 137 additions & 1 deletion graalpython/com.oracle.graal.python.test/src/tests/test_generators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2018, 2025, Oracle and/or its affiliates.
# Copyright (c) 2018, 2026, Oracle and/or its affiliates.
# Copyright (C) 1996-2017 Python Software Foundation
#
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
Expand Down Expand Up @@ -635,3 +635,139 @@ def gen():
assert False
except StopIteration:
pass

# ------
# send/throw lookup raises StopIteration:

original_ex = None
class BaseTestGenerator:
def __iter__(self):
return self
def __next__(self):
return 1

class NormalTestGenerator(BaseTestGenerator):
def send(self, value):
raise StopIteration(f"Stop from send method, {value=}")

def throw(self, value):
raise StopIteration(f"Stop from throw method, {value=}")

class StopOnLookupGenerator(BaseTestGenerator):
class StopIterationDescr:
def __init__(self, value):
self.value = value
def __get__(self, obj, owner=None):
global original_ex
original_ex = StopIteration(self.value)
raise original_ex
send = StopIterationDescr("Stop from send lookup")
throw = StopIterationDescr("Stop from throw lookup")

def delegator(it, expected_ex_repr=None):
try:
return (yield from it)
except Exception as e:
if not expected_ex_repr:
assert False, f"unexpected exception: {e}"
assert repr(e) == expected_ex_repr, f"'{e}' != '{expected_ex_repr}'"
raise e

def test_raise_in_lookup():
global original_ex
original_ex = None
it = StopOnLookupGenerator()
g = delegator(it)
next(g)
try:
g.send("SENT_VALUE1")
except StopIteration as e:
assert e.value == "Stop from send lookup", e.value
assert e != original_ex

def test_normal_generator():
global original_ex
original_ex = None
it = NormalTestGenerator()
g = delegator(it)
next(g)
try:
g.send("SENT_VALUE2")
except StopIteration as e:
assert e.value == "Stop from send method, value='SENT_VALUE2'", e.value
assert e != original_ex

@util.skipUnlessBytecodeDSL()
def test_raise_stop_iter_in_throw_generator():
global original_ex
original_ex = None
it = NormalTestGenerator()
g = delegator(it)
next(g)
try:
g.throw(AttributeError())
except StopIteration as e:
assert e.value == "Stop from throw method, value=AttributeError()", e.value
assert e != original_ex


class RaiseInThrowGenerator(BaseTestGenerator):
def throw(self, value):
global original_ex
original_ex = NameError()
raise original_ex


@util.skipUnlessBytecodeDSL()
def test_raise_ex_in_throw_generator():
global original_ex
original_ex = None
it = RaiseInThrowGenerator()
g = delegator(it, 'NameError()')
next(g)
try:
g.throw(AttributeError())
except NameError as e:
assert e == original_ex

# The following 2 tests look like CPyton bug or UB:
#
# In GraalPy the `throw` lookup is performed in `delegator`, so the error from
# the lookup is raised there and the gets handled in the `except` block in `delegator`.
#
# In CPython the throw lookup is already performed in this function, or more
# precisely in the `throw` called from this function, bypassing the `delegator`,
# and any exception raised during the lookup surfaces here and not in `delegator`
if sys.implementation.name != 'graalpy':
def test_raise_stop_iter_in_throw_lookup():
global original_ex
original_ex = None
it = StopOnLookupGenerator()
g = delegator(it)
next(g)
try:
g.throw(AttributeError())
except StopIteration as e:
assert e.value == "Stop from throw lookup", e.value
assert e == original_ex

class GenericErrorInThrowGenerator(BaseTestGenerator):
class NameErrorDescr:
def __init__(self, value):
self.value = value
def __get__(self, obj, owner=None):
global original_ex
original_ex = NameError(self.value)
raise original_ex
throw = NameErrorDescr("Stop from throw lookup")

def test_raise_generic_ex_in_throw_lookup():
global original_ex
original_ex = None
it = GenericErrorInThrowGenerator()
g = delegator(it)
next(g)
try:
g.throw(AttributeError())
except NameError as e:
assert e == original_ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ test.test_memoryio.CBytesIOTest.test_bytes_array @ darwin-arm64,linux-aarch64,li
test.test_memoryio.CBytesIOTest.test_detach @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.CBytesIOTest.test_flags @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.CBytesIOTest.test_flush @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
# GR-71890
!test.test_memoryio.CBytesIOTest.test_getbuffer_gc_collect @ darwin-arm64,linux-aarch64,linux-x86_64
test.test_memoryio.CBytesIOTest.test_getbuffer_gc_collect @ darwin-arm64,linux-aarch64,linux-x86_64
test.test_memoryio.CBytesIOTest.test_getstate @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.CBytesIOTest.test_getvalue @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.CBytesIOTest.test_init @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
Expand Down Expand Up @@ -90,8 +89,7 @@ test.test_memoryio.PyBytesIOTest.test_bytes_array @ darwin-arm64,linux-aarch64,l
test.test_memoryio.PyBytesIOTest.test_detach @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.PyBytesIOTest.test_flags @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.PyBytesIOTest.test_flush @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
# GR-71890
!test.test_memoryio.PyBytesIOTest.test_getbuffer_gc_collect @ darwin-arm64,linux-aarch64,linux-x86_64
test.test_memoryio.PyBytesIOTest.test_getbuffer_gc_collect @ darwin-arm64,linux-aarch64,linux-x86_64
test.test_memoryio.PyBytesIOTest.test_getvalue @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.PyBytesIOTest.test_init @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
test.test_memoryio.PyBytesIOTest.test_instance_dict_leak @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
Expand Down
Loading
Loading