1try: 2 from socket import inet_pton 3except ImportError: 4 from typing import TYPE_CHECKING 5 6 if TYPE_CHECKING: # pragma: no cover 7 pass 8 else: 9 # based on https://gist.github.com/nnemkin/4966028 10 # this code only applies on Windows Python 2.7 11 import ctypes 12 import socket 13 14 class SockAddr(ctypes.Structure): 15 _fields_ = [ 16 ("sa_family", ctypes.c_short), 17 ("__pad1", ctypes.c_ushort), 18 ("ipv4_addr", ctypes.c_byte * 4), 19 ("ipv6_addr", ctypes.c_byte * 16), 20 ("__pad2", ctypes.c_ulong), 21 ] 22 23 WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA 24 WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA 25 26 def inet_pton(address_family, ip_string): 27 # type: (int, str) -> bytes 28 addr = SockAddr() 29 ip_string_bytes = ip_string.encode("ascii") 30 addr.sa_family = address_family 31 addr_size = ctypes.c_int(ctypes.sizeof(addr)) 32 33 try: 34 attribute, size = { 35 socket.AF_INET: ("ipv4_addr", 4), 36 socket.AF_INET6: ("ipv6_addr", 16), 37 }[address_family] 38 except KeyError: 39 raise socket.error("unknown address family") 40 41 if ( 42 WSAStringToAddressA( 43 ip_string_bytes, 44 address_family, 45 None, 46 ctypes.byref(addr), 47 ctypes.byref(addr_size), 48 ) 49 != 0 50 ): 51 raise socket.error(ctypes.FormatError()) 52 53 return ctypes.string_at(getattr(addr, attribute), size) 54