-
Notifications
You must be signed in to change notification settings - Fork 14
Multiaddresses: a novel libp2p peeps idea worth embracing?
#429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
goodboy
wants to merge
11
commits into
subsys_reorg
Choose a base branch
from
multiaddr_support
base: subsys_reorg
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f94b562
Add `uds` to `._multiaddr`, tweak typing
goodboy 7b220c9
Add `multiaddr` usage snippet for IP4 and UDS
goodboy 536110f
Add `multiaddr` dep to `pyproject.toml`
goodboy 2de1d03
Use upstream `py-multiaddr` for `._multiaddr`
goodboy d09ecde
Use `_tpt_proto_to_maddr` lookup in `mk_maddr()`
goodboy 3ed5328
Add `test_multiaddr.py` suite for `mk_maddr()`
goodboy 4d435eb
Move `test_discovery` to `tests/discovery/test_registrar`
goodboy abff33c
Add `parse_maddr()` + `str` arm in `wrap_address()`
goodboy 59f5a9e
Add `parse_maddr()` tests + registrar maddr integ test
goodboy 3a7154b
Fix `mk_maddr()` crash on absolute UDS paths
goodboy 1e0bca2
Preserve absolute UDS paths in `parse_maddr()`
goodboy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from pathlib import Path | ||
| from multiaddr import Multiaddr | ||
|
|
||
| # construct from a string | ||
| m1 = Multiaddr("/ip4/127.0.0.1/udp/1234") | ||
| m2 = Multiaddr("/unix/run/user/1000/sway-ipc.1000.1557.sock") | ||
| for key in m1.protocols(): | ||
| key | ||
|
|
||
| uds_sock_path = Path(m2.values()[0]) | ||
| uds_sock_path | ||
| uds_sock_path.is_file() | ||
| uds_sock_path.is_socket() | ||
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,251 @@ | ||
| ''' | ||
| Multiaddr construction, parsing, and round-trip tests for | ||
| `tractor.discovery._multiaddr.mk_maddr()` and | ||
| `tractor.discovery._multiaddr.parse_maddr()`. | ||
|
|
||
| ''' | ||
| from pathlib import Path | ||
| from types import SimpleNamespace | ||
|
|
||
| import pytest | ||
| from multiaddr import Multiaddr | ||
|
|
||
| from tractor.ipc._tcp import TCPAddress | ||
| from tractor.ipc._uds import UDSAddress | ||
| from tractor.discovery._multiaddr import ( | ||
| mk_maddr, | ||
| parse_maddr, | ||
| _tpt_proto_to_maddr, | ||
| _maddr_to_tpt_proto, | ||
| ) | ||
| from tractor.discovery._addr import wrap_address | ||
|
|
||
|
|
||
| def test_tpt_proto_to_maddr_mapping(): | ||
| ''' | ||
| `_tpt_proto_to_maddr` maps all supported `proto_key` | ||
| values to their correct multiaddr protocol names. | ||
|
|
||
| ''' | ||
| assert _tpt_proto_to_maddr['tcp'] == 'tcp' | ||
| assert _tpt_proto_to_maddr['uds'] == 'unix' | ||
| assert len(_tpt_proto_to_maddr) == 2 | ||
|
|
||
|
|
||
| def test_mk_maddr_tcp_ipv4(): | ||
| ''' | ||
| `mk_maddr()` on a `TCPAddress` with an IPv4 host | ||
| produces the correct `/ip4/<host>/tcp/<port>` multiaddr. | ||
|
|
||
| ''' | ||
| addr = TCPAddress('127.0.0.1', 1234) | ||
| result: Multiaddr = mk_maddr(addr) | ||
|
|
||
| assert isinstance(result, Multiaddr) | ||
| assert str(result) == '/ip4/127.0.0.1/tcp/1234' | ||
|
|
||
| protos = result.protocols() | ||
| assert protos[0].name == 'ip4' | ||
| assert protos[1].name == 'tcp' | ||
|
|
||
| assert result.value_for_protocol('ip4') == '127.0.0.1' | ||
| assert result.value_for_protocol('tcp') == '1234' | ||
|
|
||
|
|
||
| def test_mk_maddr_tcp_ipv6(): | ||
| ''' | ||
| `mk_maddr()` on a `TCPAddress` with an IPv6 host | ||
| produces the correct `/ip6/<host>/tcp/<port>` multiaddr. | ||
|
|
||
| ''' | ||
| addr = TCPAddress('::1', 5678) | ||
| result: Multiaddr = mk_maddr(addr) | ||
|
|
||
| assert str(result) == '/ip6/::1/tcp/5678' | ||
|
|
||
| protos = result.protocols() | ||
| assert protos[0].name == 'ip6' | ||
| assert protos[1].name == 'tcp' | ||
|
|
||
|
|
||
| def test_mk_maddr_uds(): | ||
| ''' | ||
| `mk_maddr()` on a `UDSAddress` produces a `/unix/<path>` | ||
| multiaddr containing the full socket path. | ||
|
|
||
| ''' | ||
| # NOTE, use an absolute `filedir` to match real runtime | ||
| # UDS paths; `mk_maddr()` strips the leading `/` to avoid | ||
| # the double-slash `/unix//run/..` that py-multiaddr | ||
| # rejects as "empty protocol path". | ||
| filedir = '/tmp/tractor_test' | ||
| filename = 'test_sock.sock' | ||
| addr = UDSAddress( | ||
| filedir=filedir, | ||
| filename=filename, | ||
| ) | ||
| result: Multiaddr = mk_maddr(addr) | ||
|
|
||
| assert isinstance(result, Multiaddr) | ||
|
|
||
| result_str: str = str(result) | ||
| assert result_str.startswith('/unix/') | ||
| # verify the leading `/` was stripped to avoid double-slash | ||
| assert '/unix/tmp/tractor_test/' in result_str | ||
|
|
||
| sockpath_rel: str = str( | ||
| Path(filedir) / filename | ||
| ).lstrip('/') | ||
| unix_val: str = result.value_for_protocol('unix') | ||
| assert unix_val.endswith(sockpath_rel) | ||
|
|
||
|
|
||
| def test_mk_maddr_unsupported_proto_key(): | ||
| ''' | ||
| `mk_maddr()` raises `ValueError` for an unsupported | ||
| `proto_key`. | ||
|
|
||
| ''' | ||
| fake_addr = SimpleNamespace(proto_key='quic') | ||
| with pytest.raises( | ||
| ValueError, | ||
| match='Unsupported proto_key', | ||
| ): | ||
| mk_maddr(fake_addr) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| 'addr', | ||
| [ | ||
| pytest.param( | ||
| TCPAddress('127.0.0.1', 9999), | ||
| id='tcp-ipv4', | ||
| ), | ||
| pytest.param( | ||
| UDSAddress( | ||
| filedir='/tmp/tractor_rt', | ||
| filename='roundtrip.sock', | ||
| ), | ||
| id='uds', | ||
| ), | ||
| ], | ||
| ) | ||
| def test_mk_maddr_roundtrip(addr): | ||
| ''' | ||
| `mk_maddr()` output is valid multiaddr syntax that the | ||
| library can re-parse back into an equivalent `Multiaddr`. | ||
|
|
||
| ''' | ||
| maddr: Multiaddr = mk_maddr(addr) | ||
| reparsed = Multiaddr(str(maddr)) | ||
|
|
||
| assert reparsed == maddr | ||
| assert str(reparsed) == str(maddr) | ||
|
|
||
|
|
||
| # ------ parse_maddr() tests ------ | ||
|
|
||
| def test_maddr_to_tpt_proto_mapping(): | ||
| ''' | ||
| `_maddr_to_tpt_proto` is the exact inverse of | ||
| `_tpt_proto_to_maddr`. | ||
|
|
||
| ''' | ||
| assert _maddr_to_tpt_proto == { | ||
| 'tcp': 'tcp', | ||
| 'unix': 'uds', | ||
| } | ||
|
|
||
|
|
||
| def test_parse_maddr_tcp_ipv4(): | ||
| ''' | ||
| `parse_maddr()` on an IPv4 TCP multiaddr string | ||
| produce a `TCPAddress` with the correct host and port. | ||
|
|
||
| ''' | ||
| result = parse_maddr('/ip4/127.0.0.1/tcp/1234') | ||
|
|
||
| assert isinstance(result, TCPAddress) | ||
| assert result.unwrap() == ('127.0.0.1', 1234) | ||
|
|
||
|
|
||
| def test_parse_maddr_tcp_ipv6(): | ||
| ''' | ||
| `parse_maddr()` on an IPv6 TCP multiaddr string | ||
| produce a `TCPAddress` with the correct host and port. | ||
|
|
||
| ''' | ||
| result = parse_maddr('/ip6/::1/tcp/5678') | ||
|
|
||
| assert isinstance(result, TCPAddress) | ||
| assert result.unwrap() == ('::1', 5678) | ||
|
|
||
|
|
||
| def test_parse_maddr_uds(): | ||
| ''' | ||
| `parse_maddr()` on a `/unix/...` multiaddr string | ||
| produce a `UDSAddress` with the correct dir and filename, | ||
| preserving absolute path semantics. | ||
|
|
||
| ''' | ||
| result = parse_maddr('/unix/tmp/tractor_test/test.sock') | ||
|
|
||
| assert isinstance(result, UDSAddress) | ||
| filedir, filename = result.unwrap() | ||
| assert filename == 'test.sock' | ||
| assert str(filedir) == '/tmp/tractor_test' | ||
|
|
||
|
|
||
| def test_parse_maddr_unsupported(): | ||
| ''' | ||
| `parse_maddr()` raise `ValueError` for an unsupported | ||
| protocol combination like UDP. | ||
|
|
||
| ''' | ||
| with pytest.raises( | ||
| ValueError, | ||
| match='Unsupported multiaddr protocol combo', | ||
| ): | ||
| parse_maddr('/ip4/127.0.0.1/udp/1234') | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| 'addr', | ||
| [ | ||
| pytest.param( | ||
| TCPAddress('127.0.0.1', 9999), | ||
| id='tcp-ipv4', | ||
| ), | ||
| pytest.param( | ||
| UDSAddress( | ||
| filedir='/tmp/tractor_rt', | ||
| filename='roundtrip.sock', | ||
| ), | ||
| id='uds', | ||
| ), | ||
| ], | ||
| ) | ||
| def test_parse_maddr_roundtrip(addr): | ||
| ''' | ||
| Full round-trip: `addr -> mk_maddr -> str -> parse_maddr` | ||
| produce an `Address` whose `.unwrap()` matches the original. | ||
|
|
||
| ''' | ||
| maddr: Multiaddr = mk_maddr(addr) | ||
| maddr_str: str = str(maddr) | ||
| parsed = parse_maddr(maddr_str) | ||
|
|
||
| assert type(parsed) is type(addr) | ||
| assert parsed.unwrap() == addr.unwrap() | ||
|
|
||
|
|
||
| def test_wrap_address_maddr_str(): | ||
| ''' | ||
| `wrap_address()` accept a multiaddr-format string and | ||
| return the correct `Address` type. | ||
|
|
||
| ''' | ||
| result = wrap_address('/ip4/127.0.0.1/tcp/9999') | ||
|
|
||
| assert isinstance(result, TCPAddress) | ||
| assert result.unwrap() == ('127.0.0.1', 9999) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pathis used but not imported, so this snippet won't run as-is. Addfrom pathlib import Path(and consider normalizing spacing) to keep the example executable.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
from pathlib import Pathimport to the snippet.