Skip to content

Commit 7c4ef18

Browse files
committed
Make instantiation fast when using the default alphabet and blocklist
1 parent 5452169 commit 7c4ef18

File tree

4 files changed

+742
-27
lines changed

4 files changed

+742
-27
lines changed

assets/filter_blocklist.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import pathlib
2+
import sys
3+
from typing import Set, Tuple
4+
5+
6+
repo_root = pathlib.Path(__file__).parent.parent
7+
this_file = pathlib.Path(__file__).relative_to(repo_root)
8+
constants_path = repo_root / "sqids/constants.py"
9+
import sqids.constants # noqa
10+
11+
12+
DIGITS = set("0123456789")
13+
14+
15+
def filter_blocklist() -> Tuple[Set[str], Set[str], Set[str]]:
16+
"""Pre-filter the blocklist and update the constants file."""
17+
18+
exact_match = set()
19+
match_at_ends = set()
20+
match_anywhere = set()
21+
22+
for word in sqids.constants.DEFAULT_BLOCKLIST:
23+
if len(word) == 3:
24+
exact_match.add(word)
25+
elif set(word) & DIGITS:
26+
match_at_ends.add(word)
27+
else:
28+
match_anywhere.add(word)
29+
30+
return exact_match, match_at_ends, match_anywhere
31+
32+
33+
def generate_new_constants_file(
34+
exact_match: Set[str],
35+
match_at_ends: Set[str],
36+
match_anywhere: Set[str],
37+
) -> str:
38+
"""Generate the text of a new constants file."""
39+
40+
lines = [
41+
f'DEFAULT_ALPHABET = "{sqids.constants.DEFAULT_ALPHABET}"',
42+
f"DEFAULT_MIN_LENGTH = {sqids.constants.DEFAULT_MIN_LENGTH}",
43+
"",
44+
"# =======",
45+
"# NOTE",
46+
"# =======",
47+
"#",
48+
f"# When updating the blocklist, run {this_file} to pre-filter constants.",
49+
"# This is critical for performance.",
50+
"#",
51+
"",
52+
"DEFAULT_BLOCKLIST = [",
53+
]
54+
# Output a sorted blocklist.
55+
for word in sorted(sqids.constants.DEFAULT_BLOCKLIST):
56+
lines.append(f' "{word}",')
57+
lines.append("]")
58+
59+
# Output exact-match blocklist words.
60+
lines.append("")
61+
lines.append("_exact_match = {")
62+
for word in sorted(exact_match):
63+
lines.append(f' "{word}",')
64+
lines.append("}")
65+
66+
# Output match-at-ends blocklist words.
67+
lines.append("")
68+
lines.append("_match_at_ends = (")
69+
for word in sorted(match_at_ends):
70+
lines.append(f' "{word}",')
71+
lines.append(")")
72+
73+
# Output match-anywhere blocklist words.
74+
lines.append("")
75+
lines.append("_match_anywhere = {")
76+
for word in sorted(match_anywhere):
77+
lines.append(f' "{word}",')
78+
lines.append("}")
79+
80+
return "\n".join(lines).rstrip() + "\n" # Include a trailing newline.
81+
82+
83+
def main() -> int:
84+
text = constants_path.read_text()
85+
86+
exact_match, match_at_ends, match_anywhere = filter_blocklist()
87+
new_text = generate_new_constants_file(exact_match, match_at_ends, match_anywhere)
88+
89+
if text == new_text:
90+
print("No changes necessary")
91+
return 0
92+
93+
print(f"Updating {constants_path.relative_to(repo_root)}")
94+
constants_path.write_text(new_text, newline="\n", encoding="utf-8")
95+
return 1
96+
97+
98+
if __name__ == "__main__":
99+
sys.exit(main())

0 commit comments

Comments
 (0)