forked from goodboy/tractor
				
			First draft "namespace path" named tuple; probably will discard
							parent
							
								
									094206ee9d
								
							
						
					
					
						commit
						949cb2c9fe
					
				| 
						 | 
				
			
			@ -14,11 +14,13 @@
 | 
			
		|||
# You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
'''
 | 
			
		||||
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,12 +68,39 @@ 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'):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue