Coverage for src/gentrie/protocols.py: 100%
8 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-08-20 09:30 -0700
« prev ^ index » next coverage.py v7.6.10, created at 2025-08-20 09:30 -0700
1# -*- coding: utf-8 -*-
2"""Protocols and type definitions for the gentrie package."""
4from collections.abc import Sequence
5from typing import Protocol, TypeAlias, runtime_checkable
8@runtime_checkable
9class TrieKeyToken(Protocol):
10 """:class:`TrieKeyToken` is a protocol that defines key tokens that are usable with a :class:`GeneralizedTrie`.
12 The protocol requires that a token object be *hashable*. This means that it
13 implements both an ``__eq__()`` method and a ``__hash__()`` method.
15 Some examples of built-in types that are suitable for use as tokens in a key:
17 * :class:`str`
18 * :class:`bytes`
19 * :class:`int`
20 * :class:`float`
21 * :class:`complex`
22 * :class:`frozenset`
23 * :class:`tuple`
24 * :class:`None`
26 Note: frozensets and tuples are only hashable *if their contents are hashable*.
28 Usage:
30 .. code-block:: python
31 :linenos:
33 from gentrie import TrieKeyToken
35 token = SomeTokenClass()
36 if isinstance(token, TrieKeyToken):
37 print("supports the TrieKeyToken protocol")
38 else:
39 print("does not support the TrieKeyToken protocol")
41 .. warning:: **Using User Defined Classes As Tokens In Keys**
43 User-defined classes are hashable by default, but you should implement the
44 ``__eq__()`` and ``__hash__()`` dunder methods in a content-aware way (the hash and eq values
45 must depend on the content of the object) if you want to use them as tokens in a key. The default
46 implementation of ``__eq__()`` and ``__hash__()`` uses the memory address of the object, which
47 means that two different instances of the same class will not be considered equal.
49 """
50 def __eq__(self, value: object, /) -> bool: ...
52 def __hash__(self) -> int: ...
55@runtime_checkable
56class Hashable(TrieKeyToken, Protocol):
57 """The Hashable protocol is deprecated and will be removed in a future version.
59 This protocol is a sub-class of :class:`TrieKeyToken` and is only provided for backward compatibility.
61 Use :class:`TrieKeyToken` instead.
62 """
63 def __eq__(self, value: object, /) -> bool: ...
65 def __hash__(self) -> int: ...
68GeneralizedKey: TypeAlias = Sequence[TrieKeyToken]
69"""A :class:`GeneralizedKey` is an object of any class that is a :class:`Sequence` and
70that when iterated returns tokens conforming to the :class:`TrieKeyToken` protocol.
73.. warning:: **Keys Must Be Immutable**
75 Once a key is added to the trie, neither the key sequence itself nor any of its
76 constituent tokens should be mutated. Modifying a key after it has been added
77 can corrupt the internal state of the trie, leading to unpredictable behavior
78 and making entries unreachable. The trie does not create a deep copy of keys
79 for performance reasons.
81 If you need to modify a key, you should remove the old key and add a new one
82 with the modified value.
84**Examples of valid :class:`GeneralizedKey` types**
86* :class:`str`
87* :class:`bytes`
88* :class:`list[bool]`
89* :class:`list[int]`
90* :class:`list[bytes]`
91* :class:`list[str]`
92* :class:`list[Optional[str]]`
93* :class:`tuple[int, int, str]`
95"""