Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow higher priority dictionaries to delete entries from others #1160

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news.d/feature/1160.core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow higher priority dictionaries to delete entries from others.
26 changes: 22 additions & 4 deletions plover/steno_dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,13 @@ def longest_key(self):
def set_dicts(self, dicts):
self.dicts = dicts[:]

def _lookup(self, key, dicts=None, filters=()):
def _lookup_keep_deleted(self, key, dicts=None, filters=()):
"""
Lookup a key in the given dicts.
If key appears in none of the dicts, return None.
If key appears in some dicts but with "{plover:deleted}" as value,
return "{plover:deleted}".
"""
if dicts is None:
dicts = self.dicts
key_len = len(key)
Expand All @@ -190,14 +196,26 @@ def _lookup(self, key, dicts=None, filters=()):
if key_len > d.longest_key:
continue
value = d.get(key)
if value:
if value is not None:
if not any(f(key, value) for f in filters):
return value

def _lookup(self, key, dicts=None, filters=()):
"""
Same as _lookup_keep_deleted, but if key appears in some dicts
but with "{plover:deleted}" as value (case-insensitive),
return None instead.
"""
result = self._lookup_keep_deleted(key, dicts, filters)
if result is None or result.lower() == "{plover:deleted}":
return None
return result

def _lookup_from_all(self, key, dicts=None, filters=()):
''' Key lookup from all dictionaries

Returns list of (value, dictionary) tuples
Returns list of (value, dictionary) tuples.
Entries with value "{plover:deleted}" are kept.
'''
if dicts is None:
dicts = self.dicts
Expand Down Expand Up @@ -241,7 +259,7 @@ def reverse_lookup(self, value):
continue
# Ignore key if it's overridden by a higher priority dictionary.
keys.update(k for k in d.reverse_lookup(value)
if self._lookup(k, dicts=self.dicts[:n]) is None)
if self._lookup_keep_deleted(k, dicts=self.dicts[:n]) is None)
return keys

def casereverse_lookup(self, value):
Expand Down
8 changes: 8 additions & 0 deletions test/test_steno_dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,26 @@ def test_dictionary_collection():
d1 = StenoDictionary()
d1[('S',)] = 'a'
d1[('T',)] = 'b'
d1[('H',)] = '{PLOVER:deleted}'
d1[('R',)] = 'e'
d1.path = 'd1'
d2 = StenoDictionary()
d2[('S',)] = 'c'
d2[('W',)] = 'd'
d2[('H',)] = 'f'
d2[('R',)] = '{plover:deleted}'
d2.path = 'd2'
dc = StenoDictionaryCollection([d2, d1])
assert dc.lookup(('S',)) == 'c'
assert dc.lookup(('W',)) == 'd'
assert dc.lookup(('T',)) == 'b'
assert dc.lookup(('H',)) == 'f'
assert dc.lookup(('R',)) == None
assert dc.lookup_from_all(('S',)) == [('c', d2), ('a', d1)]
assert dc.lookup_from_all(('W',)) == [('d', d2)]
assert dc.lookup_from_all(('T',)) == [('b', d1)]
assert dc.lookup_from_all(('H',)) == [('f', d2), ('{PLOVER:deleted}', d1)]
assert dc.lookup_from_all(('R',)) == [('{plover:deleted}', d2), ('e', d1)]
f = lambda k, v: v == 'c'
dc.add_filter(f)
assert dc.lookup(('S',)) == 'a'
Expand Down