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
d099423c
Commit
d099423c
authored
Jan 16, 2020
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix tests on windows, where SelectSelector._select is a normal method.
parent
3d4404d2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
128 additions
and
114 deletions
+128
-114
src/gevent/select.py
src/gevent/select.py
+125
-114
src/gevent/tests/test__monkey_selectors.py
src/gevent/tests/test__monkey_selectors.py
+3
-0
No files found.
src/gevent/select.py
View file @
d099423c
...
...
@@ -28,14 +28,17 @@ else:
try
:
from
select
import
poll
as
original_poll
from
select
import
POLLIN
,
POLLOUT
,
POLLNVAL
__implements__
=
[
'select'
,
'poll'
]
except
ImportError
:
original_poll
=
None
POLLIN
=
1
POLLOUT
=
4
POLLNVAL
=
32
__implements__
=
[
'select'
]
__all__
=
[
'error'
]
+
__implements__
if
'poll'
not
in
__all__
:
__all__
.
append
(
'poll'
)
import
select
as
__select__
...
...
@@ -184,121 +187,123 @@ def select(rlist, wlist, xlist, timeout=None): # pylint:disable=unused-argument
return
result
.
select
(
rlist
,
wlist
,
timeout
)
if
original_poll
is
not
None
:
class
PollResult
(
object
):
__slots__
=
(
'events'
,
'event'
)
def
__init__
(
self
):
self
.
events
=
set
()
self
.
event
=
Event
()
class
PollResult
(
object
):
__slots__
=
(
'events'
,
'event'
)
def
add_event
(
self
,
events
,
fd
):
if
events
<
0
:
result_flags
=
POLLNVAL
else
:
result_flags
=
0
if
events
&
_EV_READ
:
result_flags
=
POLLIN
if
events
&
_EV_WRITE
:
result_flags
|=
POLLOUT
def
__init__
(
self
):
self
.
events
=
set
()
self
.
event
=
Event
()
self
.
events
.
add
((
fd
,
result_flags
))
self
.
event
.
set
()
def
add_event
(
self
,
events
,
fd
):
if
events
<
0
:
result_flags
=
POLLNVAL
else
:
result_flags
=
0
if
events
&
_EV_READ
:
result_flags
=
POLLIN
if
events
&
_EV_WRITE
:
result_flags
|=
POLLOUT
class
poll
(
object
):
self
.
events
.
add
((
fd
,
result_flags
))
self
.
event
.
set
()
class
poll
(
object
):
"""
An implementation of :class:`select.poll` that blocks only the current greenlet.
.. caution:: ``POLLPRI`` data is not supported.
.. versionadded:: 1.1b1
.. versionchanged:: 1.5
This is now always defined, regardless of whether the standard library
defines :func:`select.poll` or not. Note that it may have different performance
characteristics.
"""
def
__init__
(
self
):
# {int -> flags}
# We can't keep watcher objects in here because people commonly
# just drop the poll object when they're done, without calling
# unregister(). dnspython does this.
self
.
fds
=
{}
self
.
loop
=
get_hub
().
loop
def
register
(
self
,
fd
,
eventmask
=
_NONE
):
if
eventmask
is
_NONE
:
flags
=
_EV_READ
|
_EV_WRITE
else
:
flags
=
0
if
eventmask
&
POLLIN
:
flags
=
_EV_READ
if
eventmask
&
POLLOUT
:
flags
|=
_EV_WRITE
# If they ask for POLLPRI, we can't support
# that. Should we raise an error?
fileno
=
get_fileno
(
fd
)
self
.
fds
[
fileno
]
=
flags
def
modify
(
self
,
fd
,
eventmask
):
self
.
register
(
fd
,
eventmask
)
def
poll
(
self
,
timeout
=
None
):
"""
An implementation of :class:`select.poll` that blocks only the current greenlet
.
poll the registered fds
.
.. caution:: ``POLLPRI`` data is not supported.
.. versionchanged:: 1.2a1
File descriptors that are closed are reported with POLLNVAL.
.. versionadded:: 1.1b1
.. versionchanged:: 1.3a2
Under libuv, interpret *timeout* values less than 0 the same as *None*,
i.e., block. This was always the case with libev.
"""
def
__init__
(
self
):
# {int -> flags}
# We can't keep watcher objects in here because people commonly
# just drop the poll object when they're done, without calling
# unregister(). dnspython does this.
self
.
fds
=
{}
self
.
loop
=
get_hub
().
loop
def
register
(
self
,
fd
,
eventmask
=
_NONE
):
if
eventmask
is
_NONE
:
flags
=
_EV_READ
|
_EV_WRITE
else
:
flags
=
0
if
eventmask
&
POLLIN
:
flags
=
_EV_READ
if
eventmask
&
POLLOUT
:
flags
|=
_EV_WRITE
# If they ask for POLLPRI, we can't support
# that. Should we raise an error?
fileno
=
get_fileno
(
fd
)
self
.
fds
[
fileno
]
=
flags
def
modify
(
self
,
fd
,
eventmask
):
self
.
register
(
fd
,
eventmask
)
def
poll
(
self
,
timeout
=
None
):
"""
poll the registered fds.
.. versionchanged:: 1.2a1
File descriptors that are closed are reported with POLLNVAL.
.. versionchanged:: 1.3a2
Under libuv, interpret *timeout* values less than 0 the same as *None*,
i.e., block. This was always the case with libev.
"""
result
=
PollResult
()
watchers
=
[]
io
=
self
.
loop
.
io
MAXPRI
=
self
.
loop
.
MAXPRI
try
:
for
fd
,
flags
in
iteritems
(
self
.
fds
):
watcher
=
io
(
fd
,
flags
)
watchers
.
append
(
watcher
)
watcher
.
priority
=
MAXPRI
watcher
.
start
(
result
.
add_event
,
fd
,
pass_events
=
True
)
if
timeout
is
not
None
:
if
timeout
<
0
:
# The docs for python say that an omitted timeout,
# a negative timeout and a timeout of None are all
# supposed to block forever. Many, but not all
# OS's accept any negative number to mean that. Some
# OS's raise errors for anything negative but not -1.
# Python 3.7 changes to always pass exactly -1 in that
# case from selectors.
# Our Timeout class currently does not have a defined behaviour
# for negative values. On libuv, it uses a check watcher and effectively
# doesn't block. On libev, it seems to block. In either case, we
# *want* to block, so turn this into the sure fire block request.
timeout
=
None
elif
timeout
:
# The docs for poll.poll say timeout is in
# milliseconds. Our result objects work in
# seconds, so this should be *=, shouldn't it?
timeout
/=
1000.0
result
.
event
.
wait
(
timeout
=
timeout
)
return
list
(
result
.
events
)
finally
:
for
awatcher
in
watchers
:
awatcher
.
stop
()
awatcher
.
close
()
def
unregister
(
self
,
fd
):
"""
Unregister the *fd*.
.. versionchanged:: 1.2a1
Raise a `KeyError` if *fd* was not registered, like the standard
library. Previously gevent did nothing.
"""
fileno
=
get_fileno
(
fd
)
del
self
.
fds
[
fileno
]
del
original_poll
result
=
PollResult
()
watchers
=
[]
io
=
self
.
loop
.
io
MAXPRI
=
self
.
loop
.
MAXPRI
try
:
for
fd
,
flags
in
iteritems
(
self
.
fds
):
watcher
=
io
(
fd
,
flags
)
watchers
.
append
(
watcher
)
watcher
.
priority
=
MAXPRI
watcher
.
start
(
result
.
add_event
,
fd
,
pass_events
=
True
)
if
timeout
is
not
None
:
if
timeout
<
0
:
# The docs for python say that an omitted timeout,
# a negative timeout and a timeout of None are all
# supposed to block forever. Many, but not all
# OS's accept any negative number to mean that. Some
# OS's raise errors for anything negative but not -1.
# Python 3.7 changes to always pass exactly -1 in that
# case from selectors.
# Our Timeout class currently does not have a defined behaviour
# for negative values. On libuv, it uses a check watcher and effectively
# doesn't block. On libev, it seems to block. In either case, we
# *want* to block, so turn this into the sure fire block request.
timeout
=
None
elif
timeout
:
# The docs for poll.poll say timeout is in
# milliseconds. Our result objects work in
# seconds, so this should be *=, shouldn't it?
timeout
/=
1000.0
result
.
event
.
wait
(
timeout
=
timeout
)
return
list
(
result
.
events
)
finally
:
for
awatcher
in
watchers
:
awatcher
.
stop
()
awatcher
.
close
()
def
unregister
(
self
,
fd
):
"""
Unregister the *fd*.
.. versionchanged:: 1.2a1
Raise a `KeyError` if *fd* was not registered, like the standard
library. Previously gevent did nothing.
"""
fileno
=
get_fileno
(
fd
)
del
self
.
fds
[
fileno
]
def
_gevent_do_monkey_patch
(
patch_request
):
...
...
@@ -323,13 +328,19 @@ def _gevent_do_monkey_patch(patch_request):
# package? If so, must be careful to deal with DoNotPatch exceptions.
# Python 3 wants to use `select.select` as a member function,
# leading to this error in selectors.py (because gevent.select.select is
# not a builtin and doesn't get the magic auto-static that they do)
# leading to this error in selectors.py (because
# gevent.select.select is not a builtin and doesn't get the
# magic auto-static that they do):
#
# r, w, _ = self._select(self._readers, self._writers, [], timeout)
# TypeError: select() takes from 3 to 4 positional arguments but 5 were given
# Note that this obviously only happens if selectors was imported after we had patched
# select; but there is a code path that leads to it being imported first (but now we've
# patched select---so we can't compare them identically)
#
# Note that this obviously only happens if selectors was
# imported after we had patched select; but there is a code
# path that leads to it being imported first (but now we've
# patched select---so we can't compare them identically). It also doesn't
# happen on Windows, because they define a normal method for _select, to work around
# some weirdness in the handling of the third argument.
orig_select_select
=
patch_request
.
get_original
(
'select'
,
'select'
)
assert
target_mod
.
select
is
not
orig_select_select
...
...
src/gevent/tests/test__monkey_selectors.py
View file @
d099423c
...
...
@@ -21,6 +21,9 @@ patch_all()
)
class
TestSelectors
(
greentest
.
TestCase
):
@
greentest
.
skipOnWindows
(
"SelectSelector._select is a normal function on Windows"
)
def
test_selectors_select_is_patched
(
self
):
# https://github.com/gevent/gevent/issues/835
_select
=
selectors
.
SelectSelector
.
_select
...
...
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