mirror of
https://github.com/wassname/ray.git
synced 2026-07-01 00:52:45 +08:00
Better error message for actor class inheritance (#5598)
This commit is contained in:
committed by
Philipp Moritz
parent
c3b0c62290
commit
4ed6ee0b1e
+49
-10
@@ -204,8 +204,51 @@ class ActorClass(object):
|
||||
each actor method.
|
||||
"""
|
||||
|
||||
def __init__(self, modified_class, class_id, max_reconstructions, num_cpus,
|
||||
num_gpus, memory, object_store_memory, resources):
|
||||
def __init__(cls, name, bases, attr):
|
||||
"""Prevents users from directly inheriting from an ActorClass.
|
||||
|
||||
This will be called when a class is defined with an ActorClass object
|
||||
as one of its base classes. To intentionally construct an ActorClass,
|
||||
use the '_from_modified_class' classmethod.
|
||||
|
||||
Raises:
|
||||
TypeError: Always.
|
||||
"""
|
||||
for base in bases:
|
||||
if isinstance(base, ActorClass):
|
||||
raise TypeError("Attempted to define subclass '{}' of actor "
|
||||
"class '{}'. Inheriting from actor classes is "
|
||||
"not currently supported. You can instead "
|
||||
"inherit from a non-actor base class and make "
|
||||
"the derived class an actor class (with "
|
||||
"@ray.remote).".format(name, base._class_name))
|
||||
|
||||
# This shouldn't be reached because one of the base classes must be
|
||||
# an actor class if this was meant to be subclassed.
|
||||
assert False, ("ActorClass.__init__ should not be called. Please use "
|
||||
"the @ray.remote decorator instead.")
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""Prevents users from directly instantiating an ActorClass.
|
||||
|
||||
This will be called instead of __init__ when 'ActorClass()' is executed
|
||||
because an is an object rather than a metaobject. To properly
|
||||
instantiated a remote actor, use 'ActorClass.remote()'.
|
||||
|
||||
Raises:
|
||||
Exception: Always.
|
||||
"""
|
||||
raise Exception("Actors cannot be instantiated directly. "
|
||||
"Instead of '{}()', use '{}.remote()'.".format(
|
||||
self._class_name, self._class_name))
|
||||
|
||||
@classmethod
|
||||
def _from_modified_class(cls, modified_class, class_id,
|
||||
max_reconstructions, num_cpus, num_gpus, memory,
|
||||
object_store_memory, resources):
|
||||
# Construct the base object.
|
||||
self = cls.__new__(cls)
|
||||
|
||||
self._modified_class = modified_class
|
||||
self._class_id = class_id
|
||||
self._class_name = modified_class.__name__
|
||||
@@ -262,10 +305,7 @@ class ActorClass(object):
|
||||
self._method_decorators[method_name] = (
|
||||
method.__ray_invocation_decorator__)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise Exception("Actors methods cannot be instantiated directly. "
|
||||
"Instead of running '{}()', try '{}.remote()'.".format(
|
||||
self._class_name, self._class_name))
|
||||
return self
|
||||
|
||||
def remote(self, *args, **kwargs):
|
||||
"""Create an actor.
|
||||
@@ -806,10 +846,9 @@ def make_actor(cls, num_cpus, num_gpus, memory, object_store_memory, resources,
|
||||
Class.__module__ = cls.__module__
|
||||
Class.__name__ = cls.__name__
|
||||
|
||||
class_id = ActorClassID.from_random()
|
||||
|
||||
return ActorClass(Class, class_id, max_reconstructions, num_cpus, num_gpus,
|
||||
memory, object_store_memory, resources)
|
||||
return ActorClass._from_modified_class(
|
||||
Class, ActorClassID.from_random(), max_reconstructions, num_cpus,
|
||||
num_gpus, memory, object_store_memory, resources)
|
||||
|
||||
|
||||
def exit_actor():
|
||||
|
||||
@@ -362,6 +362,33 @@ def test_actor_class_name(ray_start_regular):
|
||||
assert actor_class_info[b"module"] == b"ray.tests.test_actor"
|
||||
|
||||
|
||||
def test_actor_inheritance(ray_start_regular):
|
||||
class NonActorBase(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# Test that an actor class can inherit from a non-actor class.
|
||||
@ray.remote
|
||||
class ActorBase(NonActorBase):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# Test that you can't instantiate an actor class directly.
|
||||
with pytest.raises(
|
||||
Exception, match="Actors cannot be instantiated directly."):
|
||||
ActorBase()
|
||||
|
||||
# Test that you can't inherit from an actor class.
|
||||
with pytest.raises(
|
||||
TypeError,
|
||||
match="Inheriting from actor classes is not "
|
||||
"currently supported."):
|
||||
|
||||
class Derived(ActorBase):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_multiple_return_values(ray_start_regular):
|
||||
@ray.remote
|
||||
class Foo(object):
|
||||
|
||||
Reference in New Issue
Block a user