diff -r 52ec6a3eeda5 Doc/library/selectors.rst --- a/Doc/library/selectors.rst Wed Oct 30 18:27:13 2013 +0100 +++ b/Doc/library/selectors.rst Wed Oct 30 19:36:39 2013 +0100 @@ -164,6 +164,14 @@ This returns the :class:`SelectorKey` instance associated to this file 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() diff -r 52ec6a3eeda5 Lib/selectors.py --- a/Lib/selectors.py Wed Oct 30 18:27:13 2013 +0100 +++ b/Lib/selectors.py Wed Oct 30 19:36:39 2013 +0100 @@ -6,7 +6,7 @@ from abc import ABCMeta, abstractmethod -from collections import namedtuple +from collections import namedtuple, Mapping import functools import select import sys @@ -44,6 +44,25 @@ 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): """Base selector class. @@ -62,6 +81,8 @@ def __init__(self): # this maps file descriptors to keys self._fd_to_key = {} + # read-only mapping returned by get_map() + self._map = _SelectorMapping(self) def register(self, fileobj, events, data=None): """Register a file object. @@ -162,6 +183,10 @@ except KeyError: 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): return self diff -r 52ec6a3eeda5 Lib/test/test_selectors.py --- a/Lib/test/test_selectors.py Wed Oct 30 18:27:13 2013 +0100 +++ b/Lib/test/test_selectors.py Wed Oct 30 19:36:39 2013 +0100 @@ -153,6 +153,33 @@ # unknown file obj 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): s = self.SELECTOR() self.addCleanup(s.close)