309 lines
8.3 KiB
Python
309 lines
8.3 KiB
Python
import sys
|
|
from textwrap import dedent
|
|
|
|
import pytest
|
|
|
|
import ray
|
|
from ray.exceptions import (
|
|
ActorDiedError,
|
|
RayTaskError,
|
|
TaskCancelledError,
|
|
WorkerCrashedError,
|
|
)
|
|
|
|
|
|
def test_baseexception_task(ray_start_regular_shared):
|
|
class MyBaseException(BaseException):
|
|
pass
|
|
|
|
@ray.remote
|
|
def task():
|
|
raise MyBaseException("abc")
|
|
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(task.remote())
|
|
|
|
|
|
def test_baseexception_actor_task(ray_start_regular_shared):
|
|
class MyBaseException(BaseException):
|
|
pass
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def f(self):
|
|
raise MyBaseException("abc")
|
|
|
|
async def async_f(self):
|
|
raise MyBaseException("abc")
|
|
|
|
a = Actor.remote()
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(a.f.remote())
|
|
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(a.async_f.remote())
|
|
|
|
|
|
def test_baseexception_actor_creation(ray_start_regular_shared):
|
|
class MyBaseException(BaseException):
|
|
pass
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def __init__(self):
|
|
raise MyBaseException("abc")
|
|
|
|
with pytest.raises(ActorDiedError) as e:
|
|
a = Actor.remote()
|
|
ray.get(a.__ray_ready__.remote())
|
|
assert "MyBaseException" in str(e.value)
|
|
|
|
|
|
def test_baseexception_streaming_generator(ray_start_regular_shared):
|
|
class MyBaseException(BaseException):
|
|
pass
|
|
|
|
@ray.remote
|
|
def raise_at_beginning():
|
|
raise MyBaseException("rip")
|
|
yield 1
|
|
|
|
raise_at_beginning_ref = raise_at_beginning.remote()
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(next(raise_at_beginning_ref))
|
|
|
|
@ray.remote
|
|
def raise_at_middle():
|
|
for i in range(1, 10):
|
|
if i == 5:
|
|
raise MyBaseException("rip")
|
|
yield i
|
|
|
|
raise_at_middle_ref = raise_at_middle.remote()
|
|
for i in range(1, 5):
|
|
assert i == ray.get(next(raise_at_middle_ref))
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(next(raise_at_middle_ref))
|
|
|
|
@ray.remote(_generator_backpressure_num_objects=1)
|
|
def raise_after_backpressure():
|
|
for i in range(1, 10):
|
|
if i == 5:
|
|
raise MyBaseException("rip")
|
|
yield i
|
|
|
|
raise_after_backpressure_ref = raise_after_backpressure.remote()
|
|
for i in range(1, 5):
|
|
assert i == ray.get(next(raise_after_backpressure_ref))
|
|
with pytest.raises(MyBaseException):
|
|
ray.get(next(raise_after_backpressure_ref))
|
|
|
|
|
|
def test_raise_system_exit(ray_start_regular_shared):
|
|
@ray.remote
|
|
def task():
|
|
raise SystemExit("abc")
|
|
|
|
with pytest.raises(WorkerCrashedError):
|
|
ray.get(task.remote())
|
|
|
|
|
|
def test_raise_keyboard_interrupt(ray_start_regular_shared):
|
|
@ray.remote
|
|
def task():
|
|
raise KeyboardInterrupt("abc")
|
|
|
|
with pytest.raises(TaskCancelledError):
|
|
ray.get(task.remote())
|
|
|
|
|
|
skip_if_python_less_than_3_11 = pytest.mark.skipif(
|
|
sys.version_info < (3, 11),
|
|
reason="ExceptionGroup is only available in Python 3.11+",
|
|
)
|
|
|
|
|
|
@skip_if_python_less_than_3_11
|
|
def test_baseexceptiongroup_task(ray_start_regular_shared):
|
|
baseexceptiongroup = BaseExceptionGroup( # noqa: F821
|
|
"test baseexceptiongroup", [BaseException("abc")]
|
|
)
|
|
|
|
@ray.remote
|
|
def task():
|
|
raise baseexceptiongroup
|
|
|
|
with pytest.raises(ray.exceptions.RayTaskError): # noqa: F821
|
|
ray.get(task.remote())
|
|
|
|
|
|
@skip_if_python_less_than_3_11
|
|
def test_baseexceptiongroup_actor(ray_start_regular_shared):
|
|
baseexceptiongroup = BaseExceptionGroup( # noqa: F821
|
|
"test baseexceptiongroup", [BaseException("abc")]
|
|
)
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def f(self):
|
|
raise baseexceptiongroup
|
|
|
|
with pytest.raises(ray.exceptions.RayTaskError): # noqa: F821
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
|
|
|
|
@skip_if_python_less_than_3_11
|
|
def test_except_exceptiongroup(ray_start_regular_shared):
|
|
exceptiongroup = ExceptionGroup( # noqa: F821
|
|
"test exceptiongroup", [ValueError(), TypeError()]
|
|
)
|
|
|
|
@ray.remote
|
|
def task():
|
|
raise exceptiongroup
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def f(self):
|
|
raise exceptiongroup
|
|
|
|
try:
|
|
ray.get(task.remote())
|
|
except Exception as ex:
|
|
assert isinstance(ex, RayTaskError)
|
|
assert isinstance(ex, ExceptionGroup) # noqa: F821
|
|
assert len(ex.exceptions) == 2
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
assert isinstance(ex.exceptions[1], TypeError)
|
|
|
|
try:
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
except Exception as ex:
|
|
assert isinstance(ex, RayTaskError)
|
|
assert isinstance(ex, ExceptionGroup) # noqa: F821
|
|
assert len(ex.exceptions) == 2
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
assert isinstance(ex.exceptions[1], TypeError)
|
|
|
|
|
|
@skip_if_python_less_than_3_11
|
|
def test_except_star_exception(ray_start_regular_shared):
|
|
@ray.remote
|
|
def task():
|
|
raise ValueError
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def f(self):
|
|
raise ValueError
|
|
|
|
# TODO: Don't use exec() when we only support Python 3.11+
|
|
# Here the exec() is used to avoid SyntaxError for except* for Python < 3.11
|
|
python_code = dedent(
|
|
"""\
|
|
try:
|
|
ray.get(task.remote())
|
|
except* RayTaskError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], RayTaskError)
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
|
|
try:
|
|
ray.get(task.remote())
|
|
except* ValueError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], RayTaskError)
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
|
|
try:
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
except* RayTaskError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], RayTaskError)
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
|
|
try:
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
except* ValueError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], RayTaskError)
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
"""
|
|
)
|
|
exec(python_code)
|
|
|
|
|
|
@skip_if_python_less_than_3_11
|
|
def test_except_star_exceptiongroup(ray_start_regular_shared):
|
|
exceptiongroup = ExceptionGroup( # noqa: F821
|
|
"test exceptiongroup", [ValueError(), TypeError()]
|
|
)
|
|
|
|
@ray.remote
|
|
def task():
|
|
raise exceptiongroup
|
|
|
|
@ray.remote
|
|
class Actor:
|
|
def f(self):
|
|
raise exceptiongroup
|
|
|
|
# TODO: Don't use exec() when we only support Python 3.11+
|
|
# Here the exec() is used to avoid SyntaxError for except* for Python < 3.11
|
|
python_code = dedent(
|
|
"""\
|
|
try:
|
|
ray.get(task.remote())
|
|
except* RayTaskError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 2
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
assert isinstance(ex.exceptions[1], TypeError)
|
|
|
|
try:
|
|
ray.get(task.remote())
|
|
except* ValueError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
except* TypeError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], TypeError)
|
|
|
|
try:
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
except* RayTaskError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 2
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
assert isinstance(ex.exceptions[1], TypeError)
|
|
|
|
try:
|
|
a = Actor.remote()
|
|
ray.get(a.f.remote())
|
|
except* ValueError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], ValueError)
|
|
except* TypeError as ex:
|
|
assert isinstance(ex, ExceptionGroup)
|
|
assert len(ex.exceptions) == 1
|
|
assert isinstance(ex.exceptions[0], TypeError)
|
|
"""
|
|
)
|
|
exec(python_code)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(pytest.main(["-sv", __file__]))
|