• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pymorphy2-fork / DAWG-Python / 13091030656

01 Feb 2025 05:55PM CUT coverage: 87.367%. Remained the same
13091030656

Pull #40

github

web-flow
Merge 0379cc6a7 into daced09a2
Pull Request #40: Bump ruff from 0.8.4 to 0.9.4 in the dev-dependencies group

166 of 214 branches covered (77.57%)

Branch coverage included in aggregate %.

657 of 728 relevant lines covered (90.25%)

5.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.42
/dawg_python/wrapper.py
1
import array
6✔
2
import struct
6✔
3

4
from . import units
6✔
5

6

7
class Dictionary:
6✔
8
    """
9
    Dictionary class for retrieval and binary I/O.
10
    """
11

12
    def __init__(self) -> None:
6✔
13
        self._units = array.array("I")
6✔
14

15
    ROOT = 0
6✔
16
    "Root index"
4✔
17

18
    def has_value(self, index):
6✔
19
        """Checks if a given index is related to the end of a key."""
20
        return units.has_leaf(self._units[index])
6✔
21

22
    def value(self, index):
6✔
23
        """Gets a value from a given index."""
24
        offset = units.offset(self._units[index])
6✔
25
        value_index = (index ^ offset) & units.PRECISION_MASK
6✔
26
        return units.value(self._units[value_index])
6✔
27

28
    def read(self, fp) -> None:
6✔
29
        """Reads a dictionary from an input stream."""
30
        base_size = struct.unpack("=I", fp.read(4))[0]
6✔
31
        self._units.fromfile(fp, base_size)
6✔
32

33
    def contains(self, key):
6✔
34
        """Exact matching."""
35
        index = self.follow_bytes(key, self.ROOT)
6✔
36
        if index is None:
6✔
37
            return False
6✔
38
        return self.has_value(index)
6✔
39

40
    def find(self, key):
6✔
41
        """Exact matching (returns value)"""
42
        index = self.follow_bytes(key, self.ROOT)
6✔
43
        if index is None:
6!
44
            return -1
×
45
        if not self.has_value(index):
6✔
46
            return -1
6✔
47
        return self.value(index)
6✔
48

49
    def follow_char(self, label, index):
6✔
50
        """Follows a transition"""
51
        offset = units.offset(self._units[index])
6✔
52
        next_index = (index ^ offset ^ label) & units.PRECISION_MASK
6✔
53

54
        if units.label(self._units[next_index]) != label:
6✔
55
            return None
6✔
56

57
        return next_index
6✔
58

59
    def follow_bytes(self, s, index):
6✔
60
        """Follows transitions."""
61
        for ch in s:
6✔
62
            index = self.follow_char(ch, index)
6✔
63
            if index is None:
6✔
64
                return None
6✔
65

66
        return index
6✔
67

68
    @classmethod
6✔
69
    def load(cls, path):
6✔
70
        dawg = cls()
6✔
71
        with open(path, "rb") as f:
6✔
72
            dawg.read(f)
6✔
73
        return dawg
6✔
74

75

76
class Guide:
6✔
77

78
    ROOT = 0
6✔
79

80
    def __init__(self) -> None:
6✔
81
        self._units = array.array("B")
6✔
82

83
    def child(self, index):
6✔
84
        return self._units[index * 2]
6✔
85

86
    def sibling(self, index):
6✔
87
        return self._units[index * 2 + 1]
6✔
88

89
    def read(self, fp) -> None:
6✔
90
        base_size = struct.unpack("=I", fp.read(4))[0]
6✔
91
        self._units.fromfile(fp, base_size * 2)
6✔
92

93
    def size(self):
6✔
94
        return len(self._units)
6✔
95

96

97
class Completer:
6✔
98
    def __init__(self, dic=None, guide=None) -> None:
6✔
99
        self._dic = dic
6✔
100
        self._guide = guide
6✔
101

102
    def value(self):
6✔
103
        return self._dic.value(self._last_index)
6✔
104

105
    def start(self, index, prefix=b"") -> None:
6✔
106
        self.key = bytearray(prefix)
6✔
107

108
        if self._guide.size():
6✔
109
            self._index_stack = [index]
6✔
110
            self._last_index = self._dic.ROOT
6✔
111
        else:
112
            self._index_stack = []
6✔
113

114
    def next(self):
6✔
115
        "Gets the next key"
116

117
        if not self._index_stack:
6✔
118
            return False
6✔
119

120
        index = self._index_stack[-1]
6✔
121

122
        if self._last_index != self._dic.ROOT:
6✔
123

124
            child_label = self._guide.child(index)  # UCharType
6✔
125

126
            if child_label:
6✔
127
                # Follows a transition to the first child.
128
                index = self._follow(child_label, index)
6✔
129
                if index is None:
6!
130
                    return False
×
131
            else:
132
                while True:
4✔
133
                    sibling_label = self._guide.sibling(index)
6✔
134
                    # Moves to the previous node.
135
                    if len(self.key) > 0:
6✔
136
                        self.key.pop()
6✔
137

138
                    self._index_stack.pop()
6✔
139
                    if not self._index_stack:
6✔
140
                        return False
6✔
141

142
                    index = self._index_stack[-1]
6✔
143
                    if sibling_label:
6✔
144
                        # Follows a transition to the next sibling.
145
                        index = self._follow(sibling_label, index)
6✔
146
                        if index is None:
6!
147
                            return False
×
148
                        break
4✔
149

150
        return self._find_terminal(index)
6✔
151

152
    def _follow(self, label, index):
6✔
153
        next_index = self._dic.follow_char(label, index)
6✔
154
        if next_index is None:
6!
155
            return None
×
156

157
        self.key.append(label)
6✔
158
        self._index_stack.append(next_index)
6✔
159
        return next_index
6✔
160

161
    def _find_terminal(self, index) -> bool:
6✔
162
        while not self._dic.has_value(index):
6✔
163
            label = self._guide.child(index)
6✔
164

165
            index = self._dic.follow_char(label, index)
6✔
166
            if index is None:
6!
167
                return False
×
168

169
            self.key.append(label)
6✔
170
            self._index_stack.append(index)
6✔
171

172
        self._last_index = index
6✔
173
        return True
6✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc