Skip to content

Commit 678c231

Browse files
authored
Add types for zxcvbn (#8089)
1 parent 7ee3b56 commit 678c231

8 files changed

+202
-0
lines changed

stubs/zxcvbn/METADATA.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
version = "4.4.*"

stubs/zxcvbn/zxcvbn/__init__.pyi

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import datetime
2+
from collections.abc import Iterable
3+
from decimal import Decimal
4+
from typing_extensions import TypedDict
5+
6+
from .feedback import _Feedback
7+
from .matching import _Match
8+
from .time_estimates import _TimeEstimate
9+
10+
class _Result(_TimeEstimate, TypedDict):
11+
password: str
12+
guesses: Decimal
13+
guesses_log10: float
14+
sequence: list[_Match]
15+
calc_time: datetime.timedelta
16+
feedback: _Feedback
17+
18+
def zxcvbn(password: str, user_inputs: Iterable[object] | None = ...) -> _Result: ...
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from typing_extensions import TypeAlias
2+
3+
_Graph: TypeAlias = dict[str, list[str | None]]
4+
5+
ADJACENCY_GRAPHS: dict[str, _Graph]

stubs/zxcvbn/zxcvbn/feedback.pyi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from collections.abc import Sequence
2+
from typing_extensions import Literal, TypedDict
3+
4+
from .matching import _Match
5+
6+
class _Feedback(TypedDict):
7+
warning: str
8+
suggestions: list[str]
9+
10+
def get_feedback(score: Literal[0, 1, 2, 3, 4], sequence: Sequence[_Match]) -> _Feedback: ...
11+
def get_match_feedback(match: _Match, is_sole_match: bool) -> _Feedback: ...
12+
def get_dictionary_match_feedback(match: _Match, is_sole_match: bool) -> _Feedback: ...
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FREQUENCY_LISTS: dict[str, list[str]]

stubs/zxcvbn/zxcvbn/matching.pyi

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from collections.abc import Iterable, Mapping
2+
from decimal import Decimal
3+
from typing import Any, Pattern
4+
from typing_extensions import Literal, NotRequired, TypedDict
5+
6+
from .adjacency_graphs import _Graph
7+
8+
class _Match(TypedDict):
9+
pattern: Literal["dictionary", "spatial", "repeat", "sequence", "regex", "date"]
10+
token: str
11+
i: int
12+
j: int
13+
guesses: NotRequired[int] # all patterns except 'date'
14+
guesses_log10: NotRequired[float] # all patterns except 'date'
15+
16+
# pattern == 'date'
17+
separator: NotRequired[str]
18+
year: NotRequired[int]
19+
month: NotRequired[int]
20+
day: NotRequired[int]
21+
22+
# pattern == 'dictionary'
23+
matched_word: NotRequired[str]
24+
dictionary_name: NotRequired[str]
25+
l33t: NotRequired[bool]
26+
reversed: NotRequired[bool]
27+
rank: NotRequired[int]
28+
base_guesses: NotRequired[int | Decimal] # Decimal for 'repeat', see below
29+
uppercase_variations: NotRequired[int]
30+
l33t_variations: NotRequired[int]
31+
32+
# pattern == 'spatial'
33+
turns: NotRequired[int]
34+
35+
# pattern == 'repeat'
36+
base_token: NotRequired[str]
37+
# base_guesses: NotRequired[Decimal]
38+
base_matches: NotRequired[list[Any]] # Any = _Match, https://github.com/python/mypy/issues/731
39+
repeat_count: NotRequired[float]
40+
41+
# pattern == 'regex'
42+
regex_name: NotRequired[str]
43+
44+
def build_ranked_dict(ordered_list: Iterable[str]) -> dict[str, int]: ...
45+
46+
RANKED_DICTIONARIES: dict[str, dict[str, int]]
47+
48+
def add_frequency_lists(frequency_lists_: Mapping[str, Iterable[str]]) -> None: ...
49+
50+
GRAPHS: dict[str, dict[str, list[str | None]]]
51+
L33T_TABLE: dict[str, list[str]]
52+
REGEXEN: dict[str, Pattern[str]]
53+
DATE_MAX_YEAR: int
54+
DATE_MIN_YEAR: int
55+
DATE_SPLITS: dict[int, list[list[int]]]
56+
57+
def omnimatch(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
58+
def dictionary_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
59+
def reverse_dictionary_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
60+
def relevant_l33t_subtable(password: str, table: Mapping[str, Iterable[str]]) -> dict[str, list[str]]: ...
61+
def enumerate_l33t_subs(table: Mapping[str, Iterable[str]]) -> list[dict[str, str]]: ...
62+
def translate(string: str, chr_map: Mapping[str, str]) -> str: ...
63+
def l33t_match(
64+
password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ..., _l33t_table: dict[str, list[str]] = ...
65+
) -> list[_Match]: ...
66+
def repeat_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
67+
def spatial_match(
68+
password: str, _graphs: dict[str, _Graph] = ..., _ranked_dictionaries: dict[str, dict[str, int]] = ...
69+
) -> list[_Match]: ...
70+
71+
SHIFTED_RX: Pattern[str]
72+
73+
def spatial_match_helper(password: str, graph: _Graph, graph_name: str) -> list[_Match]: ...
74+
75+
MAX_DELTA: int
76+
77+
def sequence_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
78+
def regex_match(
79+
password: str, _regexen: dict[str, Pattern[str]] = ..., _ranked_dictionaries: dict[str, dict[str, int]] = ...
80+
) -> list[_Match]: ...
81+
def date_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
82+
83+
class _DM(TypedDict):
84+
month: int
85+
day: int
86+
87+
class _DMY(TypedDict):
88+
year: int
89+
month: int
90+
day: int
91+
92+
def map_ints_to_dmy(ints: tuple[int, int, int]) -> _DMY | None: ...
93+
def map_ints_to_dm(ints: tuple[int, int]) -> _DM | None: ...
94+
def two_to_four_digit_year(year: int) -> int: ...

stubs/zxcvbn/zxcvbn/scoring.pyi

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from collections.abc import Iterable
2+
from decimal import Decimal
3+
from typing import Pattern
4+
from typing_extensions import TypedDict
5+
6+
from .adjacency_graphs import _Graph
7+
from .matching import _Match
8+
9+
def calc_average_degree(graph: _Graph) -> float: ...
10+
11+
BRUTEFORCE_CARDINALITY: int
12+
MIN_GUESSES_BEFORE_GROWING_SEQUENCE: int
13+
MIN_SUBMATCH_GUESSES_SINGLE_CHAR: int
14+
MIN_SUBMATCH_GUESSES_MULTI_CHAR: int
15+
MIN_YEAR_SPACE: int
16+
REFERENCE_YEAR: int
17+
18+
class _GuessesResult(TypedDict):
19+
password: str
20+
guesses: int
21+
guesses_log10: float
22+
sequence: list[_Match]
23+
24+
def nCk(n: int, k: int) -> float: ...
25+
def most_guessable_match_sequence(password: str, matches: Iterable[_Match], _exclude_additive: bool = ...) -> _GuessesResult: ...
26+
def estimate_guesses(match: _Match, password: str) -> Decimal: ...
27+
def bruteforce_guesses(match: _Match) -> int: ...
28+
def dictionary_guesses(match: _Match) -> int: ...
29+
def repeat_guesses(match: _Match) -> Decimal: ...
30+
def sequence_guesses(match: _Match) -> int: ...
31+
def regex_guesses(match: _Match) -> int | None: ...
32+
def date_guesses(match: _Match) -> int: ...
33+
34+
KEYBOARD_AVERAGE_DEGREE: float
35+
KEYPAD_AVERAGE_DEGREE: float
36+
KEYBOARD_STARTING_POSITIONS: int
37+
KEYPAD_STARTING_POSITIONS: int
38+
39+
def spatial_guesses(match: _Match) -> int: ...
40+
41+
START_UPPER: Pattern[str]
42+
END_UPPER: Pattern[str]
43+
ALL_UPPER: Pattern[str]
44+
ALL_LOWER: Pattern[str]
45+
46+
def uppercase_variations(match: _Match) -> int: ...
47+
def l33t_variations(match: _Match) -> int: ...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from decimal import Decimal
2+
from typing_extensions import Literal, TypedDict
3+
4+
class _TimeEstimate(TypedDict):
5+
crack_times_seconds: _CrackTimeSeconds
6+
crack_times_display: _CrackTimesDisplay
7+
score: Literal[0, 1, 2, 3, 4]
8+
9+
class _CrackTimeSeconds(TypedDict):
10+
online_throttling_100_per_hour: Decimal
11+
online_no_throttling_10_per_second: Decimal
12+
offline_slow_hashing_1e4_per_second: Decimal
13+
offline_fast_hashing_1e10_per_second: Decimal
14+
15+
class _CrackTimesDisplay(TypedDict):
16+
online_throttling_100_per_hour: str
17+
online_no_throttling_10_per_second: str
18+
offline_slow_hashing_1e4_per_second: str
19+
offline_fast_hashing_1e10_per_second: str
20+
21+
def estimate_attack_times(guesses: Decimal | float) -> _TimeEstimate: ...
22+
def guesses_to_score(guesses: Decimal) -> Literal[0, 1, 2, 3, 4]: ...
23+
def display_time(seconds: float) -> str: ...
24+
def float_to_decimal(f: float) -> Decimal: ...

0 commit comments

Comments
 (0)