diff -r eb1edc9e3722 Doc/library/selectors.rst --- a/Doc/library/selectors.rst Fri Oct 25 17:56:00 2013 +0200 +++ b/Doc/library/selectors.rst Fri Oct 25 19:47:35 2013 +0200 @@ -157,12 +157,13 @@ This must be called to make sure that any underlying resource is freed. The selector shall not be used once it has been closed. - .. method:: get_key(fileobj) + .. method:: get_map() - Return the key associated to a registered file object. + Return a mapping of file objects to selector keys. - This returns the :class:`SelectorKey` instance associated to this file - object, or raises :exc:`KeyError` if the file object is not registered. + This returns a :class:`~collections.abc.Mapping` instance mapping + registered file objects to their associated :class:`SelectorKey` + instance. .. class:: DefaultSelector() diff -r eb1edc9e3722 Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py Fri Oct 25 17:56:00 2013 +0200 +++ b/Lib/asyncio/selector_events.py Fri Oct 25 19:47:35 2013 +0200 @@ -122,7 +122,7 @@ """Add a reader callback.""" handle = events.make_handle(callback, args) try: - key = self._selector.get_key(fd) + key = self._selector.get_map()[fd] except KeyError: self._selector.register(fd, selectors.EVENT_READ, (handle, None)) @@ -136,7 +136,7 @@ def remove_reader(self, fd): """Remove a reader callback.""" try: - key = self._selector.get_key(fd) + key = self._selector.get_map()[fd] except KeyError: return False else: @@ -157,7 +157,7 @@ """Add a writer callback..""" handle = events.make_handle(callback, args) try: - key = self._selector.get_key(fd) + key = self._selector.get_map()[fd] except KeyError: self._selector.register(fd, selectors.EVENT_WRITE, (None, handle)) @@ -171,7 +171,7 @@ def remove_writer(self, fd): """Remove a writer callback.""" try: - key = self._selector.get_key(fd) + key = self._selector.get_map()[fd] except KeyError: return False else: diff -r eb1edc9e3722 Lib/selectors.py --- a/Lib/selectors.py Fri Oct 25 17:56:00 2013 +0200 +++ b/Lib/selectors.py Fri Oct 25 19:47:35 2013 +0200 @@ -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._fd_to_key = selector._fd_to_key + + def __len__(self): + return len(self._fd_to_key) + + def __getitem__(self, fileobj): + try: + return self._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._fd_to_key) + + class BaseSelector(metaclass=ABCMeta): """Base selector class. @@ -151,16 +170,9 @@ """ self._fd_to_key.clear() - def get_key(self, fileobj): - """Return the key associated to a registered file object. - - Returns: - SelectorKey for this file object - """ - try: - return self._fd_to_key[_fileobj_to_fd(fileobj)] - 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 _SelectorMapping(self) def __enter__(self): return self diff -r eb1edc9e3722 Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py Fri Oct 25 17:56:00 2013 +0200 +++ b/Lib/test/test_asyncio/test_selector_events.py Fri Oct 25 19:47:35 2013 +0200 @@ -396,7 +396,7 @@ self.assertIs(err, f.exception()) def test_add_reader(self): - self.loop._selector.get_key.side_effect = KeyError + self.loop._selector.get_map.return_value = {} cb = lambda: True self.loop.add_reader(1, cb) @@ -410,8 +410,8 @@ def test_add_reader_existing(self): reader = unittest.mock.Mock() writer = unittest.mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (reader, writer)) + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( + 1, 1, selectors.EVENT_WRITE, (reader, writer))} cb = lambda: True self.loop.add_reader(1, cb) @@ -426,8 +426,8 @@ def test_add_reader_existing_writer(self): writer = unittest.mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (None, writer)) + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( + 1, 1, selectors.EVENT_WRITE, (None, writer))} cb = lambda: True self.loop.add_reader(1, cb) @@ -440,8 +440,8 @@ self.assertEqual(writer, w) def test_remove_reader(self): - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (None, None)) + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( + 1, 1, selectors.EVENT_READ, (None, None))} self.assertFalse(self.loop.remove_reader(1)) self.assertTrue(self.loop._selector.unregister.called) @@ -449,9 +449,9 @@ def test_remove_reader_read_write(self): reader = unittest.mock.Mock() writer = unittest.mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, - (reader, writer)) + (reader, writer))} self.assertTrue( self.loop.remove_reader(1)) @@ -461,12 +461,12 @@ self.loop._selector.modify.call_args[0]) def test_remove_reader_unknown(self): - self.loop._selector.get_key.side_effect = KeyError + self.loop._selector.get_map.return_value = {} self.assertFalse( self.loop.remove_reader(1)) def test_add_writer(self): - self.loop._selector.get_key.side_effect = KeyError + self.loop._selector.get_map.return_value = {} cb = lambda: True self.loop.add_writer(1, cb) @@ -480,8 +480,8 @@ def test_add_writer_existing(self): reader = unittest.mock.Mock() writer = unittest.mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_READ, (reader, writer)) + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( + 1, 1, selectors.EVENT_READ, (reader, writer))} cb = lambda: True self.loop.add_writer(1, cb) @@ -495,8 +495,8 @@ self.assertEqual(cb, w._callback) def test_remove_writer(self): - self.loop._selector.get_key.return_value = selectors.SelectorKey( - 1, 1, selectors.EVENT_WRITE, (None, None)) + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( + 1, 1, selectors.EVENT_WRITE, (None, None))} self.assertFalse(self.loop.remove_writer(1)) self.assertTrue(self.loop._selector.unregister.called) @@ -504,9 +504,9 @@ def test_remove_writer_read_write(self): reader = unittest.mock.Mock() writer = unittest.mock.Mock() - self.loop._selector.get_key.return_value = selectors.SelectorKey( + self.loop._selector.get_map.return_value = {1: selectors.SelectorKey( 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, - (reader, writer)) + (reader, writer))} self.assertTrue( self.loop.remove_writer(1)) @@ -516,7 +516,7 @@ self.loop._selector.modify.call_args[0]) def test_remove_writer_unknown(self): - self.loop._selector.get_key.side_effect = KeyError + self.loop._selector.get_map.return_value = {} self.assertFalse( self.loop.remove_writer(1)) diff -r eb1edc9e3722 Lib/test/test_asyncio/test_selectors.py --- a/Lib/test/test_asyncio/test_selectors.py Fri Oct 25 17:56:00 2013 +0200 +++ b/Lib/test/test_asyncio/test_selectors.py Fri Oct 25 19:47:35 2013 +0200 @@ -85,7 +85,7 @@ self.assertNotEqual(key.events, key2.events) self.assertEqual( selectors.SelectorKey(fobj, 10, selectors.EVENT_WRITE, None), - s.get_key(fobj)) + s.get_map()[fobj]) def test_modify_data(self): fobj = unittest.mock.Mock() @@ -101,7 +101,7 @@ self.assertNotEqual(key.data, key2.data) self.assertEqual( selectors.SelectorKey(fobj, 10, selectors.EVENT_READ, d2), - s.get_key(fobj)) + s.get_map()[fobj]) def test_modify_same(self): fobj = unittest.mock.Mock() diff -r eb1edc9e3722 Lib/test/test_selectors.py --- a/Lib/test/test_selectors.py Fri Oct 25 17:56:00 2013 +0200 +++ b/Lib/test/test_selectors.py Fri Oct 25 19:47:35 2013 +0200 @@ -106,7 +106,7 @@ # modify events key2 = s.modify(rd, selectors.EVENT_WRITE) self.assertNotEqual(key.events, key2.events) - self.assertEqual(key2, s.get_key(rd)) + self.assertEqual(key2, s.get_map()[rd]) s.unregister(rd) @@ -118,7 +118,7 @@ key2 = s.modify(rd, selectors.EVENT_READ, d2) self.assertEqual(key.events, key2.events) self.assertNotEqual(key.data, key2.data) - self.assertEqual(key2, s.get_key(rd)) + self.assertEqual(key2, s.get_map()[rd]) self.assertEqual(key2.data, d2) # modify unknown file obj @@ -136,10 +136,12 @@ s.register(wr, selectors.EVENT_WRITE) s.close() - self.assertRaises(KeyError, s.get_key, rd) - self.assertRaises(KeyError, s.get_key, wr) + with self.assertRaises(KeyError): + s.get_map()[rd] + with self.assertRaises(KeyError): + s.get_map()[wr] - def test_get_key(self): + def test_get_map(self): s = self.SELECTOR() self.addCleanup(s.close) @@ -147,11 +149,24 @@ 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.assertEqual(key, s.get_key(rd)) + 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 - self.assertRaises(KeyError, s.get_key, 999999) + with self.assertRaises(KeyError): + keys[999999] + + # Read-only mapping + with self.assertRaises(TypeError): + del keys[rd] def test_select(self): s = self.SELECTOR() @@ -185,8 +200,8 @@ sel.register(rd, selectors.EVENT_READ) sel.register(wr, selectors.EVENT_WRITE) - self.assertRaises(KeyError, s.get_key, rd) - self.assertRaises(KeyError, s.get_key, wr) + self.assertNotIn(rd, s.get_map()) + self.assertNotIn(wr, s.get_map()) def test_fileno(self): s = self.SELECTOR()