Skip to content

Commit

Permalink
feat: add addr_to_addr_info util for converting addr to addr_infos (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Dec 11, 2023
1 parent 114c7ef commit 2e25a98
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ pop_addr_infos_interleave(addr_info, 1)
# Remove all matching address from addr_info
remove_addr_infos(addr_info, "dead::beef::")

# Convert a local_addr to local_addr_infos
local_addr_infos = addr_to_addr_infos(("127.0.0.1",0))
```

## Credits
Expand Down
3 changes: 3 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ aiohappyeyeballs.pop_addr_infos_interleave(addr_info, 1)

# Remove all matching address from addr_info
aiohappyeyeballs.remove_addr_infos(addr_info, "dead::beef::")

# Convert a local_addr to local_addr_infos
local_addr_infos = addr_to_addr_infos(("127.0.0.1",0))
```
3 changes: 2 additions & 1 deletion src/aiohappyeyeballs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

from .impl import start_connection
from .types import AddrInfoType
from .utils import pop_addr_infos_interleave, remove_addr_infos
from .utils import addr_to_addr_infos, pop_addr_infos_interleave, remove_addr_infos

__all__ = (
"start_connection",
"AddrInfoType",
"remove_addr_infos",
"pop_addr_infos_interleave",
"addr_to_addr_infos",
)
30 changes: 29 additions & 1 deletion src/aiohappyeyeballs/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
"""Utility functions for aiohappyeyeballs."""

import ipaddress
from typing import Dict, List, Tuple, Union
import socket
from typing import Dict, List, Optional, Tuple, Union

from .types import AddrInfoType


def addr_to_addr_infos(
addr: Optional[
Union[Tuple[str, int, int, int], Tuple[str, int, int], Tuple[str, int]]
]
) -> Optional[List[AddrInfoType]]:
"""Convert an address tuple to a list of addr_info tuples."""
if addr is None:
return None
host = addr[0]
port = addr[1]
is_ipv6 = ":" in host
if is_ipv6:
flowinfo = 0
scopeid = 0
addr_len = len(addr)
if addr_len >= 4:
scopeid = addr[3] # type: ignore[misc]
if addr_len >= 3:
flowinfo = addr[2] # type: ignore[misc]
addr = (host, port, flowinfo, scopeid)
family = socket.AF_INET6
else:
addr = (host, port)
family = socket.AF_INET
return [(family, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", addr)]


def pop_addr_infos_interleave(addr_infos: List[AddrInfoType], interleave: int) -> None:
"""
Pop addr_info from the list of addr_infos by family up to interleave times.
Expand Down
68 changes: 67 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@

import pytest

from aiohappyeyeballs import AddrInfoType, pop_addr_infos_interleave, remove_addr_infos
from aiohappyeyeballs import (
AddrInfoType,
addr_to_addr_infos,
pop_addr_infos_interleave,
remove_addr_infos,
)


def test_pop_addr_infos_interleave():
Expand Down Expand Up @@ -114,3 +119,64 @@ def test_remove_addr_infos_slow_path():
):
remove_addr_infos(addr_info_copy, ("107.6.106.2", 80))
assert addr_info_copy == [ipv4_addr_info]


def test_addr_to_addr_infos():
"""Test addr_to_addr_infos."""
assert addr_to_addr_infos(("1.2.3.4", 43)) == [
(
socket.AF_INET,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("1.2.3.4", 43),
)
]
assert addr_to_addr_infos(
("dead:aaaa:0000:0000:0000:0000:0000:0000", 80, 0, 0)
) == [
(
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("dead:aaaa:0000:0000:0000:0000:0000:0000", 80, 0, 0),
)
]
assert addr_to_addr_infos(("dead:aaaa::", 80, 0, 0)) == [
(
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("dead:aaaa::", 80, 0, 0),
)
]
assert addr_to_addr_infos(("dead:aaaa::", 80)) == [
(
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("dead:aaaa::", 80, 0, 0),
)
]
assert addr_to_addr_infos(("dead:aaaa::", 80, 1)) == [
(
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("dead:aaaa::", 80, 1, 0),
)
]
assert addr_to_addr_infos(("dead:aaaa::", 80, 1, 1)) == [
(
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"",
("dead:aaaa::", 80, 1, 1),
)
]
assert addr_to_addr_infos(None) is None

0 comments on commit 2e25a98

Please sign in to comment.