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
2d37899f
Commit
2d37899f
authored
Feb 19, 2018
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Be more careful about issuing the SSL warning on Py2.
Fixes #1108.
parent
811837cb
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
165 additions
and
81 deletions
+165
-81
CHANGES.rst
CHANGES.rst
+3
-0
src/gevent/monkey.py
src/gevent/monkey.py
+32
-14
src/greentest/test__monkey.py
src/greentest/test__monkey.py
+95
-67
src/greentest/test__monkey_ssl_warning.py
src/greentest/test__monkey_ssl_warning.py
+34
-0
src/greentest/tests_that_dont_do_leakchecks.txt
src/greentest/tests_that_dont_do_leakchecks.txt
+1
-0
No files found.
CHANGES.rst
View file @
2d37899f
...
...
@@ -77,6 +77,9 @@
- Update c-ares to 1.14.0. See :issue:`1105`.
- Be more careful about issuing a warning about patching SSL on
Python 2. See :issue:`1108`.
1.3a1 (2018-01-27)
==================
...
...
src/gevent/monkey.py
View file @
2d37899f
...
...
@@ -90,6 +90,14 @@ else:
WIN
=
sys
.
platform
.
startswith
(
"win"
)
class
MonkeyPatchWarning
(
RuntimeWarning
):
"""
The type of warnings we issue.
.. versionadded:: 1.3a2
"""
# maps module name -> {attribute name: original item}
# e.g. "time" -> {"sleep": built-in function sleep}
saved
=
{}
...
...
@@ -195,7 +203,7 @@ def _queue_warning(message, _warnings):
def
_process_warnings
(
_warnings
):
import
warnings
for
warning
in
_warnings
:
warnings
.
warn
(
warning
,
Runtime
Warning
,
stacklevel
=
3
)
warnings
.
warn
(
warning
,
MonkeyPatch
Warning
,
stacklevel
=
3
)
def
_patch_sys_std
(
name
):
...
...
@@ -295,6 +303,8 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
existing_locks
=
True
,
_warnings
=
None
):
"""
patch_thread(threading=True, _threading_local=True, Event=False, logging=True, existing_lockes=True) -> None
Replace the standard :mod:`thread` module to make it greenlet-based.
- If *threading* is true (the default), also patch ``threading``.
...
...
@@ -474,17 +484,25 @@ def patch_dns():
patch_module
(
'socket'
,
items
=
socket
.
__dns__
)
# pylint:disable=no-member
def
patch_ssl
(
_warnings
=
None
):
"""Replace SSLSocket object and socket wrapping functions in :mod:`ssl` with cooperative versions.
def
patch_ssl
(
_warnings
=
None
,
_first_time
=
True
):
"""
patch_ssl() -> None
Replace SSLSocket object and socket wrapping functions in
:mod:`ssl` with cooperative versions.
This is only useful if :func:`patch_socket` has been called.
"""
if
'ssl'
in
sys
.
modules
and
hasattr
(
sys
.
modules
[
'ssl'
],
'SSLContext'
):
_queue_warning
(
'Monkey-patching ssl after ssl has already been imported '
'may lead to errors, including RecursionError on Python 3.6. '
'Please monkey-patch earlier. '
'See https://github.com/gevent/gevent/issues/1016'
,
_warnings
)
if
_first_time
and
'ssl'
in
sys
.
modules
and
hasattr
(
sys
.
modules
[
'ssl'
],
'SSLContext'
):
if
sys
.
version_info
[
0
]
>
2
or
(
'pkg_resources'
not
in
sys
.
modules
):
# Don't warn on Python 2 if pkg_resources has been imported
# because that imports ssl and it's commonly used for namespace packages,
# which typically means we're still in some early part of the import cycle
_queue_warning
(
'Monkey-patching ssl after ssl has already been imported '
'may lead to errors, including RecursionError on Python 3.6. '
'Please monkey-patch earlier. '
'See https://github.com/gevent/gevent/issues/1016'
,
_warnings
)
patch_module
(
'ssl'
,
_warnings
=
_warnings
)
...
...
@@ -570,7 +588,7 @@ def patch_subprocess():
def
patch_builtins
():
"""
Make the builtin
__import__
function `greenlet safe`_ under Python 2.
Make the builtin
:func:`__import__`
function `greenlet safe`_ under Python 2.
.. note::
This does nothing under Python 3 as it is not necessary. Python 3 features
...
...
@@ -585,12 +603,12 @@ def patch_builtins():
def
patch_signal
():
"""
Make the
signal.signal function work with a monkey-patched os
.
Make the
:func:`signal.signal` function work with a :func:`monkey-patched os <patch_os>`
.
.. caution:: This method must be used with :func:`patch_os` to have proper
SIGCHLD
.. caution:: This method must be used with :func:`patch_os` to have proper
``SIGCHLD``
handling. :func:`patch_all` calls both by default.
.. caution:: For proper
SIGCHLD
handling, you must yield to the event loop.
.. caution:: For proper
``SIGCHLD``
handling, you must yield to the event loop.
Using :func:`patch_all` is the easiest way to ensure this.
.. seealso:: :mod:`gevent.signal`
...
...
@@ -652,7 +670,7 @@ def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=Tru
if
select
:
patch_select
(
aggressive
=
aggressive
)
if
ssl
:
patch_ssl
(
_warnings
=
_warnings
)
patch_ssl
(
_warnings
=
_warnings
,
_first_time
=
first_time
)
if
httplib
:
raise
ValueError
(
'gevent.httplib is no longer provided, httplib must be False'
)
if
subprocess
:
...
...
src/greentest/test__monkey.py
View file @
2d37899f
from
gevent
import
monkey
monkey
.
patch_all
()
import
sys
import
unittest
class
TestMonkey
(
unittest
.
TestCase
):
maxDiff
=
None
def
test_time
(
self
):
import
time
from
gevent
import
time
as
gtime
self
.
assertIs
(
time
.
sleep
,
gtime
.
sleep
)
def
test_thread
(
self
):
try
:
import
thread
except
ImportError
:
import
_thread
as
thread
import
threading
from
gevent
import
thread
as
gthread
self
.
assertIs
(
thread
.
start_new_thread
,
gthread
.
start_new_thread
)
self
.
assertIs
(
threading
.
_start_new_thread
,
gthread
.
start_new_thread
)
if
sys
.
version_info
[
0
]
==
2
:
from
gevent
import
threading
as
gthreading
self
.
assertIs
(
threading
.
_sleep
,
gthreading
.
_sleep
)
self
.
assertFalse
(
monkey
.
is_object_patched
(
'threading'
,
'Event'
))
monkey
.
patch_thread
(
Event
=
True
)
self
.
assertTrue
(
monkey
.
is_object_patched
(
'threading'
,
'Event'
))
def
test_socket
(
self
):
import
socket
from
gevent
import
socket
as
gevent_socket
self
.
assertIs
(
socket
.
create_connection
,
gevent_socket
.
create_connection
)
def
test_os
(
self
):
import
os
import
types
from
gevent
import
os
as
gos
for
name
in
(
'fork'
,
'forkpty'
):
if
hasattr
(
os
,
name
):
attr
=
getattr
(
os
,
name
)
assert
'built-in'
not
in
repr
(
attr
),
repr
(
attr
)
assert
not
isinstance
(
attr
,
types
.
BuiltinFunctionType
),
repr
(
attr
)
assert
isinstance
(
attr
,
types
.
FunctionType
),
repr
(
attr
)
self
.
assertIs
(
attr
,
getattr
(
gos
,
name
))
def
test_saved
(
self
):
self
.
assertTrue
(
monkey
.
saved
)
for
modname
in
monkey
.
saved
:
self
.
assertTrue
(
monkey
.
is_module_patched
(
modname
))
for
objname
in
monkey
.
saved
[
modname
]:
self
.
assertTrue
(
monkey
.
is_object_patched
(
modname
,
objname
))
def
test_patch_twice
(
self
):
import
warnings
orig_saved
=
{}
for
k
,
v
in
monkey
.
saved
.
items
():
orig_saved
[
k
]
=
v
.
copy
()
with
warnings
.
catch_warnings
(
record
=
True
)
as
issued_warnings
:
# Patch again, triggering three warnings, one for os=False/signal=True,
# one for repeated monkey-patching, one for patching after ssl (on python >= 2.7.9)
monkey
.
patch_all
(
os
=
False
)
self
.
assertGreaterEqual
(
len
(
issued_warnings
),
2
)
self
.
assertIn
(
'SIGCHLD'
,
str
(
issued_warnings
[
-
1
].
message
))
self
.
assertIn
(
'more than once'
,
str
(
issued_warnings
[
0
].
message
))
# Patching with the exact same argument doesn't issue a second warning.
# in fact, it doesn't do anything
del
issued_warnings
[:]
monkey
.
patch_all
(
os
=
False
)
orig_saved
[
'_gevent_saved_patch_all'
]
=
monkey
.
saved
[
'_gevent_saved_patch_all'
]
self
.
assertFalse
(
issued_warnings
)
# Make sure that re-patching did not change the monkey.saved
# attribute, overwriting the original functions.
if
'logging'
in
monkey
.
saved
and
'logging'
not
in
orig_saved
:
# some part of the warning or unittest machinery imports logging
orig_saved
[
'logging'
]
=
monkey
.
saved
[
'logging'
]
self
.
assertEqual
(
orig_saved
,
monkey
.
saved
)
# Make sure some problematic attributes stayed correct.
# NOTE: This was only a problem if threading was not previously imported.
for
k
,
v
in
monkey
.
saved
[
'threading'
].
items
():
self
.
assertNotIn
(
'gevent'
,
str
(
v
))
import
time
assert
'built-in'
not
in
repr
(
time
.
sleep
),
repr
(
time
.
sleep
)
try
:
import
thread
except
ImportError
:
import
_thread
as
thread
import
threading
assert
'built-in'
not
in
repr
(
thread
.
start_new_thread
),
repr
(
thread
.
start_new_thread
)
assert
'built-in'
not
in
repr
(
threading
.
_start_new_thread
),
repr
(
threading
.
_start_new_thread
)
if
sys
.
version_info
[
0
]
==
2
:
assert
'built-in'
not
in
repr
(
threading
.
_sleep
),
repr
(
threading
.
_sleep
)
import
socket
from
gevent
import
socket
as
gevent_socket
assert
socket
.
create_connection
is
gevent_socket
.
create_connection
import
os
import
types
for
name
in
(
'fork'
,
'forkpty'
):
if
hasattr
(
os
,
name
):
attr
=
getattr
(
os
,
name
)
assert
'built-in'
not
in
repr
(
attr
),
repr
(
attr
)
assert
not
isinstance
(
attr
,
types
.
BuiltinFunctionType
),
repr
(
attr
)
assert
isinstance
(
attr
,
types
.
FunctionType
),
repr
(
attr
)
assert
monkey
.
saved
assert
not
monkey
.
is_object_patched
(
'threading'
,
'Event'
)
monkey
.
patch_thread
(
Event
=
True
)
assert
monkey
.
is_object_patched
(
'threading'
,
'Event'
)
for
modname
in
monkey
.
saved
:
assert
monkey
.
is_module_patched
(
modname
)
for
objname
in
monkey
.
saved
[
modname
]:
assert
monkey
.
is_object_patched
(
modname
,
objname
)
orig_saved
=
{}
for
k
,
v
in
monkey
.
saved
.
items
():
orig_saved
[
k
]
=
v
.
copy
()
import
warnings
with
warnings
.
catch_warnings
(
record
=
True
)
as
issued_warnings
:
# Patch again, triggering three warnings, one for os=False/signal=True,
# one for repeated monkey-patching, one for patching after ssl (on python >= 2.7.9)
monkey
.
patch_all
(
os
=
False
)
assert
len
(
issued_warnings
)
>=
2
,
[
str
(
x
)
for
x
in
issued_warnings
]
assert
'SIGCHLD'
in
str
(
issued_warnings
[
-
1
].
message
),
issued_warnings
[
-
1
]
assert
'more than once'
in
str
(
issued_warnings
[
0
].
message
),
issued_warnings
[
0
]
# Patching with the exact same argument doesn't issue a second warning.
# in fact, it doesn't do anything
del
issued_warnings
[:]
monkey
.
patch_all
(
os
=
False
)
orig_saved
[
'_gevent_saved_patch_all'
]
=
monkey
.
saved
[
'_gevent_saved_patch_all'
]
assert
not
issued_warnings
,
[
str
(
x
)
for
x
in
issued_warnings
]
# Make sure that re-patching did not change the monkey.saved
# attribute, overwriting the original functions.
assert
orig_saved
==
monkey
.
saved
,
(
orig_saved
,
monkey
.
saved
)
# Make sure some problematic attributes stayed correct.
# NOTE: This was only a problem if threading was not previously imported.
for
k
,
v
in
monkey
.
saved
[
'threading'
].
items
():
assert
'gevent'
not
in
str
(
v
),
(
k
,
v
)
if
__name__
==
'__main__'
:
unittest
.
main
()
src/greentest/test__monkey_ssl_warning.py
0 → 100644
View file @
2d37899f
import
unittest
import
warnings
# This file should only have this one test in it
# because we have to be careful about our imports
# and because we need to be careful about our patching.
class
Test
(
unittest
.
TestCase
):
def
test_with_pkg_resources
(
self
):
# Issue 1108: Python 2, importing pkg_resources,
# as is done for namespace packages, imports ssl,
# leading to an unwanted SSL warning.
__import__
(
'pkg_resources'
)
from
gevent
import
monkey
self
.
assertFalse
(
monkey
.
saved
)
with
warnings
.
catch_warnings
(
record
=
True
)
as
issued_warnings
:
warnings
.
simplefilter
(
'always'
)
monkey
.
patch_all
()
monkey
.
patch_all
()
issued_warnings
=
[
x
for
x
in
issued_warnings
if
isinstance
(
x
.
message
,
monkey
.
MonkeyPatchWarning
)]
self
.
assertFalse
(
issued_warnings
,
[
str
(
i
)
for
i
in
issued_warnings
])
self
.
assertEqual
(
0
,
len
(
issued_warnings
))
if
__name__
==
'__main__'
:
unittest
.
main
()
src/greentest/tests_that_dont_do_leakchecks.txt
View file @
2d37899f
test___monkey_patching.py
test__monkey_ssl_warning.py
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