Skip to content

Commit 031c6f5

Browse files
committed
Refactor CharClass and BackReference to improve type hints and clarity; update version to 0.9.5
1 parent af4cb0a commit 031c6f5

File tree

4 files changed

+23
-10
lines changed

4 files changed

+23
-10
lines changed

regex_enumerator/regex_parser.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def _parseRegex(self, to_close: bool) -> RegexTree:
9393
chars = self._parseEscapeChar()
9494
min_len, max_len = self._parseQuantifier()
9595
elements.append(
96-
CharClass(chars, min_len, max_len, self.precompute))
96+
CharClass([chars], min_len, max_len, self.precompute))
9797
continue
9898
if isinstance(reference, str):
9999
if reference not in named_groups:
@@ -257,7 +257,7 @@ def _parseCharClass(self) -> list[str]:
257257

258258
return chars_list
259259

260-
def _parseQuantifier(self) -> tuple[int, int]:
260+
def _parseQuantifier(self) -> tuple[int, int | None]:
261261

262262
if len(self.regex) <= self.index:
263263
return 1, 1

regex_enumerator/regex_tree.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class RegexTree:
33

44

55
class CharClass:
6-
def __init__(self, chars_list: list[str], min_len: int, max_len: int, precompute: bool):
6+
def __init__(self, chars_list: list[str], min_len: int, max_len: int | None, precompute: bool):
77
self._index = 0
88
self._precompute = precompute and max_len is not None
99
self._chars: str = ''.join(sorted(set(''.join(chars_list))))
@@ -33,7 +33,7 @@ def _compute_all(self) -> list[str]:
3333
result = []
3434
for i in range(self._min_len, self._max_len + 1):
3535
temp = ['']
36-
for j in range(i):
36+
for _ in range(i):
3737
temp = [pfx + sfx for pfx in self._chars for sfx in temp]
3838
result.extend(temp)
3939
return result
@@ -96,8 +96,7 @@ def __init__(self, reference: RegexTree, min_len: int, max_len: int | None, prec
9696
self.reference: RegexTree = reference
9797
self.done = max_len == 0 or (
9898
reference.done and len(reference.current) == 0)
99-
self.current: dict[str, list[str]
100-
] = self._calculate() if not self.done else {}
99+
self.current: dict[str, list[str]] = self._calculate() if not self.done else {}
101100

102101
def update_reference(self, new_strings: set[str]) -> None:
103102
if self._max_len is not None and self._min_len + self._index >= self._max_len and self.reference.done:
@@ -108,7 +107,7 @@ def update_reference(self, new_strings: set[str]) -> None:
108107
self.current[string] = [
109108
string * i for i in range(self._min_len, self._min_len + self._index + 1)]
110109

111-
def _calculate(self) -> dict[str, set[str]]:
110+
def _calculate(self) -> dict[str, list[str]]:
112111
current_ref = self.reference.current
113112
if self._max_len is not None and self._min_len + self._index >= self._max_len:
114113
self.done = True
@@ -121,7 +120,7 @@ def _calculate(self) -> dict[str, set[str]]:
121120

122121
return result
123122

124-
def next(self) -> dict[str, set[str]]:
123+
def next(self) -> dict[str, list[str]]:
125124
assert not self.done
126125
self._index += 1
127126
if self._max_len is not None and self._min_len + self._index >= self._max_len:
@@ -270,7 +269,7 @@ def _calculate_first(self) -> set[str]:
270269

271270
return result
272271

273-
def add_reference(self, reference: BackReference):
272+
def add_reference(self, reference: BackReference) -> None:
274273
if reference.done and len(reference.current) == 0:
275274
return
276275
self.references.append(reference)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name='regex_enumerator',
8-
version='0.9.4',
8+
version='0.9.5',
99
packages=find_packages(include=['regex_enumerator', 'regex_enumerator.*']),
1010
description='Enumerate all strings that match a given regex',
1111
author='Vincenzo Greco',

tests/test_mixed.py

+14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def test_done():
3131

3232
f_finite(regex, possibilities)
3333

34+
3435
def test_empty_additional_charset():
3536
regexEnumerator = RegexEnumerator(r'')
3637
assert regexEnumerator.next() == ''
@@ -63,3 +64,16 @@ def test_weak_password():
6364
l_char + o + v + e + y + year + special_1 + special_2)
6465

6566
f_finite(regex, possibilities)
67+
68+
69+
def test_complete_regex():
70+
regex = r'[Ll]([Uu])?\1{0,2}(0|1){0,3}[!1.]'
71+
possibilities = []
72+
73+
for l_char in 'Ll':
74+
for u in ['U', 'UU', 'UUU', 'u', 'uu', 'uuu', '']:
75+
for num in ['0', '1', '00', '01', '10', '11', '000', '001', '010', '011', '100', '101', '110', '111', '']:
76+
for special in ['!', '1', '.']:
77+
possibilities.append(l_char + u + num + special)
78+
79+
f_finite(regex, possibilities)

0 commit comments

Comments
 (0)