diff --git a/tractor/_portal.py b/tractor/_portal.py index 1dc6ee4..58dbce5 100644 --- a/tractor/_portal.py +++ b/tractor/_portal.py @@ -14,11 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -""" +''' Memory boundary "Portals": an API for structured concurrency linked tasks running in disparate memory domains. -""" +''' +from __future__ import annotations +from typing import NamedTuple import importlib import inspect from typing import ( @@ -66,11 +68,38 @@ async def maybe_open_nursery( yield nursery -def func_deats(func: Callable) -> tuple[str, str]: - return ( - func.__module__, - func.__name__, - ) +class NamespacePath(NamedTuple): + ''' + A serializeable description of a (function) object location + described by the target's module path and its namespace key. + + ''' + mod: str + key: str + + def load(self) -> Callable: + return getattr( + importlib.import_module(self.mod), + self.key + ) + + @classmethod + def from_ref( + cls, + obj, + + ) -> NamespacePath: + return cls( + obj.__module__, + obj.__name__, + ) + + +# def func_deats(func: Callable) -> NamespacePath[str, str]: +# return NamespacePath( +# func.__module__, +# func.__name__, +# ) def _unwrap_msg( @@ -86,6 +115,7 @@ def _unwrap_msg( assert msg.get('cid'), "Received internal error at portal?" raise unpack_error(msg, channel) + class MessagingError(Exception): 'Some kind of unexpected SC messaging dialog issue' @@ -316,7 +346,8 @@ class Portal: raise TypeError( f'{func} must be a non-streaming async function!') - fn_mod_path, fn_name = func_deats(func) + # fn_mod_path, fn_name = func_deats(func) + fn_mod_path, fn_name = NamespacePath.from_ref(func) ctx = await self.actor.start_remote_task( self.channel, @@ -346,7 +377,8 @@ class Portal: raise TypeError( f'{async_gen_func} must be an async generator function!') - fn_mod_path, fn_name = func_deats(async_gen_func) + # fn_mod_path, fn_name = func_deats(async_gen_func) + fn_mod_path, fn_name = NamespacePath.from_ref(async_gen_func) ctx = await self.actor.start_remote_task( self.channel, fn_mod_path, @@ -412,7 +444,8 @@ class Portal: raise TypeError( f'{func} must be an async generator function!') - fn_mod_path, fn_name = func_deats(func) + # fn_mod_path, fn_name = func_deats(func) + fn_mod_path, fn_name = NamespacePath.from_ref(func) ctx = await self.actor.start_remote_task( self.channel, @@ -430,7 +463,7 @@ class Portal: first = msg['started'] ctx._started_called = True - except KeyError as kerr: + except KeyError: assert msg.get('cid'), ("Received internal error at context?") if msg.get('error'):