_rlcompleter: use blockingCallFromThread for all Helper APIs
We were missing two (the calls to choose_nameplate() and choose_words() that happen after the input() function has finished, but while we're still inside the thread that makes it safe for input() to block). This almost certainly caused the crash seen in issue #280. Update the tests to match: CodeInputter.finish must now be called with deferToThread from inside tests, or the internal blockingCallFromThread must be stubbed out.
This commit is contained in:
parent
3847339f43
commit
af406a600e
|
@ -134,11 +134,13 @@ class CodeInputter(object):
|
|||
raise AlreadyInputNameplateError("nameplate (%s-) already entered, cannot go back" % self._committed_nameplate)
|
||||
else:
|
||||
debug(" choose_nameplate(%s)" % nameplate)
|
||||
self._input_helper.choose_nameplate(nameplate)
|
||||
self.bcft(self._input_helper.choose_nameplate, nameplate)
|
||||
debug(" choose_words(%s)" % words)
|
||||
self._input_helper.choose_words(words)
|
||||
self.bcft(self._input_helper.choose_words, words)
|
||||
|
||||
def _input_code_with_completion(prompt, input_helper, reactor):
|
||||
# reminder: this all occurs in a separate thread. All calls to input_helper
|
||||
# must go through blockingCallFromThread()
|
||||
c = CodeInputter(input_helper, reactor)
|
||||
if readline is not None:
|
||||
if readline.__doc__ and "libedit" in readline.__doc__:
|
||||
|
|
|
@ -147,11 +147,15 @@ def get_completions(c, prefix):
|
|||
return completions
|
||||
completions.append(text)
|
||||
|
||||
def fake_blockingCallFromThread(f, *a, **kw):
|
||||
return f(*a, **kw)
|
||||
|
||||
class Completion(unittest.TestCase):
|
||||
def test_simple(self):
|
||||
# no actual completion
|
||||
helper = mock.Mock()
|
||||
c = CodeInputter(helper, "reactor")
|
||||
c.bcft = fake_blockingCallFromThread
|
||||
c.finish("1-code-ghost")
|
||||
self.assertFalse(c.used_completion)
|
||||
self.assertEqual(helper.mock_calls,
|
||||
|
@ -164,6 +168,7 @@ class Completion(unittest.TestCase):
|
|||
# check that it calls _commit_and_build_completions correctly
|
||||
helper = mock.Mock()
|
||||
c = CodeInputter(helper, "reactor")
|
||||
c.bcft = fake_blockingCallFromThread
|
||||
|
||||
# pretend nameplates: 1, 12, 34
|
||||
|
||||
|
@ -304,12 +309,13 @@ class Completion(unittest.TestCase):
|
|||
self.assertEqual(gwc.mock_calls, [mock.call("and-b")])
|
||||
gwc.reset_mock()
|
||||
|
||||
c.finish("12-and-bat")
|
||||
yield deferToThread(c.finish, "12-and-bat")
|
||||
self.assertEqual(cw.mock_calls, [mock.call("and-bat")])
|
||||
|
||||
def test_incomplete_code(self):
|
||||
helper = mock.Mock()
|
||||
c = CodeInputter(helper, "reactor")
|
||||
c.bcft = fake_blockingCallFromThread
|
||||
with self.assertRaises(KeyFormatError) as e:
|
||||
c.finish("1")
|
||||
self.assertEqual(str(e.exception), "incomplete wormhole code")
|
||||
|
@ -349,7 +355,7 @@ class Completion(unittest.TestCase):
|
|||
self.assertEqual(matches, ["1-code", "1-court"])
|
||||
helper.reset_mock()
|
||||
with self.assertRaises(AlreadyInputNameplateError) as e:
|
||||
c.finish("2-code")
|
||||
yield deferToThread(c.finish, "2-code")
|
||||
self.assertEqual(str(e.exception),
|
||||
"nameplate (1-) already entered, cannot go back")
|
||||
self.assertEqual(helper.mock_calls, [])
|
||||
|
|
Loading…
Reference in New Issue
Block a user