forked from Rust-related/RustPython
Update selectors from CPython v3.12.3
This commit is contained in:
committed by
Jeong YunWon
parent
75a985e63e
commit
94e6648ee5
18
Lib/selectors.py
vendored
18
Lib/selectors.py
vendored
@@ -50,12 +50,11 @@ SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
|
||||
Object used to associate a file object to its backing
|
||||
file descriptor, selected event mask, and attached data.
|
||||
"""
|
||||
if sys.version_info >= (3, 5):
|
||||
SelectorKey.fileobj.__doc__ = 'File object registered.'
|
||||
SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
|
||||
SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
|
||||
SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
|
||||
For example, this could be used to store a per-client session ID.''')
|
||||
SelectorKey.fileobj.__doc__ = 'File object registered.'
|
||||
SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
|
||||
SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
|
||||
SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
|
||||
For example, this could be used to store a per-client session ID.''')
|
||||
|
||||
|
||||
class _SelectorMapping(Mapping):
|
||||
@@ -510,6 +509,7 @@ if hasattr(select, 'kqueue'):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._selector = select.kqueue()
|
||||
self._max_events = 0
|
||||
|
||||
def fileno(self):
|
||||
return self._selector.fileno()
|
||||
@@ -521,10 +521,12 @@ if hasattr(select, 'kqueue'):
|
||||
kev = select.kevent(key.fd, select.KQ_FILTER_READ,
|
||||
select.KQ_EV_ADD)
|
||||
self._selector.control([kev], 0, 0)
|
||||
self._max_events += 1
|
||||
if events & EVENT_WRITE:
|
||||
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
|
||||
select.KQ_EV_ADD)
|
||||
self._selector.control([kev], 0, 0)
|
||||
self._max_events += 1
|
||||
except:
|
||||
super().unregister(fileobj)
|
||||
raise
|
||||
@@ -535,6 +537,7 @@ if hasattr(select, 'kqueue'):
|
||||
if key.events & EVENT_READ:
|
||||
kev = select.kevent(key.fd, select.KQ_FILTER_READ,
|
||||
select.KQ_EV_DELETE)
|
||||
self._max_events -= 1
|
||||
try:
|
||||
self._selector.control([kev], 0, 0)
|
||||
except OSError:
|
||||
@@ -544,6 +547,7 @@ if hasattr(select, 'kqueue'):
|
||||
if key.events & EVENT_WRITE:
|
||||
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
|
||||
select.KQ_EV_DELETE)
|
||||
self._max_events -= 1
|
||||
try:
|
||||
self._selector.control([kev], 0, 0)
|
||||
except OSError:
|
||||
@@ -556,7 +560,7 @@ if hasattr(select, 'kqueue'):
|
||||
# If max_ev is 0, kqueue will ignore the timeout. For consistent
|
||||
# behavior with the other selector classes, we prevent that here
|
||||
# (using max). See https://bugs.python.org/issue29255
|
||||
max_ev = max(len(self._fd_to_key), 1)
|
||||
max_ev = self._max_events or 1
|
||||
ready = []
|
||||
try:
|
||||
kev_list = self._selector.control(None, max_ev, timeout)
|
||||
|
||||
34
Lib/test/test_selectors.py
vendored
34
Lib/test/test_selectors.py
vendored
@@ -19,6 +19,10 @@ except ImportError:
|
||||
resource = None
|
||||
|
||||
|
||||
if support.is_emscripten or support.is_wasi:
|
||||
raise unittest.SkipTest("Cannot create socketpair on Emscripten/WASI.")
|
||||
|
||||
|
||||
if hasattr(socket, 'socketpair'):
|
||||
socketpair = socket.socketpair
|
||||
else:
|
||||
@@ -276,6 +280,35 @@ class BaseSelectorTestCase:
|
||||
|
||||
self.assertEqual([(wr_key, selectors.EVENT_WRITE)], result)
|
||||
|
||||
def test_select_read_write(self):
|
||||
# gh-110038: when a file descriptor is registered for both read and
|
||||
# write, the two events must be seen on a single call to select().
|
||||
s = self.SELECTOR()
|
||||
self.addCleanup(s.close)
|
||||
|
||||
sock1, sock2 = self.make_socketpair()
|
||||
sock2.send(b"foo")
|
||||
my_key = s.register(sock1, selectors.EVENT_READ | selectors.EVENT_WRITE)
|
||||
|
||||
seen_read, seen_write = False, False
|
||||
result = s.select()
|
||||
# We get the read and write either in the same result entry or in two
|
||||
# distinct entries with the same key.
|
||||
self.assertLessEqual(len(result), 2)
|
||||
for key, events in result:
|
||||
self.assertTrue(isinstance(key, selectors.SelectorKey))
|
||||
self.assertEqual(key, my_key)
|
||||
self.assertFalse(events & ~(selectors.EVENT_READ |
|
||||
selectors.EVENT_WRITE))
|
||||
if events & selectors.EVENT_READ:
|
||||
self.assertFalse(seen_read)
|
||||
seen_read = True
|
||||
if events & selectors.EVENT_WRITE:
|
||||
self.assertFalse(seen_write)
|
||||
seen_write = True
|
||||
self.assertTrue(seen_read)
|
||||
self.assertTrue(seen_write)
|
||||
|
||||
def test_context_manager(self):
|
||||
s = self.SELECTOR()
|
||||
self.addCleanup(s.close)
|
||||
@@ -446,6 +479,7 @@ class ScalableSelectorMixIn:
|
||||
# see issue #18963 for why it's skipped on older OS X versions
|
||||
@support.requires_mac_ver(10, 5)
|
||||
@unittest.skipUnless(resource, "Test needs resource module")
|
||||
@support.requires_resource('cpu')
|
||||
def test_above_fd_setsize(self):
|
||||
# A scalable implementation should have no problem with more than
|
||||
# FD_SETSIZE file descriptors. Since we don't know the value, we just
|
||||
|
||||
Reference in New Issue
Block a user