diff --git a/tractor/discovery/_addr.py b/tractor/discovery/_addr.py index cb95f792..2697c5c9 100644 --- a/tractor/discovery/_addr.py +++ b/tractor/discovery/_addr.py @@ -206,7 +206,7 @@ def mk_uuid() -> str: def wrap_address( - addr: UnwrappedAddress + addr: UnwrappedAddress|str, ) -> Address: ''' Wrap an `UnwrappedAddress` as an `Address`-type based @@ -257,6 +257,14 @@ def wrap_address( cls: Type[Address] = get_address_cls(_def_tpt_proto) addr: UnwrappedAddress = cls.get_root().unwrap() + # multiaddr-format string, e.g. + # '/ip4/127.0.0.1/tcp/1616' + case str() if addr.startswith('/'): + from tractor.discovery._multiaddr import ( + parse_maddr, + ) + return parse_maddr(addr) + case _: # import pdbp; pdbp.set_trace() # from tractor.devx import mk_pdb diff --git a/tractor/discovery/_multiaddr.py b/tractor/discovery/_multiaddr.py index 4f62d73a..2a0ee7e6 100644 --- a/tractor/discovery/_multiaddr.py +++ b/tractor/discovery/_multiaddr.py @@ -40,6 +40,12 @@ _tpt_proto_to_maddr: dict[str, str] = { 'uds': 'unix', } +# reverse mapping: multiaddr protocol name -> tractor proto_key +_maddr_to_tpt_proto: dict[str, str] = { + v: k for k, v in _tpt_proto_to_maddr.items() +} +# {'tcp': 'tcp', 'unix': 'uds'} + def mk_maddr( addr: 'Address', @@ -75,3 +81,46 @@ def mk_maddr( return Multiaddr( f'/{maddr_proto}/{filepath}' ) + + +def parse_maddr( + maddr_str: str, +) -> 'Address': + ''' + Parse a multiaddr string into a tractor `Address`. + + Inverse of `mk_maddr()`. + + ''' + # lazy imports to avoid circular deps + from tractor.ipc._tcp import TCPAddress + from tractor.ipc._uds import UDSAddress + + maddr = Multiaddr(maddr_str) + proto_names: list[str] = [ + p.name for p in maddr.protocols() + ] + + match proto_names: + case [('ip4' | 'ip6') as net_proto, 'tcp']: + host: str = maddr.value_for_protocol(net_proto) + port: int = int(maddr.value_for_protocol('tcp')) + return TCPAddress(host, port) + + case ['unix']: + # NOTE, the multiaddr lib prepends a `/` to the + # unix protocol value; strip it to recover the + # original relative path. + raw: str = maddr.value_for_protocol('unix') + sockpath = Path(raw.lstrip('/')) + return UDSAddress( + filedir=str(sockpath.parent), + filename=str(sockpath.name), + ) + + case _: + raise ValueError( + f'Unsupported multiaddr protocol combo: ' + f'{proto_names!r}\n' + f'from maddr: {maddr_str!r}\n' + )