Commit d9e2479b authored by Jason Madden's avatar Jason Madden

More removal of obsolete code.

parent 07035b7e
......@@ -427,6 +427,8 @@ def run_setup(ext_modules):
# leak checks. previously we had a hand-rolled version.
'objgraph',
# We still have some places we like to test with pkg_resources
'setuptools',
],
},
# It's always safe to pass the CFFI keyword, even if
......
......@@ -12,12 +12,6 @@ import sys
import os
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] >= 3
PY35 = sys.version_info[:2] >= (3, 5)
PY36 = sys.version_info[:2] >= (3, 6)
PY37 = sys.version_info[:2] >= (3, 7)
PY38 = sys.version_info[:2] >= (3, 8)
PY39 = sys.version_info[:2] >= (3, 9)
PY311 = sys.version_info[:2] >= (3, 11)
PYPY = hasattr(sys, 'pypy_version_info')
......@@ -30,20 +24,12 @@ PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON')
## Types
if PY3:
string_types = (str,)
integer_types = (int,)
text_type = str
native_path_types = (str, bytes)
thread_mod_name = '_thread'
else:
import __builtin__ # pylint:disable=import-error
string_types = (__builtin__.basestring,)
text_type = __builtin__.unicode
integer_types = (int, __builtin__.long)
native_path_types = string_types
thread_mod_name = 'thread'
string_types = (str,)
integer_types = (int,)
text_type = str
native_path_types = (str, bytes)
thread_mod_name = '_thread'
hostname_types = tuple(set(string_types + (bytearray, bytes)))
......@@ -51,27 +37,20 @@ def NativeStrIO():
import io
return io.BytesIO() if str is bytes else io.StringIO()
try:
from abc import ABC
except ImportError:
import abc
ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
del abc
from abc import ABC # pylint:disable=unused-import
## Exceptions
if PY3:
def reraise(t, value, tb=None): # pylint:disable=unused-argument
if value.__traceback__ is not tb and tb is not None:
raise value.with_traceback(tb)
raise value
def exc_clear():
pass
else:
from gevent._util_py2 import reraise # pylint:disable=import-error,no-name-in-module
reraise = reraise # export
exc_clear = sys.exc_clear
def reraise(t, value, tb=None): # pylint:disable=unused-argument
if value.__traceback__ is not tb and tb is not None:
raise value.with_traceback(tb)
raise value
def exc_clear():
pass
## import locks
try:
......@@ -86,127 +65,28 @@ imp_acquire_lock = imp.acquire_lock
imp_release_lock = imp.release_lock
## Functions
if PY3:
iteritems = dict.items
itervalues = dict.values
xrange = range
izip = zip
else:
iteritems = dict.iteritems # python 3: pylint:disable=no-member
itervalues = dict.itervalues # python 3: pylint:disable=no-member
xrange = __builtin__.xrange
from itertools import izip # python 3: pylint:disable=no-member,no-name-in-module
izip = izip
iteritems = dict.items
itervalues = dict.values
xrange = range
izip = zip
## The __fspath__ protocol
try:
from os import PathLike # pylint:disable=unused-import
except ImportError:
class PathLike(ABC):
@classmethod
def __subclasshook__(cls, subclass):
return hasattr(subclass, '__fspath__')
# fspath from 3.6 os.py, but modified to raise the same exceptions as the
# real native implementation.
# Define for testing
def _fspath(path):
"""
Return the path representation of a path-like object.
If str or bytes is passed in, it is returned unchanged. Otherwise the
os.PathLike interface is used to get the path representation. If the
path representation is not str or bytes, TypeError is raised. If the
provided path is not str, bytes, or os.PathLike, TypeError is raised.
"""
if isinstance(path, native_path_types):
return path
# Work from the object's type to match method resolution of other magic
# methods.
path_type = type(path)
try:
path_type_fspath = path_type.__fspath__
except AttributeError:
raise TypeError("expected str, bytes or os.PathLike object, "
"not " + path_type.__name__)
path_repr = path_type_fspath(path)
if isinstance(path_repr, native_path_types):
return path_repr
raise TypeError("expected {}.__fspath__() to return str or bytes, "
"not {}".format(path_type.__name__,
type(path_repr).__name__))
try:
from os import fspath # pylint: disable=unused-import,no-name-in-module
except ImportError:
# if not available, use the Python version as transparently as
# possible
fspath = _fspath
fspath.__name__ = 'fspath'
try:
from os import fsencode # pylint: disable=unused-import,no-name-in-module
except ImportError:
encoding = sys.getfilesystemencoding() or ('utf-8' if not WIN else 'mbcs')
errors = 'strict' if WIN and encoding == 'mbcs' else 'surrogateescape'
# Added in 3.2, so this is for Python 2.7. Note that it doesn't have
# sys.getfilesystemencodeerrors(), which was added in 3.6
def fsencode(filename):
"""Encode filename (an os.PathLike, bytes, or str) to the filesystem
encoding with 'surrogateescape' error handler, return bytes unchanged.
On Windows, use 'strict' error handler if the file system encoding is
'mbcs' (which is the default encoding).
"""
filename = fspath(filename) # Does type-checking of `filename`.
if isinstance(filename, bytes):
return filename
try:
return filename.encode(encoding, errors)
except LookupError:
# Can't encode it, and the error handler doesn't
# exist. Probably on Python 2 with an astral character.
# Not sure how to handle this.
raise UnicodeEncodeError("Can't encode path to filesystem encoding")
try:
from os import fsdecode # pylint:disable=unused-import
except ImportError:
def fsdecode(filename):
"""Decode filename (an os.PathLike, bytes, or str) from the filesystem
encoding with 'surrogateescape' error handler, return str unchanged. On
Windows, use 'strict' error handler if the file system encoding is
'mbcs' (which is the default encoding).
"""
filename = fspath(filename) # Does type-checking of `filename`.
if PY3 and isinstance(filename, bytes):
return filename.decode(encoding, errors)
return filename
## The __fspath__ protocol
from os import PathLike # pylint:disable=unused-import
from os import fspath
_fspath = fspath
from os import fsencode # pylint:disable=unused-import
from os import fsdecode # pylint:disable=unused-import
## Clocks
try:
# Python 3.3+ (PEP 418)
from time import perf_counter
from time import get_clock_info
from time import monotonic
perf_counter = perf_counter
monotonic = monotonic
get_clock_info = get_clock_info
except ImportError:
import time
if sys.platform == "win32":
perf_counter = time.clock # pylint:disable=no-member
else:
perf_counter = time.time
monotonic = perf_counter
def get_clock_info(_):
return 'Unknown'
# Python 3.3+ (PEP 418)
from time import perf_counter
from time import get_clock_info
from time import monotonic
perf_counter = perf_counter
monotonic = monotonic
get_clock_info = get_clock_info
## Monitoring
def get_this_psutil_process():
......
......@@ -14,7 +14,6 @@ import sys
import os
from gevent.hub import _get_hub_noargs as get_hub
from gevent._compat import PY2
from gevent._compat import integer_types
from gevent._compat import reraise
from gevent._compat import fspath
......@@ -393,18 +392,12 @@ class OpenDescriptor(object): # pylint:disable=too-many-instance-attributes
if not self.binary:
# Either native or text at this point.
if PY2 and self.native:
# Neither text mode nor binary mode specified.
if self.universal:
# universal was requested, e.g., 'rU'
result = UniversalNewlineBytesWrapper(result, line_buffering)
else:
# Python 2 and text mode, or Python 3 and either text or native (both are the same)
if not isinstance(raw, io.TextIOBase):
# Avoid double-wrapping a TextIOBase in another TextIOWrapper.
# That tends not to work. See https://github.com/gevent/gevent/issues/1542
result = io.TextIOWrapper(result, self.encoding, self.errors, self.newline,
line_buffering)
# Python 2 and text mode, or Python 3 and either text or native (both are the same)
if not isinstance(raw, io.TextIOBase):
# Avoid double-wrapping a TextIOBase in another TextIOWrapper.
# That tends not to work. See https://github.com/gevent/gevent/issues/1542
result = io.TextIOWrapper(result, self.encoding, self.errors, self.newline,
line_buffering)
if result is not raw or self._raw_object_is_new(raw):
# Set the mode, if possible, but only if we created a new
......
......@@ -12,7 +12,7 @@ from __future__ import absolute_import, print_function
import importlib
import sys
from gevent._compat import PY3
from gevent._compat import iteritems
from gevent._compat import imp_acquire_lock
from gevent._compat import imp_release_lock
......@@ -25,23 +25,20 @@ MAPPING = {
'gevent.local': '_threading_local',
'gevent.socket': 'socket',
'gevent.select': 'select',
'gevent.selectors': 'selectors' if PY3 else 'selectors2',
'gevent.selectors': 'selectors',
'gevent.ssl': 'ssl',
'gevent.thread': '_thread' if PY3 else 'thread',
'gevent.thread': '_thread',
'gevent.subprocess': 'subprocess',
'gevent.os': 'os',
'gevent.threading': 'threading',
'gevent.builtins': 'builtins' if PY3 else '__builtin__',
'gevent.builtins': 'builtins',
'gevent.signal': 'signal',
'gevent.time': 'time',
'gevent.queue': 'queue' if PY3 else 'Queue',
'gevent.queue': 'queue',
'gevent.contextvars': 'contextvars',
}
OPTIONAL_STDLIB_MODULES = frozenset() if PY3 else frozenset([
'selectors2',
])
OPTIONAL_STDLIB_MODULES = frozenset()
_PATCH_PREFIX = '__g_patched_module_'
def _collect_stdlib_gevent_modules():
......
......@@ -270,10 +270,16 @@ def getfqdn(name=''):
First the hostname returned by gethostbyaddr() is checked, then
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
.. versionchanged:: NEXT
The IPv6 generic address '::' now returns the result of
``gethostname``, like the IPv4 address '0.0.0.0'.
"""
# pylint: disable=undefined-variable
name = name.strip()
if not name or name == '0.0.0.0':
# IPv6 added in a late Python 3.10/3.11 patch release.
# https://github.com/python/cpython/issues/100374
if not name or name in ('0.0.0.0', '::'):
name = gethostname()
try:
hostname, aliases, _ = gethostbyaddr(name)
......
......@@ -13,13 +13,13 @@ import ssl as __ssl__
_ssl = __ssl__._ssl
import errno
import sys
from gevent.socket import socket, timeout_default
from gevent.socket import error as socket_error
from gevent.socket import timeout as _socket_timeout
from gevent._util import copy_globals
from gevent._compat import PY36
from weakref import ref as _wref
......@@ -49,8 +49,8 @@ from ssl import SSL_ERROR_EOF
from ssl import SSL_ERROR_WANT_READ
from ssl import SSL_ERROR_WANT_WRITE
from ssl import PROTOCOL_SSLv23
from ssl import SSLObject
from ssl import match_hostname
#from ssl import SSLObject
from ssl import CHANNEL_BINDING_TYPES
from ssl import CERT_REQUIRED
from ssl import DER_cert_to_PEM_cert
......@@ -674,32 +674,14 @@ class SSLSocket(socket):
raise
self._wait(self._write_event, timeout_exc=_SSLErrorHandshakeTimeout)
if sys.version_info[:2] < (3, 7) and self._context.check_hostname:
# In Python 3.7, the underlying OpenSSL name matching is used.
# The version implemented in Python doesn't understand IDNA encoding.
if not self.server_hostname:
raise ValueError("check_hostname needs server_hostname "
"argument")
match_hostname(self.getpeercert(), self.server_hostname) # pylint:disable=deprecated-method
if hasattr(SSLObject, '_create'):
# 3.7+, making it difficult to create these objects.
# There's a new type, _ssl.SSLSocket, that takes the
# place of SSLObject for self._sslobj. This one does it all.
def __create_sslobj(self, server_side=False, session=None):
return self.context._wrap_socket(
self._sock, server_side, self.server_hostname,
owner=self._sock, session=session
)
elif PY36: # 3.6
def __create_sslobj(self, server_side=False, session=None):
sslobj = self._context._wrap_socket(self._sock, server_side, self.server_hostname)
return SSLObject(sslobj, owner=self._sock, session=session)
else: # 3.5
def __create_sslobj(self, server_side=False, session=None): # pylint:disable=unused-argument
sslobj = self._context._wrap_socket(self._sock, server_side, self.server_hostname)
return SSLObject(sslobj, owner=self._sock)
# 3.7+, making it difficult to create these objects.
# There's a new type, _ssl.SSLSocket, that takes the
# place of SSLObject for self._sslobj. This one does it all.
def __create_sslobj(self, server_side=False, session=None):
return self.context._wrap_socket(
self._sock, server_side, self.server_hostname,
owner=self._sock, session=session
)
def _real_connect(self, addr, connect_ex):
if self.server_side:
......
......@@ -9,8 +9,6 @@ from collections import deque
from gevent import monkey
from gevent._compat import thread_mod_name
from gevent._compat import PY3
__all__ = [
'Lock',
......@@ -33,21 +31,10 @@ start_new_thread, Lock, get_thread_ident, = monkey.get_original(thread_mod_name,
#
#
# In all cases, a timeout value of -1 means "infinite". Sigh.
if PY3:
def acquire_with_timeout(lock, timeout=-1):
globals()['acquire_with_timeout'] = type(lock).acquire
return lock.acquire(timeout=timeout)
else:
def acquire_with_timeout(lock, timeout=-1,
_time=monkey.get_original('time', 'time'),
_sleep=monkey.get_original('time', 'sleep')):
deadline = _time() + timeout if timeout != -1 else None
while 1:
if lock.acquire(False): # Can we acquire non-blocking?
return True
if deadline is not None and _time() >= deadline:
return False
_sleep(0.005)
def acquire_with_timeout(lock, timeout=-1):
globals()['acquire_with_timeout'] = type(lock).acquire
return lock.acquire(timeout=timeout)
class _Condition(object):
# We could use libuv's ``uv_cond_wait`` to implement this whole
......
......@@ -18,8 +18,7 @@ from gevent.greenlet import Greenlet
from gevent.hub import getcurrent
from gevent.server import StreamServer
from gevent.pool import Pool
from gevent._compat import PY36
from gevent._compat import exc_clear
__all__ = [
'BackdoorServer',
......@@ -174,15 +173,13 @@ class BackdoorServer(StreamServer):
getcurrent().switch_in()
try:
console = InteractiveConsole(self._create_interactive_locals())
if PY36:
# Beginning in 3.6, the console likes to print "now exiting <class>"
# but probably our socket is already closed, so this just causes problems.
console.interact(banner=self.banner, exitmsg='') # pylint:disable=unexpected-keyword-arg
else:
console.interact(banner=self.banner)
# Beginning in 3.6, the console likes to print "now exiting <class>"
# but probably our socket is already closed, so this just causes problems.
console.interact(banner=self.banner, exitmsg='') # pylint:disable=unexpected-keyword-arg
except SystemExit:
# raised by quit(); obviously this cannot propagate.
exc_clear() # Python 2
pass
finally:
raw_file.close()
conn.close()
......
......@@ -5,25 +5,14 @@ from __future__ import absolute_import
import weakref
from gevent.lock import RLock
from gevent._compat import PY3
from gevent._compat import imp_acquire_lock
from gevent._compat import imp_release_lock
# Normally we'd have the "expected" case inside the try
# (Python 3, because Python 3 is the way forward). But
# under Python 2, the popular `future` library *also* provides
# a `builtins` module---which lacks the __import__ attribute.
# So we test for the old, deprecated version first
try: # Py2
import __builtin__ as __gbuiltins__
_allowed_module_name_types = (basestring,) # pylint:disable=undefined-variable
__target__ = '__builtin__'
except ImportError:
import builtins as __gbuiltins__ # pylint: disable=import-error
_allowed_module_name_types = (str,)
__target__ = 'builtins'
import builtins as __gbuiltins__
_allowed_module_name_types = (str,)
__target__ = 'builtins'
_import = __gbuiltins__.__import__
......@@ -121,11 +110,9 @@ def _lock_imports():
global __lock_imports
__lock_imports = True
if PY3:
__implements__ = []
__import__ = _import
else:
__implements__ = ['__import__']
__implements__ = []
__import__ = _import
__all__ = __implements__
......
......@@ -53,12 +53,12 @@ try:
except ImportError:
from collections import Mapping # pylint:disable=deprecated-class
from gevent._compat import PY37
from gevent._util import _NONE
from gevent.local import local
__stdlib_expected__ = __all__
__implements__ = __stdlib_expected__ if PY37 else None
__implements__ = __stdlib_expected__
# In the reference implementation, the interpreter level OS thread state
# is modified to contain a pointer to the current context. Obviously we can't
......
......@@ -130,7 +130,7 @@ def notify_and_call_entry_points(event):
entry_points = set(
ep
for ep
in ep_dict.get(event.ENTRY_POINT_NAME)
in ep_dict.get(event.ENTRY_POINT_NAME, ())
)
for plugin in entry_points:
......
......@@ -597,21 +597,7 @@ if local.__module__ == 'gevent.local':
# module has a different name than the pure-Python version and we can check for that.
# It's not as direct, but it works.
# So here we're not compiled
from gevent._compat import PYPY
from gevent._compat import PY2
if PYPY and PY2:
# The behaviour changed with no warning between PyPy2 7.3.2 and 7.3.3.
local.__new__ = __new__
try:
local() # <= 7.3.2
except TypeError:
# >= 7.3.3
local.__new__ = classmethod(__new__)
else:
local.__new__ = classmethod(__new__)
del PYPY
del PY2
local.__new__ = classmethod(__new__)
else: # pragma: no cover
# Make sure we revisit in case of changes to the (accelerator) module names.
if local.__module__ != 'gevent._gevent_clocal':
......
......@@ -12,7 +12,7 @@ from __future__ import print_function
from gevent.hub import getcurrent
from gevent._compat import PURE_PYTHON
from gevent._compat import PY2
# This is the one exception to the rule of where to
# import Semaphore, obviously
from gevent import monkey
......@@ -180,8 +180,6 @@ def _fixup_docstrings():
assert c.__doc__ == b.__doc__
for m in 'acquire', 'release', 'wait':
c_meth = getattr(c, m)
if PY2:
c_meth = c_meth.__func__
b_meth = getattr(b, m)
c_meth.__doc__ = b_meth.__doc__
......
This diff is collapsed.
......@@ -48,7 +48,6 @@ import sys
from gevent.hub import _get_hub_noargs as get_hub
from gevent.hub import reinit
from gevent._config import config
from gevent._compat import PY3
from gevent._util import copy_globals
import errno
......@@ -102,8 +101,6 @@ if fcntl:
except OSError as e:
if e.errno not in ignored_errors:
raise
if not PY3:
sys.exc_clear()
if hub is None:
hub = get_hub()
event = hub.loop.io(fd, 1)
......@@ -133,8 +130,6 @@ if fcntl:
except OSError as e:
if e.errno not in ignored_errors:
raise
if not PY3:
sys.exc_clear()
if hub is None:
hub = get_hub()
event = hub.loop.io(fd, 2)
......
......@@ -31,13 +31,10 @@ from gevent import socket
import gevent
from gevent.server import StreamServer
from gevent.hub import GreenletExit
from gevent._compat import PY3, reraise
from gevent._compat import reraise
from functools import partial
if PY3:
unquote_latin1 = partial(unquote, encoding='latin-1')
else:
unquote_latin1 = unquote
unquote_latin1 = partial(unquote, encoding='latin-1')
_no_undoc_members = True # Don't put undocumented things into sphinx
......@@ -89,8 +86,7 @@ def format_date_time(timestamp):
# Return a byte string, not a native string
year, month, day, hh, mm, ss, wd, _y, _z = time.gmtime(timestamp)
value = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (_WEEKDAYNAME[wd], day, _MONTHNAME[month], year, hh, mm, ss)
if PY3:
value = value.encode("latin-1")
value = value.encode("latin-1")
return value
......@@ -392,13 +388,9 @@ class WSGIHandler(object):
# pylint:disable=too-many-instance-attributes
protocol_version = 'HTTP/1.1'
if PY3:
# if we do like Py2, then headers_factory unconditionally
# becomes a bound method, meaning the fp argument becomes WSGIHandler
def MessageClass(self, *args):
return headers_factory(*args)
else:
MessageClass = headers_factory
def MessageClass(self, *args):
return headers_factory(*args)
# Attributes reset at various times for each request; not public
# documented. Class attributes to keep the constructor fast
......@@ -562,10 +554,10 @@ class WSGIHandler(object):
if self.request_version == "HTTP/1.1":
conntype = self.headers.get("Connection", "").lower()
self.close_connection = (conntype == 'close')
self.close_connection = (conntype == 'close') # pylint:disable=superfluous-parens
elif self.request_version == 'HTTP/1.0':
conntype = self.headers.get("Connection", "close").lower()
self.close_connection = (conntype != 'keep-alive')
self.close_connection = (conntype != 'keep-alive') # pylint:disable=superfluous-parens
else:
# XXX: HTTP 0.9. We should drop support
self.close_connection = True
......@@ -606,8 +598,7 @@ class WSGIHandler(object):
latin-1).
"""
line = self.rfile.readline(MAX_REQUEST_LINE)
if PY3:
line = line.decode('latin-1')
line = line.decode('latin-1')
return line
def handle_one_request(self):
......@@ -659,7 +650,7 @@ class WSGIHandler(object):
try:
self.requestline = self.read_requestline()
# Account for old subclasses that haven't done this
if PY3 and isinstance(self.requestline, bytes):
if isinstance(self.requestline, bytes):
self.requestline = self.requestline.decode('latin-1')
except socket.error:
# "Connection reset by peer" or other socket errors aren't interesting here
......@@ -720,8 +711,7 @@ class WSGIHandler(object):
if hasattr(self.result, '__len__'):
total_len = sum(len(chunk) for chunk in self.result)
total_len_str = str(total_len)
if PY3:
total_len_str = total_len_str.encode("latin-1")
total_len_str = total_len_str.encode("latin-1")
self.response_headers.append((b'Content-Length', total_len_str))
else:
self.response_use_chunked = (
......@@ -856,8 +846,8 @@ class WSGIHandler(object):
# Note: Some Python 2 implementations, like Jython, may allow non-octet (above 255) values
# in their str implementation; this is mentioned in the WSGI spec, but we don't
# run on any platform like that so we can assume that a str value is pure bytes.
response_headers.append((header if not PY3 else header.encode("latin-1"),
value if not PY3 else value.encode("latin-1")))
response_headers.append((header.encode("latin-1"),
value.encode("latin-1")))
except UnicodeEncodeError:
# If we get here, we're guaranteed to have a header and value
raise UnicodeError("Non-latin1 header", repr(header), repr(value))
......@@ -871,7 +861,7 @@ class WSGIHandler(object):
# code
code = int(status.split(' ', 1)[0])
self.status = status if not PY3 else status.encode("latin-1")
self.status = status.encode("latin-1")
self._orig_status = status # Preserve the native string for logging
self.response_headers = response_headers
self.code = code
......@@ -898,8 +888,7 @@ class WSGIHandler(object):
if self.code in (304, 204):
if self.provided_content_length is not None and self.provided_content_length != '0':
msg = 'Invalid Content-Length for %s response: %r (must be absent or zero)' % (self.code, self.provided_content_length)
if PY3:
msg = msg.encode('latin-1')
msg = msg.encode('latin-1')
raise self.ApplicationError(msg)
return self.write
......@@ -1012,8 +1001,6 @@ class WSGIHandler(object):
except socket.error as ex:
if ex.args[0] in self.ignored_socket_errors:
# See description of self.ignored_socket_errors.
if not PY3:
sys.exc_clear()
self.close_connection = True
else:
self.handle_error(*sys.exc_info())
......@@ -1032,8 +1019,6 @@ class WSGIHandler(object):
self.start_response(status, headers[:])
self.write(body)
except socket.error:
if not PY3:
sys.exc_clear()
self.close_connection = True
def _log_error(self, t, v, tb):
......@@ -1558,7 +1543,7 @@ class WSGIServer(StreamServer):
name = socket.getfqdn(address[0])
except socket.error:
name = str(address[0])
if PY3 and not isinstance(name, str):
if not isinstance(name, str):
name = name.decode('ascii')
self.environ['SERVER_NAME'] = name
self.environ.setdefault('SERVER_PORT', str(address[1]))
......
......@@ -25,7 +25,6 @@ from gevent._compat import string_types
from gevent._compat import text_type
from gevent._compat import hostname_types
from gevent._compat import integer_types
from gevent._compat import PY3
from gevent._compat import PYPY
from gevent._compat import MAC
......@@ -98,7 +97,7 @@ def _resolve_special(hostname, family):
class AbstractResolver(object):
HOSTNAME_ENCODING = 'idna' if PY3 else 'ascii'
HOSTNAME_ENCODING = 'idna'
_LOCAL_HOSTNAMES = (
b'localhost',
......
......@@ -4,8 +4,6 @@ from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from contextlib import closing
import sys
from _socket import error as SocketError
......@@ -17,7 +15,7 @@ from _socket import SOCK_DGRAM
from gevent.baseserver import BaseServer
from gevent.socket import EWOULDBLOCK
from gevent.socket import socket as GeventSocket
from gevent._compat import PYPY, PY3
from gevent._compat import PYPY
__all__ = ['StreamServer', 'DatagramServer']
......@@ -29,13 +27,9 @@ else:
DEFAULT_REUSE_ADDR = 1
if PY3:
# sockets and SSL sockets are context managers on Python 3
def _closing_socket(sock):
return sock
else:
# but they are not guaranteed to be so on Python 2
_closing_socket = closing
# sockets and SSL sockets are context managers on Python 3
def _closing_socket(sock):
return sock
class StreamServer(BaseServer):
......@@ -191,38 +185,21 @@ class StreamServer(BaseServer):
backlog = cls.backlog
return _tcp_listener(address, backlog=backlog, reuse_addr=cls.reuse_addr, family=family)
if PY3:
def do_read(self):
sock = self.socket
try:
fd, address = sock._accept()
except BlockingIOError: # python 2: pylint: disable=undefined-variable
if not sock.timeout:
return
raise
sock = GeventSocket(sock.family, sock.type, sock.proto, fileno=fd)
# XXX Python 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."
return sock, address
else:
def do_read(self):
try:
client_socket, address = self.socket.accept()
except SocketError as err:
if err.args[0] == EWOULDBLOCK:
return
raise
sockobj = GeventSocket(_sock=client_socket)
if PYPY:
# Undo the ref-count bump that the constructor
# did. We gave it ownership.
client_socket._drop()
return sockobj, address
def do_read(self):
sock = self.socket
try:
fd, address = sock._accept()
except BlockingIOError: # python 2: pylint: disable=undefined-variable
if not sock.timeout:
return
raise
sock = GeventSocket(sock.family, sock.type, sock.proto, fileno=fd)
# XXX Python 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."
return sock, address
def do_close(self, sock, *args):
# pylint:disable=arguments-differ
......
......@@ -13,16 +13,15 @@ as well as the constants from the :mod:`socket` module are imported into this mo
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
from gevent._compat import PY3
from gevent._compat import PY311
from gevent._compat import exc_clear
from gevent._util import copy_globals
if PY3:
from gevent import _socket3 as _source # python 2: pylint:disable=no-name-in-module
else:
from gevent import _socket2 as _source
from gevent import _socket3 as _source
# define some things we're expecting to overwrite; each module
# needs to define these
......
"""
Secure Sockets Layer (SSL/TLS) module.
"""
from gevent._compat import PY2
from gevent._util import copy_globals
# things we expect to override, here for static analysis
......@@ -9,27 +9,8 @@ def wrap_socket(_sock, **_kwargs):
# pylint:disable=unused-argument
raise NotImplementedError()
if PY2:
if hasattr(__import__('ssl'), 'SSLContext'):
# It's not sufficient to check for >= 2.7.9; some distributions
# have backported most of PEP 466. Try to accommodate them. See Issue #702.
# We're just about to import ssl anyway so it's fine to import it here, just
# don't pollute the namespace
from gevent import _sslgte279 as _source
else: # pragma: no cover
from gevent import _ssl2 as _source
import warnings
warnings.warn(
"This version of Python has an insecure SSL implementation. "
"gevent is no longer tested with it, and support will be removed "
"in gevent 1.5. Please use Python 2.7.9 or newer.",
DeprecationWarning,
stacklevel=2,
)
del warnings
else:
# Py3
from gevent import _ssl3 as _source # pragma: no cover
from gevent import _ssl3 as _source
copy_globals(_source, globals())
This diff is collapsed.
......@@ -115,7 +115,6 @@ from .skipping import skipOnPy310
from .skipping import skipOnPy3
from .skipping import skipWithoutResource
from .skipping import skipWithoutExternalNetwork
from .skipping import skipOnPy2
from .skipping import skipOnManylinux
from .skipping import skipOnMacOnCI
......
......@@ -45,7 +45,6 @@ skipOnPyPy3OnCI = _do_not_skip
skipOnPyPy3 = _do_not_skip
skipOnPyPyOnWindows = _do_not_skip
skipOnPy2 = unittest.skip if sysinfo.PY2 else _do_not_skip
skipOnPy3 = unittest.skip if sysinfo.PY3 else _do_not_skip
skipOnPy37 = unittest.skip if sysinfo.PY37 else _do_not_skip
skipOnPy310 = unittest.skip if sysinfo.PY310 else _do_not_skip
......
......@@ -17,18 +17,10 @@ try:
except ImportError:
GreenOpenDescriptor = None
from gevent._compat import PY2
from gevent._compat import PY3
from gevent._compat import text_type
import gevent.testing as greentest
from gevent.testing import sysinfo
try:
ResourceWarning # pylint:disable=used-before-assignment
except NameError:
class ResourceWarning(Warning):
"Python 2 fallback"
# pylint:disable=unspecified-encoding
......@@ -136,11 +128,9 @@ class TestFileObjectBlock(CleanupMixin,
with open(path, 'rb') as f_raw:
f = self._makeOne(f_raw, 'rb', close=False)
if PY3 or hasattr(f, 'seekable'):
# On Python 3, all objects should have seekable.
# On Python 2, only our custom objects do.
self.assertTrue(f.seekable())
# On Python 3, all objects should have seekable.
# On Python 2, only our custom objects do.
self.assertTrue(f.seekable())
f.seek(15)
self.assertEqual(15, f.tell())
......@@ -169,7 +159,7 @@ class TestFileObjectBlock(CleanupMixin,
else:
# Note that we don't use ``io.open()`` for the raw file,
# on Python 2. We want 'r' to mean what the usual call to open() means.
opener = io.open if PY3 else open
opener = io.open
with opener(path, open_mode, **open_kwargs) as raw:
with self._makeOne(raw) as f:
gevent_data = getattr(f, meth)()
......@@ -190,7 +180,7 @@ class TestFileObjectBlock(CleanupMixin,
'r+',
buffering=5, encoding='utf-8'
)
self.assertIsInstance(gevent_data, text_type)
self.assertIsInstance(gevent_data, str)
@skipUnlessWorksWithRegularFiles
def test_does_not_leak_on_exception(self):
......@@ -341,7 +331,7 @@ class ConcurrentFileObjectMixin(object):
self.addCleanup(os.close, w)
reader = self._makeOne(r)
self._close_on_teardown(reader)
self.assertEqual(PY2, hasattr(reader, 'read1'))
self.assertFalse(hasattr(reader, 'read1'))
def test_bufsize_0(self):
# Issue #840
......
import sys
import unittest
from gevent.testing import skipOnPy2
class TestSubnormalFloatsAreNotDisabled(unittest.TestCase):
@skipOnPy2('This test always fails on Python 2')
def test_subnormal_is_not_zero(self):
# Enabling the -Ofast compiler flag resulted in subnormal floats getting
# disabled the moment when gevent was imported. This impacted libraries
......@@ -21,7 +19,7 @@ class TestSubnormalFloatsAreNotDisabled(unittest.TestCase):
# `sys.float_info.min` is the minimum representable positive normalized
# float, so dividing it by two gives us a positive subnormal float,
# as long as subnormals floats are not disabled.
self.assertGreater(sys.float_info.min / 2, 0)
self.assertGreater(sys.float_info.min / 2, 0.0)
if __name__ == "__main__":
......
......@@ -104,21 +104,19 @@ class TestRun(greentest.TestCase):
# Also, occasionally, they get '3' instead of '2' for the number of threads.
# That could have something to do with...? Most commonly that's PyPy, but
# sometimes CPython. Again, haven't reproduced.
@greentest.skipOnPy2("lost sys.stderr sometimes")
# Not relevant since Py2 has been dropped.
def test_threadpool_in_patched_after_patch(self):
# Issue 1484
# If we don't have this correct, then we get exceptions
out = self._run(os.path.join('monkey_package', 'threadpool_monkey_patches.py'))
self.assertEqual(out, ['False', '2'])
@greentest.skipOnPy2("lost sys.stderr sometimes")
def test_threadpool_in_patched_after_patch_module(self):
# Issue 1484
# If we don't have this correct, then we get exceptions
out = self._run('monkey_package.threadpool_monkey_patches', module=True)
self.assertEqual(out, ['False', '2'])
@greentest.skipOnPy2("lost sys.stderr sometimes")
def test_threadpool_not_patched_after_patch_module(self):
# Issue 1484
# If we don't have this correct, then we get exceptions
......
......@@ -17,9 +17,6 @@ from gevent.tests.test__selectors import SelectorTestMixin
class TestSelectors(SelectorTestMixin, greentest.TestCase):
@greentest.skipOnPy2(
'selectors2 backport does not use _select'
)
@greentest.skipOnWindows(
"SelectSelector._select is a normal function on Windows"
)
......
......@@ -11,6 +11,7 @@ class Test(unittest.TestCase):
# Issue 1108: Python 2, importing pkg_resources,
# as is done for namespace packages, imports ssl,
# leading to an unwanted SSL warning.
# This is a deprecated API though.
__import__('pkg_resources')
from gevent import monkey
......
......@@ -111,7 +111,6 @@ class TestPopen(greentest.TestCase):
'pineapple\n\xff\xff\xf2\xf9\n')
@greentest.skipOnWindows("Windows IO is weird; this doesn't raise")
@greentest.skipOnPy2("Only Python 2 decodes")
def test_communicate_undecodable(self):
# If the subprocess writes non-decodable data, `communicate` raises the
# same UnicodeDecodeError that the stdlib does, instead of
......
......@@ -9,7 +9,6 @@ Implementation of the standard :mod:`thread` module that spawns greenlets.
:class:`gevent.Greenlet` class or :func:`gevent.spawn`.
"""
from __future__ import absolute_import
import sys
__implements__ = [
'allocate_lock',
......@@ -22,31 +21,23 @@ __implements__ = [
]
__imports__ = ['error']
if sys.version_info[0] == 2:
import thread as __thread__ # pylint:disable=import-error
PY2 = True
PY3 = False
# Name the `future` backport that might already have been imported;
# Importing `pkg_resources` imports this, for example.
__alternate_targets__ = ('_thread',)
else:
import _thread as __thread__ # pylint:disable=import-error
PY2 = False
PY3 = True
__target__ = '_thread'
__imports__ += [
'TIMEOUT_MAX',
'allocate',
'exit_thread',
'interrupt_main',
'start_new'
]
if sys.version_info[:2] >= (3, 8):
# We can't actually produce a value that "may be used
# to identify this particular thread system-wide", right?
# Even if we could, I imagine people will want to pass this to
# non-Python (native) APIs, so we shouldn't mess with it.
__imports__.append('get_native_id')
import _thread as __thread__ # pylint:disable=import-error
__target__ = '_thread'
__imports__ += [
'TIMEOUT_MAX',
'allocate',
'exit_thread',
'interrupt_main',
'start_new'
]
# We can't actually produce a value that "may be used
# to identify this particular thread system-wide", right?
# Even if we could, I imagine people will want to pass this to
# non-Python (native) APIs, so we shouldn't mess with it.
__imports__.append('get_native_id')
error = __thread__.error
......@@ -63,7 +54,6 @@ from gevent.local import local as _local
from gevent.exceptions import LoopExit
if hasattr(__thread__, 'RLock'):
assert PY3 or PYPY
# Added in Python 3.4, backported to PyPy 2.7-7.0
__imports__.append("RLock")
......@@ -88,13 +78,11 @@ class LockType(BoundedSemaphore):
# and any other API changes we need to make to match behaviour
_OVER_RELEASE_ERROR = __thread__.error
if PYPY and PY3:
if PYPY:
_OVER_RELEASE_ERROR = RuntimeError
if PY3:
_TIMEOUT_MAX = __thread__.TIMEOUT_MAX # python 2: pylint:disable=no-member
else:
_TIMEOUT_MAX = 9223372036.0
_TIMEOUT_MAX = __thread__.TIMEOUT_MAX # pylint:disable=no-member
def acquire(self, blocking=True, timeout=-1):
# This is the Python 3 signature.
......
......@@ -50,8 +50,7 @@ from gevent.thread import get_ident as _get_ident
from gevent.hub import sleep as _sleep, getcurrent
from gevent.lock import RLock
from gevent._compat import PY3
from gevent._compat import PYPY
from gevent._util import LazyOnClass
# Exports, prevent unused import warnings.
......@@ -168,46 +167,45 @@ else:
return main_threads[0]
if PY3:
# XXX: Issue 18808 breaks us on Python 3.4+.
# Thread objects now expect a callback from the interpreter itself
# (threadmodule.c:release_sentinel) when the C-level PyThreadState
# object is being deallocated. Because this never happens
# when a greenlet exits, join() and friends will block forever.
# Fortunately this is easy to fix: just ensure that the allocation of the
# lock, _set_sentinel, creates a *gevent* lock, and release it when
# we're done. The main _shutdown code is in Python and deals with
# this gracefully.
class Thread(__threading__.Thread):
# XXX: Issue 18808 breaks us on Python 3.4+.
# Thread objects now expect a callback from the interpreter itself
# (threadmodule.c:release_sentinel) when the C-level PyThreadState
# object is being deallocated. Because this never happens
# when a greenlet exits, join() and friends will block forever.
# Fortunately this is easy to fix: just ensure that the allocation of the
# lock, _set_sentinel, creates a *gevent* lock, and release it when
# we're done. The main _shutdown code is in Python and deals with
# this gracefully.
def _set_tstate_lock(self):
super(Thread, self)._set_tstate_lock()
greenlet = getcurrent()
greenlet.rawlink(self.__greenlet_finished)
class Thread(__threading__.Thread):
def __greenlet_finished(self, _):
if self._tstate_lock:
self._tstate_lock.release()
self._stop()
def _set_tstate_lock(self):
super(Thread, self)._set_tstate_lock()
greenlet = getcurrent()
greenlet.rawlink(self.__greenlet_finished)
__implements__.append('Thread')
def __greenlet_finished(self, _):
if self._tstate_lock:
self._tstate_lock.release()
self._stop()
class Timer(Thread, __threading__.Timer): # pylint:disable=abstract-method,inherit-non-class
pass
__implements__.append('Thread')
class Timer(Thread, __threading__.Timer): # pylint:disable=abstract-method,inherit-non-class
pass
__implements__.append('Timer')
__implements__.append('Timer')
_set_sentinel = allocate_lock
__implements__.append('_set_sentinel')
# The main thread is patched up with more care
# in _gevent_will_monkey_patch
_set_sentinel = allocate_lock
__implements__.append('_set_sentinel')
# The main thread is patched up with more care
# in _gevent_will_monkey_patch
if PY3:
__implements__.remove('_get_ident')
__implements__.append('get_ident')
get_ident = _get_ident
__implements__.remove('_sleep')
__implements__.remove('_get_ident')
__implements__.append('get_ident')
get_ident = _get_ident
__implements__.remove('_sleep')
if hasattr(__threading__, '_CRLock'):
# Python 3 changed the implementation of threading.RLock
......@@ -219,7 +217,6 @@ if hasattr(__threading__, '_CRLock'):
# if the imported _CRLock is None; this arranges for that to be the case.
# This was also backported to PyPy 2.7-7.0
assert PY3 or PYPY, "Unsupported Python version"
_CRLock = None
__implements__.append('_CRLock')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment