1111 abc
1212)
1313from typing import (
14- Any , Callable , Dict , Generator , List , Mapping , Optional , Sequence , Set , Tuple , Union
14+ Any , Callable , Dict , Generator , List , Mapping , MutableMapping , Optional , Sequence , Set , Tuple , Union
1515)
1616
1717import os
@@ -48,8 +48,8 @@ class TrieNode:
4848 PRESENT = True
4949
5050 def __init__ (self ):
51- self .children = defaultdict (self .__class__ )
52- self .value = self .__class__ .EMPTY
51+ self .children : MutableMapping [ str , TrieNode ] = defaultdict (self .__class__ )
52+ self .value : Any = self .__class__ .EMPTY
5353
5454
5555class Trie :
@@ -223,6 +223,8 @@ def unmark( word_composed: str ) -> str:
223223class WordIndices ( abc .Mapping ):
224224 """A Mapping which holds a Sequence of Mnemonic words.
225225
226+ The underlying Trie is built during construction, but a WordIndices Mapping is not mutable.
227+
226228 Acts like a basic { "word": index, ... } dict but with additional word flexibility.
227229
228230 Also behaves like a ["word", "word", ...] list for iteration and indexing.
@@ -244,12 +246,12 @@ class WordIndices( abc.Mapping ):
244246
245247 """
246248 def __init__ (self , sequence : Sequence [str ]):
247- """Insert a sequence of Unicode words (and optionally value(s)) into a Trie , making the
249+ """Insert a sequence of Unicode words with a value equal to the enumeration , making the
248250 "unmarked" version an alias of the regular Unicode version.
249251
250252 """
251253 self ._trie = Trie ()
252- self ._words = []
254+ self ._words : List [ str ] = []
253255 for i , word in enumerate ( sequence ):
254256 self ._words .append ( word )
255257 word_unmarked = unmark ( word )
@@ -265,14 +267,15 @@ def __init__(self, sequence: Sequence[str]):
265267 # never get a None (lose the plot) because we've just inserted 'word'! This will
266268 # "alias" each glyph with a mark, to the .children entry for the non-marked glyph.
267269 self ._trie .insert ( word_unmarked , i )
268- for c , c_un , (_ , _ , n ) in zip ( word , word_unmarked , self ._trie .find ( word )):
270+ for c , c_un , (_ , _ , n ) in zip ( word , word_unmarked , self ._trie .find ( word_unmarked )):
271+ assert n is not None
269272 if c != c_un :
270273 if c in n .children and c_un in n .children :
271274 assert n .children [c_un ] is n .children [c ], \
272- f"Attempting to alias { c_un !r} to { c !r} but already exists as a non-alias"
275+ f"Attempting to alias { c !r} to { c_un !r} but already exists as a non-alias"
273276 n .children [c ] = n .children [c_un ]
274277
275- def __getitem__ (self , key : Union [str , int ]) -> int :
278+ def __getitem__ (self , key : Union [str , int ]) -> Union [ int , str ] :
276279 """A Mapping from "word" to index, or the reverse.
277280
278281 Any unique abbreviation with/without UTF-8 "Marks" is accepted. We keep this return value
@@ -296,11 +299,11 @@ def get_details(self, key: Union[int, str]) -> Tuple[str, int, Set[str]]:
296299 # The key'th word (or IndexError)
297300 return self ._words [key ], key , set ()
298301
299- terminal , prefix , node = self ._trie .search ( key , complete = Trie )
302+ terminal , prefix , node = self ._trie .search ( key , complete = True )
300303 if not terminal :
301304 # We're nowhere in the Trie with this word
302305 raise KeyError (f"{ key !r} does not match any word" )
303-
306+ assert node is not None
304307 return self ._words [node .value ], node .value , set (node .children )
305308
306309 def __len__ (self ):
@@ -352,7 +355,7 @@ class IMnemonic(ABC):
352355 _words : int
353356 _language : str
354357 _mnemonic_type : Optional [str ]
355- _word_indices : Dict [str , int ]
358+ _word_indices : Mapping [str , int ]
356359
357360 words_list : List [int ] # The valid mnemonic length(s) available, in words
358361 languages : List [str ]
@@ -385,10 +388,11 @@ def __init__(self, mnemonic: Union[str, List[str]], **kwargs) -> None:
385388 # However, they may have been abbreviations, or had optional UTF-8 Marks removed. So, use
386389 # the _word_indices mapping twice, from str (matching word/abbrev) -> int (index) -> str
387390 # (canonical word from keys). This will work with a find_languages that returns either a
388- # WordIndices Mapping or a simple dict (but not abbreviations or missing Marks will be
389- # supported)
391+ # WordIndices Mapping or a simple dict word->index Mapping (but abbreviations or missing
392+ # Marks will not be supported)
393+ canonical_words = list (self ._word_indices )
390394 self ._mnemonic : List [str ] = [
391- self . _word_indices . keys () [self ._word_indices [word ]]
395+ canonical_words [self ._word_indices [word ]]
392396 for word in mnemonic_list
393397 ]
394398 self ._words = len (self ._mnemonic )
0 commit comments