Add `Portal.run_from_ns()`
It turns out in order to maintain our sneaky little "call an `Actor` method in this remote process" we still need the ability to invoke functions from a namespace. We're currently using a "self" namespace as a way to do this for internal inter-process method calling. Either way, I see no reason not to keep a public method for this invoke style (we just won't market it) since it is still how the machinery works underneath.func_refs_always
							parent
							
								
									a668f714d5
								
							
						
					
					
						commit
						7134f35d6e
					
				|  | @ -120,7 +120,7 @@ class ReceiveStream(trio.abc.ReceiveChannel): | |||
|             # NOTE: we're telling the far end actor to cancel a task | ||||
|             # corresponding to *this actor*. The far end local channel | ||||
|             # instance is passed to `Actor._cancel_task()` implicitly. | ||||
|             await self._portal.run('self', '_cancel_task', cid=cid) | ||||
|             await self._portal.run_from_ns('self', '_cancel_task', cid=cid) | ||||
| 
 | ||||
|         if cs.cancelled_caught: | ||||
|             # XXX: there's no way to know if the remote task was indeed | ||||
|  | @ -212,9 +212,12 @@ class Portal: | |||
|         """ | ||||
|         if isinstance(func_or_ns, str): | ||||
|             warnings.warn( | ||||
|                 "`Portal.run(namespace: str, funcname: str)` is now deprecated, " | ||||
|                 "pass a function reference directly instead", | ||||
|                 DeprecationWarning | ||||
|                 "`Portal.run(namespace: str, funcname: str)` is now" | ||||
|                 "deprecated, pass a function reference directly instead\n" | ||||
|                 "If you still want to run a remote function by name use" | ||||
|                 "`Portal.run_from_ns()`", | ||||
|                 DeprecationWarning, | ||||
|                 stacklevel=2, | ||||
|             ) | ||||
|             fn_mod_path = func_or_ns | ||||
|             assert isinstance(fn_name, str) | ||||
|  | @ -228,6 +231,28 @@ class Portal: | |||
|             *(await self._submit(fn_mod_path, fn_name, kwargs)) | ||||
|         ) | ||||
| 
 | ||||
|     async def run_from_ns( | ||||
|         self, | ||||
|         namespace_path: str, | ||||
|         function_name: str, | ||||
|         **kwargs, | ||||
|     ) -> Any: | ||||
|         """Run a function from a (remote) namespace in a new task on the far-end actor. | ||||
| 
 | ||||
|         This is a more explitcit way to run tasks in a remote-process | ||||
|         actor using explicit object-path syntax. Hint: this is how | ||||
|         `.run()` works underneath. | ||||
| 
 | ||||
|         Note:: | ||||
| 
 | ||||
|             A special namespace `self` can be used to invoke `Actor` | ||||
|             instance methods in the remote runtime. Currently this should only | ||||
|             be used for `tractor` internals. | ||||
|         """ | ||||
|         return await self._return_from_resptype( | ||||
|             *(await self._submit(namespace_path, function_name, kwargs)) | ||||
|         ) | ||||
| 
 | ||||
|     async def _return_from_resptype( | ||||
|         self, | ||||
|         cid: str, | ||||
|  | @ -329,13 +354,16 @@ class Portal: | |||
|             # with trio.CancelScope(shield=True) as cancel_scope: | ||||
|             with trio.move_on_after(0.5) as cancel_scope: | ||||
|                 cancel_scope.shield = True | ||||
|                 await self.run('self', 'cancel') | ||||
| 
 | ||||
|                 await self.run_from_ns('self', 'cancel') | ||||
|                 return True | ||||
| 
 | ||||
|             if cancel_scope.cancelled_caught: | ||||
|                 log.warning(f"May have failed to cancel {self.channel.uid}") | ||||
| 
 | ||||
|             # if we get here some weird cancellation case happened | ||||
|             return False | ||||
| 
 | ||||
|         except trio.ClosedResourceError: | ||||
|             log.warning( | ||||
|                 f"{self.channel} for {self.channel.uid} was already closed?") | ||||
|  | @ -352,8 +380,10 @@ class LocalPortal: | |||
|     actor: 'Actor'  # type: ignore # noqa | ||||
|     channel: Channel | ||||
| 
 | ||||
|     async def run(self, ns: str, func_name: str, **kwargs) -> Any: | ||||
|         """Run a requested function locally and return it's result. | ||||
|     async def run_from_ns(self, ns: str, func_name: str, **kwargs) -> Any: | ||||
|         """Run a requested local function from a namespace path and | ||||
|         return it's result. | ||||
| 
 | ||||
|         """ | ||||
|         obj = self.actor if ns == 'self' else importlib.import_module(ns) | ||||
|         func = getattr(obj, func_name) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue