diff -r 268259370a01 Lib/selectors.py --- a/Lib/selectors.py Mon Nov 04 13:18:19 2013 -0800 +++ b/Lib/selectors.py Mon Nov 04 23:26:26 2013 +0100 @@ -138,11 +138,14 @@ key = self._fd_to_key[_fileobj_to_fd(fileobj)] except KeyError: raise KeyError("{!r} is not registered".format(fileobj)) from None - if events != key.events or data != key.data: - # TODO: If only the data changed, use a shortcut that only - # updates the data. + if events != key.events: self.unregister(fileobj) return self.register(fileobj, events, data) + elif data != key.data: + # Use a shortcut to update the data. + key = key._replace(data=data) + self._fd_to_key[key.fd] = key + return key else: return key diff -r 268259370a01 Lib/test/test_selectors.py --- a/Lib/test/test_selectors.py Mon Nov 04 13:18:19 2013 -0800 +++ b/Lib/test/test_selectors.py Mon Nov 04 23:26:26 2013 +0100 @@ -6,6 +6,8 @@ from test import support from time import sleep import unittest +from unittest.mock import Mock + try: from time import monotonic as time except ImportError: @@ -46,6 +48,70 @@ return match +class FakeSelector(selectors.BaseSelector): + """Trivial non-abstract subclass of BaseSelector.""" + + def select(self, timeout=None): + raise NotImplementedError + + +class _SelectorMappingTests(unittest.TestCase): + + def test_len(self): + s = self.SELECTOR() + self.addCleanup(s.close) + + map = selectors._SelectorMapping(s) + self.assertTrue(map.__len__() == 0) + + f = Mock() + f.fileno.return_value = 10 + s.register(f, selectors.EVENT_READ, None) + self.assertTrue(len(map) == 1) + + def test_getitem(self): + s = self.SELECTOR() + self.addCleanup(s.close) + + map = selectors._SelectorMapping(s) + f = Mock() + f.fileno.return_value = 10 + s.register(f, selectors.EVENT_READ, None) + attended = selectors.SelectorKey(f, 10, selectors.EVENT_READ, None) + self.assertEqual(attended, map.__getitem__(f)) + + def test_getitem_key_error(self): + s = self.SELECTOR() + self.addCleanup(s.close) + + map = selectors._SelectorMapping(s) + self.assertTrue(len(map) == 0) + f = Mock() + f.fileno.return_value = 10 + s.register(f, selectors.EVENT_READ, None) + self.assertRaises(KeyError, map.__getitem__, 5) + + def test_iter(self): + s = self.SELECTOR() + self.addCleanup(s.close) + + map = selectors._SelectorMapping(s) + self.assertTrue(len(map) == 0) + f = Mock() + f.fileno.return_value = 5 + s.register(f, selectors.EVENT_READ, None) + + counter = 0 + for fileno in map.__iter__(): + self.assertEqual(5, fileno) + counter += 1 + self.assertEqual(1, counter) + + for idx in map: + self.assertEqual(f, map[idx].fileobj) + + + class BaseSelectorTestCase(unittest.TestCase): def test_register(self): @@ -113,6 +179,7 @@ # modify data d1 = object() d2 = object() + d3 = object() key = s.register(rd, selectors.EVENT_READ, d1) key2 = s.modify(rd, selectors.EVENT_READ, d2) @@ -121,6 +188,15 @@ self.assertEqual(key2, s.get_key(rd)) self.assertEqual(key2.data, d2) + # modify data uses shortcut + + s.unregister = Mock() + s.register = Mock() + s.modify(rd, selectors.EVENT_READ, d3) + self.assertFalse(s.unregister.called) + self.assertFalse(s.register.called) + + # modify unknown file obj self.assertRaises(KeyError, s.modify, 999999, selectors.EVENT_READ)