Treat static methods as class methods instead of instance methods in actors (#6756)

* Treat static methods as class methods rather than instance methods

* Add tests for static methods in actors

* Revert formatting changes

* Readd future imports

* Restructure static method check

* Documentation enhancements

* Fix linting issues
This commit is contained in:
Ziyad Edher
2020-01-15 20:38:41 -05:00
committed by Edward Oakes
parent 2e972e725a
commit c480d1d1e4
4 changed files with 76 additions and 2 deletions
+8 -1
View File
@@ -211,12 +211,19 @@ class ActorClassMetadata:
self.method_signatures = {}
self.actor_method_num_return_vals = {}
for method_name, method in self.actor_methods:
# Whether or not this method requires binding of its first
# argument. For class and static methods, we do not want to bind
# the first argument, but we do for instance methods
is_bound = (ray.utils.is_class_method(method)
or ray.utils.is_static_method(self.modified_class,
method_name))
# Print a warning message if the method signature is not
# supported. We don't raise an exception because if the actor
# inherits from a class that has a method whose signature we
# don't support, there may not be much the user can do about it.
self.method_signatures[method_name] = signature.extract_signature(
method, ignore_first=not ray.utils.is_class_method(method))
method, ignore_first=not is_bound)
# Set the default number of return values for this method.
if hasattr(method, "__ray_num_return_vals__"):
self.actor_method_num_return_vals[method_name] = (
+4 -1
View File
@@ -21,6 +21,7 @@ from ray.utils import (
binary_to_hex,
is_function_or_method,
is_class_method,
is_static_method,
check_oversized_pickle,
decode,
ensure_str,
@@ -753,7 +754,9 @@ class FunctionActorManager:
# Execute the assigned method and save a checkpoint if necessary.
try:
if is_class_method(method):
is_bound = (is_class_method(method)
or is_static_method(type(actor), method_name))
if is_bound:
method_returns = method(*args, **kwargs)
else:
method_returns = method(actor, *args, **kwargs)
+49
View File
@@ -208,6 +208,55 @@ def test_actor_class_attributes(ray_start_regular):
assert ray.get(t.g.remote()) == 3
def test_actor_static_attributes(ray_start_regular):
class Grandparent:
GRANDPARENT = 2
@staticmethod
def grandparent_static():
assert Grandparent.GRANDPARENT == 2
return 1
class Parent1(Grandparent):
PARENT1 = 6
@staticmethod
def parent1_static():
assert Parent1.PARENT1 == 6
return 2
def parent1(self):
assert Parent1.PARENT1 == 6
class Parent2:
PARENT2 = 7
def parent2(self):
assert Parent2.PARENT2 == 7
@ray.remote
class TestActor(Parent1, Parent2):
X = 3
@staticmethod
def f():
assert TestActor.GRANDPARENT == 2
assert TestActor.PARENT1 == 6
assert TestActor.PARENT2 == 7
assert TestActor.X == 3
return 4
def g(self):
assert TestActor.GRANDPARENT == 2
assert TestActor.PARENT1 == 6
assert TestActor.PARENT2 == 7
assert TestActor.f() == 4
return TestActor.X
t = TestActor.remote()
assert ray.get(t.g.remote()) == 3
def test_caching_actors(shutdown_only):
# Test defining actors before ray.init() has been called.
+15
View File
@@ -127,6 +127,21 @@ def is_class_method(f):
return hasattr(f, "__self__") and f.__self__ is not None
def is_static_method(cls, f_name):
"""Returns whether the class has a static method with the given name.
Args:
cls: The Python class (i.e. object of type `type`) to
search for the method in.
f_name: The name of the method to look up in this class
and check whether or not it is static.
"""
for cls in inspect.getmro(cls):
if f_name in cls.__dict__:
return isinstance(cls.__dict__[f_name], staticmethod)
return False
def random_string():
"""Generate a random string to use as an ID.