mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Update enum and socket to versions from CPython 3.8.3
This commit is contained in:
2 files changed
+333
-124
No files matched your search
Vendored
+141
-107
@@ -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 = []
|
||||
|
||||
Vendored
+192
-17
@@ -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.
|
||||
|
||||
|
||||
Reference in new issue
Block a user