Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gevent
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gevent
Commits
d9e2479b
Commit
d9e2479b
authored
Jul 07, 2023
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More removal of obsolete code.
parent
07035b7e
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
437 additions
and
813 deletions
+437
-813
setup.py
setup.py
+2
-0
src/gevent/_compat.py
src/gevent/_compat.py
+35
-155
src/gevent/_fileobjectcommon.py
src/gevent/_fileobjectcommon.py
+6
-13
src/gevent/_patcher.py
src/gevent/_patcher.py
+6
-9
src/gevent/_socketcommon.py
src/gevent/_socketcommon.py
+7
-1
src/gevent/_ssl3.py
src/gevent/_ssl3.py
+12
-30
src/gevent/_threading.py
src/gevent/_threading.py
+4
-17
src/gevent/backdoor.py
src/gevent/backdoor.py
+6
-9
src/gevent/builtins.py
src/gevent/builtins.py
+6
-19
src/gevent/contextvars.py
src/gevent/contextvars.py
+2
-2
src/gevent/events.py
src/gevent/events.py
+1
-1
src/gevent/local.py
src/gevent/local.py
+1
-15
src/gevent/lock.py
src/gevent/lock.py
+1
-3
src/gevent/monkey.py
src/gevent/monkey.py
+107
-151
src/gevent/os.py
src/gevent/os.py
+0
-5
src/gevent/pywsgi.py
src/gevent/pywsgi.py
+16
-31
src/gevent/resolver/__init__.py
src/gevent/resolver/__init__.py
+1
-2
src/gevent/server.py
src/gevent/server.py
+19
-42
src/gevent/socket.py
src/gevent/socket.py
+4
-5
src/gevent/ssl.py
src/gevent/ssl.py
+3
-22
src/gevent/subprocess.py
src/gevent/subprocess.py
+137
-186
src/gevent/testing/__init__.py
src/gevent/testing/__init__.py
+0
-1
src/gevent/testing/skipping.py
src/gevent/testing/skipping.py
+0
-1
src/gevent/tests/test__fileobject.py
src/gevent/tests/test__fileobject.py
+6
-16
src/gevent/tests/test__issue1864.py
src/gevent/tests/test__issue1864.py
+1
-3
src/gevent/tests/test__monkey_module_run.py
src/gevent/tests/test__monkey_module_run.py
+1
-3
src/gevent/tests/test__monkey_selectors.py
src/gevent/tests/test__monkey_selectors.py
+0
-3
src/gevent/tests/test__monkey_ssl_warning.py
src/gevent/tests/test__monkey_ssl_warning.py
+1
-0
src/gevent/tests/test__subprocess.py
src/gevent/tests/test__subprocess.py
+0
-1
src/gevent/thread.py
src/gevent/thread.py
+20
-32
src/gevent/threading.py
src/gevent/threading.py
+32
-35
No files found.
setup.py
View file @
d9e2479b
...
@@ -427,6 +427,8 @@ def run_setup(ext_modules):
...
@@ -427,6 +427,8 @@ def run_setup(ext_modules):
# leak checks. previously we had a hand-rolled version.
# leak checks. previously we had a hand-rolled version.
'objgraph'
,
'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
# It's always safe to pass the CFFI keyword, even if
...
...
src/gevent/_compat.py
View file @
d9e2479b
...
@@ -12,12 +12,6 @@ import sys
...
@@ -12,12 +12,6 @@ import sys
import
os
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
)
PY39
=
sys
.
version_info
[:
2
]
>=
(
3
,
9
)
PY311
=
sys
.
version_info
[:
2
]
>=
(
3
,
11
)
PY311
=
sys
.
version_info
[:
2
]
>=
(
3
,
11
)
PYPY
=
hasattr
(
sys
,
'pypy_version_info'
)
PYPY
=
hasattr
(
sys
,
'pypy_version_info'
)
...
@@ -30,20 +24,12 @@ PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON')
...
@@ -30,20 +24,12 @@ PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON')
## Types
## Types
if
PY3
:
string_types
=
(
str
,)
string_types
=
(
str
,)
integer_types
=
(
int
,)
integer_types
=
(
int
,)
text_type
=
str
text_type
=
str
native_path_types
=
(
str
,
bytes
)
native_path_types
=
(
str
,
bytes
)
thread_mod_name
=
'_thread'
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'
hostname_types
=
tuple
(
set
(
string_types
+
(
bytearray
,
bytes
)))
hostname_types
=
tuple
(
set
(
string_types
+
(
bytearray
,
bytes
)))
...
@@ -51,27 +37,20 @@ def NativeStrIO():
...
@@ -51,27 +37,20 @@ def NativeStrIO():
import
io
import
io
return
io
.
BytesIO
()
if
str
is
bytes
else
io
.
StringIO
()
return
io
.
BytesIO
()
if
str
is
bytes
else
io
.
StringIO
()
try
:
from
abc
import
ABC
from
abc
import
ABC
# pylint:disable=unused-import
except
ImportError
:
import
abc
ABC
=
abc
.
ABCMeta
(
'ABC'
,
(
object
,),
{
'__slots__'
:
()})
del
abc
## Exceptions
## Exceptions
if
PY3
:
def
reraise
(
t
,
value
,
tb
=
None
):
# pylint:disable=unused-argument
def
reraise
(
t
,
value
,
tb
=
None
):
# pylint:disable=unused-argument
if
value
.
__traceback__
is
not
tb
and
tb
is
not
None
:
if
value
.
__traceback__
is
not
tb
and
tb
is
not
None
:
raise
value
.
with_traceback
(
tb
)
raise
value
.
with_traceback
(
tb
)
raise
value
raise
value
def
exc_clear
():
def
exc_clear
():
pass
pass
else
:
from
gevent._util_py2
import
reraise
# pylint:disable=import-error,no-name-in-module
reraise
=
reraise
# export
exc_clear
=
sys
.
exc_clear
## import locks
## import locks
try
:
try
:
...
@@ -86,127 +65,28 @@ imp_acquire_lock = imp.acquire_lock
...
@@ -86,127 +65,28 @@ imp_acquire_lock = imp.acquire_lock
imp_release_lock
=
imp
.
release_lock
imp_release_lock
=
imp
.
release_lock
## Functions
## Functions
if
PY3
:
iteritems
=
dict
.
items
iteritems
=
dict
.
items
itervalues
=
dict
.
values
itervalues
=
dict
.
values
xrange
=
range
xrange
=
range
izip
=
zip
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
## The __fspath__ protocol
try
:
## The __fspath__ protocol
from
os
import
PathLike
# pylint:disable=unused-import
from
os
import
PathLike
# pylint:disable=unused-import
except
ImportError
:
from
os
import
fspath
class
PathLike
(
ABC
):
_fspath
=
fspath
@
classmethod
from
os
import
fsencode
# pylint:disable=unused-import
def
__subclasshook__
(
cls
,
subclass
):
from
os
import
fsdecode
# pylint:disable=unused-import
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
## Clocks
## Clocks
try
:
# Python 3.3+ (PEP 418)
# Python 3.3+ (PEP 418)
from
time
import
perf_counter
from
time
import
perf_counter
from
time
import
get_clock_info
from
time
import
get_clock_info
from
time
import
monotonic
from
time
import
monotonic
perf_counter
=
perf_counter
perf_counter
=
perf_counter
monotonic
=
monotonic
monotonic
=
monotonic
get_clock_info
=
get_clock_info
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'
## Monitoring
## Monitoring
def
get_this_psutil_process
():
def
get_this_psutil_process
():
...
...
src/gevent/_fileobjectcommon.py
View file @
d9e2479b
...
@@ -14,7 +14,6 @@ import sys
...
@@ -14,7 +14,6 @@ import sys
import
os
import
os
from
gevent.hub
import
_get_hub_noargs
as
get_hub
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
integer_types
from
gevent._compat
import
reraise
from
gevent._compat
import
reraise
from
gevent._compat
import
fspath
from
gevent._compat
import
fspath
...
@@ -393,18 +392,12 @@ class OpenDescriptor(object): # pylint:disable=too-many-instance-attributes
...
@@ -393,18 +392,12 @@ class OpenDescriptor(object): # pylint:disable=too-many-instance-attributes
if
not
self
.
binary
:
if
not
self
.
binary
:
# Either native or text at this point.
# Either native or text at this point.
if
PY2
and
self
.
native
:
# Python 2 and text mode, or Python 3 and either text or native (both are the same)
# Neither text mode nor binary mode specified.
if
not
isinstance
(
raw
,
io
.
TextIOBase
):
if
self
.
universal
:
# Avoid double-wrapping a TextIOBase in another TextIOWrapper.
# universal was requested, e.g., 'rU'
# That tends not to work. See https://github.com/gevent/gevent/issues/1542
result
=
UniversalNewlineBytesWrapper
(
result
,
line_buffering
)
result
=
io
.
TextIOWrapper
(
result
,
self
.
encoding
,
self
.
errors
,
self
.
newline
,
else
:
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
):
if
result
is
not
raw
or
self
.
_raw_object_is_new
(
raw
):
# Set the mode, if possible, but only if we created a new
# Set the mode, if possible, but only if we created a new
...
...
src/gevent/_patcher.py
View file @
d9e2479b
...
@@ -12,7 +12,7 @@ from __future__ import absolute_import, print_function
...
@@ -12,7 +12,7 @@ from __future__ import absolute_import, print_function
import
importlib
import
importlib
import
sys
import
sys
from
gevent._compat
import
PY3
from
gevent._compat
import
iteritems
from
gevent._compat
import
iteritems
from
gevent._compat
import
imp_acquire_lock
from
gevent._compat
import
imp_acquire_lock
from
gevent._compat
import
imp_release_lock
from
gevent._compat
import
imp_release_lock
...
@@ -25,23 +25,20 @@ MAPPING = {
...
@@ -25,23 +25,20 @@ MAPPING = {
'gevent.local'
:
'_threading_local'
,
'gevent.local'
:
'_threading_local'
,
'gevent.socket'
:
'socket'
,
'gevent.socket'
:
'socket'
,
'gevent.select'
:
'select'
,
'gevent.select'
:
'select'
,
'gevent.selectors'
:
'selectors'
if
PY3
else
'selectors2'
,
'gevent.selectors'
:
'selectors'
,
'gevent.ssl'
:
'ssl'
,
'gevent.ssl'
:
'ssl'
,
'gevent.thread'
:
'_thread'
if
PY3
else
'thread'
,
'gevent.thread'
:
'_thread'
,
'gevent.subprocess'
:
'subprocess'
,
'gevent.subprocess'
:
'subprocess'
,
'gevent.os'
:
'os'
,
'gevent.os'
:
'os'
,
'gevent.threading'
:
'threading'
,
'gevent.threading'
:
'threading'
,
'gevent.builtins'
:
'builtins'
if
PY3
else
'__builtin__'
,
'gevent.builtins'
:
'builtins'
,
'gevent.signal'
:
'signal'
,
'gevent.signal'
:
'signal'
,
'gevent.time'
:
'time'
,
'gevent.time'
:
'time'
,
'gevent.queue'
:
'queue'
if
PY3
else
'Queue'
,
'gevent.queue'
:
'queue'
,
'gevent.contextvars'
:
'contextvars'
,
'gevent.contextvars'
:
'contextvars'
,
}
}
OPTIONAL_STDLIB_MODULES
=
frozenset
()
if
PY3
else
frozenset
([
OPTIONAL_STDLIB_MODULES
=
frozenset
()
'selectors2'
,
])
_PATCH_PREFIX
=
'__g_patched_module_'
_PATCH_PREFIX
=
'__g_patched_module_'
def
_collect_stdlib_gevent_modules
():
def
_collect_stdlib_gevent_modules
():
...
...
src/gevent/_socketcommon.py
View file @
d9e2479b
...
@@ -270,10 +270,16 @@ def getfqdn(name=''):
...
@@ -270,10 +270,16 @@ def getfqdn(name=''):
First the hostname returned by gethostbyaddr() is checked, then
First the hostname returned by gethostbyaddr() is checked, then
possibly existing aliases. In case no FQDN is available, hostname
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
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
# pylint: disable=undefined-variable
name
=
name
.
strip
()
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
()
name
=
gethostname
()
try
:
try
:
hostname
,
aliases
,
_
=
gethostbyaddr
(
name
)
hostname
,
aliases
,
_
=
gethostbyaddr
(
name
)
...
...
src/gevent/_ssl3.py
View file @
d9e2479b
...
@@ -13,13 +13,13 @@ import ssl as __ssl__
...
@@ -13,13 +13,13 @@ import ssl as __ssl__
_ssl
=
__ssl__
.
_ssl
_ssl
=
__ssl__
.
_ssl
import
errno
import
errno
import
sys
from
gevent.socket
import
socket
,
timeout_default
from
gevent.socket
import
socket
,
timeout_default
from
gevent.socket
import
error
as
socket_error
from
gevent.socket
import
error
as
socket_error
from
gevent.socket
import
timeout
as
_socket_timeout
from
gevent.socket
import
timeout
as
_socket_timeout
from
gevent._util
import
copy_globals
from
gevent._util
import
copy_globals
from
gevent._compat
import
PY36
from
weakref
import
ref
as
_wref
from
weakref
import
ref
as
_wref
...
@@ -49,8 +49,8 @@ from ssl import SSL_ERROR_EOF
...
@@ -49,8 +49,8 @@ from ssl import SSL_ERROR_EOF
from
ssl
import
SSL_ERROR_WANT_READ
from
ssl
import
SSL_ERROR_WANT_READ
from
ssl
import
SSL_ERROR_WANT_WRITE
from
ssl
import
SSL_ERROR_WANT_WRITE
from
ssl
import
PROTOCOL_SSLv23
from
ssl
import
PROTOCOL_SSLv23
from
ssl
import
SSLObject
#
from ssl import SSLObject
from
ssl
import
match_hostname
from
ssl
import
CHANNEL_BINDING_TYPES
from
ssl
import
CHANNEL_BINDING_TYPES
from
ssl
import
CERT_REQUIRED
from
ssl
import
CERT_REQUIRED
from
ssl
import
DER_cert_to_PEM_cert
from
ssl
import
DER_cert_to_PEM_cert
...
@@ -674,32 +674,14 @@ class SSLSocket(socket):
...
@@ -674,32 +674,14 @@ class SSLSocket(socket):
raise
raise
self
.
_wait
(
self
.
_write_event
,
timeout_exc
=
_SSLErrorHandshakeTimeout
)
self
.
_wait
(
self
.
_write_event
,
timeout_exc
=
_SSLErrorHandshakeTimeout
)
if
sys
.
version_info
[:
2
]
<
(
3
,
7
)
and
self
.
_context
.
check_hostname
:
# 3.7+, making it difficult to create these objects.
# In Python 3.7, the underlying OpenSSL name matching is used.
# There's a new type, _ssl.SSLSocket, that takes the
# The version implemented in Python doesn't understand IDNA encoding.
# place of SSLObject for self._sslobj. This one does it all.
if
not
self
.
server_hostname
:
def
__create_sslobj
(
self
,
server_side
=
False
,
session
=
None
):
raise
ValueError
(
"check_hostname needs server_hostname "
return
self
.
context
.
_wrap_socket
(
"argument"
)
self
.
_sock
,
server_side
,
self
.
server_hostname
,
match_hostname
(
self
.
getpeercert
(),
self
.
server_hostname
)
# pylint:disable=deprecated-method
owner
=
self
.
_sock
,
session
=
session
)
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
)
def
_real_connect
(
self
,
addr
,
connect_ex
):
def
_real_connect
(
self
,
addr
,
connect_ex
):
if
self
.
server_side
:
if
self
.
server_side
:
...
...
src/gevent/_threading.py
View file @
d9e2479b
...
@@ -9,8 +9,6 @@ from collections import deque
...
@@ -9,8 +9,6 @@ from collections import deque
from
gevent
import
monkey
from
gevent
import
monkey
from
gevent._compat
import
thread_mod_name
from
gevent._compat
import
thread_mod_name
from
gevent._compat
import
PY3
__all__
=
[
__all__
=
[
'Lock'
,
'Lock'
,
...
@@ -33,21 +31,10 @@ start_new_thread, Lock, get_thread_ident, = monkey.get_original(thread_mod_name,
...
@@ -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.
# In all cases, a timeout value of -1 means "infinite". Sigh.
if
PY3
:
def
acquire_with_timeout
(
lock
,
timeout
=-
1
):
def
acquire_with_timeout
(
lock
,
timeout
=-
1
):
globals
()[
'acquire_with_timeout'
]
=
type
(
lock
).
acquire
globals
()[
'acquire_with_timeout'
]
=
type
(
lock
).
acquire
return
lock
.
acquire
(
timeout
=
timeout
)
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
)
class
_Condition
(
object
):
class
_Condition
(
object
):
# We could use libuv's ``uv_cond_wait`` to implement this whole
# We could use libuv's ``uv_cond_wait`` to implement this whole
...
...
src/gevent/backdoor.py
View file @
d9e2479b
...
@@ -18,8 +18,7 @@ from gevent.greenlet import Greenlet
...
@@ -18,8 +18,7 @@ from gevent.greenlet import Greenlet
from
gevent.hub
import
getcurrent
from
gevent.hub
import
getcurrent
from
gevent.server
import
StreamServer
from
gevent.server
import
StreamServer
from
gevent.pool
import
Pool
from
gevent.pool
import
Pool
from
gevent._compat
import
PY36
from
gevent._compat
import
exc_clear
__all__
=
[
__all__
=
[
'BackdoorServer'
,
'BackdoorServer'
,
...
@@ -174,15 +173,13 @@ class BackdoorServer(StreamServer):
...
@@ -174,15 +173,13 @@ class BackdoorServer(StreamServer):
getcurrent
().
switch_in
()
getcurrent
().
switch_in
()
try
:
try
:
console
=
InteractiveConsole
(
self
.
_create_interactive_locals
())
console
=
InteractiveConsole
(
self
.
_create_interactive_locals
())
if
PY36
:
# Beginning in 3.6, the console likes to print "now exiting <class>"
# Beginning in 3.6, the console likes to print "now exiting <class>"
# but probably our socket is already closed, so this just causes problems.
# but probably our socket is already closed, so this just causes problems.
console
.
interact
(
banner
=
self
.
banner
,
exitmsg
=
''
)
# pylint:disable=unexpected-keyword-arg
console
.
interact
(
banner
=
self
.
banner
,
exitmsg
=
''
)
# pylint:disable=unexpected-keyword-arg
else
:
console
.
interact
(
banner
=
self
.
banner
)
except
SystemExit
:
except
SystemExit
:
# raised by quit(); obviously this cannot propagate.
# raised by quit(); obviously this cannot propagate.
exc_clear
()
# Python 2
pass
finally
:
finally
:
raw_file
.
close
()
raw_file
.
close
()
conn
.
close
()
conn
.
close
()
...
...
src/gevent/builtins.py
View file @
d9e2479b
...
@@ -5,25 +5,14 @@ from __future__ import absolute_import
...
@@ -5,25 +5,14 @@ from __future__ import absolute_import
import
weakref
import
weakref
from
gevent.lock
import
RLock
from
gevent.lock
import
RLock
from
gevent._compat
import
PY3
from
gevent._compat
import
imp_acquire_lock
from
gevent._compat
import
imp_acquire_lock
from
gevent._compat
import
imp_release_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
builtins
as
__gbuiltins__
import
__builtin__
as
__gbuiltins__
_allowed_module_name_types
=
(
str
,)
_allowed_module_name_types
=
(
basestring
,)
# pylint:disable=undefined-variable
__target__
=
'builtins'
__target__
=
'__builtin__'
except
ImportError
:
import
builtins
as
__gbuiltins__
# pylint: disable=import-error
_allowed_module_name_types
=
(
str
,)
__target__
=
'builtins'
_import
=
__gbuiltins__
.
__import__
_import
=
__gbuiltins__
.
__import__
...
@@ -121,11 +110,9 @@ def _lock_imports():
...
@@ -121,11 +110,9 @@ def _lock_imports():
global
__lock_imports
global
__lock_imports
__lock_imports
=
True
__lock_imports
=
True
if
PY3
:
__implements__
=
[]
__implements__
=
[]
__import__
=
_import
__import__
=
_import
else
:
__implements__
=
[
'__import__'
]
__all__
=
__implements__
__all__
=
__implements__
...
...
src/gevent/contextvars.py
View file @
d9e2479b
...
@@ -53,12 +53,12 @@ try:
...
@@ -53,12 +53,12 @@ try:
except
ImportError
:
except
ImportError
:
from
collections
import
Mapping
# pylint:disable=deprecated-class
from
collections
import
Mapping
# pylint:disable=deprecated-class
from
gevent._compat
import
PY37
from
gevent._util
import
_NONE
from
gevent._util
import
_NONE
from
gevent.local
import
local
from
gevent.local
import
local
__stdlib_expected__
=
__all__
__stdlib_expected__
=
__all__
__implements__
=
__stdlib_expected__
if
PY37
else
None
__implements__
=
__stdlib_expected__
# In the reference implementation, the interpreter level OS thread state
# In the reference implementation, the interpreter level OS thread state
# is modified to contain a pointer to the current context. Obviously we can't
# is modified to contain a pointer to the current context. Obviously we can't
...
...
src/gevent/events.py
View file @
d9e2479b
...
@@ -130,7 +130,7 @@ def notify_and_call_entry_points(event):
...
@@ -130,7 +130,7 @@ def notify_and_call_entry_points(event):
entry_points
=
set
(
entry_points
=
set
(
ep
ep
for
ep
for
ep
in
ep_dict
.
get
(
event
.
ENTRY_POINT_NAME
)
in
ep_dict
.
get
(
event
.
ENTRY_POINT_NAME
,
()
)
)
)
for
plugin
in
entry_points
:
for
plugin
in
entry_points
:
...
...
src/gevent/local.py
View file @
d9e2479b
...
@@ -597,21 +597,7 @@ if local.__module__ == 'gevent.local':
...
@@ -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.
# module has a different name than the pure-Python version and we can check for that.
# It's not as direct, but it works.
# It's not as direct, but it works.
# So here we're not compiled
# So here we're not compiled
from
gevent._compat
import
PYPY
local
.
__new__
=
classmethod
(
__new__
)
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
else
:
# pragma: no cover
else
:
# pragma: no cover
# Make sure we revisit in case of changes to the (accelerator) module names.
# Make sure we revisit in case of changes to the (accelerator) module names.
if
local
.
__module__
!=
'gevent._gevent_clocal'
:
if
local
.
__module__
!=
'gevent._gevent_clocal'
:
...
...
src/gevent/lock.py
View file @
d9e2479b
...
@@ -12,7 +12,7 @@ from __future__ import print_function
...
@@ -12,7 +12,7 @@ from __future__ import print_function
from
gevent.hub
import
getcurrent
from
gevent.hub
import
getcurrent
from
gevent._compat
import
PURE_PYTHON
from
gevent._compat
import
PURE_PYTHON
from
gevent._compat
import
PY2
# This is the one exception to the rule of where to
# This is the one exception to the rule of where to
# import Semaphore, obviously
# import Semaphore, obviously
from
gevent
import
monkey
from
gevent
import
monkey
...
@@ -180,8 +180,6 @@ def _fixup_docstrings():
...
@@ -180,8 +180,6 @@ def _fixup_docstrings():
assert
c
.
__doc__
==
b
.
__doc__
assert
c
.
__doc__
==
b
.
__doc__
for
m
in
'acquire'
,
'release'
,
'wait'
:
for
m
in
'acquire'
,
'release'
,
'wait'
:
c_meth
=
getattr
(
c
,
m
)
c_meth
=
getattr
(
c
,
m
)
if
PY2
:
c_meth
=
c_meth
.
__func__
b_meth
=
getattr
(
b
,
m
)
b_meth
=
getattr
(
b
,
m
)
c_meth
.
__doc__
=
b_meth
.
__doc__
c_meth
.
__doc__
=
b_meth
.
__doc__
...
...
src/gevent/monkey.py
View file @
d9e2479b
...
@@ -149,20 +149,7 @@ __all__ = [
...
@@ -149,20 +149,7 @@ __all__ = [
'main'
,
'main'
,
]
]
if
sys
.
version_info
[
0
]
>=
3
:
string_types
=
(
str
,)
PY3
=
True
PY2
=
False
else
:
import
__builtin__
# pylint:disable=import-error
string_types
=
(
__builtin__
.
basestring
,)
PY3
=
False
PY2
=
True
WIN
=
sys
.
platform
.
startswith
(
"win"
)
WIN
=
sys
.
platform
.
startswith
(
"win"
)
PY36
=
sys
.
version_info
[:
2
]
>=
(
3
,
6
)
PY37
=
sys
.
version_info
[:
2
]
>=
(
3
,
7
)
class
_BadImplements
(
AttributeError
):
class
_BadImplements
(
AttributeError
):
"""
"""
...
@@ -280,8 +267,8 @@ def get_original(mod_name, item_name):
...
@@ -280,8 +267,8 @@ def get_original(mod_name, item_name):
``item_name`` or a sequence of original values if a
``item_name`` or a sequence of original values if a
sequence was passed.
sequence was passed.
"""
"""
mod_names
=
[
mod_name
]
if
isinstance
(
mod_name
,
str
ing_types
)
else
mod_name
mod_names
=
[
mod_name
]
if
isinstance
(
mod_name
,
str
)
else
mod_name
if
isinstance
(
item_name
,
str
ing_types
):
if
isinstance
(
item_name
,
str
):
item_names
=
[
item_name
]
item_names
=
[
item_name
]
unpack
=
True
unpack
=
True
else
:
else
:
...
@@ -333,7 +320,6 @@ def __call_module_hook(gevent_module, name, module, items, _warnings):
...
@@ -333,7 +320,6 @@ def __call_module_hook(gevent_module, name, module, items, _warnings):
class
_GeventDoPatchRequest
(
object
):
class
_GeventDoPatchRequest
(
object
):
PY3
=
PY3
get_original
=
staticmethod
(
get_original
)
get_original
=
staticmethod
(
get_original
)
def
__init__
(
self
,
def
__init__
(
self
,
...
@@ -513,7 +499,7 @@ def _patch_sys_std(name):
...
@@ -513,7 +499,7 @@ def _patch_sys_std(name):
patch_item
(
sys
,
name
,
FileObjectThread
(
orig
))
patch_item
(
sys
,
name
,
FileObjectThread
(
orig
))
@
_ignores_DoNotPatch
@
_ignores_DoNotPatch
def
patch_sys
(
stdin
=
True
,
stdout
=
True
,
stderr
=
True
):
def
patch_sys
(
stdin
=
True
,
stdout
=
True
,
stderr
=
True
):
# pylint:disable=unused-argument
"""
"""
Patch sys.std[in,out,err] to use a cooperative IO via a
Patch sys.std[in,out,err] to use a cooperative IO via a
threadpool.
threadpool.
...
@@ -529,29 +515,11 @@ def patch_sys(stdin=True, stdout=True, stderr=True):
...
@@ -529,29 +515,11 @@ def patch_sys(stdin=True, stdout=True, stderr=True):
time leads to a hang.
time leads to a hang.
.. _`misinterpreting control keys`: https://github.com/gevent/gevent/issues/274
.. _`misinterpreting control keys`: https://github.com/gevent/gevent/issues/274
"""
# test__issue6.py demonstrates the hang if these lines are removed;
# strangely enough that test passes even without monkey-patching sys
if
PY3
:
items
=
None
else
:
items
=
set
([(
'stdin'
if
stdin
else
None
),
(
'stdout'
if
stdout
else
None
),
(
'stderr'
if
stderr
else
None
)])
items
.
discard
(
None
)
items
=
list
(
items
)
if
not
items
:
return
from
gevent
import
events
.. deprecated:: NEXT
_notify_patch
(
events
.
GeventWillPatchModuleEvent
(
'sys'
,
None
,
sys
,
Does nothing on any supported version.
items
))
"""
return
for
item
in
items
:
_patch_sys_std
(
item
)
_notify_patch
(
events
.
GeventDidPatchModuleEvent
(
'sys'
,
None
,
sys
))
@
_ignores_DoNotPatch
@
_ignores_DoNotPatch
def
patch_os
():
def
patch_os
():
...
@@ -612,21 +580,11 @@ def patch_contextvars():
...
@@ -612,21 +580,11 @@ def patch_contextvars():
natively handles switching context vars when greenlets are switched.
natively handles switching context vars when greenlets are switched.
Older versions of Python that have the backport installed will
Older versions of Python that have the backport installed will
still be patched.
still be patched.
.. deprecated:: NEXT
Does nothing on any supported version.
"""
"""
if
PY37
:
return
return
try
:
__import__
(
'contextvars'
)
except
ImportError
:
pass
else
:
try
:
_patch_module
(
'contextvars'
)
except
_BadImplements
:
# Prior to Python 3.7, but the backport must be installed.
# *Assume* it has the same things as the standard library would.
import
gevent.contextvars
_patch_module
(
'contextvars'
,
gevent
.
contextvars
.
__stdlib_expected__
)
def
_patch_existing_locks
(
threading
):
def
_patch_existing_locks
(
threading
):
...
@@ -853,103 +811,101 @@ def patch_thread(threading=True, _threading_local=True, Event=True, logging=True
...
@@ -853,103 +811,101 @@ def patch_thread(threading=True, _threading_local=True, Event=True, logging=True
continue
continue
thread
.
join
=
make_join_func
(
thread
,
None
)
thread
.
join
=
make_join_func
(
thread
,
None
)
if
PY3
:
# Issue 18808 changes the nature of Thread.join() to use
# locks. This means that a greenlet spawned in the main thread
# Issue 18808 changes the nature of Thread.join() to use
# (which is already running) cannot wait for the main thread---it
# locks. This means that a greenlet spawned in the main thread
# hangs forever. We patch around this if possible. See also
# (which is already running) cannot wait for the main thread---it
# gevent.threading.
# hangs forever. We patch around this if possible. See also
greenlet
=
__import__
(
'greenlet'
)
# gevent.threading.
already_patched
=
is_object_patched
(
'threading'
,
'_shutdown'
)
greenlet
=
__import__
(
'greenlet'
)
orig_shutdown
=
threading_mod
.
_shutdown
already_patched
=
is_object_patched
(
'threading'
,
'_shutdown'
)
orig_shutdown
=
threading_mod
.
_shutdown
if
orig_current_thread
==
threading_mod
.
main_thread
()
and
not
already_patched
:
main_thread
=
threading_mod
.
main_thread
()
if
orig_current_thread
==
threading_mod
.
main_thread
()
and
not
already_patched
:
_greenlet
=
main_thread
.
_greenlet
=
greenlet
.
getcurrent
()
main_thread
=
threading_mod
.
main_thread
()
main_thread
.
__real_tstate_lock
=
main_thread
.
_tstate_lock
_greenlet
=
main_thread
.
_greenlet
=
greenlet
.
getcurrent
()
assert
main_thread
.
__real_tstate_lock
is
not
None
main_thread
.
__real_tstate_lock
=
main_thread
.
_tstate_lock
# The interpreter will call threading._shutdown
assert
main_thread
.
__real_tstate_lock
is
not
None
# when the main thread exits and is about to
# The interpreter will call threading._shutdown
# go away. It is called *in* the main thread. This
# when the main thread exits and is about to
# is a perfect place to notify other greenlets that
# go away. It is called *in* the main thread. This
# the main thread is done. We do this by overriding the
# is a perfect place to notify other greenlets that
# lock of the main thread during operation, and only restoring
# the main thread is done. We do this by overriding the
# it to the native blocking version at shutdown time
# lock of the main thread during operation, and only restoring
# (the interpreter also has a reference to this lock in a
# it to the native blocking version at shutdown time
# C data structure).
# (the interpreter also has a reference to this lock in a
main_thread
.
_tstate_lock
=
threading_mod
.
Lock
()
# C data structure).
main_thread
.
_tstate_lock
.
acquire
()
main_thread
.
_tstate_lock
=
threading_mod
.
Lock
()
main_thread
.
_tstate_lock
.
acquire
()
def
_shutdown
():
# Release anyone trying to join() me,
def
_shutdown
():
# and let us switch to them.
# Release anyone trying to join() me,
if
not
main_thread
.
_tstate_lock
:
# and let us switch to them.
return
if
not
main_thread
.
_tstate_lock
:
return
main_thread
.
_tstate_lock
.
release
()
main_thread
.
_tstate_lock
.
release
()
from
gevent
import
sleep
from
gevent
import
sleep
try
:
try
:
sleep
()
sleep
()
except
:
# pylint:disable=bare-except
except
:
# pylint:disable=bare-except
# A greenlet could have .kill() us
# A greenlet could have .kill() us
# or .throw() to us. I'm the main greenlet,
# or .throw() to us. I'm the main greenlet,
# there's no where else for this to go.
# there's no where else for this to go.
from
gevent
import
get_hub
from
gevent
import
get_hub
get_hub
().
print_exception
(
_greenlet
,
*
sys
.
exc_info
())
get_hub
().
print_exception
(
_greenlet
,
*
sys
.
exc_info
())
# Now, this may have resulted in us getting stopped
# Now, this may have resulted in us getting stopped
# if some other greenlet actually just ran there.
# if some other greenlet actually just ran there.
# That's not good, we're not supposed to be stopped
# That's not good, we're not supposed to be stopped
# when we enter _shutdown.
# when we enter _shutdown.
main_thread
.
_is_stopped
=
False
main_thread
.
_is_stopped
=
False
main_thread
.
_tstate_lock
=
main_thread
.
__real_tstate_lock
main_thread
.
_tstate_lock
=
main_thread
.
__real_tstate_lock
main_thread
.
__real_tstate_lock
=
None
main_thread
.
__real_tstate_lock
=
None
# The only truly blocking native shutdown lock to
# The only truly blocking native shutdown lock to
# acquire should be our own (hopefully), and the call to
# acquire should be our own (hopefully), and the call to
# _stop that orig_shutdown makes will discard it.
# _stop that orig_shutdown makes will discard it.
orig_shutdown
()
orig_shutdown
()
patch_item
(
threading_mod
,
'_shutdown'
,
orig_shutdown
)
patch_item
(
threading_mod
,
'_shutdown'
,
orig_shutdown
)
patch_item
(
threading_mod
,
'_shutdown'
,
_shutdown
)
patch_item
(
threading_mod
,
'_shutdown'
,
_shutdown
)
# We create a bit of a reference cycle here,
# We create a bit of a reference cycle here,
# so main_thread doesn't get to be collected in a timely way.
# so main_thread doesn't get to be collected in a timely way.
# Not good. Take it out of dangling so we don't get
# Not good. Take it out of dangling so we don't get
# warned about it.
# warned about it.
threading_mod
.
_dangling
.
remove
(
main_thread
)
threading_mod
.
_dangling
.
remove
(
main_thread
)
# Patch up the ident of the main thread to match. This
# Patch up the ident of the main thread to match. This
# matters if threading was imported before monkey-patching
# matters if threading was imported before monkey-patching
# thread
# thread
oldid
=
main_thread
.
ident
oldid
=
main_thread
.
ident
main_thread
.
_ident
=
threading_mod
.
get_ident
()
if
oldid
in
threading_mod
.
_active
:
threading_mod
.
_active
[
main_thread
.
ident
]
=
threading_mod
.
_active
[
oldid
]
if
oldid
!=
main_thread
.
ident
:
del
threading_mod
.
_active
[
oldid
]
elif
not
already_patched
:
_queue_warning
(
"Monkey-patching not on the main thread; "
"threading.main_thread().join() will hang from a greenlet"
,
_warnings
)
main_thread
=
threading_mod
.
main_thread
()
def
_shutdown
():
# We've patched get_ident but *did not* patch the
# main_thread.ident value. Beginning in Python 3.9.8
# and then later releases (3.10.1, probably), the
# _main_thread object is only _stop() if the ident of
# the current thread (the *real* main thread) matches
# the ident of the _main_thread object. But without doing that,
# the main thread's shutdown lock (threading._shutdown_locks) is never
# removed *or released*, thus hanging the interpreter.
# XXX: There's probably a better way to do this. Probably need to take a
# step back and look at the whole picture.
main_thread
.
_ident
=
threading_mod
.
get_ident
()
main_thread
.
_ident
=
threading_mod
.
get_ident
()
if
oldid
in
threading_mod
.
_active
:
orig_shutdown
()
threading_mod
.
_active
[
main_thread
.
ident
]
=
threading_mod
.
_active
[
oldid
]
patch_item
(
threading_mod
,
'_shutdown'
,
orig_shutdown
)
if
oldid
!=
main_thread
.
ident
:
patch_item
(
threading_mod
,
'_shutdown'
,
_shutdown
)
del
threading_mod
.
_active
[
oldid
]
elif
not
already_patched
:
_queue_warning
(
"Monkey-patching not on the main thread; "
"threading.main_thread().join() will hang from a greenlet"
,
_warnings
)
main_thread
=
threading_mod
.
main_thread
()
def
_shutdown
():
# We've patched get_ident but *did not* patch the
# main_thread.ident value. Beginning in Python 3.9.8
# and then later releases (3.10.1, probably), the
# _main_thread object is only _stop() if the ident of
# the current thread (the *real* main thread) matches
# the ident of the _main_thread object. But without doing that,
# the main thread's shutdown lock (threading._shutdown_locks) is never
# removed *or released*, thus hanging the interpreter.
# XXX: There's probably a better way to do this. Probably need to take a
# step back and look at the whole picture.
main_thread
.
_ident
=
threading_mod
.
get_ident
()
orig_shutdown
()
patch_item
(
threading_mod
,
'_shutdown'
,
orig_shutdown
)
patch_item
(
threading_mod
,
'_shutdown'
,
_shutdown
)
from
gevent
import
events
from
gevent
import
events
_notify_patch
(
events
.
GeventDidPatchModuleEvent
(
'thread'
,
gevent_thread_mod
,
thread_mod
))
_notify_patch
(
events
.
GeventDidPatchModuleEvent
(
'thread'
,
gevent_thread_mod
,
thread_mod
))
...
@@ -1031,7 +987,6 @@ def patch_ssl(_warnings=None, _first_time=True):
...
@@ -1031,7 +987,6 @@ def patch_ssl(_warnings=None, _first_time=True):
"""
"""
may_need_warning
=
(
may_need_warning
=
(
_first_time
_first_time
and
PY36
and
'ssl'
in
sys
.
modules
and
'ssl'
in
sys
.
modules
and
hasattr
(
sys
.
modules
[
'ssl'
],
'SSLContext'
))
and
hasattr
(
sys
.
modules
[
'ssl'
],
'SSLContext'
))
# Previously, we didn't warn on Python 2 if pkg_resources has been imported
# Previously, we didn't warn on Python 2 if pkg_resources has been imported
...
@@ -1145,9 +1100,10 @@ def patch_builtins():
...
@@ -1145,9 +1100,10 @@ def patch_builtins():
.. _greenlet safe: https://github.com/gevent/gevent/issues/108
.. _greenlet safe: https://github.com/gevent/gevent/issues/108
.. deprecated:: NEXT
Does nothing on any supported platform.
"""
"""
if
PY2
:
_patch_module
(
'builtins'
)
@
_ignores_DoNotPatch
@
_ignores_DoNotPatch
def
patch_signal
():
def
patch_signal
():
...
...
src/gevent/os.py
View file @
d9e2479b
...
@@ -48,7 +48,6 @@ import sys
...
@@ -48,7 +48,6 @@ import sys
from
gevent.hub
import
_get_hub_noargs
as
get_hub
from
gevent.hub
import
_get_hub_noargs
as
get_hub
from
gevent.hub
import
reinit
from
gevent.hub
import
reinit
from
gevent._config
import
config
from
gevent._config
import
config
from
gevent._compat
import
PY3
from
gevent._util
import
copy_globals
from
gevent._util
import
copy_globals
import
errno
import
errno
...
@@ -102,8 +101,6 @@ if fcntl:
...
@@ -102,8 +101,6 @@ if fcntl:
except
OSError
as
e
:
except
OSError
as
e
:
if
e
.
errno
not
in
ignored_errors
:
if
e
.
errno
not
in
ignored_errors
:
raise
raise
if
not
PY3
:
sys
.
exc_clear
()
if
hub
is
None
:
if
hub
is
None
:
hub
=
get_hub
()
hub
=
get_hub
()
event
=
hub
.
loop
.
io
(
fd
,
1
)
event
=
hub
.
loop
.
io
(
fd
,
1
)
...
@@ -133,8 +130,6 @@ if fcntl:
...
@@ -133,8 +130,6 @@ if fcntl:
except
OSError
as
e
:
except
OSError
as
e
:
if
e
.
errno
not
in
ignored_errors
:
if
e
.
errno
not
in
ignored_errors
:
raise
raise
if
not
PY3
:
sys
.
exc_clear
()
if
hub
is
None
:
if
hub
is
None
:
hub
=
get_hub
()
hub
=
get_hub
()
event
=
hub
.
loop
.
io
(
fd
,
2
)
event
=
hub
.
loop
.
io
(
fd
,
2
)
...
...
src/gevent/pywsgi.py
View file @
d9e2479b
...
@@ -31,13 +31,10 @@ from gevent import socket
...
@@ -31,13 +31,10 @@ from gevent import socket
import
gevent
import
gevent
from
gevent.server
import
StreamServer
from
gevent.server
import
StreamServer
from
gevent.hub
import
GreenletExit
from
gevent.hub
import
GreenletExit
from
gevent._compat
import
PY3
,
reraise
from
gevent._compat
import
reraise
from
functools
import
partial
from
functools
import
partial
if
PY3
:
unquote_latin1
=
partial
(
unquote
,
encoding
=
'latin-1'
)
unquote_latin1
=
partial
(
unquote
,
encoding
=
'latin-1'
)
else
:
unquote_latin1
=
unquote
_no_undoc_members
=
True
# Don't put undocumented things into sphinx
_no_undoc_members
=
True
# Don't put undocumented things into sphinx
...
@@ -89,8 +86,7 @@ def format_date_time(timestamp):
...
@@ -89,8 +86,7 @@ def format_date_time(timestamp):
# Return a byte string, not a native string
# Return a byte string, not a native string
year
,
month
,
day
,
hh
,
mm
,
ss
,
wd
,
_y
,
_z
=
time
.
gmtime
(
timestamp
)
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
)
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
return
value
...
@@ -392,13 +388,9 @@ class WSGIHandler(object):
...
@@ -392,13 +388,9 @@ class WSGIHandler(object):
# pylint:disable=too-many-instance-attributes
# pylint:disable=too-many-instance-attributes
protocol_version
=
'HTTP/1.1'
protocol_version
=
'HTTP/1.1'
if
PY3
:
# if we do like Py2, then headers_factory unconditionally
def
MessageClass
(
self
,
*
args
):
# becomes a bound method, meaning the fp argument becomes WSGIHandler
return
headers_factory
(
*
args
)
def
MessageClass
(
self
,
*
args
):
return
headers_factory
(
*
args
)
else
:
MessageClass
=
headers_factory
# Attributes reset at various times for each request; not public
# Attributes reset at various times for each request; not public
# documented. Class attributes to keep the constructor fast
# documented. Class attributes to keep the constructor fast
...
@@ -562,10 +554,10 @@ class WSGIHandler(object):
...
@@ -562,10 +554,10 @@ class WSGIHandler(object):
if
self
.
request_version
==
"HTTP/1.1"
:
if
self
.
request_version
==
"HTTP/1.1"
:
conntype
=
self
.
headers
.
get
(
"Connection"
,
""
).
lower
()
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'
:
elif
self
.
request_version
==
'HTTP/1.0'
:
conntype
=
self
.
headers
.
get
(
"Connection"
,
"close"
).
lower
()
conntype
=
self
.
headers
.
get
(
"Connection"
,
"close"
).
lower
()
self
.
close_connection
=
(
conntype
!=
'keep-alive'
)
self
.
close_connection
=
(
conntype
!=
'keep-alive'
)
# pylint:disable=superfluous-parens
else
:
else
:
# XXX: HTTP 0.9. We should drop support
# XXX: HTTP 0.9. We should drop support
self
.
close_connection
=
True
self
.
close_connection
=
True
...
@@ -606,8 +598,7 @@ class WSGIHandler(object):
...
@@ -606,8 +598,7 @@ class WSGIHandler(object):
latin-1).
latin-1).
"""
"""
line
=
self
.
rfile
.
readline
(
MAX_REQUEST_LINE
)
line
=
self
.
rfile
.
readline
(
MAX_REQUEST_LINE
)
if
PY3
:
line
=
line
.
decode
(
'latin-1'
)
line
=
line
.
decode
(
'latin-1'
)
return
line
return
line
def
handle_one_request
(
self
):
def
handle_one_request
(
self
):
...
@@ -659,7 +650,7 @@ class WSGIHandler(object):
...
@@ -659,7 +650,7 @@ class WSGIHandler(object):
try
:
try
:
self
.
requestline
=
self
.
read_requestline
()
self
.
requestline
=
self
.
read_requestline
()
# Account for old subclasses that haven't done this
# 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'
)
self
.
requestline
=
self
.
requestline
.
decode
(
'latin-1'
)
except
socket
.
error
:
except
socket
.
error
:
# "Connection reset by peer" or other socket errors aren't interesting here
# "Connection reset by peer" or other socket errors aren't interesting here
...
@@ -720,8 +711,7 @@ class WSGIHandler(object):
...
@@ -720,8 +711,7 @@ class WSGIHandler(object):
if
hasattr
(
self
.
result
,
'__len__'
):
if
hasattr
(
self
.
result
,
'__len__'
):
total_len
=
sum
(
len
(
chunk
)
for
chunk
in
self
.
result
)
total_len
=
sum
(
len
(
chunk
)
for
chunk
in
self
.
result
)
total_len_str
=
str
(
total_len
)
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
))
self
.
response_headers
.
append
((
b'Content-Length'
,
total_len_str
))
else
:
else
:
self
.
response_use_chunked
=
(
self
.
response_use_chunked
=
(
...
@@ -856,8 +846,8 @@ class WSGIHandler(object):
...
@@ -856,8 +846,8 @@ class WSGIHandler(object):
# Note: Some Python 2 implementations, like Jython, may allow non-octet (above 255) values
# 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
# 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.
# 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"
),
response_headers
.
append
((
header
.
encode
(
"latin-1"
),
value
if
not
PY3
else
value
.
encode
(
"latin-1"
)))
value
.
encode
(
"latin-1"
)))
except
UnicodeEncodeError
:
except
UnicodeEncodeError
:
# If we get here, we're guaranteed to have a header and value
# If we get here, we're guaranteed to have a header and value
raise
UnicodeError
(
"Non-latin1 header"
,
repr
(
header
),
repr
(
value
))
raise
UnicodeError
(
"Non-latin1 header"
,
repr
(
header
),
repr
(
value
))
...
@@ -871,7 +861,7 @@ class WSGIHandler(object):
...
@@ -871,7 +861,7 @@ class WSGIHandler(object):
# code
# code
code
=
int
(
status
.
split
(
' '
,
1
)[
0
])
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
.
_orig_status
=
status
# Preserve the native string for logging
self
.
response_headers
=
response_headers
self
.
response_headers
=
response_headers
self
.
code
=
code
self
.
code
=
code
...
@@ -898,8 +888,7 @@ class WSGIHandler(object):
...
@@ -898,8 +888,7 @@ class WSGIHandler(object):
if
self
.
code
in
(
304
,
204
):
if
self
.
code
in
(
304
,
204
):
if
self
.
provided_content_length
is
not
None
and
self
.
provided_content_length
!=
'0'
:
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
)
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
)
raise
self
.
ApplicationError
(
msg
)
return
self
.
write
return
self
.
write
...
@@ -1012,8 +1001,6 @@ class WSGIHandler(object):
...
@@ -1012,8 +1001,6 @@ class WSGIHandler(object):
except
socket
.
error
as
ex
:
except
socket
.
error
as
ex
:
if
ex
.
args
[
0
]
in
self
.
ignored_socket_errors
:
if
ex
.
args
[
0
]
in
self
.
ignored_socket_errors
:
# See description of self.ignored_socket_errors.
# See description of self.ignored_socket_errors.
if
not
PY3
:
sys
.
exc_clear
()
self
.
close_connection
=
True
self
.
close_connection
=
True
else
:
else
:
self
.
handle_error
(
*
sys
.
exc_info
())
self
.
handle_error
(
*
sys
.
exc_info
())
...
@@ -1032,8 +1019,6 @@ class WSGIHandler(object):
...
@@ -1032,8 +1019,6 @@ class WSGIHandler(object):
self
.
start_response
(
status
,
headers
[:])
self
.
start_response
(
status
,
headers
[:])
self
.
write
(
body
)
self
.
write
(
body
)
except
socket
.
error
:
except
socket
.
error
:
if
not
PY3
:
sys
.
exc_clear
()
self
.
close_connection
=
True
self
.
close_connection
=
True
def
_log_error
(
self
,
t
,
v
,
tb
):
def
_log_error
(
self
,
t
,
v
,
tb
):
...
@@ -1558,7 +1543,7 @@ class WSGIServer(StreamServer):
...
@@ -1558,7 +1543,7 @@ class WSGIServer(StreamServer):
name
=
socket
.
getfqdn
(
address
[
0
])
name
=
socket
.
getfqdn
(
address
[
0
])
except
socket
.
error
:
except
socket
.
error
:
name
=
str
(
address
[
0
])
name
=
str
(
address
[
0
])
if
PY3
and
not
isinstance
(
name
,
str
):
if
not
isinstance
(
name
,
str
):
name
=
name
.
decode
(
'ascii'
)
name
=
name
.
decode
(
'ascii'
)
self
.
environ
[
'SERVER_NAME'
]
=
name
self
.
environ
[
'SERVER_NAME'
]
=
name
self
.
environ
.
setdefault
(
'SERVER_PORT'
,
str
(
address
[
1
]))
self
.
environ
.
setdefault
(
'SERVER_PORT'
,
str
(
address
[
1
]))
...
...
src/gevent/resolver/__init__.py
View file @
d9e2479b
...
@@ -25,7 +25,6 @@ from gevent._compat import string_types
...
@@ -25,7 +25,6 @@ from gevent._compat import string_types
from
gevent._compat
import
text_type
from
gevent._compat
import
text_type
from
gevent._compat
import
hostname_types
from
gevent._compat
import
hostname_types
from
gevent._compat
import
integer_types
from
gevent._compat
import
integer_types
from
gevent._compat
import
PY3
from
gevent._compat
import
PYPY
from
gevent._compat
import
PYPY
from
gevent._compat
import
MAC
from
gevent._compat
import
MAC
...
@@ -98,7 +97,7 @@ def _resolve_special(hostname, family):
...
@@ -98,7 +97,7 @@ def _resolve_special(hostname, family):
class
AbstractResolver
(
object
):
class
AbstractResolver
(
object
):
HOSTNAME_ENCODING
=
'idna'
if
PY3
else
'ascii'
HOSTNAME_ENCODING
=
'idna'
_LOCAL_HOSTNAMES
=
(
_LOCAL_HOSTNAMES
=
(
b'localhost'
,
b'localhost'
,
...
...
src/gevent/server.py
View file @
d9e2479b
...
@@ -4,8 +4,6 @@ from __future__ import print_function
...
@@ -4,8 +4,6 @@ from __future__ import print_function
from
__future__
import
absolute_import
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
division
from
contextlib
import
closing
import
sys
import
sys
from
_socket
import
error
as
SocketError
from
_socket
import
error
as
SocketError
...
@@ -17,7 +15,7 @@ from _socket import SOCK_DGRAM
...
@@ -17,7 +15,7 @@ from _socket import SOCK_DGRAM
from
gevent.baseserver
import
BaseServer
from
gevent.baseserver
import
BaseServer
from
gevent.socket
import
EWOULDBLOCK
from
gevent.socket
import
EWOULDBLOCK
from
gevent.socket
import
socket
as
GeventSocket
from
gevent.socket
import
socket
as
GeventSocket
from
gevent._compat
import
PYPY
,
PY3
from
gevent._compat
import
PYPY
__all__
=
[
'StreamServer'
,
'DatagramServer'
]
__all__
=
[
'StreamServer'
,
'DatagramServer'
]
...
@@ -29,13 +27,9 @@ else:
...
@@ -29,13 +27,9 @@ else:
DEFAULT_REUSE_ADDR
=
1
DEFAULT_REUSE_ADDR
=
1
if
PY3
:
# sockets and SSL sockets are context managers on Python 3
# sockets and SSL sockets are context managers on Python 3
def
_closing_socket
(
sock
):
def
_closing_socket
(
sock
):
return
sock
return
sock
else
:
# but they are not guaranteed to be so on Python 2
_closing_socket
=
closing
class
StreamServer
(
BaseServer
):
class
StreamServer
(
BaseServer
):
...
@@ -191,38 +185,21 @@ class StreamServer(BaseServer):
...
@@ -191,38 +185,21 @@ class StreamServer(BaseServer):
backlog
=
cls
.
backlog
backlog
=
cls
.
backlog
return
_tcp_listener
(
address
,
backlog
=
backlog
,
reuse_addr
=
cls
.
reuse_addr
,
family
=
family
)
return
_tcp_listener
(
address
,
backlog
=
backlog
,
reuse_addr
=
cls
.
reuse_addr
,
family
=
family
)
if
PY3
:
def
do_read
(
self
):
def
do_read
(
self
):
sock
=
self
.
socket
sock
=
self
.
socket
try
:
try
:
fd
,
address
=
sock
.
_accept
()
fd
,
address
=
sock
.
_accept
()
except
BlockingIOError
:
# python 2: pylint: disable=undefined-variable
except
BlockingIOError
:
# python 2: pylint: disable=undefined-variable
if
not
sock
.
timeout
:
if
not
sock
.
timeout
:
return
return
raise
raise
sock
=
GeventSocket
(
sock
.
family
,
sock
.
type
,
sock
.
proto
,
fileno
=
fd
)
sock
=
GeventSocket
(
sock
.
family
,
sock
.
type
,
sock
.
proto
,
fileno
=
fd
)
# XXX Python issue #7995? "if no default timeout is set
# XXX Python issue #7995? "if no default timeout is set
# and the listening socket had a (non-zero) timeout, force
# and the listening socket had a (non-zero) timeout, force
# the new socket in blocking mode to override
# the new socket in blocking mode to override
# platform-specific socket flags inheritance."
# platform-specific socket flags inheritance."
return
sock
,
address
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_close
(
self
,
sock
,
*
args
):
def
do_close
(
self
,
sock
,
*
args
):
# pylint:disable=arguments-differ
# pylint:disable=arguments-differ
...
...
src/gevent/socket.py
View file @
d9e2479b
...
@@ -13,16 +13,15 @@ as well as the constants from the :mod:`socket` module are imported into this mo
...
@@ -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
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
# pylint: disable=undefined-variable
from
gevent._compat
import
PY3
from
gevent._compat
import
PY311
from
gevent._compat
import
PY311
from
gevent._compat
import
exc_clear
from
gevent._compat
import
exc_clear
from
gevent._util
import
copy_globals
from
gevent._util
import
copy_globals
if
PY3
:
from
gevent
import
_socket3
as
_source
# python 2: pylint:disable=no-name-in-module
from
gevent
import
_socket3
as
_source
else
:
from
gevent
import
_socket2
as
_source
# define some things we're expecting to overwrite; each module
# define some things we're expecting to overwrite; each module
# needs to define these
# needs to define these
...
...
src/gevent/ssl.py
View file @
d9e2479b
"""
"""
Secure Sockets Layer (SSL/TLS) module.
Secure Sockets Layer (SSL/TLS) module.
"""
"""
from
gevent._compat
import
PY2
from
gevent._util
import
copy_globals
from
gevent._util
import
copy_globals
# things we expect to override, here for static analysis
# things we expect to override, here for static analysis
...
@@ -9,27 +9,8 @@ def wrap_socket(_sock, **_kwargs):
...
@@ -9,27 +9,8 @@ def wrap_socket(_sock, **_kwargs):
# pylint:disable=unused-argument
# pylint:disable=unused-argument
raise
NotImplementedError
()
raise
NotImplementedError
()
if
PY2
:
if
hasattr
(
__import__
(
'ssl'
),
'SSLContext'
):
from
gevent
import
_ssl3
as
_source
# 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
copy_globals
(
_source
,
globals
())
copy_globals
(
_source
,
globals
())
src/gevent/subprocess.py
View file @
d9e2479b
...
@@ -59,11 +59,11 @@ from gevent.hub import linkproxy
...
@@ -59,11 +59,11 @@ from gevent.hub import linkproxy
from
gevent.hub
import
sleep
from
gevent.hub
import
sleep
from
gevent.hub
import
getcurrent
from
gevent.hub
import
getcurrent
from
gevent._compat
import
integer_types
,
string_types
,
xrange
from
gevent._compat
import
integer_types
,
string_types
,
xrange
from
gevent._compat
import
PY3
#
from gevent._compat import PY3
from
gevent._compat
import
PY35
#
from gevent._compat import PY35
from
gevent._compat
import
PY36
#
from gevent._compat import PY36
from
gevent._compat
import
PY37
#
from gevent._compat import PY37
from
gevent._compat
import
PY38
#
from gevent._compat import PY38
from
gevent._compat
import
PY311
from
gevent._compat
import
PY311
from
gevent._compat
import
PYPY
from
gevent._compat
import
PYPY
from
gevent._compat
import
reraise
from
gevent._compat
import
reraise
...
@@ -85,7 +85,7 @@ __implements__ = [
...
@@ -85,7 +85,7 @@ __implements__ = [
'check_call'
,
'check_call'
,
'check_output'
,
'check_output'
,
]
]
if
PY3
and
not
sys
.
platform
.
startswith
(
'win32'
):
if
not
sys
.
platform
.
startswith
(
'win32'
):
__implements__
.
append
(
"_posixsubprocess"
)
__implements__
.
append
(
"_posixsubprocess"
)
_posixsubprocess
=
None
_posixsubprocess
=
None
...
@@ -142,74 +142,69 @@ __extra__ = [
...
@@ -142,74 +142,69 @@ __extra__ = [
'CompletedProcess'
,
'CompletedProcess'
,
]
]
if
PY3
:
__imports__
+=
[
__imports__
+=
[
'DEVNULL'
,
'DEVNULL'
,
'getstatusoutput'
,
'getstatusoutput'
,
'getoutput'
,
'getoutput'
,
'SubprocessError'
,
'SubprocessError'
,
'TimeoutExpired'
,
'TimeoutExpired'
,
]
]
else
:
__extra__
.
append
(
"TimeoutExpired"
)
if
PY35
:
__extra__
.
remove
(
'run'
)
__extra__
.
remove
(
'CompletedProcess'
)
__implements__
.
append
(
'run'
)
__implements__
.
append
(
'CompletedProcess'
)
# Removed in Python 3.5; this is the exact code that was removed:
# https://hg.python.org/cpython/rev/f98b0a5e5ef5
__extra__
.
remove
(
'MAXFD'
)
try
:
MAXFD
=
os
.
sysconf
(
"SC_OPEN_MAX"
)
except
:
MAXFD
=
256
if
PY36
:
# This was added to __all__ for windows in 3.6
__extra__
.
remove
(
'STARTUPINFO'
)
__imports__
.
append
(
'STARTUPINFO'
)
if
PY37
:
# Became standard in 3.5
__imports__
.
extend
([
__extra__
.
remove
(
'run'
)
'ABOVE_NORMAL_PRIORITY_CLASS'
,
'BELOW_NORMAL_PRIORITY_CLASS'
,
__extra__
.
remove
(
'CompletedProcess'
)
'HIGH_PRIORITY_CLASS'
,
'IDLE_PRIORITY_CLASS'
,
__implements__
.
append
(
'run'
)
'NORMAL_PRIORITY_CLASS'
,
__implements__
.
append
(
'CompletedProcess'
)
'REALTIME_PRIORITY_CLASS'
,
'CREATE_NO_WINDOW'
,
'DETACHED_PROCESS'
,
'CREATE_DEFAULT_ERROR_MODE'
,
'CREATE_BREAKAWAY_FROM_JOB'
])
if
PY38
:
# Removed in Python 3.5; this is the exact code that was removed:
# Using os.posix_spawn() to start subprocesses
# https://hg.python.org/cpython/rev/f98b0a5e5ef5
# bypasses our child watchers on certain operating systems,
__extra__
.
remove
(
'MAXFD'
)
# and with certain library versions. Possibly the right
try
:
# fix is to monkey-patch os.posix_spawn like we do os.fork?
MAXFD
=
os
.
sysconf
(
"SC_OPEN_MAX"
)
# These have no effect, they're just here to match the stdlib.
except
:
# TODO: When available, given a monkey patch on them, I think
MAXFD
=
256
# we ought to be able to use them if the stdlib has identified them
# as suitable.
# This was added to __all__ for windows in 3.6
__extra__
.
remove
(
'STARTUPINFO'
)
__imports__
.
append
(
'STARTUPINFO'
)
__imports__
.
extend
([
'ABOVE_NORMAL_PRIORITY_CLASS'
,
'BELOW_NORMAL_PRIORITY_CLASS'
,
'HIGH_PRIORITY_CLASS'
,
'IDLE_PRIORITY_CLASS'
,
'NORMAL_PRIORITY_CLASS'
,
'REALTIME_PRIORITY_CLASS'
,
'CREATE_NO_WINDOW'
,
'DETACHED_PROCESS'
,
'CREATE_DEFAULT_ERROR_MODE'
,
'CREATE_BREAKAWAY_FROM_JOB'
])
# Using os.posix_spawn() to start subprocesses
# bypasses our child watchers on certain operating systems,
# and with certain library versions. Possibly the right
# fix is to monkey-patch os.posix_spawn like we do os.fork?
# These have no effect, they're just here to match the stdlib.
# TODO: When available, given a monkey patch on them, I think
# we ought to be able to use them if the stdlib has identified them
# as suitable.
__implements__
.
extend
([
'_use_posix_spawn'
,
])
def
_use_posix_spawn
():
return
False
_USE_POSIX_SPAWN
=
False
if
__subprocess__
.
_USE_POSIX_SPAWN
:
__implements__
.
extend
([
__implements__
.
extend
([
'_use_posix_spawn'
,
'_USE_POSIX_SPAWN'
,
])
else
:
__imports__
.
extend
([
'_USE_POSIX_SPAWN'
,
])
])
def
_use_posix_spawn
():
return
False
_USE_POSIX_SPAWN
=
False
if
__subprocess__
.
_USE_POSIX_SPAWN
:
__implements__
.
extend
([
'_USE_POSIX_SPAWN'
,
])
else
:
__imports__
.
extend
([
'_USE_POSIX_SPAWN'
,
])
if
PY311
:
if
PY311
:
# Python 3.11 added some module-level attributes to control the
# Python 3.11 added some module-level attributes to control the
...
@@ -270,26 +265,25 @@ for _x in ('run', 'CompletedProcess', 'TimeoutExpired'):
...
@@ -270,26 +265,25 @@ for _x in ('run', 'CompletedProcess', 'TimeoutExpired'):
mswindows
=
sys
.
platform
==
'win32'
mswindows
=
sys
.
platform
==
'win32'
if
mswindows
:
if
mswindows
:
import
msvcrt
# pylint: disable=import-error
import
msvcrt
# pylint: disable=import-error
if
PY3
:
class
Handle
(
int
):
class
Handle
(
int
):
closed
=
False
closed
=
False
def
Close
(
self
):
def
Close
(
self
):
if
not
self
.
closed
:
if
not
self
.
closed
:
self
.
closed
=
True
self
.
closed
=
True
_winapi
.
CloseHandle
(
self
)
_winapi
.
CloseHandle
(
self
)
def
Detach
(
self
):
def
Detach
(
self
):
if
not
self
.
closed
:
if
not
self
.
closed
:
self
.
closed
=
True
self
.
closed
=
True
return
int
(
self
)
return
int
(
self
)
raise
ValueError
(
"already closed"
)
raise
ValueError
(
"already closed"
)
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"Handle(%d)"
%
int
(
self
)
return
"Handle(%d)"
%
int
(
self
)
__del__
=
Close
__del__
=
Close
__str__
=
__repr__
__str__
=
__repr__
else
:
else
:
import
fcntl
import
fcntl
import
pickle
import
pickle
...
@@ -478,14 +472,6 @@ def FileObject(*args, **kwargs):
...
@@ -478,14 +472,6 @@ def FileObject(*args, **kwargs):
# Defer importing FileObject until we need it
# Defer importing FileObject until we need it
# to allow it to be configured more easily.
# to allow it to be configured more easily.
from
gevent.fileobject
import
FileObject
as
_FileObject
from
gevent.fileobject
import
FileObject
as
_FileObject
if
not
PY3
:
# Make write behave like the old Python 2 file
# write and loop to consume output, even when not
# buffered.
__FileObject
=
_FileObject
def
_FileObject
(
*
args
,
**
kwargs
):
kwargs
[
'atomic_write'
]
=
True
return
__FileObject
(
*
args
,
**
kwargs
)
globals
()[
'FileObject'
]
=
_FileObject
globals
()[
'FileObject'
]
=
_FileObject
return
_FileObject
(
*
args
)
return
_FileObject
(
*
args
)
...
@@ -666,13 +652,13 @@ class Popen(object):
...
@@ -666,13 +652,13 @@ class Popen(object):
_communicate_empty_value
=
b''
_communicate_empty_value
=
b''
def
__init__
(
self
,
args
,
def
__init__
(
self
,
args
,
bufsize
=-
1
if
PY3
else
0
,
bufsize
=-
1
,
executable
=
None
,
executable
=
None
,
stdin
=
None
,
stdout
=
None
,
stderr
=
None
,
stdin
=
None
,
stdout
=
None
,
stderr
=
None
,
preexec_fn
=
None
,
close_fds
=
_PLATFORM_DEFAULT_CLOSE_FDS
,
shell
=
False
,
preexec_fn
=
None
,
close_fds
=
_PLATFORM_DEFAULT_CLOSE_FDS
,
shell
=
False
,
cwd
=
None
,
env
=
None
,
universal_newlines
=
None
,
cwd
=
None
,
env
=
None
,
universal_newlines
=
None
,
startupinfo
=
None
,
creationflags
=
0
,
startupinfo
=
None
,
creationflags
=
0
,
restore_signals
=
PY3
,
start_new_session
=
False
,
restore_signals
=
True
,
start_new_session
=
False
,
pass_fds
=
(),
pass_fds
=
(),
# Added in 3.6. These are kept as ivars
# Added in 3.6. These are kept as ivars
encoding
=
None
,
errors
=
None
,
encoding
=
None
,
errors
=
None
,
...
@@ -696,7 +682,7 @@ class Popen(object):
...
@@ -696,7 +682,7 @@ class Popen(object):
if
bufsize
is
None
:
if
bufsize
is
None
:
# Python 2 doesn't allow None at all, but Python 3 treats
# Python 2 doesn't allow None at all, but Python 3 treats
# it the same as the default. We do as well.
# it the same as the default. We do as well.
bufsize
=
-
1
if
PY3
else
0
bufsize
=
-
1
if
not
isinstance
(
bufsize
,
integer_types
):
if
not
isinstance
(
bufsize
,
integer_types
):
raise
TypeError
(
"bufsize must be an integer"
)
raise
TypeError
(
"bufsize must be an integer"
)
...
@@ -704,20 +690,10 @@ class Popen(object):
...
@@ -704,20 +690,10 @@ class Popen(object):
if
preexec_fn
is
not
None
:
if
preexec_fn
is
not
None
:
raise
ValueError
(
"preexec_fn is not supported on Windows "
raise
ValueError
(
"preexec_fn is not supported on Windows "
"platforms"
)
"platforms"
)
if
PY37
:
if
close_fds
is
_PLATFORM_DEFAULT_CLOSE_FDS
:
if
close_fds
is
_PLATFORM_DEFAULT_CLOSE_FDS
:
close_fds
=
True
close_fds
=
True
else
:
any_stdio_set
=
(
stdin
is
not
None
or
stdout
is
not
None
or
stderr
is
not
None
)
if
close_fds
is
_PLATFORM_DEFAULT_CLOSE_FDS
:
if
any_stdio_set
:
close_fds
=
False
else
:
close_fds
=
True
elif
close_fds
and
any_stdio_set
:
raise
ValueError
(
"close_fds is not supported on Windows "
"platforms if you redirect stdin/stdout/stderr"
)
if
threadpool
is
None
:
if
threadpool
is
None
:
threadpool
=
hub
.
threadpool
threadpool
=
hub
.
threadpool
self
.
threadpool
=
threadpool
self
.
threadpool
=
threadpool
...
@@ -726,10 +702,7 @@ class Popen(object):
...
@@ -726,10 +702,7 @@ class Popen(object):
# POSIX
# POSIX
if
close_fds
is
_PLATFORM_DEFAULT_CLOSE_FDS
:
if
close_fds
is
_PLATFORM_DEFAULT_CLOSE_FDS
:
# close_fds has different defaults on Py3/Py2
# close_fds has different defaults on Py3/Py2
if
PY3
:
# pylint: disable=simplifiable-if-statement
close_fds
=
True
close_fds
=
True
else
:
close_fds
=
False
if
pass_fds
and
not
close_fds
:
if
pass_fds
and
not
close_fds
:
import
warnings
import
warnings
...
@@ -791,7 +764,7 @@ class Popen(object):
...
@@ -791,7 +764,7 @@ class Popen(object):
if
errread
!=
-
1
:
if
errread
!=
-
1
:
errread
=
msvcrt
.
open_osfhandle
(
errread
.
Detach
(),
0
)
errread
=
msvcrt
.
open_osfhandle
(
errread
.
Detach
(),
0
)
text_mode
=
PY3
and
(
self
.
encoding
or
self
.
errors
or
universal_newlines
or
text
)
text_mode
=
self
.
encoding
or
self
.
errors
or
universal_newlines
or
text
if
text_mode
or
universal_newlines
:
if
text_mode
or
universal_newlines
:
# Always a native str in universal_newlines mode, even when that
# Always a native str in universal_newlines mode, even when that
# str type is bytes. Additionally, text_mode is only true under
# str type is bytes. Additionally, text_mode is only true under
...
@@ -801,7 +774,7 @@ class Popen(object):
...
@@ -801,7 +774,7 @@ class Popen(object):
uid
,
gid
,
gids
=
self
.
__handle_uids
(
user
,
group
,
extra_groups
)
uid
,
gid
,
gids
=
self
.
__handle_uids
(
user
,
group
,
extra_groups
)
if
p2cwrite
!=
-
1
:
if
p2cwrite
!=
-
1
:
if
PY3
and
text_mode
:
if
text_mode
:
# Under Python 3, if we left on the 'b' we'd get different results
# Under Python 3, if we left on the 'b' we'd get different results
# depending on whether we used FileObjectPosix or FileObjectThread
# depending on whether we used FileObjectPosix or FileObjectThread
self
.
stdin
=
FileObject
(
p2cwrite
,
'w'
,
bufsize
,
self
.
stdin
=
FileObject
(
p2cwrite
,
'w'
,
bufsize
,
...
@@ -811,25 +784,20 @@ class Popen(object):
...
@@ -811,25 +784,20 @@ class Popen(object):
if
c2pread
!=
-
1
:
if
c2pread
!=
-
1
:
if
universal_newlines
or
text_mode
:
if
universal_newlines
or
text_mode
:
if
PY3
:
self
.
stdout
=
FileObject
(
c2pread
,
'r'
,
bufsize
,
self
.
stdout
=
FileObject
(
c2pread
,
'r'
,
bufsize
,
encoding
=
self
.
encoding
,
errors
=
self
.
errors
)
encoding
=
self
.
encoding
,
errors
=
self
.
errors
)
# NOTE: Universal Newlines are broken on Windows/Py3, at least
# NOTE: Universal Newlines are broken on Windows/Py3, at least
# in some cases. This is true in the stdlib subprocess module
# in some cases. This is true in the stdlib subprocess module
# as well; the following line would fix the test cases in
# as well; the following line would fix the test cases in
# test__subprocess.py that depend on python_universal_newlines,
# test__subprocess.py that depend on python_universal_newlines,
# but would be inconsistent with the stdlib:
# but would be inconsistent with the stdlib:
else
:
self
.
stdout
=
FileObject
(
c2pread
,
'rU'
,
bufsize
)
else
:
else
:
self
.
stdout
=
FileObject
(
c2pread
,
'rb'
,
bufsize
)
self
.
stdout
=
FileObject
(
c2pread
,
'rb'
,
bufsize
)
if
errread
!=
-
1
:
if
errread
!=
-
1
:
if
universal_newlines
or
text_mode
:
if
universal_newlines
or
text_mode
:
if
PY3
:
self
.
stderr
=
FileObject
(
errread
,
'r'
,
bufsize
,
self
.
stderr
=
FileObject
(
errread
,
'r'
,
bufsize
,
encoding
=
encoding
,
errors
=
errors
)
encoding
=
encoding
,
errors
=
errors
)
else
:
self
.
stderr
=
FileObject
(
errread
,
'rU'
,
bufsize
)
else
:
else
:
self
.
stderr
=
FileObject
(
errread
,
'rb'
,
bufsize
)
self
.
stderr
=
FileObject
(
errread
,
'rb'
,
bufsize
)
...
@@ -853,8 +821,6 @@ class Popen(object):
...
@@ -853,8 +821,6 @@ class Popen(object):
# (gevent: New in python3, but reported as gevent bug in #347.
# (gevent: New in python3, but reported as gevent bug in #347.
# Note that under Py2, any error raised below will replace the
# Note that under Py2, any error raised below will replace the
# original error so we have to use reraise)
# original error so we have to use reraise)
if
not
PY3
:
exc_info
=
sys
.
exc_info
()
for
f
in
filter
(
None
,
(
self
.
stdin
,
self
.
stdout
,
self
.
stderr
)):
for
f
in
filter
(
None
,
(
self
.
stdin
,
self
.
stdout
,
self
.
stderr
)):
try
:
try
:
f
.
close
()
f
.
close
()
...
@@ -876,11 +842,6 @@ class Popen(object):
...
@@ -876,11 +842,6 @@ class Popen(object):
os
.
close
(
fd
)
os
.
close
(
fd
)
except
(
OSError
,
IOError
):
except
(
OSError
,
IOError
):
pass
pass
if
not
PY3
:
try
:
reraise
(
*
exc_info
)
finally
:
del
exc_info
raise
raise
def
__handle_uids
(
self
,
user
,
group
,
extra_groups
):
def
__handle_uids
(
self
,
user
,
group
,
extra_groups
):
...
@@ -1074,7 +1035,7 @@ class Popen(object):
...
@@ -1074,7 +1035,7 @@ class Popen(object):
# blocks forever.
# blocks forever.
self
.
wait
()
self
.
wait
()
def
_gevent_result_wait
(
self
,
timeout
=
None
,
raise_exc
=
PY3
):
def
_gevent_result_wait
(
self
,
timeout
=
None
,
raise_exc
=
True
):
result
=
self
.
result
.
wait
(
timeout
=
timeout
)
result
=
self
.
result
.
wait
(
timeout
=
timeout
)
if
raise_exc
and
timeout
is
not
None
and
not
self
.
result
.
ready
():
if
raise_exc
and
timeout
is
not
None
and
not
self
.
result
.
ready
():
raise
TimeoutExpired
(
self
.
args
,
timeout
)
raise
TimeoutExpired
(
self
.
args
,
timeout
)
...
@@ -1108,13 +1069,11 @@ class Popen(object):
...
@@ -1108,13 +1069,11 @@ class Popen(object):
p2cread
=
GetStdHandle
(
STD_INPUT_HANDLE
)
p2cread
=
GetStdHandle
(
STD_INPUT_HANDLE
)
if
p2cread
is
None
:
if
p2cread
is
None
:
p2cread
,
_
=
CreatePipe
(
None
,
0
)
p2cread
,
_
=
CreatePipe
(
None
,
0
)
if
PY3
:
p2cread
=
Handle
(
p2cread
)
p2cread
=
Handle
(
p2cread
)
_winapi
.
CloseHandle
(
_
)
_winapi
.
CloseHandle
(
_
)
elif
stdin
==
PIPE
:
elif
stdin
==
PIPE
:
p2cread
,
p2cwrite
=
CreatePipe
(
None
,
0
)
p2cread
,
p2cwrite
=
CreatePipe
(
None
,
0
)
if
PY3
:
p2cread
,
p2cwrite
=
Handle
(
p2cread
),
Handle
(
p2cwrite
)
p2cread
,
p2cwrite
=
Handle
(
p2cread
),
Handle
(
p2cwrite
)
elif
stdin
==
_devnull
:
elif
stdin
==
_devnull
:
p2cread
=
msvcrt
.
get_osfhandle
(
self
.
_get_devnull
())
p2cread
=
msvcrt
.
get_osfhandle
(
self
.
_get_devnull
())
elif
isinstance
(
stdin
,
int
):
elif
isinstance
(
stdin
,
int
):
...
@@ -1128,13 +1087,11 @@ class Popen(object):
...
@@ -1128,13 +1087,11 @@ class Popen(object):
c2pwrite
=
GetStdHandle
(
STD_OUTPUT_HANDLE
)
c2pwrite
=
GetStdHandle
(
STD_OUTPUT_HANDLE
)
if
c2pwrite
is
None
:
if
c2pwrite
is
None
:
_
,
c2pwrite
=
CreatePipe
(
None
,
0
)
_
,
c2pwrite
=
CreatePipe
(
None
,
0
)
if
PY3
:
c2pwrite
=
Handle
(
c2pwrite
)
c2pwrite
=
Handle
(
c2pwrite
)
_winapi
.
CloseHandle
(
_
)
_winapi
.
CloseHandle
(
_
)
elif
stdout
==
PIPE
:
elif
stdout
==
PIPE
:
c2pread
,
c2pwrite
=
CreatePipe
(
None
,
0
)
c2pread
,
c2pwrite
=
CreatePipe
(
None
,
0
)
if
PY3
:
c2pread
,
c2pwrite
=
Handle
(
c2pread
),
Handle
(
c2pwrite
)
c2pread
,
c2pwrite
=
Handle
(
c2pread
),
Handle
(
c2pwrite
)
elif
stdout
==
_devnull
:
elif
stdout
==
_devnull
:
c2pwrite
=
msvcrt
.
get_osfhandle
(
self
.
_get_devnull
())
c2pwrite
=
msvcrt
.
get_osfhandle
(
self
.
_get_devnull
())
elif
isinstance
(
stdout
,
int
):
elif
isinstance
(
stdout
,
int
):
...
@@ -1148,13 +1105,11 @@ class Popen(object):
...
@@ -1148,13 +1105,11 @@ class Popen(object):
errwrite
=
GetStdHandle
(
STD_ERROR_HANDLE
)
errwrite
=
GetStdHandle
(
STD_ERROR_HANDLE
)
if
errwrite
is
None
:
if
errwrite
is
None
:
_
,
errwrite
=
CreatePipe
(
None
,
0
)
_
,
errwrite
=
CreatePipe
(
None
,
0
)
if
PY3
:
errwrite
=
Handle
(
errwrite
)
errwrite
=
Handle
(
errwrite
)
_winapi
.
CloseHandle
(
_
)
_winapi
.
CloseHandle
(
_
)
elif
stderr
==
PIPE
:
elif
stderr
==
PIPE
:
errread
,
errwrite
=
CreatePipe
(
None
,
0
)
errread
,
errwrite
=
CreatePipe
(
None
,
0
)
if
PY3
:
errread
,
errwrite
=
Handle
(
errread
),
Handle
(
errwrite
)
errread
,
errwrite
=
Handle
(
errread
),
Handle
(
errwrite
)
elif
stderr
==
STDOUT
:
elif
stderr
==
STDOUT
:
errwrite
=
c2pwrite
errwrite
=
c2pwrite
elif
stderr
==
_devnull
:
elif
stderr
==
_devnull
:
...
@@ -1223,7 +1178,7 @@ class Popen(object):
...
@@ -1223,7 +1178,7 @@ class Popen(object):
if
isinstance
(
args
,
str
):
if
isinstance
(
args
,
str
):
pass
pass
elif
isinstance
(
args
,
bytes
):
elif
isinstance
(
args
,
bytes
):
if
shell
and
PY3
:
if
shell
:
raise
TypeError
(
'bytes args is not allowed on Windows'
)
raise
TypeError
(
'bytes args is not allowed on Windows'
)
args
=
list2cmdline
([
args
])
args
=
list2cmdline
([
args
])
elif
isinstance
(
args
,
PathLike
):
elif
isinstance
(
args
,
PathLike
):
...
@@ -1317,7 +1272,7 @@ class Popen(object):
...
@@ -1317,7 +1272,7 @@ class Popen(object):
# CreateProcess call on PyPy. Currently we don't test PyPy3 on Windows,
# CreateProcess call on PyPy. Currently we don't test PyPy3 on Windows,
# so we don't know for sure if it's built into CreateProcess there.
# so we don't know for sure if it's built into CreateProcess there.
if
PYPY
:
if
PYPY
:
def
_check_nul
(
s
,
err_kind
=
(
ValueError
if
PY3
else
TypeError
)
):
def
_check_nul
(
s
,
err_kind
=
ValueError
):
if
not
s
:
if
not
s
:
return
return
nul
=
b'
\
0
'
if
isinstance
(
s
,
bytes
)
else
'
\
0
'
nul
=
b'
\
0
'
if
isinstance
(
s
,
bytes
)
else
'
\
0
'
...
@@ -1347,14 +1302,13 @@ class Popen(object):
...
@@ -1347,14 +1302,13 @@ class Popen(object):
env
,
env
,
cwd
,
# fsdecode handled earlier
cwd
,
# fsdecode handled earlier
startupinfo
)
startupinfo
)
except
IOError
as
e
:
# From 2.6 on, pywintypes.error was defined as IOError
# except IOError as e: # From 2.6 on, pywintypes.error was defined as IOError
# Translate pywintypes.error to WindowsError, which is
# # Translate pywintypes.error to WindowsError, which is
# a subclass of OSError. FIXME: We should really
# # a subclass of OSError. FIXME: We should really
# translate errno using _sys_errlist (or similar), but
# # translate errno using _sys_errlist (or similar), but
# how can this be done from Python?
# # how can this be done from Python?
if
PY3
:
# raise # don't remap here
raise
# don't remap here
# raise WindowsError(*e.args)
raise
WindowsError
(
*
e
.
args
)
finally
:
finally
:
# Child is launched. Close the parent's copy of those pipe
# Child is launched. Close the parent's copy of those pipe
# handles that only the child should have open. You need
# handles that only the child should have open. You need
...
@@ -1408,7 +1362,7 @@ class Popen(object):
...
@@ -1408,7 +1362,7 @@ class Popen(object):
def
_wait
(
self
):
def
_wait
(
self
):
self
.
threadpool
.
spawn
(
self
.
_blocking_wait
).
rawlink
(
self
.
result
)
self
.
threadpool
.
spawn
(
self
.
_blocking_wait
).
rawlink
(
self
.
result
)
def
wait
(
self
,
timeout
=
None
,
_raise_exc
=
PY3
):
def
wait
(
self
,
timeout
=
None
,
_raise_exc
=
True
):
"""Wait for child process to terminate. Returns returncode
"""Wait for child process to terminate. Returns returncode
attribute."""
attribute."""
if
self
.
returncode
is
None
:
if
self
.
returncode
is
None
:
...
@@ -1628,9 +1582,7 @@ class Popen(object):
...
@@ -1628,9 +1582,7 @@ class Popen(object):
start_new_session
,
process_group
):
start_new_session
,
process_group
):
"""Execute program (POSIX version)"""
"""Execute program (POSIX version)"""
if
PY3
and
isinstance
(
args
,
(
str
,
bytes
)):
if
isinstance
(
args
,
(
str
,
bytes
)):
args
=
[
args
]
elif
not
PY3
and
isinstance
(
args
,
string_types
):
args
=
[
args
]
args
=
[
args
]
elif
isinstance
(
args
,
PathLike
):
elif
isinstance
(
args
,
PathLike
):
if
shell
:
if
shell
:
...
@@ -1728,7 +1680,7 @@ class Popen(object):
...
@@ -1728,7 +1680,7 @@ class Popen(object):
# Close pipe fds. Make sure we don't close the
# Close pipe fds. Make sure we don't close the
# same fd more than once, or standard fds.
# same fd more than once, or standard fds.
if
not
PY3
:
if
not
True
:
closed
=
set
([
None
])
closed
=
set
([
None
])
for
fd
in
[
p2cread
,
c2pwrite
,
errwrite
]:
for
fd
in
[
p2cread
,
c2pwrite
,
errwrite
]:
if
fd
not
in
closed
and
fd
>
2
:
if
fd
not
in
closed
and
fd
>
2
:
...
@@ -1785,17 +1737,16 @@ class Popen(object):
...
@@ -1785,17 +1737,16 @@ class Popen(object):
if
env
is
None
:
if
env
is
None
:
os
.
execvp
(
executable
,
args
)
os
.
execvp
(
executable
,
args
)
else
:
else
:
if
PY3
:
# Python 3.6 started testing for
# Python 3.6 started testing for
# bytes values in the env; it also
# bytes values in the env; it also
# started encoding strs using
# started encoding strs using
# fsencode and using a lower-level
# fsencode and using a lower-level
# API that takes a list of keys
# API that takes a list of keys
# and values. We don't have access
# and values. We don't have access
# to that API, so we go the reverse direction.
# to that API, so we go the reverse direction.
env
=
{
os
.
fsdecode
(
k
)
if
isinstance
(
k
,
bytes
)
else
k
:
env
=
{
os
.
fsdecode
(
k
)
if
isinstance
(
k
,
bytes
)
else
k
:
os
.
fsdecode
(
v
)
if
isinstance
(
v
,
bytes
)
else
v
os
.
fsdecode
(
v
)
if
isinstance
(
v
,
bytes
)
else
v
for
k
,
v
in
env
.
items
()}
for
k
,
v
in
env
.
items
()}
os
.
execvpe
(
executable
,
args
,
env
)
os
.
execvpe
(
executable
,
args
,
env
)
except
:
except
:
...
@@ -1893,7 +1844,7 @@ class Popen(object):
...
@@ -1893,7 +1844,7 @@ class Popen(object):
sleep
(
0.00001
)
sleep
(
0.00001
)
return
self
.
returncode
return
self
.
returncode
def
wait
(
self
,
timeout
=
None
,
_raise_exc
=
PY3
):
def
wait
(
self
,
timeout
=
None
,
_raise_exc
=
True
):
"""
"""
Wait for child process to terminate. Returns :attr:`returncode`
Wait for child process to terminate. Returns :attr:`returncode`
attribute.
attribute.
...
...
src/gevent/testing/__init__.py
View file @
d9e2479b
...
@@ -115,7 +115,6 @@ from .skipping import skipOnPy310
...
@@ -115,7 +115,6 @@ from .skipping import skipOnPy310
from
.skipping
import
skipOnPy3
from
.skipping
import
skipOnPy3
from
.skipping
import
skipWithoutResource
from
.skipping
import
skipWithoutResource
from
.skipping
import
skipWithoutExternalNetwork
from
.skipping
import
skipWithoutExternalNetwork
from
.skipping
import
skipOnPy2
from
.skipping
import
skipOnManylinux
from
.skipping
import
skipOnManylinux
from
.skipping
import
skipOnMacOnCI
from
.skipping
import
skipOnMacOnCI
...
...
src/gevent/testing/skipping.py
View file @
d9e2479b
...
@@ -45,7 +45,6 @@ skipOnPyPy3OnCI = _do_not_skip
...
@@ -45,7 +45,6 @@ skipOnPyPy3OnCI = _do_not_skip
skipOnPyPy3
=
_do_not_skip
skipOnPyPy3
=
_do_not_skip
skipOnPyPyOnWindows
=
_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
skipOnPy3
=
unittest
.
skip
if
sysinfo
.
PY3
else
_do_not_skip
skipOnPy37
=
unittest
.
skip
if
sysinfo
.
PY37
else
_do_not_skip
skipOnPy37
=
unittest
.
skip
if
sysinfo
.
PY37
else
_do_not_skip
skipOnPy310
=
unittest
.
skip
if
sysinfo
.
PY310
else
_do_not_skip
skipOnPy310
=
unittest
.
skip
if
sysinfo
.
PY310
else
_do_not_skip
...
...
src/gevent/tests/test__fileobject.py
View file @
d9e2479b
...
@@ -17,18 +17,10 @@ try:
...
@@ -17,18 +17,10 @@ try:
except
ImportError
:
except
ImportError
:
GreenOpenDescriptor
=
None
GreenOpenDescriptor
=
None
from
gevent._compat
import
PY2
from
gevent._compat
import
PY3
from
gevent._compat
import
text_type
import
gevent.testing
as
greentest
import
gevent.testing
as
greentest
from
gevent.testing
import
sysinfo
from
gevent.testing
import
sysinfo
try
:
ResourceWarning
# pylint:disable=used-before-assignment
except
NameError
:
class
ResourceWarning
(
Warning
):
"Python 2 fallback"
# pylint:disable=unspecified-encoding
# pylint:disable=unspecified-encoding
...
@@ -136,11 +128,9 @@ class TestFileObjectBlock(CleanupMixin,
...
@@ -136,11 +128,9 @@ class TestFileObjectBlock(CleanupMixin,
with
open
(
path
,
'rb'
)
as
f_raw
:
with
open
(
path
,
'rb'
)
as
f_raw
:
f
=
self
.
_makeOne
(
f_raw
,
'rb'
,
close
=
False
)
f
=
self
.
_makeOne
(
f_raw
,
'rb'
,
close
=
False
)
# On Python 3, all objects should have seekable.
if
PY3
or
hasattr
(
f
,
'seekable'
):
# On Python 2, only our custom objects do.
# On Python 3, all objects should have seekable.
self
.
assertTrue
(
f
.
seekable
())
# On Python 2, only our custom objects do.
self
.
assertTrue
(
f
.
seekable
())
f
.
seek
(
15
)
f
.
seek
(
15
)
self
.
assertEqual
(
15
,
f
.
tell
())
self
.
assertEqual
(
15
,
f
.
tell
())
...
@@ -169,7 +159,7 @@ class TestFileObjectBlock(CleanupMixin,
...
@@ -169,7 +159,7 @@ class TestFileObjectBlock(CleanupMixin,
else
:
else
:
# Note that we don't use ``io.open()`` for the raw file,
# 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.
# 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
opener
(
path
,
open_mode
,
**
open_kwargs
)
as
raw
:
with
self
.
_makeOne
(
raw
)
as
f
:
with
self
.
_makeOne
(
raw
)
as
f
:
gevent_data
=
getattr
(
f
,
meth
)()
gevent_data
=
getattr
(
f
,
meth
)()
...
@@ -190,7 +180,7 @@ class TestFileObjectBlock(CleanupMixin,
...
@@ -190,7 +180,7 @@ class TestFileObjectBlock(CleanupMixin,
'r+'
,
'r+'
,
buffering
=
5
,
encoding
=
'utf-8'
buffering
=
5
,
encoding
=
'utf-8'
)
)
self
.
assertIsInstance
(
gevent_data
,
text_type
)
self
.
assertIsInstance
(
gevent_data
,
str
)
@
skipUnlessWorksWithRegularFiles
@
skipUnlessWorksWithRegularFiles
def
test_does_not_leak_on_exception
(
self
):
def
test_does_not_leak_on_exception
(
self
):
...
@@ -341,7 +331,7 @@ class ConcurrentFileObjectMixin(object):
...
@@ -341,7 +331,7 @@ class ConcurrentFileObjectMixin(object):
self
.
addCleanup
(
os
.
close
,
w
)
self
.
addCleanup
(
os
.
close
,
w
)
reader
=
self
.
_makeOne
(
r
)
reader
=
self
.
_makeOne
(
r
)
self
.
_close_on_teardown
(
reader
)
self
.
_close_on_teardown
(
reader
)
self
.
assert
Equal
(
PY2
,
hasattr
(
reader
,
'read1'
))
self
.
assert
False
(
hasattr
(
reader
,
'read1'
))
def
test_bufsize_0
(
self
):
def
test_bufsize_0
(
self
):
# Issue #840
# Issue #840
...
...
src/gevent/tests/test__issue1864.py
View file @
d9e2479b
import
sys
import
sys
import
unittest
import
unittest
from
gevent.testing
import
skipOnPy2
class
TestSubnormalFloatsAreNotDisabled
(
unittest
.
TestCase
):
class
TestSubnormalFloatsAreNotDisabled
(
unittest
.
TestCase
):
@
skipOnPy2
(
'This test always fails on Python 2'
)
def
test_subnormal_is_not_zero
(
self
):
def
test_subnormal_is_not_zero
(
self
):
# Enabling the -Ofast compiler flag resulted in subnormal floats getting
# Enabling the -Ofast compiler flag resulted in subnormal floats getting
# disabled the moment when gevent was imported. This impacted libraries
# disabled the moment when gevent was imported. This impacted libraries
...
@@ -21,7 +19,7 @@ class TestSubnormalFloatsAreNotDisabled(unittest.TestCase):
...
@@ -21,7 +19,7 @@ class TestSubnormalFloatsAreNotDisabled(unittest.TestCase):
# `sys.float_info.min` is the minimum representable positive normalized
# `sys.float_info.min` is the minimum representable positive normalized
# float, so dividing it by two gives us a positive subnormal float,
# float, so dividing it by two gives us a positive subnormal float,
# as long as subnormals floats are not disabled.
# 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__"
:
if
__name__
==
"__main__"
:
...
...
src/gevent/tests/test__monkey_module_run.py
View file @
d9e2479b
...
@@ -104,21 +104,19 @@ class TestRun(greentest.TestCase):
...
@@ -104,21 +104,19 @@ class TestRun(greentest.TestCase):
# Also, occasionally, they get '3' instead of '2' for the number of threads.
# 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
# That could have something to do with...? Most commonly that's PyPy, but
# sometimes CPython. Again, haven't reproduced.
# 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
):
def
test_threadpool_in_patched_after_patch
(
self
):
# Issue 1484
# Issue 1484
# If we don't have this correct, then we get exceptions
# If we don't have this correct, then we get exceptions
out
=
self
.
_run
(
os
.
path
.
join
(
'monkey_package'
,
'threadpool_monkey_patches.py'
))
out
=
self
.
_run
(
os
.
path
.
join
(
'monkey_package'
,
'threadpool_monkey_patches.py'
))
self
.
assertEqual
(
out
,
[
'False'
,
'2'
])
self
.
assertEqual
(
out
,
[
'False'
,
'2'
])
@
greentest
.
skipOnPy2
(
"lost sys.stderr sometimes"
)
def
test_threadpool_in_patched_after_patch_module
(
self
):
def
test_threadpool_in_patched_after_patch_module
(
self
):
# Issue 1484
# Issue 1484
# If we don't have this correct, then we get exceptions
# If we don't have this correct, then we get exceptions
out
=
self
.
_run
(
'monkey_package.threadpool_monkey_patches'
,
module
=
True
)
out
=
self
.
_run
(
'monkey_package.threadpool_monkey_patches'
,
module
=
True
)
self
.
assertEqual
(
out
,
[
'False'
,
'2'
])
self
.
assertEqual
(
out
,
[
'False'
,
'2'
])
@
greentest
.
skipOnPy2
(
"lost sys.stderr sometimes"
)
def
test_threadpool_not_patched_after_patch_module
(
self
):
def
test_threadpool_not_patched_after_patch_module
(
self
):
# Issue 1484
# Issue 1484
# If we don't have this correct, then we get exceptions
# If we don't have this correct, then we get exceptions
...
...
src/gevent/tests/test__monkey_selectors.py
View file @
d9e2479b
...
@@ -17,9 +17,6 @@ from gevent.tests.test__selectors import SelectorTestMixin
...
@@ -17,9 +17,6 @@ from gevent.tests.test__selectors import SelectorTestMixin
class
TestSelectors
(
SelectorTestMixin
,
greentest
.
TestCase
):
class
TestSelectors
(
SelectorTestMixin
,
greentest
.
TestCase
):
@
greentest
.
skipOnPy2
(
'selectors2 backport does not use _select'
)
@
greentest
.
skipOnWindows
(
@
greentest
.
skipOnWindows
(
"SelectSelector._select is a normal function on Windows"
"SelectSelector._select is a normal function on Windows"
)
)
...
...
src/gevent/tests/test__monkey_ssl_warning.py
View file @
d9e2479b
...
@@ -11,6 +11,7 @@ class Test(unittest.TestCase):
...
@@ -11,6 +11,7 @@ class Test(unittest.TestCase):
# Issue 1108: Python 2, importing pkg_resources,
# Issue 1108: Python 2, importing pkg_resources,
# as is done for namespace packages, imports ssl,
# as is done for namespace packages, imports ssl,
# leading to an unwanted SSL warning.
# leading to an unwanted SSL warning.
# This is a deprecated API though.
__import__
(
'pkg_resources'
)
__import__
(
'pkg_resources'
)
from
gevent
import
monkey
from
gevent
import
monkey
...
...
src/gevent/tests/test__subprocess.py
View file @
d9e2479b
...
@@ -111,7 +111,6 @@ class TestPopen(greentest.TestCase):
...
@@ -111,7 +111,6 @@ class TestPopen(greentest.TestCase):
'pineapple
\
n
\
xff
\
xff
\
xf2
\
xf9
\
n
'
)
'pineapple
\
n
\
xff
\
xff
\
xf2
\
xf9
\
n
'
)
@
greentest
.
skipOnWindows
(
"Windows IO is weird; this doesn't raise"
)
@
greentest
.
skipOnWindows
(
"Windows IO is weird; this doesn't raise"
)
@
greentest
.
skipOnPy2
(
"Only Python 2 decodes"
)
def
test_communicate_undecodable
(
self
):
def
test_communicate_undecodable
(
self
):
# If the subprocess writes non-decodable data, `communicate` raises the
# If the subprocess writes non-decodable data, `communicate` raises the
# same UnicodeDecodeError that the stdlib does, instead of
# same UnicodeDecodeError that the stdlib does, instead of
...
...
src/gevent/thread.py
View file @
d9e2479b
...
@@ -9,7 +9,6 @@ Implementation of the standard :mod:`thread` module that spawns greenlets.
...
@@ -9,7 +9,6 @@ Implementation of the standard :mod:`thread` module that spawns greenlets.
:class:`gevent.Greenlet` class or :func:`gevent.spawn`.
:class:`gevent.Greenlet` class or :func:`gevent.spawn`.
"""
"""
from
__future__
import
absolute_import
from
__future__
import
absolute_import
import
sys
__implements__
=
[
__implements__
=
[
'allocate_lock'
,
'allocate_lock'
,
...
@@ -22,31 +21,23 @@ __implements__ = [
...
@@ -22,31 +21,23 @@ __implements__ = [
]
]
__imports__
=
[
'error'
]
__imports__
=
[
'error'
]
if
sys
.
version_info
[
0
]
==
2
:
import
thread
as
__thread__
# pylint:disable=import-error
import
_thread
as
__thread__
# pylint:disable=import-error
PY2
=
True
PY3
=
False
__target__
=
'_thread'
# Name the `future` backport that might already have been imported;
__imports__
+=
[
# Importing `pkg_resources` imports this, for example.
'TIMEOUT_MAX'
,
__alternate_targets__
=
(
'_thread'
,)
'allocate'
,
else
:
'exit_thread'
,
import
_thread
as
__thread__
# pylint:disable=import-error
'interrupt_main'
,
PY2
=
False
'start_new'
PY3
=
True
]
__target__
=
'_thread'
__imports__
+=
[
# We can't actually produce a value that "may be used
'TIMEOUT_MAX'
,
# to identify this particular thread system-wide", right?
'allocate'
,
# Even if we could, I imagine people will want to pass this to
'exit_thread'
,
# non-Python (native) APIs, so we shouldn't mess with it.
'interrupt_main'
,
__imports__
.
append
(
'get_native_id'
)
'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'
)
error
=
__thread__
.
error
error
=
__thread__
.
error
...
@@ -63,7 +54,6 @@ from gevent.local import local as _local
...
@@ -63,7 +54,6 @@ from gevent.local import local as _local
from
gevent.exceptions
import
LoopExit
from
gevent.exceptions
import
LoopExit
if
hasattr
(
__thread__
,
'RLock'
):
if
hasattr
(
__thread__
,
'RLock'
):
assert
PY3
or
PYPY
# Added in Python 3.4, backported to PyPy 2.7-7.0
# Added in Python 3.4, backported to PyPy 2.7-7.0
__imports__
.
append
(
"RLock"
)
__imports__
.
append
(
"RLock"
)
...
@@ -88,13 +78,11 @@ class LockType(BoundedSemaphore):
...
@@ -88,13 +78,11 @@ class LockType(BoundedSemaphore):
# and any other API changes we need to make to match behaviour
# and any other API changes we need to make to match behaviour
_OVER_RELEASE_ERROR
=
__thread__
.
error
_OVER_RELEASE_ERROR
=
__thread__
.
error
if
PYPY
and
PY3
:
if
PYPY
:
_OVER_RELEASE_ERROR
=
RuntimeError
_OVER_RELEASE_ERROR
=
RuntimeError
if
PY3
:
_TIMEOUT_MAX
=
__thread__
.
TIMEOUT_MAX
# python 2: pylint:disable=no-member
_TIMEOUT_MAX
=
__thread__
.
TIMEOUT_MAX
# pylint:disable=no-member
else
:
_TIMEOUT_MAX
=
9223372036.0
def
acquire
(
self
,
blocking
=
True
,
timeout
=-
1
):
def
acquire
(
self
,
blocking
=
True
,
timeout
=-
1
):
# This is the Python 3 signature.
# This is the Python 3 signature.
...
...
src/gevent/threading.py
View file @
d9e2479b
...
@@ -50,8 +50,7 @@ from gevent.thread import get_ident as _get_ident
...
@@ -50,8 +50,7 @@ from gevent.thread import get_ident as _get_ident
from
gevent.hub
import
sleep
as
_sleep
,
getcurrent
from
gevent.hub
import
sleep
as
_sleep
,
getcurrent
from
gevent.lock
import
RLock
from
gevent.lock
import
RLock
from
gevent._compat
import
PY3
from
gevent._compat
import
PYPY
from
gevent._util
import
LazyOnClass
from
gevent._util
import
LazyOnClass
# Exports, prevent unused import warnings.
# Exports, prevent unused import warnings.
...
@@ -168,46 +167,45 @@ else:
...
@@ -168,46 +167,45 @@ else:
return
main_threads
[
0
]
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
):
class
Thread
(
__threading__
.
Thread
):
super
(
Thread
,
self
).
_set_tstate_lock
()
greenlet
=
getcurrent
()
greenlet
.
rawlink
(
self
.
__greenlet_finished
)
def
__greenlet_finished
(
self
,
_
):
def
_set_tstate_lock
(
self
):
if
self
.
_tstate_lock
:
super
(
Thread
,
self
).
_set_tstate_lock
()
self
.
_tstate_lock
.
release
()
greenlet
=
getcurrent
()
self
.
_stop
(
)
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
__implements__
.
append
(
'Thread'
)
pass
class
Timer
(
Thread
,
__threading__
.
Timer
):
# pylint:disable=abstract-method,inherit-non-class
pass
__implements__
.
append
(
'Timer'
)
__implements__
.
append
(
'Timer'
)
_set_sentinel
=
allocate_lock
_set_sentinel
=
allocate_lock
__implements__
.
append
(
'_set_sentinel'
)
__implements__
.
append
(
'_set_sentinel'
)
# The main thread is patched up with more care
# The main thread is patched up with more care
# in _gevent_will_monkey_patch
# in _gevent_will_monkey_patch
if
PY3
:
__implements__
.
remove
(
'_get_ident'
)
__implements__
.
remove
(
'_get_ident'
)
__implements__
.
append
(
'get_ident'
)
__implements__
.
append
(
'get_ident'
)
get_ident
=
_get_ident
get_ident
=
_get_ident
__implements__
.
remove
(
'_sleep'
)
__implements__
.
remove
(
'_sleep'
)
if
hasattr
(
__threading__
,
'_CRLock'
):
if
hasattr
(
__threading__
,
'_CRLock'
):
# Python 3 changed the implementation of threading.RLock
# Python 3 changed the implementation of threading.RLock
...
@@ -219,7 +217,6 @@ if hasattr(__threading__, '_CRLock'):
...
@@ -219,7 +217,6 @@ if hasattr(__threading__, '_CRLock'):
# if the imported _CRLock is None; this arranges for that to be the case.
# if the imported _CRLock is None; this arranges for that to be the case.
# This was also backported to PyPy 2.7-7.0
# This was also backported to PyPy 2.7-7.0
assert
PY3
or
PYPY
,
"Unsupported Python version"
_CRLock
=
None
_CRLock
=
None
__implements__
.
append
(
'_CRLock'
)
__implements__
.
append
(
'_CRLock'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment