diff --git a/examples/assigning_values_to_entries.py b/examples/assigning_values_to_entries.py old mode 100644 new mode 100755 index 31d34da..6da733f --- a/examples/assigning_values_to_entries.py +++ b/examples/assigning_values_to_entries.py @@ -68,9 +68,9 @@ You can also retrieve all entries that are prefixes for or prefixed by a given key: -- `trie.prefixed_by(key)` returns a set of `TrieEntry` objects that +- `trie.prefixed_by(key)` returns an Iterator of `TrieEntry` objects that are prefixed_by of the given key. -- `trie.prefixes(key)` returns a set of `TrieEntry` objects that +- `trie.prefixes(key)` returns an Iterator of `TrieEntry` objects that are prefixes of the given key. These methods are useful for searching and retrieving entries @@ -81,7 +81,7 @@ trie = GeneralizedTrie() # Adding entries using the trie[key] = value syntax -entries: list[tuple[str, str | list[str]]] = [ +entries = [ ('abcdef', 'value1'), ('abc', 'value2'), ('abcd', 'value3'), @@ -89,13 +89,14 @@ ('xyz', ['lists', 'are', 'also', 'supported']), ('xy', 'value6'), ] + for key, value in entries: trie[key] = value -prefixed_by: set[TrieEntry] = set(trie.prefixed_by('xy')) +prefixed_by: list[TrieEntry] = list(trie.prefixed_by('xy')) print(f'prefixed_by = {prefixed_by}') -prefixes: set[TrieEntry] = set(trie.prefixes('abcdefg')) +prefixes: list[TrieEntry] = list(trie.prefixes('abcdefg')) print(f'prefixes = {prefixes}') # prefixed_by = { @@ -111,22 +112,22 @@ # Adding using the add method # This will throw an error if the key already exists. -more_entries: list[tuple[str | tuple[int, ...], str]] = [ +more_entries = [ ((128, 96, 160, 0), 'value5'), ((128, 90), 'value5b'), ('xy', 'value6'), ] -for key, value in more_entries: +for different_key, different_value in more_entries: try: - trie.add(key, value) - print(f'Added entry: {key} -> {value}') + trie.add(different_key, different_value) + print(f'Added entry: {different_key} -> {different_value}') except DuplicateKeyError: - print(f'DuplicateKeyError - entry already exists: {key}') + print(f'DuplicateKeyError - entry already exists: {different_key}') -prefixed_by: set[TrieEntry] = set(trie.prefixed_by([128])) +prefixed_by = list(trie.prefixed_by([128])) print(f'prefixed_by = {prefixed_by}') -prefixes: set[TrieEntry] = set(trie.prefixes([128, 90])) +prefixes = list(trie.prefixes([128, 90])) print(f'prefixes = {prefixes}') # prefixed_by = { @@ -149,20 +150,26 @@ for key, value in even_more_entries: trie.update(key, value) -prefixed_by = set(trie.prefixed_by('abcd')) +prefixed_by = list(trie.prefixed_by('abcd')) print(f'prefixed_by = {prefixed_by}') -prefixes = set(trie.prefixes('abcdefg')) +prefixes = list(trie.prefixes('abcdefg')) print(f'prefixes = {prefixes}') -# prefixed_by = { -# TrieEntry(ident=3, key='abcd', value='value8'), -# TrieEntry(ident=9, key='abcdefghi', value='value7'), -# TrieEntry(ident=1, key='abcdef', value='value1') -# } -# -# prefixes = { -# TrieEntry(ident=2, key='abc', value='value2'), -# TrieEntry(ident=3, key='abcd', value='value8'), -# TrieEntry(ident=1, key='abcdef', value='value1') -# } +# prefixed_by = [TrieEntry(ident=TrieId(6), key='xy', value='value6'), +# TrieEntry(ident=TrieId(5), key='xyz', value=['lists', 'are', 'also', 'supported'])] +# prefixes = [TrieEntry(ident=TrieId(2), key='abc', value='value2'), +# TrieEntry(ident=TrieId(3), key='abcd', value='value3'), +# TrieEntry(ident=TrieId(1), key='abcdef', value='value1')] +# Added entry: (128, 96, 160, 0) -> value5 +# Added entry: (128, 90) -> value5b +# DuplicateKeyError - entry already exists: xy +# prefixed_by = [TrieEntry(ident=TrieId(8), key=(128, 90), value='value5b'), +# TrieEntry(ident=TrieId(7), key=(128, 96, 160, 0), value='value5')] +# prefixes = [TrieEntry(ident=TrieId(8), key=(128, 90), value='value5b')] +# prefixed_by = [TrieEntry(ident=TrieId(3), key='abcd', value='value8'), +# TrieEntry(ident=TrieId(1), key='abcdef', value='value1'), +# TrieEntry(ident=TrieId(9), key='abcdefghi', value='value7')] +# prefixes = [TrieEntry(ident=TrieId(2), key='abc', value='value2'), +# TrieEntry(ident=TrieId(3), key='abcd', value='value8'), +# TrieEntry(ident=TrieId(1), key='abcdef', value='value1')] diff --git a/examples/prefixed_by_example.py b/examples/prefixed_by_example.py index 1dca1d9..f058836 100755 --- a/examples/prefixed_by_example.py +++ b/examples/prefixed_by_example.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 """Example of using a GeneralizedTrie for indexing sequences of strings.""" -from typing import Generator +from typing import Iterator from gentrie import GeneralizedTrie, TrieEntry trie = GeneralizedTrie() keys: list[str] = ['abcdef', 'abc', 'a', 'abcd', 'qrs'] for entry in keys: trie.add(entry) -matches: Generator[TrieEntry, None, None] = trie.prefixed_by('abcd') +matches: Iterator[TrieEntry] = trie.prefixed_by('abcd') for trie_entry in sorted(list(matches)): print(f'{trie_entry.ident}: {trie_entry.key}') diff --git a/examples/prefixes_example.py b/examples/prefixes_example.py index a6088ef..dababff 100755 --- a/examples/prefixes_example.py +++ b/examples/prefixes_example.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Example of using prefixes() method""" -from typing import Generator +from typing import Iterator from gentrie import GeneralizedTrie, TrieEntry @@ -8,7 +8,7 @@ keys: list[str] = ['abcdef', 'abc', 'a', 'abcd', 'qrs'] for entry in keys: trie.add(entry) -matches: Generator[TrieEntry, None, None] = trie.prefixes('abcd') +matches: Iterator[TrieEntry] = trie.prefixes('abcd') for trie_entry in sorted(list(matches)): print(f'{trie_entry.ident}: {trie_entry.key}') diff --git a/examples/url_suffixes.py b/examples/url_suffixes.py index b3a21f4..8c6fff3 100755 --- a/examples/url_suffixes.py +++ b/examples/url_suffixes.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Example of using a GeneralizedTrie for indexing website URLs by path""" -from typing import Generator +from typing import Iterator from gentrie import GeneralizedTrie, TrieEntry @@ -17,13 +17,13 @@ # Find https URLs with "example.com" domain or sub-domain print("HTTPS URLs for domains or sub-domains of 'example.com'") -prefixed_by: Generator[TrieEntry, None, None] = url_trie.prefixed_by(["https", ":", "//", "com", "example"]) +prefixed_by: Iterator[TrieEntry] = url_trie.prefixed_by(["https", ":", "//", "com", "example"]) for entry in prefixed_by: print(f"Found URL: {entry.value}") # Find ftp protocol URLs print("FTP URLs") -prefixed_by: Generator[TrieEntry, None, None] = url_trie.prefixed_by(["ftp"]) +prefixed_by = url_trie.prefixed_by(["ftp"]) for entry in prefixed_by: print(f"Found URL: {entry.value}") diff --git a/src/gentrie/types.py b/src/gentrie/types.py index b7dd6e0..89764ad 100644 --- a/src/gentrie/types.py +++ b/src/gentrie/types.py @@ -49,4 +49,5 @@ def __eq__(self, other: object) -> bool: other.key) and self.value == other.value def __hash__(self) -> int: + print(f'Hashing TrieEntry: ident={self.ident}, key={self.key}, value={self.value}') return hash((self.ident, tuple(self.key), self.value)) # pyright: ignore[reportUnknownArgumentType] diff --git a/tests/gentrie/test_gentri.py b/tests/gentrie/test_gentri.py index e2b605a..7ac61cd 100755 --- a/tests/gentrie/test_gentri.py +++ b/tests/gentrie/test_gentri.py @@ -1420,6 +1420,25 @@ def test_prefixed_by(self) -> None: ] run_tests_list(self, tests) + # New untouched trie for the next sequence of tests + # Not using clear() here to keep the clear() tests cleanly separated + # from the prefixed_by() tests. + trie = GeneralizedTrie() + entries = [ + ('abcdef', 'value1'), + ('abc', 'value2'), + ('abcd', 'value3'), + ('qrf', 'value4'), + ('xyz', ['lists', 'are', 'also', 'supported']), + ('xy', 'value6'), + ] + for key, value in entries: + trie.add(key, value) + with self.subTest(msg='[TGT_TPB013] trie.prefixed_by("xy")'): + expected = tuple([trie['xy'], trie['xyz']]) + found = tuple(trie.prefixed_by('xy')) + self.assertEqual(expected, found, msg=f'Expected {expected}, found {found}') + @pytest.mark.order(after=['test_create_trie', 'test_add', 'test_trieid_class', 'test_contains_dunder']) @pytest.mark.dependency( name='test_deeply_nested_keys',