|
1 | 1 | import re |
| 2 | +from functools import lru_cache |
2 | 3 |
|
3 | 4 | from .reserved_words import get_reserved_words |
4 | 5 |
|
|
17 | 18 | ) |
18 | 19 |
|
19 | 20 |
|
| 21 | +@lru_cache(maxsize=1) |
| 22 | +def _get_cached_reserved_words(): |
| 23 | + """Cache reserved words to avoid repeated file I/O.""" |
| 24 | + return get_reserved_words() |
| 25 | + |
| 26 | + |
20 | 27 | def is_safe_username( |
21 | 28 | username: str, whitelist=None, blacklist=None, regex=username_regex, max_length=None |
22 | 29 | ) -> bool: |
23 | | - # check for max length |
| 30 | + # check for max length (fastest check first) |
24 | 31 | if max_length and len(username) > max_length: |
25 | 32 | return False |
26 | 33 |
|
27 | 34 | # check against provided regex |
28 | | - if not re.match(regex, username): |
| 35 | + if not regex.match(username): |
29 | 36 | return False |
30 | 37 |
|
31 | | - # ensure the word is not in the blacklist and is not a reserved word |
32 | | - if whitelist is None: |
33 | | - whitelist = [] |
| 38 | + username_lower = username.lower() |
34 | 39 |
|
35 | | - if blacklist is None: |
36 | | - blacklist = [] |
| 40 | + # Fast path: no custom lists |
| 41 | + if not whitelist and not blacklist: |
| 42 | + return username_lower not in _get_cached_reserved_words() |
37 | 43 |
|
38 | | - default_words = get_reserved_words() |
| 44 | + # Start with reserved words |
| 45 | + forbidden = _get_cached_reserved_words().copy() |
39 | 46 |
|
40 | | - whitelist = set( |
41 | | - [each_whitelisted_name.lower() for each_whitelisted_name in whitelist] |
42 | | - ) |
43 | | - blacklist = set( |
44 | | - [each_blacklisted_name.lower() for each_blacklisted_name in blacklist] |
45 | | - ) |
| 47 | + # Apply whitelist (remove from forbidden) |
| 48 | + if whitelist: |
| 49 | + whitelist_set = {w.lower() for w in whitelist} |
| 50 | + forbidden -= whitelist_set |
46 | 51 |
|
47 | | - default_words = default_words - whitelist |
48 | | - default_words = default_words.union(blacklist) |
| 52 | + # Apply blacklist (add to forbidden) |
| 53 | + if blacklist: |
| 54 | + blacklist_set = {w.lower() for w in blacklist} |
| 55 | + forbidden |= blacklist_set |
49 | 56 |
|
50 | | - return False if username.lower() in default_words else True |
| 57 | + return username_lower not in forbidden |
0 commit comments