more work: allocator, input, shift responsibilities

This commit is contained in:
Brian Warner 2017-03-12 18:38:48 +01:00
parent 79d38da497
commit 4f1b352b2a
13 changed files with 305 additions and 99 deletions

View File

@ -176,46 +176,46 @@ for consistency.
The code-entry Helper object has the following API: The code-entry Helper object has the following API:
* `update_nameplates()`: requests an updated list of nameplates from the * `refresh_nameplates()`: requests an updated list of nameplates from the
Rendezvous Server. These form the first portion of the wormhole code (e.g. Rendezvous Server. These form the first portion of the wormhole code (e.g.
"4" in "4-purple-sausages"). Note that they are unicode strings (so "4", "4" in "4-purple-sausages"). Note that they are unicode strings (so "4",
not 4). The Helper will get the response in the background, and calls to not 4). The Helper will get the response in the background, and calls to
`complete_nameplate()` after the response will use the new list. `get_nameplate_completions()` after the response will use the new list.
* `completions = h.complete_nameplate(prefix)`: returns (synchronously) a * `completions = h.get_nameplate_completions(prefix)`: returns
list of suffixes for the given nameplate prefix. For example, if the server (synchronously) a list of suffixes for the given nameplate prefix. For
reports nameplates 1, 12, 13, 24, and 170 are in use, example, if the server reports nameplates 1, 12, 13, 24, and 170 are in
`complete_nameplate("1")` will return `["", "2", "3", "70"]`. Raises use, `get_nameplate_completions("1")` will return `["", "2", "3", "70"]`.
`AlreadyClaimedNameplateError` if called after `h.claim_nameplate`. Raises `AlreadyClaimedNameplateError` if called after `h.choose_nameplate`.
* `d = h.claim_nameplate(nameplate)`: accepts a string with the chosen * `h.choose_nameplate(nameplate)`: accepts a string with the chosen nameplate.
nameplate. May only be called once, after which `OnlyOneNameplateError` is May only be called once, after which `OnlyOneNameplateError` is raised. (in
raised. Returns a Deferred that fires (with None) when the nameplate's this future, this might return a Deferred that fires (with None) when the
wordlist is known (which happens after the nameplate is claimed, requiring nameplate's wordlist is known (which happens after the nameplate is
a roundtrip to the server). claimed, requiring a roundtrip to the server)).
* `completions = h.complete_words(prefix)`: return (synchronously) a list of * `completions = h.get_word_completions(prefix)`: return (synchronously) a
suffixes for the given words prefix. The possible completions depend upon list of suffixes for the given words prefix. The possible completions
the wordlist in use for the previously-claimed nameplate, so calling this depend upon the wordlist in use for the previously-claimed nameplate, so
before `claim_nameplate` will raise `MustClaimNameplateFirstError`. Given a calling this before `choose_nameplate` will raise
prefix like "su", this returns a list of strings which are appropriate to `MustClaimNameplateFirstError`. Given a prefix like "su", this returns a
append to the prefix (e.g. `["pportive", "rrender", "spicious"]`, for list of strings which are appropriate to append to the prefix (e.g.
expansion into "supportive", "surrender", and "suspicious". The prefix `["pportive", "rrender", "spicious"]`, for expansion into "supportive",
should not include the nameplate, but *should* include whatever words and "surrender", and "suspicious". The prefix should not include the nameplate,
hyphens have been typed so far (the default wordlist uses alternate lists, but *should* include whatever words and hyphens have been typed so far (the
where even numbered words have three syllables, and odd numbered words have default wordlist uses alternate lists, where even numbered words have three
two, so the completions depend upon how many words are present, not just syllables, and odd numbered words have two, so the completions depend upon
the partial last word). E.g. `complete_words("pr")` will return how many words are present, not just the partial last word). E.g.
`["ocessor", "ovincial", "oximate"]`, while `complete_words("opulent-pr")` `get_word_completions("pr")` will return `["ocessor", "ovincial",
will return `["eclude", "efer", "eshrunk", "inter", "owler"]`. "oximate"]`, while `get_word_completions("opulent-pr")` will return
If the wordlist is not yet known (i.e. the Deferred from `claim_nameplate` `["eclude", "efer", "eshrunk", "inter", "owler"]`. If the wordlist is not
has not yet fired), this returns an empty list. It will also return an yet known, this returns an empty list. It will also return an empty list if
empty list if the prefix is complete (the last word matches something in the prefix is complete (the last word matches something in the completion
the completion list, and there are no longer extension words), although the list, and there are no longer extension words), although the code may not
code may not yet be complete if there are additional words. The completions yet be complete if there are additional words. The completions will never
will never include a hyphen: the UI frontend must supply these if desired. include a hyphen: the UI frontend must supply these if desired.
* `h.submit_words(words)`: call this when the user is finished typing in the * `h.choose_words(words)`: call this when the user is finished typing in the
code. It does not return anything, but will cause the Wormhole's code. It does not return anything, but will cause the Wormhole's
`w.when_code()` (or corresponding delegate) to fire, and triggers the `w.when_code()` (or corresponding delegate) to fire, and triggers the
wormhole connection process. This accepts a string like "purple-sausages", wormhole connection process. This accepts a string like "purple-sausages",
without the nameplate. It must be called after `h.claim_nameplate()` or without the nameplate. It must be called after `h.choose_nameplate()` or
`MustClaimNameplateFirstError` will be raised. `MustClaimNameplateFirstError` will be raised.
The `rlcompleter` wrapper is a function that knows how to use the code-entry The `rlcompleter` wrapper is a function that knows how to use the code-entry

View File

@ -11,8 +11,12 @@ digraph {
S0B -> P_allocate [label="allocate"] S0B -> P_allocate [label="allocate"]
P_allocate [shape="box" label="RC.tx_allocate" color="orange"] P_allocate [shape="box" label="RC.tx_allocate" color="orange"]
P_allocate -> S1B [color="orange"] P_allocate -> S1B [color="orange"]
S1B [label="S1B:\nallocating" color="orange"] {rank=same; S1A P_allocate S1B}
S1B -> S1A [label="lost"] S0B -> S1B [style="invis"]
S1B [label="S1B:\nallocating\nconnected" color="orange"]
S1B -> foo [label="lost"]
foo [style="dotted" label=""]
foo -> S1A
S1A [label="S1A:\nallocating\ndisconnected" color="orange"] S1A [label="S1A:\nallocating\ndisconnected" color="orange"]
S1A -> P_allocate [label="connected" color="orange"] S1A -> P_allocate [label="connected" color="orange"]

View File

@ -12,7 +12,7 @@ digraph {
{rank=same; P0_code S0} {rank=same; P0_code S0}
P0_code [shape="box" style="dashed" P0_code [shape="box" style="dashed"
label="input -> Code.input\n or allocate -> Code.allocate\n or set_code -> Code.set_code"] label="C.input_code\n or C.allocate_code\n or C.set_code"]
P0_code -> S0 P0_code -> S0
S0 [label="S0: empty"] S0 [label="S0: empty"]
S0 -> P0_build [label="set_code"] S0 -> P0_build [label="set_code"]
@ -22,7 +22,7 @@ digraph {
P_close_error -> S_closing P_close_error -> S_closing
S0 -> P_close_lonely [label="close"] S0 -> P_close_lonely [label="close"]
P0_build [shape="box" label="W.got_code\nN.set_nameplate\nK.got_code"] P0_build [shape="box" label="W.got_code"]
P0_build -> S1 P0_build -> S1
S1 [label="S1: lonely" color="orange"] S1 [label="S1: lonely" color="orange"]
@ -67,7 +67,7 @@ digraph {
{rank=same; Other S_closed} {rank=same; Other S_closed}
Other [shape="box" style="dashed" Other [shape="box" style="dashed"
label="rx_welcome -> process\nsend -> S.send\ngot_message -> got_version or got_phase\ngot_key -> W.got_key\ngot_verifier -> W.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code" label="rx_welcome -> process\nsend -> S.send\ngot_message -> got_version or got_phase\ngot_key -> W.got_key\ngot_verifier -> W.got_verifier\nallocate_Code -> C.allocate_code\ninput_code -> C.input_code\nset_code -> C.set_code"
] ]

View File

@ -1,27 +1,39 @@
digraph { digraph {
start [label="C:\nCode\nManagement" style="dotted"] start [label="C:\nCode\n(management)" style="dotted"]
{rank=same; start S0} {rank=same; start S0}
start -> S0 [style="invis"] start -> S0 [style="invis"]
S0 [label="S0:\nidle"] S0 [label="S0:\nidle"]
S0 -> P0_got_code [label="set_code"] S0 -> P0_got_code [label="set_code"]
P0_got_code [shape="box" label="B.got_code"] P0_got_code [shape="box" label="N.set_nameplate"]
P0_got_code -> S3 P0_got_code -> P_done
S3 [label="S3: known" color="green"] P_done [shape="box" label="K.got_code\nB.got_code"]
P_done -> S5
S5 [label="S5: known" color="green"]
{rank=same; S1_inputting S2_allocating} {rank=same; S1_inputting_nameplate S3_allocating}
{rank=same; P0_got_code P1_set_nameplate P3_got_nameplate}
S0 -> P_input [label="input_code"] S0 -> P_input [label="input_code"]
P_input [shape="box" label="I.start"] P_input [shape="box" label="I.start"]
P_input -> S1_inputting P_input -> S1_inputting_nameplate
S1_inputting [label="S1:\ninputting"] S1_inputting_nameplate [label="S1:\ninputting\nnameplate"]
S1_inputting -> P0_got_code [label="finished_input"] S1_inputting_nameplate -> P1_set_nameplate [label="got_nameplate"]
P1_set_nameplate [shape="box" label="N.set_nameplate"]
P1_set_nameplate -> S2_inputting_words
S2_inputting_words [label="S2:\ninputting\nwords"]
S2_inputting_words -> P1_got_words [label="finished_input"]
P1_got_words [shape="box" label="assemble\ncode"]
P1_got_words -> P_done
P_done
S0 -> P_allocate [label="allocate_code"] S0 -> P_allocate [label="allocate_code"]
P_allocate [shape="box" label="A.allocate"] P_allocate [shape="box" label="A.allocate"]
P_allocate -> S2_allocating P_allocate -> S3_allocating
S2_allocating [label="S2:\nallocating"] S3_allocating [label="S3:\nallocating"]
S2_allocating -> P1_generate [label="allocated_nameplate"] S3_allocating -> P3_got_nameplate [label="allocated_nameplate"]
P1_generate [shape="box" label="generate\nrandom words"] P3_got_nameplate [shape="box" label="N.set_nameplate"]
P1_generate -> P0_got_code P3_got_nameplate -> P3_generate
P3_generate [shape="box" label="append\nrandom words"]
P3_generate -> P_done
} }

View File

@ -5,28 +5,39 @@ digraph {
start -> S0 [style="invis"] start -> S0 [style="invis"]
S0 [label="S0:\nidle"] S0 [label="S0:\nidle"]
S0 -> P0_list_nameplates [label="start" color="orange"] S0 -> P0_list_nameplates [label="start"]
P0_list_nameplates [shape="box" label="L.refresh_nameplates" color="orange"] P0_list_nameplates [shape="box" label="L.refresh"]
P0_list_nameplates -> S1 [color="orange"] P0_list_nameplates -> S1
S1 [label="S1: typing\nnameplate" color="orange"] S1 [label="S1: typing\nnameplate" color="orange"]
{rank=same; foo P0_list_nameplates} {rank=same; foo P0_list_nameplates}
S1 -> foo [label="update_nameplates"] S1 -> foo [label="refresh_nameplates" color="orange" fontcolor="orange"]
foo [style="dashed" label=""] foo [style="dashed" label=""]
foo -> P0_list_nameplates foo -> P0_list_nameplates
S1 -> P1_claim [label="claim_nameplate" color="orange" fontcolor="orange"] S1 -> P1_record [label="got_nameplates"]
P1_claim [shape="box" label="N.set_nameplate" color="orange"] P1_record [shape="box" label="record\nnameplates"]
P1_claim -> S2 [color="orange"] P1_record -> S1
S2 [label="S2: typing\ncode\n(no wordlist)" color="orange"]
S2 -> P2_stash_wordlist [label="got_nameplates" color="orange"]
P2_stash_wordlist [shape="box" label="stash\nwordlist" color="orange"]
P2_stash_wordlist -> S3 [color="orange"]
S2 -> P_done [label="submit_words"]
S3 [label="S3: typing\ncode\n(yes wordlist)" color="orange"]
S3 -> P_done [label="submit_words" color="orange" fontcolor="orange"]
P_done [shape="box" label="C.finished_input" color="orange"]
P_done -> S4 [color="orange"]
S4 [label="S4: known" color="green"]
S1 -> P1_claim [label="choose_nameplate" color="orange" fontcolor="orange"]
P1_claim [shape="box" label="stash nameplate\nC.got_nameplate"]
P1_claim -> S2
S2 [label="S2: typing\ncode\n(no wordlist)"]
S2 -> S2 [label="got_nameplates"]
S2 -> P2_stash_wordlist [label="got_wordlist"]
P2_stash_wordlist [shape="box" label="stash wordlist"]
P2_stash_wordlist -> S3
S2 -> P_done [label="choose_words" color="orange" fontcolor="orange"]
S3 [label="S3: typing\ncode\n(yes wordlist)"]
S3 -> S3 [label="got_nameplates"]
S3 -> P_done [label="choose_words" color="orange" fontcolor="orange"]
P_done [shape="box" label="build code\nC.finished_input"]
P_done -> S4
S4 [label="S4: done" color="green"]
S4 -> S4 [label="got_nameplates\ngot_wordlist"]
other [shape="box" style="dotted"
label="h.refresh_nameplates()\nh.get_nameplate_completions(prefix)\nh.choose_nameplate(nameplate)\nh.get_word_completions(prefix)\nh.choose_words(words)"
]
{rank=same; S4 other}
} }

View File

@ -31,12 +31,9 @@ digraph {
foo2 [label="" style="dashed"] foo2 [label="" style="dashed"]
foo2 -> P_tx foo2 -> P_tx
S0B -> P_notify [label="rx"] S0B -> P_notify [label="rx_nameplates"]
S1B -> P_notify [label="rx" color="orange" fontcolor="orange"] S1B -> P_notify [label="rx_nameplates" color="orange" fontcolor="orange"]
P_notify [shape="box" label="C.got_nameplates()"] P_notify [shape="box" label="I.got_nameplates()"]
P_notify -> S0B P_notify -> S0B
{rank=same; foo foo2 legend}
legend [shape="box" style="dotted"
label="refresh: L.refresh_nameplates()\nrx: L.rx_nameplates()"]
} }

View File

@ -2,8 +2,10 @@ digraph {
Wormhole [shape="oval" color="blue" fontcolor="blue"] Wormhole [shape="oval" color="blue" fontcolor="blue"]
Boss [shape="box" label="Boss\n(manager)" Boss [shape="box" label="Boss\n(manager)"
color="blue" fontcolor="blue"] color="blue" fontcolor="blue"]
Nameplate [shape="box" color="blue" fontcolor="blue"] Nameplate [label="Nameplate\n(claimer)"
Mailbox [shape="box" color="blue" fontcolor="blue"] shape="box" color="blue" fontcolor="blue"]
Mailbox [label="Mailbox\n(opener)"
shape="box" color="blue" fontcolor="blue"]
Connection [label="Rendezvous\nConnector" Connection [label="Rendezvous\nConnector"
shape="oval" color="blue" fontcolor="blue"] shape="oval" color="blue" fontcolor="blue"]
#websocket [color="blue" fontcolor="blue"] #websocket [color="blue" fontcolor="blue"]
@ -16,9 +18,11 @@ digraph {
color="blue" fontcolor="blue"] color="blue" fontcolor="blue"]
Allocator [shape="box" label="(nameplate)\nAllocator" Allocator [shape="box" label="(nameplate)\nAllocator"
color="blue" fontcolor="blue"] color="blue" fontcolor="blue"]
Input [shape="box" label="(code)\nInput helper" Input [shape="box" label="(interactive\ncode)\nInput"
color="blue" fontcolor="blue"] color="blue" fontcolor="blue"]
Terminator [shape="box" color="blue" fontcolor="blue"] Terminator [shape="box" color="blue" fontcolor="blue"]
InputHelperAPI [shape="oval" label="input\nhelper\nAPI"
color="blue" fontcolor="blue"]
#Connection -> websocket [color="blue"] #Connection -> websocket [color="blue"]
#Connection -> Order [color="blue"] #Connection -> Order [color="blue"]
@ -36,11 +40,8 @@ digraph {
Boss -> Send [style="dashed" color="red" fontcolor="red" label="send"] Boss -> Send [style="dashed" color="red" fontcolor="red" label="send"]
Boss -> Nameplate [style="dashed" color="red" fontcolor="red"
label="set_nameplate"]
#Boss -> Mailbox [color="blue"] #Boss -> Mailbox [color="blue"]
Mailbox -> Order [style="dashed" label="got_message (once)"] Mailbox -> Order [style="dashed" label="got_message (once)"]
Boss -> Key [style="dashed" label="got_code"]
Key -> Boss [style="dashed" label="got_key\ngot_verifier\nscared"] Key -> Boss [style="dashed" label="got_key\ngot_verifier\nscared"]
Order -> Key [style="dashed" label="got_pake"] Order -> Key [style="dashed" label="got_pake"]
Order -> Receive [style="dashed" label="got_message"] Order -> Receive [style="dashed" label="got_message"]
@ -85,15 +86,18 @@ digraph {
] ]
#Code -> Lister [color="blue"] #Code -> Lister [color="blue"]
Input -> Lister [style="dashed" color="red" fontcolor="red" Input -> Lister [style="dashed" color="red" fontcolor="red"
label="refresh_nameplates" label="refresh"
] ]
Boss -> Code [style="dashed" color="red" fontcolor="red" Boss -> Code [style="dashed" color="red" fontcolor="red"
label="allocate_code\ninput_code\nset_code"] label="allocate_code\ninput_code\nset_code"]
Code -> Boss [style="dashed" Code -> Boss [style="dashed" label="got_code"]
label="got_code"] Code -> Key [style="dashed" label="got_code"]
Code -> Nameplate [style="dashed" label="set_nameplate"]
Code -> Input [style="dashed" color="red" fontcolor="red" label="start"] Code -> Input [style="dashed" color="red" fontcolor="red" label="start"]
Input -> Code [style="dashed" label="finished_input"] Input -> Code [style="dashed" label="got_nameplate\nfinished_input"]
InputHelperAPI -> Input [label="refresh_nameplates\nget_nameplate_completions\nchoose_nameplate\nget_word_completions\nchoose_words" color="orange" fontcolor="orange"]
Code -> Allocator [style="dashed" color="red" fontcolor="red" Code -> Allocator [style="dashed" color="red" fontcolor="red"
label="allocate"] label="allocate"]
Allocator -> Code [style="dashed" label="allocated"] Allocator -> Code [style="dashed" label="allocated"]

View File

@ -0,0 +1,65 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer
from attr import attrs, attrib
from attr.validators import provides
from automat import MethodicalMachine
from . import _interfaces
@attrs
@implementer(_interfaces.IAllocator)
class Allocator(object):
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()
@m.setTrace()
def set_trace(): pass # pragma: no cover
def wire(self, rendezvous_connector, code):
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
self._C = _interfaces.ICode(code)
@m.state(initial=True)
def S0A_idle(self): pass # pragma: no cover
@m.state()
def S0B_idle_connected(self): pass # pragma: no cover
@m.state()
def S1A_allocating(self): pass # pragma: no cover
@m.state()
def S1B_allocating_connected(self): pass # pragma: no cover
@m.state()
def S2_done(self): pass # pragma: no cover
# from Code
@m.input()
def allocate(self): pass
# from RendezvousConnector
@m.input()
def connected(self): pass
@m.input()
def lost(self): pass
@m.input()
def rx_allocated(self, nameplate): pass
@m.output()
def RC_tx_allocate(self):
self._RC.tx_allocate()
@m.output()
def C_allocated(self, nameplate):
self._C.allocated(nameplate)
S0A_idle.upon(connected, enter=S0B_idle_connected, outputs=[])
S0B_idle_connected.upon(lost, enter=S0A_idle, outputs=[])
S0A_idle.upon(allocate, enter=S1A_allocating, outputs=[])
S0B_idle_connected.upon(allocate, enter=S1B_allocating_connected,
outputs=[RC_tx_allocate])
S1A_allocating.upon(connected, enter=S1B_allocating_connected,
outputs=[RC_tx_allocate])
S1B_allocating_connected.upon(lost, enter=S1A_allocating, outputs=[])
S1B_allocating_connected.upon(rx_allocated, enter=S2_done,
outputs=[C_allocated])
S2_done.upon(connected, enter=S2_done, outputs=[])
S2_done.upon(lost, enter=S2_done, outputs=[])

View File

@ -15,6 +15,8 @@ from ._key import Key
from ._receive import Receive from ._receive import Receive
from ._rendezvous import RendezvousConnector from ._rendezvous import RendezvousConnector
from ._lister import Lister from ._lister import Lister
from ._allocator import Allocator
from ._input import Input
from ._code import Code from ._code import Code
from ._terminator import Terminator from ._terminator import Terminator
from .errors import (ServerError, LonelyError, WrongPasswordError, from .errors import (ServerError, LonelyError, WrongPasswordError,
@ -49,6 +51,8 @@ class Boss(object):
self._reactor, self._journal, self._reactor, self._journal,
self._tor_manager, self._timing) self._tor_manager, self._timing)
self._L = Lister() self._L = Lister()
self._A = Allocator(self._timing)
self._I = Input(self._timing)
self._C = Code(self._timing) self._C = Code(self._timing)
self._T = Terminator() self._T = Terminator()
@ -59,7 +63,9 @@ class Boss(object):
self._K.wire(self, self._M, self._R) self._K.wire(self, self._M, self._R)
self._R.wire(self, self._S) self._R.wire(self, self._S)
self._RC.wire(self, self._N, self._M, self._C, self._L, self._T) self._RC.wire(self, self._N, self._M, self._C, self._L, self._T)
self._L.wire(self._RC, self._C) self._L.wire(self._RC, self._I)
self._A.wire(self._RC, self._C)
self._I.wire(self._C, self._L)
self._C.wire(self, self._RC, self._L) self._C.wire(self, self._RC, self._L)
self._T.wire(self, self._RC, self._N, self._M) self._T.wire(self, self._RC, self._N, self._M)
@ -189,8 +195,6 @@ class Boss(object):
@m.output() @m.output()
def do_got_code(self, code): def do_got_code(self, code):
nameplate = code.split("-")[0]
self._N.set_nameplate(nameplate)
self._K.got_code(code) self._K.got_code(code)
self._W.got_code(code) self._W.got_code(code)
@m.output() @m.output()

View File

@ -74,13 +74,11 @@ class Code(object):
@m.input() @m.input()
def got_wordlist(self, wordlist): pass def got_wordlist(self, wordlist): pass
# from CodeInputHelper # from Input
@m.input() @m.input()
def update_nameplates(self): pass def got_nameplate(self, nameplate): pass
@m.input() @m.input()
def claim_nameplate(self, nameplate): pass def finished_input(self, code): pass
@m.input()
def submit_words(self, words): pass
@m.output() @m.output()
def L_refresh_nameplates(self): def L_refresh_nameplates(self):
@ -137,6 +135,7 @@ class Code(object):
self._B_got_code() self._B_got_code()
def _B_got_code(self): def _B_got_code(self):
self._N.set_nameplate(nameplate) XXX
self._B.got_code(self._code) self._B.got_code(self._code)
S0A_unknown.upon(connected, enter=S0B_unknown_connected, outputs=[]) S0A_unknown.upon(connected, enter=S0B_unknown_connected, outputs=[])

106
src/wormhole/_input.py Normal file
View File

@ -0,0 +1,106 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer
from attr import attrs, attrib
from attr.validators import provides
from automat import MethodicalMachine
from . import _interfaces
@attrs
@implementer(_interfaces.IInput)
class Input(object):
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()
@m.setTrace()
def set_trace(): pass # pragma: no cover
def __attrs_post_init__(self):
self._nameplate = None
self._wordlist = None
self._claimed_waiter = None
def wire(self, code, lister):
self._C = _interfaces.ICode(code)
self._L = _interfaces.ILister(lister)
@m.state(initial=True)
def S0_idle(self): pass # pragma: no cover
@m.state()
def S1_nameplate(self): pass # pragma: no cover
@m.state()
def S2_code_no_wordlist(self): pass # pragma: no cover
@m.state()
def S3_code_yes_wordlist(self): pass # pragma: no cover
@m.state(terminal=True)
def S4_done(self): pass # pragma: no cover
# from Code
@m.input()
def start(self): pass
# from Lister
@m.input()
def got_nameplates(self, nameplates): pass
# from Nameplate??
@m.input()
def got_wordlist(self, wordlist): pass
# from CodeInputHelper
@m.input()
def refresh_nameplates(self): pass
@m.input()
def _choose_nameplate(self, nameplate): pass
@m.input()
def choose_words(self, words): pass
@m.output()
def L_refresh_nameplates(self):
self._L.refresh_nameplates()
@m.output()
def start_and_L_refresh_nameplates(self, input_helper):
self._input_helper = input_helper
self._L.refresh_nameplates()
@m.output()
def stash_wordlist_and_notify(self, wordlist):
self._wordlist = wordlist
if self._claimed_waiter:
self._claimed_waiter.callback(None)
del self._claimed_waiter
@m.output()
def stash_nameplate(self, nameplate):
self._nameplate = nameplate
@m.output()
def C_got_nameplate(self, nameplate):
self._C.got_nameplate(nameplate)
@m.output()
def finished(self, words):
code = self._nameplate + "-" + words
self._C.finished_input(code)
S0_idle.upon(start, enter=S1_nameplate, outputs=[L_refresh_nameplates])
S1_nameplate.upon(refresh_nameplates, enter=S1_nameplate,
outputs=[L_refresh_nameplates])
S1_nameplate.upon(_choose_nameplate, enter=S2_code_no_wordlist,
outputs=[stash_nameplate, C_got_nameplate])
S2_code_no_wordlist.upon(got_wordlist, enter=S3_code_yes_wordlist,
outputs=[stash_wordlist_and_notify])
S2_code_no_wordlist.upon(choose_words, enter=S4_done, outputs=[finished])
S3_code_yes_wordlist.upon(choose_words, enter=S4_done, outputs=[finished])
# methods for the CodeInputHelper to use
#refresh_nameplates/_choose_nameplate/choose_words: @m.input methods
def get_nameplate_completions(self, prefix):
completions = []
for nameplate in self._nameplates
pass
def choose_nameplate(self, nameplate):
if self._claimed_waiter is not None:
raise X
d = self._claimed_waiter = defer.Deferred()
self._choose_nameplate(nameplate)
def get_word_completions(self, prefix):
pass

View File

@ -22,6 +22,10 @@ class ILister(Interface):
pass pass
class ICode(Interface): class ICode(Interface):
pass pass
class IInput(Interface):
pass
class IAllocator(Interface):
pass
class ITerminator(Interface): class ITerminator(Interface):
pass pass

View File

@ -9,9 +9,9 @@ class Lister(object):
@m.setTrace() @m.setTrace()
def set_trace(): pass # pragma: no cover def set_trace(): pass # pragma: no cover
def wire(self, rendezvous_connector, code): def wire(self, rendezvous_connector, input):
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector) self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
self._C = _interfaces.ICode(code) self._I = _interfaces.IInput(input)
# Ideally, each API request would spawn a new "list_nameplates" message # Ideally, each API request would spawn a new "list_nameplates" message
# to the server, so the response would be maximally fresh, but that would # to the server, so the response would be maximally fresh, but that would
@ -44,8 +44,8 @@ class Lister(object):
def RC_tx_list(self): def RC_tx_list(self):
self._RC.tx_list() self._RC.tx_list()
@m.output() @m.output()
def C_got_nameplates(self, message): def I_got_nameplates(self, message):
self._C.got_nameplates(message["nameplates"]) self._I.got_nameplates(message["nameplates"])
S0A_idle_disconnected.upon(connected, enter=S0B_idle_connected, outputs=[]) S0A_idle_disconnected.upon(connected, enter=S0B_idle_connected, outputs=[])
S0B_idle_connected.upon(lost, enter=S0A_idle_disconnected, outputs=[]) S0B_idle_connected.upon(lost, enter=S0A_idle_disconnected, outputs=[])
@ -59,9 +59,9 @@ class Lister(object):
S0B_idle_connected.upon(refresh_nameplates, enter=S1B_wanting_connected, S0B_idle_connected.upon(refresh_nameplates, enter=S1B_wanting_connected,
outputs=[RC_tx_list]) outputs=[RC_tx_list])
S0B_idle_connected.upon(rx_nameplates, enter=S0B_idle_connected, S0B_idle_connected.upon(rx_nameplates, enter=S0B_idle_connected,
outputs=[C_got_nameplates]) outputs=[I_got_nameplates])
S1B_wanting_connected.upon(lost, enter=S1A_wanting_disconnected, outputs=[]) S1B_wanting_connected.upon(lost, enter=S1A_wanting_disconnected, outputs=[])
S1B_wanting_connected.upon(refresh_nameplates, enter=S1B_wanting_connected, S1B_wanting_connected.upon(refresh_nameplates, enter=S1B_wanting_connected,
outputs=[RC_tx_list]) outputs=[RC_tx_list])
S1B_wanting_connected.upon(rx_nameplates, enter=S0B_idle_connected, S1B_wanting_connected.upon(rx_nameplates, enter=S0B_idle_connected,
outputs=[C_got_nameplates]) outputs=[I_got_nameplates])