from socket import (AF_INET, AF_INET6, SOCK_DGRAM, error as sockerr, getaddrinfo, gaierror) try: # I'm guessing the builtin inet_pton will be faster, but if it's not # available we'll just have to use mine from socket import inet_pton except ImportError: def inet_pton(af, ip): '''inet_pton(af, ip) -> packed IP address string Convert an IP address from string format to a packed string suitable for use with low-level network functions.''' if af == AF_INET: try: return ''.join(chr(int(b)) for b in ip.split('.')) except ValueError: raise sockerr('illegal IP address string passed to inet_pton') elif af == AF_INET6: bits = ip.split('::') if len(bits) > 2: raise sockerr('illegal IP address string passed to inet_pton') try: if len(bits) == 2: # The filter(bool) replaces [''] with [] in the case that # :: begins or ends a string (so bits[i] would be empty) lead, trail = [filter(bool, s.split(':')) for s in bits] full = [int(s, 16) for s in lead] full += [0 for _ in range(8 - len(lead) - len(trail))] full += [int(s, 16) for s in trail] else: full = [int(s, 16) for s in ip.split(':')] except ValueError: raise sockerr('illegal IP address string passed to inet_pton') return ''.join([chr(b >> 8) + chr(b & 0xff) for b in full]) else: # I don't know why 97, I'm just copying the observed behaviour of # my system's inet_pton raise sockerr(97, 'Address family not supported by protocol') def valid_addr(addr, afs = (AF_INET, AF_INET6)): 'Return the address family of the given string, or None if it is invalid' for af in afs: try: inet_pton(af, addr) return af except sockerr: pass return None def parse_addrwport(addr): # docstring TODO sep = addr.rindex(':') return (addr[:sep], int(addr[sep + 1:])) def stringtosockaddr(str, family = None, socktype = SOCK_DGRAM): # docstring TODO if family == None: try: return getaddrinfo(*parse_addrwport(str) + (AF_INET, socktype))[0][-1] except gaierror: return getaddrinfo(*parse_addrwport(str) + (AF_INET6, socktype))[0][-1] return getaddrinfo(*parse_addrwport(str) + (family, socktype))[0][-1]