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

1# -*- coding: utf-8 -*- 

2"""Protocols and type definitions for the gentrie package.""" 

3 

4from collections.abc import Sequence 

5from typing import Protocol, TypeAlias, runtime_checkable 

6 

7 

8@runtime_checkable 

9class TrieKeyToken(Protocol): 

10 """:class:`TrieKeyToken` is a protocol that defines key tokens that are usable with a :class:`GeneralizedTrie`. 

11 

12 The protocol requires that a token object be *hashable*. This means that it 

13 implements both an ``__eq__()`` method and a ``__hash__()`` method. 

14 

15 Some examples of built-in types that are suitable for use as tokens in a key: 

16 

17 * :class:`str` 

18 * :class:`bytes` 

19 * :class:`int` 

20 * :class:`float` 

21 * :class:`complex` 

22 * :class:`frozenset` 

23 * :class:`tuple` 

24 * :class:`None` 

25 

26 Note: frozensets and tuples are only hashable *if their contents are hashable*. 

27 

28 Usage: 

29 

30 .. code-block:: python 

31 :linenos: 

32 

33 from gentrie import TrieKeyToken 

34 

35 token = SomeTokenClass() 

36 if isinstance(token, TrieKeyToken): 

37 print("supports the TrieKeyToken protocol") 

38 else: 

39 print("does not support the TrieKeyToken protocol") 

40 

41 .. warning:: **Using User Defined Classes As Tokens In Keys** 

42 

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. 

48 

49 """ 

50 def __eq__(self, value: object, /) -> bool: ... 

51 

52 def __hash__(self) -> int: ... 

53 

54 

55@runtime_checkable 

56class Hashable(TrieKeyToken, Protocol): 

57 """The Hashable protocol is deprecated and will be removed in a future version. 

58 

59 This protocol is a sub-class of :class:`TrieKeyToken` and is only provided for backward compatibility. 

60 

61 Use :class:`TrieKeyToken` instead. 

62 """ 

63 def __eq__(self, value: object, /) -> bool: ... 

64 

65 def __hash__(self) -> int: ... 

66 

67 

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. 

71 

72 

73.. warning:: **Keys Must Be Immutable** 

74 

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. 

80 

81 If you need to modify a key, you should remove the old key and add a new one 

82 with the modified value. 

83 

84**Examples of valid :class:`GeneralizedKey` types** 

85 

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]` 

94 

95"""