more work: allocator, input, shift responsibilities
This commit is contained in:
		
							parent
							
								
									79d38da497
								
							
						
					
					
						commit
						4f1b352b2a
					
				
							
								
								
									
										68
									
								
								docs/api.md
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								docs/api.md
									
									
									
									
									
								
							|  | @ -176,46 +176,46 @@ for consistency. | |||
| 
 | ||||
| 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. | ||||
|   "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 | ||||
|   `complete_nameplate()` after the response will use the new list. | ||||
| * `completions = h.complete_nameplate(prefix)`: returns (synchronously) a | ||||
|   list of suffixes for the given nameplate prefix. For example, if the server | ||||
|   reports nameplates 1, 12, 13, 24, and 170 are in use, | ||||
|   `complete_nameplate("1")` will return `["", "2", "3", "70"]`. Raises | ||||
|   `AlreadyClaimedNameplateError` if called after `h.claim_nameplate`. | ||||
| * `d = h.claim_nameplate(nameplate)`: accepts a string with the chosen | ||||
|   nameplate. May only be called once, after which `OnlyOneNameplateError` is | ||||
|   raised. Returns a Deferred that fires (with None) when the nameplate's | ||||
|   wordlist is known (which happens after the nameplate is claimed, requiring | ||||
|   a roundtrip to the server). | ||||
| * `completions = h.complete_words(prefix)`: return (synchronously) a list of | ||||
|   suffixes for the given words prefix. The possible completions depend upon | ||||
|   the wordlist in use for the previously-claimed nameplate, so calling this | ||||
|   before `claim_nameplate` will raise `MustClaimNameplateFirstError`. Given a | ||||
|   prefix like "su", this returns a list of strings which are appropriate to | ||||
|   append to the prefix (e.g. `["pportive", "rrender", "spicious"]`, for | ||||
|   expansion into "supportive", "surrender", and "suspicious". The prefix | ||||
|   should not include the nameplate, but *should* include whatever words and | ||||
|   hyphens have been typed so far (the default wordlist uses alternate lists, | ||||
|   where even numbered words have three syllables, and odd numbered words have | ||||
|   two, so the completions depend upon how many words are present, not just | ||||
|   the partial last word). E.g. `complete_words("pr")` will return | ||||
|   `["ocessor", "ovincial", "oximate"]`, while `complete_words("opulent-pr")` | ||||
|   will return `["eclude", "efer", "eshrunk", "inter", "owler"]`. | ||||
|   If the wordlist is not yet known (i.e. the Deferred from `claim_nameplate` | ||||
|   has not yet fired), this returns an empty list. It will also return an | ||||
|   empty list if the prefix is complete (the last word matches something in | ||||
|   the completion list, and there are no longer extension words), although the | ||||
|   code may not yet be complete if there are additional words. The completions | ||||
|   will never 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 | ||||
|   `get_nameplate_completions()` after the response will use the new list. | ||||
| * `completions = h.get_nameplate_completions(prefix)`: returns | ||||
|   (synchronously) a list of suffixes for the given nameplate prefix. For | ||||
|   example, if the server reports nameplates 1, 12, 13, 24, and 170 are in | ||||
|   use, `get_nameplate_completions("1")` will return `["", "2", "3", "70"]`. | ||||
|   Raises `AlreadyClaimedNameplateError` if called after `h.choose_nameplate`. | ||||
| * `h.choose_nameplate(nameplate)`: accepts a string with the chosen nameplate. | ||||
|   May only be called once, after which `OnlyOneNameplateError` is raised. (in | ||||
|   this future, this might return a Deferred that fires (with None) when the | ||||
|   nameplate's wordlist is known (which happens after the nameplate is | ||||
|   claimed, requiring a roundtrip to the server)). | ||||
| * `completions = h.get_word_completions(prefix)`: return (synchronously) a | ||||
|   list of suffixes for the given words prefix. The possible completions | ||||
|   depend upon the wordlist in use for the previously-claimed nameplate, so | ||||
|   calling this before `choose_nameplate` will raise | ||||
|   `MustClaimNameplateFirstError`. Given a prefix like "su", this returns a | ||||
|   list of strings which are appropriate to append to the prefix (e.g. | ||||
|   `["pportive", "rrender", "spicious"]`, for expansion into "supportive", | ||||
|   "surrender", and "suspicious". The prefix should not include the nameplate, | ||||
|   but *should* include whatever words and hyphens have been typed so far (the | ||||
|   default wordlist uses alternate lists, where even numbered words have three | ||||
|   syllables, and odd numbered words have two, so the completions depend upon | ||||
|   how many words are present, not just the partial last word). E.g. | ||||
|   `get_word_completions("pr")` will return `["ocessor", "ovincial", | ||||
|   "oximate"]`, while `get_word_completions("opulent-pr")` will return | ||||
|   `["eclude", "efer", "eshrunk", "inter", "owler"]`. If the wordlist is not | ||||
|   yet known, this returns an empty list. It will also return an empty list if | ||||
|   the prefix is complete (the last word matches something in the completion | ||||
|   list, and there are no longer extension words), although the code may not | ||||
|   yet be complete if there are additional words. The completions will never | ||||
|   include a hyphen: the UI frontend must supply these if desired. | ||||
| * `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 | ||||
|   `w.when_code()` (or corresponding delegate) to fire, and triggers the | ||||
|   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. | ||||
| 
 | ||||
| The `rlcompleter` wrapper is a function that knows how to use the code-entry | ||||
|  |  | |||
|  | @ -11,8 +11,12 @@ digraph { | |||
|         S0B -> P_allocate [label="allocate"] | ||||
|         P_allocate [shape="box" label="RC.tx_allocate" color="orange"] | ||||
|         P_allocate -> S1B [color="orange"] | ||||
|         S1B [label="S1B:\nallocating" color="orange"] | ||||
|         S1B -> S1A [label="lost"] | ||||
|         {rank=same; S1A P_allocate S1B} | ||||
|         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 -> P_allocate [label="connected" color="orange"] | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ digraph { | |||
| 
 | ||||
|         {rank=same; P0_code S0} | ||||
|         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 | ||||
|         S0 [label="S0: empty"] | ||||
|         S0 -> P0_build [label="set_code"] | ||||
|  | @ -22,7 +22,7 @@ digraph { | |||
|         P_close_error -> S_closing | ||||
|         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 | ||||
|         S1 [label="S1: lonely" color="orange"] | ||||
| 
 | ||||
|  | @ -67,7 +67,7 @@ digraph { | |||
| 
 | ||||
|         {rank=same; Other S_closed} | ||||
|         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" | ||||
|                ] | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,27 +1,39 @@ | |||
| digraph { | ||||
| 
 | ||||
|         start [label="C:\nCode\nManagement" style="dotted"] | ||||
|         start [label="C:\nCode\n(management)" style="dotted"] | ||||
|         {rank=same; start S0} | ||||
|         start -> S0 [style="invis"] | ||||
|         S0 [label="S0:\nidle"] | ||||
|         S0 -> P0_got_code [label="set_code"] | ||||
|         P0_got_code [shape="box" label="B.got_code"] | ||||
|         P0_got_code -> S3 | ||||
|         S3 [label="S3: known" color="green"] | ||||
|         P0_got_code [shape="box" label="N.set_nameplate"] | ||||
|         P0_got_code -> P_done | ||||
|         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"] | ||||
|         P_input [shape="box" label="I.start"] | ||||
|         P_input -> S1_inputting | ||||
|         S1_inputting [label="S1:\ninputting"] | ||||
|         S1_inputting -> P0_got_code [label="finished_input"] | ||||
|         P_input -> S1_inputting_nameplate | ||||
|         S1_inputting_nameplate [label="S1:\ninputting\nnameplate"] | ||||
|         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"] | ||||
|         P_allocate [shape="box" label="A.allocate"] | ||||
|         P_allocate -> S2_allocating | ||||
|         S2_allocating [label="S2:\nallocating"] | ||||
|         S2_allocating -> P1_generate [label="allocated_nameplate"] | ||||
|         P1_generate [shape="box" label="generate\nrandom words"] | ||||
|         P1_generate -> P0_got_code | ||||
|         P_allocate -> S3_allocating | ||||
|         S3_allocating [label="S3:\nallocating"] | ||||
|         S3_allocating -> P3_got_nameplate [label="allocated_nameplate"] | ||||
|         P3_got_nameplate [shape="box" label="N.set_nameplate"] | ||||
|         P3_got_nameplate -> P3_generate | ||||
|         P3_generate [shape="box" label="append\nrandom words"] | ||||
|         P3_generate -> P_done | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,28 +5,39 @@ digraph { | |||
|         start -> S0 [style="invis"] | ||||
|         S0 [label="S0:\nidle"] | ||||
| 
 | ||||
|         S0 -> P0_list_nameplates [label="start" color="orange"] | ||||
|         P0_list_nameplates [shape="box" label="L.refresh_nameplates" color="orange"] | ||||
|         P0_list_nameplates -> S1 [color="orange"] | ||||
|         S0 -> P0_list_nameplates [label="start"] | ||||
|         P0_list_nameplates [shape="box" label="L.refresh"] | ||||
|         P0_list_nameplates -> S1 | ||||
|         S1 [label="S1: typing\nnameplate" color="orange"] | ||||
| 
 | ||||
|         {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 -> P0_list_nameplates | ||||
| 
 | ||||
|         S1 -> P1_claim [label="claim_nameplate" color="orange" fontcolor="orange"] | ||||
|         P1_claim [shape="box" label="N.set_nameplate" color="orange"] | ||||
|         P1_claim -> S2 [color="orange"] | ||||
|         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_record [label="got_nameplates"] | ||||
|         P1_record [shape="box" label="record\nnameplates"] | ||||
|         P1_record -> S1 | ||||
| 
 | ||||
|         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} | ||||
| } | ||||
|  |  | |||
|  | @ -31,12 +31,9 @@ digraph { | |||
|         foo2 [label="" style="dashed"] | ||||
|         foo2 -> P_tx | ||||
| 
 | ||||
|         S0B -> P_notify [label="rx"] | ||||
|         S1B -> P_notify [label="rx" color="orange" fontcolor="orange"] | ||||
|         P_notify [shape="box" label="C.got_nameplates()"] | ||||
|         S0B -> P_notify [label="rx_nameplates"] | ||||
|         S1B -> P_notify [label="rx_nameplates" color="orange" fontcolor="orange"] | ||||
|         P_notify [shape="box" label="I.got_nameplates()"] | ||||
|         P_notify -> S0B | ||||
| 
 | ||||
|         {rank=same; foo foo2 legend} | ||||
|         legend [shape="box" style="dotted" | ||||
|                 label="refresh: L.refresh_nameplates()\nrx: L.rx_nameplates()"] | ||||
| } | ||||
|  |  | |||
|  | @ -2,8 +2,10 @@ digraph { | |||
|         Wormhole [shape="oval" color="blue" fontcolor="blue"] | ||||
|         Boss [shape="box" label="Boss\n(manager)" | ||||
|                   color="blue" fontcolor="blue"] | ||||
|         Nameplate [shape="box" color="blue" fontcolor="blue"] | ||||
|         Mailbox [shape="box" color="blue" fontcolor="blue"] | ||||
|         Nameplate [label="Nameplate\n(claimer)" | ||||
|                    shape="box" color="blue" fontcolor="blue"] | ||||
|         Mailbox [label="Mailbox\n(opener)" | ||||
|                  shape="box" color="blue" fontcolor="blue"] | ||||
|         Connection [label="Rendezvous\nConnector" | ||||
|                     shape="oval" color="blue" fontcolor="blue"] | ||||
|         #websocket [color="blue" fontcolor="blue"] | ||||
|  | @ -16,9 +18,11 @@ digraph { | |||
|                 color="blue" fontcolor="blue"] | ||||
|         Allocator [shape="box" label="(nameplate)\nAllocator" | ||||
|                    color="blue" fontcolor="blue"] | ||||
|         Input [shape="box" label="(code)\nInput helper" | ||||
|         Input [shape="box" label="(interactive\ncode)\nInput" | ||||
|                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 -> Order [color="blue"] | ||||
|  | @ -36,11 +40,8 @@ digraph { | |||
| 
 | ||||
|         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"] | ||||
|         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"] | ||||
|         Order -> Key [style="dashed" label="got_pake"] | ||||
|         Order -> Receive [style="dashed" label="got_message"] | ||||
|  | @ -85,15 +86,18 @@ digraph { | |||
|                          ] | ||||
|         #Code -> Lister [color="blue"] | ||||
|         Input -> Lister [style="dashed" color="red" fontcolor="red" | ||||
|                          label="refresh_nameplates" | ||||
|                          label="refresh" | ||||
|                          ] | ||||
|         Boss -> Code [style="dashed" color="red" fontcolor="red" | ||||
|                       label="allocate_code\ninput_code\nset_code"] | ||||
|         Code -> Boss [style="dashed" | ||||
|                       label="got_code"] | ||||
|         Code -> Boss [style="dashed" 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"] | ||||
|         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" | ||||
|                            label="allocate"] | ||||
|         Allocator -> Code [style="dashed" label="allocated"] | ||||
|  |  | |||
							
								
								
									
										65
									
								
								src/wormhole/_allocator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/wormhole/_allocator.py
									
									
									
									
									
										Normal 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=[]) | ||||
|  | @ -15,6 +15,8 @@ from ._key import Key | |||
| from ._receive import Receive | ||||
| from ._rendezvous import RendezvousConnector | ||||
| from ._lister import Lister | ||||
| from ._allocator import Allocator | ||||
| from ._input import Input | ||||
| from ._code import Code | ||||
| from ._terminator import Terminator | ||||
| from .errors import (ServerError, LonelyError, WrongPasswordError, | ||||
|  | @ -49,6 +51,8 @@ class Boss(object): | |||
|                                        self._reactor, self._journal, | ||||
|                                        self._tor_manager, self._timing) | ||||
|         self._L = Lister() | ||||
|         self._A = Allocator(self._timing) | ||||
|         self._I = Input(self._timing) | ||||
|         self._C = Code(self._timing) | ||||
|         self._T = Terminator() | ||||
| 
 | ||||
|  | @ -59,7 +63,9 @@ class Boss(object): | |||
|         self._K.wire(self, self._M, self._R) | ||||
|         self._R.wire(self, self._S) | ||||
|         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._T.wire(self, self._RC, self._N, self._M) | ||||
| 
 | ||||
|  | @ -189,8 +195,6 @@ class Boss(object): | |||
| 
 | ||||
|     @m.output() | ||||
|     def do_got_code(self, code): | ||||
|         nameplate = code.split("-")[0] | ||||
|         self._N.set_nameplate(nameplate) | ||||
|         self._K.got_code(code) | ||||
|         self._W.got_code(code) | ||||
|     @m.output() | ||||
|  |  | |||
|  | @ -74,13 +74,11 @@ class Code(object): | |||
|     @m.input() | ||||
|     def got_wordlist(self, wordlist): pass | ||||
| 
 | ||||
|     # from CodeInputHelper | ||||
|     # from Input | ||||
|     @m.input() | ||||
|     def update_nameplates(self): pass | ||||
|     def got_nameplate(self, nameplate): pass | ||||
|     @m.input() | ||||
|     def claim_nameplate(self, nameplate): pass | ||||
|     @m.input() | ||||
|     def submit_words(self, words): pass | ||||
|     def finished_input(self, code): pass | ||||
| 
 | ||||
|     @m.output() | ||||
|     def L_refresh_nameplates(self): | ||||
|  | @ -137,6 +135,7 @@ class Code(object): | |||
|         self._B_got_code() | ||||
| 
 | ||||
|     def _B_got_code(self): | ||||
|         self._N.set_nameplate(nameplate) XXX | ||||
|         self._B.got_code(self._code) | ||||
| 
 | ||||
|     S0A_unknown.upon(connected, enter=S0B_unknown_connected, outputs=[]) | ||||
|  |  | |||
							
								
								
									
										106
									
								
								src/wormhole/_input.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/wormhole/_input.py
									
									
									
									
									
										Normal 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 | ||||
|      | ||||
|  | @ -22,6 +22,10 @@ class ILister(Interface): | |||
|     pass | ||||
| class ICode(Interface): | ||||
|     pass | ||||
| class IInput(Interface): | ||||
|     pass | ||||
| class IAllocator(Interface): | ||||
|     pass | ||||
| class ITerminator(Interface): | ||||
|     pass | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,9 +9,9 @@ class Lister(object): | |||
|     @m.setTrace() | ||||
|     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._C = _interfaces.ICode(code) | ||||
|         self._I = _interfaces.IInput(input) | ||||
| 
 | ||||
|     # Ideally, each API request would spawn a new "list_nameplates" message | ||||
|     # 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): | ||||
|         self._RC.tx_list() | ||||
|     @m.output() | ||||
|     def C_got_nameplates(self, message): | ||||
|         self._C.got_nameplates(message["nameplates"]) | ||||
|     def I_got_nameplates(self, message): | ||||
|         self._I.got_nameplates(message["nameplates"]) | ||||
| 
 | ||||
|     S0A_idle_disconnected.upon(connected, enter=S0B_idle_connected, 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, | ||||
|                             outputs=[RC_tx_list]) | ||||
|     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(refresh_nameplates, enter=S1B_wanting_connected, | ||||
|                                outputs=[RC_tx_list]) | ||||
|     S1B_wanting_connected.upon(rx_nameplates, enter=S0B_idle_connected, | ||||
|                                outputs=[C_got_nameplates]) | ||||
|                                outputs=[I_got_nameplates]) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user