Source code for swimprotocol.address


from __future__ import annotations

from dataclasses import dataclass
from typing import Callable, Final, Optional, TypeAlias

__all__ = ['Address', 'AddressParser']

_AddressType: TypeAlias = Callable[[str, int], 'Address']


[docs]@dataclass(frozen=True, order=True) class Address: """Manages an address for socket connections. Args: host: The address hostname string. port: The address port number. """ host: str port: int
[docs] @classmethod def get(cls, addr: tuple[str, int]) -> Address: """Return an :class:`Address` from a ``(host, port)`` tuple. Args: addr: The address tuple from :mod:`socket` functions. """ return cls(addr[0], addr[1])
def __str__(self) -> str: return ':'.join((self.host, str(self.port)))
[docs]class AddressParser: """Manages the defaults to use when parsing an address string. Args: address_type: Override the :class:`Address` implementation. default_host: The default hostname, if missing from the address string (e.g. ``:1234:``). default_port: The default port number, if missing from the address string (e.g. ``example.tld``). """ def __init__(self, address_type: _AddressType = Address, *, default_host: Optional[str] = None, default_port: Optional[int] = None) -> None: super().__init__() self.address_type: Final = address_type self.default_host: Final = default_host self.default_port: Final = default_port def parse(self, address: str) -> Address: host, sep, port = address.rpartition(':') if sep != ':': default_port = self.default_port if default_port is not None: return self.address_type(host, default_port) else: default_host = self.default_host if host: return self.address_type(host, int(port)) elif default_host is not None: return self.address_type(default_host, int(port)) raise ValueError(address)