commit
593b359166
|
@ -108,14 +108,16 @@ class Boss(object):
|
|||
def _set_trace(self, client_name, which, file):
|
||||
names = {"B": self, "N": self._N, "M": self._M, "S": self._S,
|
||||
"O": self._O, "K": self._K, "SK": self._K._SK, "R": self._R,
|
||||
"RC": self._RC, "L": self._L, "C": self._C,
|
||||
"T": self._T}
|
||||
"RC": self._RC, "L": self._L, "A": self._A, "I": self._I,
|
||||
"C": self._C, "T": self._T}
|
||||
for machine in which.split():
|
||||
t = (lambda old_state, input, new_state, machine=machine:
|
||||
self._print_trace(old_state, input, new_state,
|
||||
client_name=client_name,
|
||||
machine=machine, file=file))
|
||||
names[machine].set_trace(t)
|
||||
if machine == "I":
|
||||
self._I.set_debug(t)
|
||||
|
||||
## def serialize(self):
|
||||
## raise NotImplemented
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
from __future__ import print_function, absolute_import, unicode_literals
|
||||
# We use 'threading' defensively here, to detect if we're being called from a
|
||||
# non-main thread. _rlcompleter.py is the only internal Wormhole code that
|
||||
# deliberately creates a new thread.
|
||||
import threading
|
||||
from zope.interface import implementer
|
||||
from attr import attrs, attrib
|
||||
from attr.validators import provides
|
||||
|
@ -22,6 +26,13 @@ class Input(object):
|
|||
self._nameplate = None
|
||||
self._wordlist = None
|
||||
self._wordlist_waiters = []
|
||||
self._trace = None
|
||||
|
||||
def set_debug(self, f):
|
||||
self._trace = f
|
||||
def _debug(self, what):
|
||||
if self._trace:
|
||||
self._trace(old_state="", input=what, new_state="")
|
||||
|
||||
def wire(self, code, lister):
|
||||
self._C = _interfaces.ICode(code)
|
||||
|
@ -233,15 +244,28 @@ class Input(object):
|
|||
class Helper(object):
|
||||
_input = attrib()
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self._main_thread = threading.current_thread().ident
|
||||
|
||||
def refresh_nameplates(self):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
self._input.refresh_nameplates()
|
||||
def get_nameplate_completions(self, prefix):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
return self._input.get_nameplate_completions(prefix)
|
||||
def choose_nameplate(self, nameplate):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
self._input._debug("I.choose_nameplate")
|
||||
self._input.choose_nameplate(nameplate)
|
||||
self._input._debug("I.choose_nameplate finished")
|
||||
def when_wordlist_is_available(self):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
return self._input.when_wordlist_is_available()
|
||||
def get_word_completions(self, prefix):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
return self._input.get_word_completions(prefix)
|
||||
def choose_words(self, words):
|
||||
assert threading.current_thread().ident == self._main_thread
|
||||
self._input._debug("I.choose_words")
|
||||
self._input.choose_words(words)
|
||||
self._input._debug("I.choose_words finished")
|
||||
|
|
|
@ -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, [])
|
||||
|
|
|
@ -214,7 +214,8 @@ class _DeferredWormhole(object):
|
|||
self._boss.close() # only need to close if it wasn't already
|
||||
return d
|
||||
|
||||
def debug_set_trace(self, client_name, which="B N M S O K SK R RC L C T",
|
||||
def debug_set_trace(self, client_name,
|
||||
which="B N M S O K SK R RC L A I C T",
|
||||
file=sys.stderr):
|
||||
self._boss._set_trace(client_name, which, file)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user