Issue #19172: Add a get_map() method to selectors.

This commit is contained in:
Charles-François Natali 2013-10-30 20:31:04 +01:00
parent 7613542a27
commit 4574b49703
3 changed files with 61 additions and 1 deletions

View file

@ -164,6 +164,14 @@ below:
This returns the :class:`SelectorKey` instance associated to this file This returns the :class:`SelectorKey` instance associated to this file
object, or raises :exc:`KeyError` if the file object is not registered. object, or raises :exc:`KeyError` if the file object is not registered.
.. method:: get_map()
Return a mapping of file objects to selector keys.
This returns a :class:`~collections.abc.Mapping` instance mapping
registered file objects to their associated :class:`SelectorKey`
instance.
.. class:: DefaultSelector() .. class:: DefaultSelector()

View file

@ -6,7 +6,7 @@ This module allows high-level and efficient I/O multiplexing, built upon the
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from collections import namedtuple from collections import namedtuple, Mapping
import functools import functools
import select import select
import sys import sys
@ -44,6 +44,25 @@ SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
selected event mask and attached data.""" selected event mask and attached data."""
class _SelectorMapping(Mapping):
"""Mapping of file objects to selector keys."""
def __init__(self, selector):
self._selector = selector
def __len__(self):
return len(self._selector._fd_to_key)
def __getitem__(self, fileobj):
try:
return self._selector._fd_to_key[_fileobj_to_fd(fileobj)]
except KeyError:
raise KeyError("{!r} is not registered".format(fileobj)) from None
def __iter__(self):
return iter(self._selector._fd_to_key)
class BaseSelector(metaclass=ABCMeta): class BaseSelector(metaclass=ABCMeta):
"""Base selector class. """Base selector class.
@ -62,6 +81,8 @@ class BaseSelector(metaclass=ABCMeta):
def __init__(self): def __init__(self):
# this maps file descriptors to keys # this maps file descriptors to keys
self._fd_to_key = {} self._fd_to_key = {}
# read-only mapping returned by get_map()
self._map = _SelectorMapping(self)
def register(self, fileobj, events, data=None): def register(self, fileobj, events, data=None):
"""Register a file object. """Register a file object.
@ -162,6 +183,10 @@ class BaseSelector(metaclass=ABCMeta):
except KeyError: except KeyError:
raise KeyError("{!r} is not registered".format(fileobj)) from None raise KeyError("{!r} is not registered".format(fileobj)) from None
def get_map(self):
"""Return a mapping of file objects to selector keys."""
return self._map
def __enter__(self): def __enter__(self):
return self return self

View file

@ -153,6 +153,33 @@ class BaseSelectorTestCase(unittest.TestCase):
# unknown file obj # unknown file obj
self.assertRaises(KeyError, s.get_key, 999999) self.assertRaises(KeyError, s.get_key, 999999)
def test_get_map(self):
s = self.SELECTOR()
self.addCleanup(s.close)
rd, wr = socketpair()
self.addCleanup(rd.close)
self.addCleanup(wr.close)
keys = s.get_map()
self.assertFalse(keys)
self.assertEqual(len(keys), 0)
self.assertEqual(list(keys), [])
key = s.register(rd, selectors.EVENT_READ, "data")
self.assertIn(rd, keys)
self.assertEqual(key, keys[rd])
self.assertEqual(len(keys), 1)
self.assertEqual(list(keys), [rd.fileno()])
self.assertEqual(list(keys.values()), [key])
# unknown file obj
with self.assertRaises(KeyError):
keys[999999]
# Read-only mapping
with self.assertRaises(TypeError):
del keys[rd]
def test_select(self): def test_select(self):
s = self.SELECTOR() s = self.SELECTOR()
self.addCleanup(s.close) self.addCleanup(s.close)