Repository: ray-project/ray

Issue:
All arguments to `_remote` should be optional. Currently `args` and `kwargs` are required.



Discussion:

Resolving patch:
diff --git a/python/ray/actor.py b/python/ray/actor.py
--- a/python/ray/actor.py
+++ b/python/ray/actor.py
@@ -125,7 +125,11 @@ def __call__(self, *args, **kwargs):
     def remote(self, *args, **kwargs):
         return self._remote(args, kwargs)
 
-    def _remote(self, args, kwargs, num_return_vals=None):
+    def _remote(self, args=None, kwargs=None, num_return_vals=None):
+        if args is None:
+            args = []
+        if kwargs is None:
+            kwargs = {}
         if num_return_vals is None:
             num_return_vals = self._num_return_vals
 
@@ -233,8 +237,8 @@ def remote(self, *args, **kwargs):
         return self._remote(args=args, kwargs=kwargs)
 
     def _remote(self,
-                args,
-                kwargs,
+                args=None,
+                kwargs=None,
                 num_cpus=None,
                 num_gpus=None,
                 resources=None):
@@ -255,6 +259,11 @@ def _remote(self,
         Returns:
             A handle to the newly created actor.
         """
+        if args is None:
+            args = []
+        if kwargs is None:
+            kwargs = {}
+
         worker = ray.worker.get_global_worker()
         if worker.mode is None:
             raise Exception("Actors cannot be created before ray.init() "
@@ -293,10 +302,6 @@ def _remote(self,
                 actor_placement_resources = resources.copy()
                 actor_placement_resources["CPU"] += 1
 
-            if args is None:
-                args = []
-            if kwargs is None:
-                kwargs = {}
             function_name = "__init__"
             function_signature = self._method_signatures[function_name]
             creation_args = signature.extend_args(function_signature, args,
diff --git a/python/ray/remote_function.py b/python/ray/remote_function.py
--- a/python/ray/remote_function.py
+++ b/python/ray/remote_function.py
@@ -107,6 +107,7 @@ def _remote(self,
             worker.function_actor_manager.export(self)
 
         kwargs = {} if kwargs is None else kwargs
+        args = [] if args is None else args
         args = ray.signature.extend_args(self._function_signature, args,
                                          kwargs)
 


Test patch:
diff --git a/python/ray/tests/test_basic.py b/python/ray/tests/test_basic.py
--- a/python/ray/tests/test_basic.py
+++ b/python/ray/tests/test_basic.py
@@ -827,51 +827,63 @@ def m(x):
     assert ray.get(k2.remote(1)) == 2
     assert ray.get(m.remote(1)) == 2
 
-    def test_submit_api(shutdown_only):
-        ray.init(num_cpus=1, num_gpus=1, resources={"Custom": 1})
 
-        @ray.remote
-        def f(n):
-            return list(range(n))
+def test_submit_api(shutdown_only):
+    ray.init(num_cpus=1, num_gpus=1, resources={"Custom": 1})
 
-        @ray.remote
-        def g():
-            return ray.get_gpu_ids()
+    @ray.remote
+    def f(n):
+        return list(range(n))
 
-        assert f._remote([0], num_return_vals=0) is None
-        id1 = f._remote(args=[1], num_return_vals=1)
-        assert ray.get(id1) == [0]
-        id1, id2 = f._remote(args=[2], num_return_vals=2)
-        assert ray.get([id1, id2]) == [0, 1]
-        id1, id2, id3 = f._remote(args=[3], num_return_vals=3)
-        assert ray.get([id1, id2, id3]) == [0, 1, 2]
-        assert ray.get(
-            g._remote(
-                args=[], num_cpus=1, num_gpus=1,
-                resources={"Custom": 1})) == [0]
-        infeasible_id = g._remote(args=[], resources={"NonexistentCustom": 1})
-        ready_ids, remaining_ids = ray.wait([infeasible_id], timeout=0.05)
-        assert len(ready_ids) == 0
-        assert len(remaining_ids) == 1
+    @ray.remote
+    def g():
+        return ray.get_gpu_ids()
+
+    assert f._remote([0], num_return_vals=0) is None
+    id1 = f._remote(args=[1], num_return_vals=1)
+    assert ray.get(id1) == [0]
+    id1, id2 = f._remote(args=[2], num_return_vals=2)
+    assert ray.get([id1, id2]) == [0, 1]
+    id1, id2, id3 = f._remote(args=[3], num_return_vals=3)
+    assert ray.get([id1, id2, id3]) == [0, 1, 2]
+    assert ray.get(
+        g._remote(args=[], num_cpus=1, num_gpus=1,
+                  resources={"Custom": 1})) == [0]
+    infeasible_id = g._remote(args=[], resources={"NonexistentCustom": 1})
+    assert ray.get(g._remote()) == []
+    ready_ids, remaining_ids = ray.wait([infeasible_id], timeout=0.05)
+    assert len(ready_ids) == 0
+    assert len(remaining_ids) == 1
 
-        @ray.remote
-        class Actor(object):
-            def __init__(self, x, y=0):
-                self.x = x
-                self.y = y
+    @ray.remote
+    class Actor(object):
+        def __init__(self, x, y=0):
+            self.x = x
+            self.y = y
 
-            def method(self, a, b=0):
-                return self.x, self.y, a, b
+        def method(self, a, b=0):
+            return self.x, self.y, a, b
+
+        def gpu_ids(self):
+            return ray.get_gpu_ids()
+
+    @ray.remote
+    class Actor2(object):
+        def __init__(self):
+            pass
+
+        def method(self):
+            pass
 
-            def gpu_ids(self):
-                return ray.get_gpu_ids()
+    a = Actor._remote(
+        args=[0], kwargs={"y": 1}, num_gpus=1, resources={"Custom": 1})
 
-        a = Actor._remote(
-            args=[0], kwargs={"y": 1}, num_gpus=1, resources={"Custom": 1})
+    a2 = Actor2._remote()
+    ray.get(a2.method._remote())
 
-        id1, id2, id3, id4 = a.method._remote(
-            args=["test"], kwargs={"b": 2}, num_return_vals=4)
-        assert ray.get([id1, id2, id3, id4]) == [0, 1, "test", 2]
+    id1, id2, id3, id4 = a.method._remote(
+        args=["test"], kwargs={"b": 2}, num_return_vals=4)
+    assert ray.get([id1, id2, id3, id4]) == [0, 1, "test", 2]
 
 
 def test_get_multiple(shutdown_only):