Update enum and socket to versions from CPython 3.8.3

This commit is contained in:
Noah committed 2020-09-18 23:56:08 -05:00
1 parent dc9b78cdcc
commit fdb15cdd75
2 files changed
+333 -124

No files matched your search

Vendored
+141 -107
View File
@@ -1,13 +1,5 @@
import sys
from types import MappingProxyType, DynamicClassAttribute
from functools import reduce
from operator import or_ as _or_, and_ as _and_, xor, neg
# try _collections first to reduce startup cost
try:
from _collections import OrderedDict
except ImportError:
from collections import OrderedDict
__all__ = [
@@ -27,18 +19,19 @@ def _is_descriptor(obj):
def _is_dunder(name):
"""Returns True if a __dunder__ name, False otherwise."""
return (name[:2] == name[-2:] == '__' and
name[2:3] != '_' and
name[-3:-2] != '_' and
len(name) > 4)
return (len(name) > 4 and
name[:2] == name[-2:] == '__' and
name[2] != '_' and
name[-3] != '_')
def _is_sunder(name):
"""Returns True if a _sunder_ name, False otherwise."""
return (name[0] == name[-1] == '_' and
return (len(name) > 2 and
name[0] == name[-1] == '_' and
name[1:2] != '_' and
name[-2:-1] != '_' and
len(name) > 2)
name[-2:-1] != '_')
def _make_class_unpicklable(cls):
"""Make the given class un-picklable."""
@@ -66,6 +59,7 @@ class _EnumDict(dict):
super().__init__()
self._member_names = []
self._last_values = []
self._ignore = []
def __setitem__(self, key, value):
"""Changes anything not dundered or not a descriptor.
@@ -79,17 +73,28 @@ class _EnumDict(dict):
if _is_sunder(key):
if key not in (
'_order_', '_create_pseudo_member_',
'_generate_next_value_', '_missing_',
'_generate_next_value_', '_missing_', '_ignore_',
):
raise ValueError('_names_ are reserved for future Enum use')
if key == '_generate_next_value_':
setattr(self, '_generate_next_value', value)
elif key == '_ignore_':
if isinstance(value, str):
value = value.replace(',',' ').split()
else:
value = list(value)
self._ignore = value
already = set(value) & set(self._member_names)
if already:
raise ValueError('_ignore_ cannot specify already set names: %r' % (already, ))
elif _is_dunder(key):
if key == '__order__':
key = '_order_'
elif key in self._member_names:
# descriptor overwriting an enum?
raise TypeError('Attempted to reuse key: %r' % key)
elif key in self._ignore:
pass
elif not _is_descriptor(value):
if key in self:
# enum overwriting a descriptor?
@@ -126,6 +131,12 @@ class EnumMeta(type):
# cannot be mixed with other types (int, float, etc.) if it has an
# inherited __new__ unless a new __new__ is defined (or the resulting
# class will fail).
#
# remove any keys listed in _ignore_
classdict.setdefault('_ignore_', []).append('_ignore_')
ignore = classdict['_ignore_']
for key in ignore:
classdict.pop(key, None)
member_type, first_enum = metacls._get_mixins_(bases)
__new__, save_new, use_args = metacls._find_new_(classdict, member_type,
first_enum)
@@ -140,7 +151,7 @@ class EnumMeta(type):
_order_ = classdict.pop('_order_', None)
# check for illegal enum names (any others?)
invalid_names = set(enum_members) & {'mro', }
invalid_names = set(enum_members) & {'mro', ''}
if invalid_names:
raise ValueError('Invalid enum member name: {0}'.format(
','.join(invalid_names)))
@@ -152,12 +163,14 @@ class EnumMeta(type):
# create our new Enum type
enum_class = super().__new__(metacls, cls, bases, classdict)
enum_class._member_names_ = [] # names in definition order
enum_class._member_map_ = OrderedDict() # name->value map
enum_class._member_map_ = {} # name->value map
enum_class._member_type_ = member_type
# save attributes from super classes so we know if we can take
# the shortcut of storing members in the class dict
base_attributes = {a for b in enum_class.mro() for a in dir(b)} # XXX modified for rustpython
# save DynamicClassAttribute attributes from super classes so we know
# if we can take the shortcut of storing members in the class dict
dynamic_attributes = {k for c in enum_class.mro()
for k, v in c.__dict__.items()
if isinstance(v, DynamicClassAttribute)}
# Reverse value->name map for hashable values.
enum_class._value2member_map_ = {}
@@ -217,7 +230,7 @@ class EnumMeta(type):
enum_class._member_names_.append(member_name)
# performance boost for any member that would not shadow
# a DynamicClassAttribute
if member_name not in base_attributes:
if member_name not in dynamic_attributes:
setattr(enum_class, member_name, enum_member)
# now add to _member_map_
enum_class._member_map_[member_name] = enum_member
@@ -293,6 +306,10 @@ class EnumMeta(type):
return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
def __contains__(cls, member):
if not isinstance(member, Enum):
raise TypeError(
"unsupported operand type(s) for 'in': '%s' and '%s'" % (
type(member).__qualname__, cls.__class__.__qualname__))
return isinstance(member, cls) and member._name_ in cls._member_map_
def __delattr__(cls, attr):
@@ -361,7 +378,7 @@ class EnumMeta(type):
raise AttributeError('Cannot reassign members.')
super().__setattr__(name, value)
def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1):
def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
"""Convenience method to create a new Enum class.
`names` can be:
@@ -381,7 +398,7 @@ class EnumMeta(type):
# special processing needed for names?
if isinstance(names, str):
names = names.replace(',', ' ').split()
if isinstance(names, (tuple, list)) and isinstance(names[0], str):
if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
original_names, names = names, []
last_values = []
for count, name in enumerate(original_names):
@@ -403,7 +420,7 @@ class EnumMeta(type):
if module is None:
try:
module = sys._getframe(2).f_globals['__name__']
except (AttributeError, ValueError) as exc:
except (AttributeError, ValueError, KeyError) as exc:
pass
if module is None:
_make_class_unpicklable(enum_class)
@@ -414,6 +431,45 @@ class EnumMeta(type):
return enum_class
def _convert_(cls, name, module, filter, source=None):
"""
Create a new Enum subclass that replaces a collection of global constants
"""
# convert all constants from source (or module) that pass filter() to
# a new Enum called name, and export the enum and its members back to
# module;
# also, replace the __reduce_ex__ method so unpickling works in
# previous Python versions
module_globals = vars(sys.modules[module])
if source:
source = vars(source)
else:
source = module_globals
# _value2member_map_ is populated in the same order every time
# for a consistent reverse mapping of number to name when there
# are multiple names for the same number.
members = [
(name, value)
for name, value in source.items()
if filter(name)]
try:
# sort by value
members.sort(key=lambda t: (t[1], t[0]))
except TypeError:
# unless some values aren't comparable, in which case sort by name
members.sort(key=lambda t: t[0])
cls = cls(name, members, module=module)
cls.__reduce_ex__ = _reduce_ex_by_name
module_globals.update(cls.__members__)
module_globals[name] = cls
return cls
def _convert(cls, *args, **kwargs):
import warnings
warnings.warn("_convert is deprecated and will be removed in 3.9, use "
"_convert_ instead.", DeprecationWarning, stacklevel=2)
return cls._convert_(*args, **kwargs)
@staticmethod
def _get_mixins_(bases):
"""Returns the type for creating enum members, and the first inherited
@@ -425,38 +481,25 @@ class EnumMeta(type):
if not bases:
return object, Enum
# double check that we are not subclassing a class with existing
# enumeration members; while we're at it, see if any other data
# type has been mixed in so we can use the correct __new__
member_type = first_enum = None
for base in bases:
if (base is not Enum and
issubclass(base, Enum) and
base._member_names_):
raise TypeError("Cannot extend enumerations")
# base is now the last base in bases
if not issubclass(base, Enum):
raise TypeError("new enumerations must be created as "
"`ClassName([mixin_type,] enum_type)`")
# get correct mix-in type (either mix-in type of Enum subclass, or
# first base if last base is Enum)
if not issubclass(bases[0], Enum):
member_type = bases[0] # first data type
first_enum = bases[-1] # enum type
else:
for base in bases[0].__mro__:
# most common: (IntEnum, int, Enum, object)
# possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
# <class 'int'>, <Enum 'Enum'>,
# <class 'object'>)
if issubclass(base, Enum):
if first_enum is None:
first_enum = base
else:
if member_type is None:
member_type = base
def _find_data_type(bases):
for chain in bases:
for base in chain.__mro__:
if base is object:
continue
elif '__new__' in base.__dict__:
if issubclass(base, Enum):
continue
return base
# ensure final parent class is an Enum derivative, find any concrete
# data type, and check that Enum has no members
first_enum = bases[-1]
if not issubclass(first_enum, Enum):
raise TypeError("new enumerations should be created as "
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
member_type = _find_data_type(bases) or object
if first_enum._member_names_:
raise TypeError("Cannot extend enumerations")
return member_type, first_enum
@staticmethod
@@ -502,7 +545,6 @@ class EnumMeta(type):
use_args = False
else:
use_args = True
return __new__, save_new, use_args
@@ -522,15 +564,35 @@ class Enum(metaclass=EnumMeta):
# by-value search for a matching enum member
# see if it's in the reverse mapping (for hashable values)
try:
if value in cls._value2member_map_:
return cls._value2member_map_[value]
return cls._value2member_map_[value]
except KeyError:
# Not found, no need to do long O(n) search
pass
except TypeError:
# not there, now do long search -- O(n) behavior
for member in cls._member_map_.values():
if member._value_ == value:
return member
# still not found -- try _missing_ hook
return cls._missing_(value)
try:
exc = None
result = cls._missing_(value)
except Exception as e:
exc = e
result = None
if isinstance(result, cls):
return result
else:
ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__))
if result is None and exc is None:
raise ve_exc
elif exc is None:
exc = TypeError(
'error in %s._missing_: returned %r instead of None or a valid member'
% (cls.__name__, result)
)
exc.__context__ = ve_exc
raise exc
def _generate_next_value_(name, start, count, last_values):
for last_value in reversed(last_values):
@@ -599,42 +661,6 @@ class Enum(metaclass=EnumMeta):
"""The value of the Enum member."""
return self._value_
@classmethod
def _convert(cls, name, module, filter, source=None):
"""
Create a new Enum subclass that replaces a collection of global constants
"""
# convert all constants from source (or module) that pass filter() to
# a new Enum called name, and export the enum and its members back to
# module;
# also, replace the __reduce_ex__ method so unpickling works in
# previous Python versions
module_globals = vars(sys.modules[module])
if source:
source = vars(source)
else:
source = module_globals
# We use an OrderedDict of sorted source keys so that the
# _value2member_map is populated in the same order every time
# for a consistent reverse mapping of number to name when there
# are multiple names for the same number rather than varying
# between runs due to hash randomization of the module dictionary.
members = [
(name, source[name])
for name in source.keys()
if filter(name)]
try:
# sort by value
members.sort(key=lambda t: (t[1], t[0]))
except TypeError:
# unless some values aren't comparable, in which case sort by name
members.sort(key=lambda t: t[0])
cls = cls(name, members, module=module)
cls.__reduce_ex__ = _reduce_ex_by_name
module_globals.update(cls.__members__)
module_globals[name] = cls
return cls
class IntEnum(int, Enum):
"""Enum where members are also (and must be) ints"""
@@ -651,7 +677,7 @@ class Flag(Enum):
Generate the next value when not given.
name: the name of the member
start: the initital start value or None
start: the initial start value or None
count: the number of existing members
last_value: the last value assigned or None
"""
@@ -690,12 +716,16 @@ class Flag(Enum):
pseudo_member = object.__new__(cls)
pseudo_member._name_ = None
pseudo_member._value_ = value
cls._value2member_map_[value] = pseudo_member
# use setdefault in case another thread already created a composite
# with this value
pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
return pseudo_member
def __contains__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
raise TypeError(
"unsupported operand type(s) for 'in': '%s' and '%s'" % (
type(other).__qualname__, self.__class__.__qualname__))
return other._value_ & self._value_ == other._value_
def __repr__(self):
@@ -742,11 +772,10 @@ class Flag(Enum):
def __invert__(self):
members, uncovered = _decompose(self.__class__, self._value_)
inverted_members = [
m for m in self.__class__
if m not in members and not m._value_ & self._value_
]
inverted = reduce(_or_, inverted_members, self.__class__(0))
inverted = self.__class__(0)
for m in self.__class__:
if m not in members and not (m._value_ & self._value_):
inverted = inverted | m
return self.__class__(inverted)
@@ -785,7 +814,9 @@ class IntFlag(int, Flag):
pseudo_member = int.__new__(cls, value)
pseudo_member._name_ = None
pseudo_member._value_ = value
cls._value2member_map_[value] = pseudo_member
# use setdefault in case another thread already created a composite
# with this value
pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
return pseudo_member
def __or__(self, other):
@@ -835,18 +866,21 @@ def _decompose(flag, value):
# _decompose is only called if the value is not named
not_covered = value
negative = value < 0
# issue29167: wrap accesses to _value2member_map_ in a list to avoid race
# conditions between iterating over it and having more pseudo-
# members added to it
if negative:
# only check for named flags
flags_to_check = [
(m, v)
for v, m in flag._value2member_map_.items()
for v, m in list(flag._value2member_map_.items())
if m.name is not None
]
else:
# check for named flags and powers-of-two flags
flags_to_check = [
(m, v)
for v, m in flag._value2member_map_.items()
for v, m in list(flag._value2member_map_.items())
if m.name is not None or _power_of_two(v)
]
members = []
+192 -17
View File
@@ -60,8 +60,8 @@ EBADF = getattr(errno, 'EBADF', 9)
EAGAIN = getattr(errno, 'EAGAIN', 11)
EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
__all__ = ["fromfd", "getfqdn", "create_connection",
"AddressFamily", "SocketKind"]
__all__ = ["fromfd", "getfqdn", "create_connection", "create_server",
"has_dualstack_ipv6", "AddressFamily", "SocketKind"]
__all__.extend(os._get_exports_list(_socket))
# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for
@@ -70,22 +70,22 @@ __all__.extend(os._get_exports_list(_socket))
# in this module understands the enums and translates them back from integers
# where needed (e.g. .family property of a socket object).
IntEnum._convert(
IntEnum._convert_(
'AddressFamily',
__name__,
lambda C: C.isupper() and C.startswith('AF_'))
IntEnum._convert(
IntEnum._convert_(
'SocketKind',
__name__,
lambda C: C.isupper() and C.startswith('SOCK_'))
IntFlag._convert(
IntFlag._convert_(
'MsgFlag',
__name__,
lambda C: C.isupper() and C.startswith('MSG_'))
IntFlag._convert(
IntFlag._convert_(
'AddressInfo',
__name__,
lambda C: C.isupper() and C.startswith('AI_'))
@@ -109,21 +109,101 @@ _realsocket = socket
# WSA error codes
if sys.platform.lower().startswith("win"):
errorTab = {}
errorTab[6] = "Specified event object handle is invalid."
errorTab[8] = "Insufficient memory available."
errorTab[87] = "One or more parameters are invalid."
errorTab[995] = "Overlapped operation aborted."
errorTab[996] = "Overlapped I/O event object not in signaled state."
errorTab[997] = "Overlapped operation will complete later."
errorTab[10004] = "The operation was interrupted."
errorTab[10009] = "A bad file handle was passed."
errorTab[10013] = "Permission denied."
errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
errorTab[10022] = "An invalid operation was attempted."
errorTab[10024] = "Too many open files."
errorTab[10035] = "The socket operation would block"
errorTab[10036] = "A blocking operation is already in progress."
errorTab[10037] = "Operation already in progress."
errorTab[10038] = "Socket operation on nonsocket."
errorTab[10039] = "Destination address required."
errorTab[10040] = "Message too long."
errorTab[10041] = "Protocol wrong type for socket."
errorTab[10042] = "Bad protocol option."
errorTab[10043] = "Protocol not supported."
errorTab[10044] = "Socket type not supported."
errorTab[10045] = "Operation not supported."
errorTab[10046] = "Protocol family not supported."
errorTab[10047] = "Address family not supported by protocol family."
errorTab[10048] = "The network address is in use."
errorTab[10049] = "Cannot assign requested address."
errorTab[10050] = "Network is down."
errorTab[10051] = "Network is unreachable."
errorTab[10052] = "Network dropped connection on reset."
errorTab[10053] = "Software caused connection abort."
errorTab[10054] = "The connection has been reset."
errorTab[10055] = "No buffer space available."
errorTab[10056] = "Socket is already connected."
errorTab[10057] = "Socket is not connected."
errorTab[10058] = "The network has been shut down."
errorTab[10059] = "Too many references."
errorTab[10060] = "The operation timed out."
errorTab[10061] = "Connection refused."
errorTab[10062] = "Cannot translate name."
errorTab[10063] = "The name is too long."
errorTab[10064] = "The host is down."
errorTab[10065] = "The host is unreachable."
errorTab[10066] = "Directory not empty."
errorTab[10067] = "Too many processes."
errorTab[10068] = "User quota exceeded."
errorTab[10069] = "Disk quota exceeded."
errorTab[10070] = "Stale file handle reference."
errorTab[10071] = "Item is remote."
errorTab[10091] = "Network subsystem is unavailable."
errorTab[10092] = "Winsock.dll version out of range."
errorTab[10093] = "Successful WSAStartup not yet performed."
errorTab[10101] = "Graceful shutdown in progress."
errorTab[10102] = "No more results from WSALookupServiceNext."
errorTab[10103] = "Call has been canceled."
errorTab[10104] = "Procedure call table is invalid."
errorTab[10105] = "Service provider is invalid."
errorTab[10106] = "Service provider failed to initialize."
errorTab[10107] = "System call failure."
errorTab[10108] = "Service not found."
errorTab[10109] = "Class type not found."
errorTab[10110] = "No more results from WSALookupServiceNext."
errorTab[10111] = "Call was canceled."
errorTab[10112] = "Database query was refused."
errorTab[11001] = "Host not found."
errorTab[11002] = "Nonauthoritative host not found."
errorTab[11003] = "This is a nonrecoverable error."
errorTab[11004] = "Valid name, no data record requested type."
errorTab[11005] = "QoS receivers."
errorTab[11006] = "QoS senders."
errorTab[11007] = "No QoS senders."
errorTab[11008] = "QoS no receivers."
errorTab[11009] = "QoS request confirmed."
errorTab[11010] = "QoS admission error."
errorTab[11011] = "QoS policy failure."
errorTab[11012] = "QoS bad style."
errorTab[11013] = "QoS bad object."
errorTab[11014] = "QoS traffic control error."
errorTab[11015] = "QoS generic error."
errorTab[11016] = "QoS service type error."
errorTab[11017] = "QoS flowspec error."
errorTab[11018] = "Invalid QoS provider buffer."
errorTab[11019] = "Invalid QoS filter style."
errorTab[11020] = "Invalid QoS filter style."
errorTab[11021] = "Incorrect QoS filter count."
errorTab[11022] = "Invalid QoS object length."
errorTab[11023] = "Incorrect QoS flow count."
errorTab[11024] = "Unrecognized QoS object."
errorTab[11025] = "Invalid QoS policy object."
errorTab[11026] = "Invalid QoS flow descriptor."
errorTab[11027] = "Invalid QoS provider-specific flowspec."
errorTab[11028] = "Invalid QoS provider-specific filterspec."
errorTab[11029] = "Invalid QoS shape discard mode object."
errorTab[11030] = "Invalid QoS shaping rate object."
errorTab[11031] = "Reserved policy QoS element type."
__all__.append("errorTab")
@@ -136,11 +216,18 @@ class socket(_socket.socket):
__slots__ = ["__weakref__", "_io_refs", "_closed"]
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
# For user code address family and type values are IntEnum members, but
# for the underlying _socket.socket they're just integers. The
# constructor of _socket.socket converts the given argument to an
# integer automatically.
if fileno is None:
if family == -1:
family = AF_INET
if type == -1:
type = SOCK_STREAM
if proto == -1:
proto = 0
_socket.socket.__init__(self, family, type, proto, fileno)
self._io_refs = 0
self._closed = False
@@ -182,7 +269,7 @@ class socket(_socket.socket):
return s
def __getstate__(self):
raise TypeError("Cannot serialize socket object")
raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
def dup(self):
"""dup() -> socket object
@@ -203,11 +290,7 @@ class socket(_socket.socket):
For IP sockets, the address info is a pair (hostaddr, port).
"""
fd, addr = self._accept()
# If our type has the SOCK_NONBLOCK flag, we shouldn't pass it onto the
# new socket. We do not currently allow passing SOCK_NONBLOCK to
# accept4, so the returned socket is always blocking.
type = self.type & ~globals().get("SOCK_NONBLOCK", 0)
sock = socket(self.family, type, self.proto, fileno=fd)
sock = socket(self.family, self.type, self.proto, fileno=fd)
# Issue #7995: if no default timeout is set and the listening
# socket had a (non-zero) timeout, force the new socket in blocking
# mode to override platform-specific socket flags inheritance.
@@ -272,8 +355,8 @@ class socket(_socket.socket):
raise _GiveupOnSendfile(err) # not a regular file
if not fsize:
return 0 # empty file
blocksize = fsize if not count else count
# Truncate to 1GiB to avoid OverflowError, see bpo-38319.
blocksize = min(count or fsize, 2 ** 30)
timeout = self.gettimeout()
if timeout == 0:
raise ValueError("non-blocking sockets are not supported")
@@ -711,6 +794,8 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
if source_address:
sock.bind(source_address)
sock.connect(sa)
# Break explicitly a reference cycle
err = None
return sock
except error as _:
@@ -719,10 +804,100 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
sock.close()
if err is not None:
raise err
try:
raise err
finally:
# Break explicitly a reference cycle
err = None
else:
raise error("getaddrinfo returns an empty list")
def has_dualstack_ipv6():
"""Return True if the platform supports creating a SOCK_STREAM socket
which can handle both AF_INET and AF_INET6 (IPv4 / IPv6) connections.
"""
if not has_ipv6 \
or not hasattr(_socket, 'IPPROTO_IPV6') \
or not hasattr(_socket, 'IPV6_V6ONLY'):
return False
try:
with socket(AF_INET6, SOCK_STREAM) as sock:
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)
return True
except error:
return False
def create_server(address, *, family=AF_INET, backlog=None, reuse_port=False,
dualstack_ipv6=False):
"""Convenience function which creates a SOCK_STREAM type socket
bound to *address* (a 2-tuple (host, port)) and return the socket
object.
*family* should be either AF_INET or AF_INET6.
*backlog* is the queue size passed to socket.listen().
*reuse_port* dictates whether to use the SO_REUSEPORT socket option.
*dualstack_ipv6*: if true and the platform supports it, it will
create an AF_INET6 socket able to accept both IPv4 or IPv6
connections. When false it will explicitly disable this option on
platforms that enable it by default (e.g. Linux).
>>> with create_server(('', 8000)) as server:
... while True:
... conn, addr = server.accept()
... # handle new connection
"""
if reuse_port and not hasattr(_socket, "SO_REUSEPORT"):
raise ValueError("SO_REUSEPORT not supported on this platform")
if dualstack_ipv6:
if not has_dualstack_ipv6():
raise ValueError("dualstack_ipv6 not supported on this platform")
if family != AF_INET6:
raise ValueError("dualstack_ipv6 requires AF_INET6 family")
sock = socket(family, SOCK_STREAM)
try:
# Note about Windows. We don't set SO_REUSEADDR because:
# 1) It's unnecessary: bind() will succeed even in case of a
# previous closed socket on the same address and still in
# TIME_WAIT state.
# 2) If set, another socket is free to bind() on the same
# address, effectively preventing this one from accepting
# connections. Also, it may set the process in a state where
# it'll no longer respond to any signals or graceful kills.
# See: msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx
if os.name not in ('nt', 'cygwin') and \
hasattr(_socket, 'SO_REUSEADDR'):
try:
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
except error:
# Fail later on bind(), for platforms which may not
# support this option.
pass
if reuse_port:
sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
if has_ipv6 and family == AF_INET6:
if dualstack_ipv6:
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)
elif hasattr(_socket, "IPV6_V6ONLY") and \
hasattr(_socket, "IPPROTO_IPV6"):
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 1)
try:
sock.bind(address)
except error as err:
msg = '%s (while attempting to bind on address %r)' % \
(err.strerror, address)
raise error(err.errno, msg) from None
if backlog is None:
sock.listen()
else:
sock.listen(backlog)
return sock
except error:
sock.close()
raise
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.