Skip to content

Add types for zxcvbn #8089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stubs/zxcvbn/METADATA.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version = "4.4.*"
18 changes: 18 additions & 0 deletions stubs/zxcvbn/zxcvbn/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import datetime
from collections.abc import Iterable
from decimal import Decimal
from typing_extensions import TypedDict

from .feedback import _Feedback
from .matching import _Match
from .time_estimates import _TimeEstimate

class _Result(_TimeEstimate, TypedDict):
password: str
guesses: Decimal
guesses_log10: float
sequence: list[_Match]
calc_time: datetime.timedelta
feedback: _Feedback

def zxcvbn(password: str, user_inputs: Iterable[object] | None = ...) -> _Result: ...
5 changes: 5 additions & 0 deletions stubs/zxcvbn/zxcvbn/adjacency_graphs.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from typing_extensions import TypeAlias

_Graph: TypeAlias = dict[str, list[str | None]]

ADJACENCY_GRAPHS: dict[str, _Graph]
12 changes: 12 additions & 0 deletions stubs/zxcvbn/zxcvbn/feedback.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from collections.abc import Sequence
from typing_extensions import Literal, TypedDict

from .matching import _Match

class _Feedback(TypedDict):
warning: str
suggestions: list[str]

def get_feedback(score: Literal[0, 1, 2, 3, 4], sequence: Sequence[_Match]) -> _Feedback: ...
def get_match_feedback(match: _Match, is_sole_match: bool) -> _Feedback: ...
def get_dictionary_match_feedback(match: _Match, is_sole_match: bool) -> _Feedback: ...
1 change: 1 addition & 0 deletions stubs/zxcvbn/zxcvbn/frequency_lists.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FREQUENCY_LISTS: dict[str, list[str]]
94 changes: 94 additions & 0 deletions stubs/zxcvbn/zxcvbn/matching.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from collections.abc import Iterable, Mapping
from decimal import Decimal
from typing import Any, Pattern
from typing_extensions import Literal, NotRequired, TypedDict

from .adjacency_graphs import _Graph

class _Match(TypedDict):
pattern: Literal["dictionary", "spatial", "repeat", "sequence", "regex", "date"]
token: str
i: int
j: int
guesses: NotRequired[int] # all patterns except 'date'
guesses_log10: NotRequired[float] # all patterns except 'date'

# pattern == 'date'
separator: NotRequired[str]
year: NotRequired[int]
month: NotRequired[int]
day: NotRequired[int]

# pattern == 'dictionary'
matched_word: NotRequired[str]
dictionary_name: NotRequired[str]
l33t: NotRequired[bool]
reversed: NotRequired[bool]
rank: NotRequired[int]
base_guesses: NotRequired[int | Decimal] # Decimal for 'repeat', see below
uppercase_variations: NotRequired[int]
l33t_variations: NotRequired[int]

# pattern == 'spatial'
turns: NotRequired[int]

# pattern == 'repeat'
base_token: NotRequired[str]
# base_guesses: NotRequired[Decimal]
base_matches: NotRequired[list[Any]] # Any = _Match, https://github.com/python/mypy/issues/731
repeat_count: NotRequired[float]

# pattern == 'regex'
regex_name: NotRequired[str]

def build_ranked_dict(ordered_list: Iterable[str]) -> dict[str, int]: ...

RANKED_DICTIONARIES: dict[str, dict[str, int]]

def add_frequency_lists(frequency_lists_: Mapping[str, Iterable[str]]) -> None: ...

GRAPHS: dict[str, dict[str, list[str | None]]]
L33T_TABLE: dict[str, list[str]]
REGEXEN: dict[str, Pattern[str]]
DATE_MAX_YEAR: int
DATE_MIN_YEAR: int
DATE_SPLITS: dict[int, list[list[int]]]

def omnimatch(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
def dictionary_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
def reverse_dictionary_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
def relevant_l33t_subtable(password: str, table: Mapping[str, Iterable[str]]) -> dict[str, list[str]]: ...
def enumerate_l33t_subs(table: Mapping[str, Iterable[str]]) -> list[dict[str, str]]: ...
def translate(string: str, chr_map: Mapping[str, str]) -> str: ...
def l33t_match(
password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ..., _l33t_table: dict[str, list[str]] = ...
) -> list[_Match]: ...
def repeat_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
def spatial_match(
password: str, _graphs: dict[str, _Graph] = ..., _ranked_dictionaries: dict[str, dict[str, int]] = ...
) -> list[_Match]: ...

SHIFTED_RX: Pattern[str]

def spatial_match_helper(password: str, graph: _Graph, graph_name: str) -> list[_Match]: ...

MAX_DELTA: int

def sequence_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...
def regex_match(
password: str, _regexen: dict[str, Pattern[str]] = ..., _ranked_dictionaries: dict[str, dict[str, int]] = ...
) -> list[_Match]: ...
def date_match(password: str, _ranked_dictionaries: dict[str, dict[str, int]] = ...) -> list[_Match]: ...

class _DM(TypedDict):
month: int
day: int

class _DMY(TypedDict):
year: int
month: int
day: int

def map_ints_to_dmy(ints: tuple[int, int, int]) -> _DMY | None: ...
def map_ints_to_dm(ints: tuple[int, int]) -> _DM | None: ...
def two_to_four_digit_year(year: int) -> int: ...
47 changes: 47 additions & 0 deletions stubs/zxcvbn/zxcvbn/scoring.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from collections.abc import Iterable
from decimal import Decimal
from typing import Pattern
from typing_extensions import TypedDict

from .adjacency_graphs import _Graph
from .matching import _Match

def calc_average_degree(graph: _Graph) -> float: ...

BRUTEFORCE_CARDINALITY: int
MIN_GUESSES_BEFORE_GROWING_SEQUENCE: int
MIN_SUBMATCH_GUESSES_SINGLE_CHAR: int
MIN_SUBMATCH_GUESSES_MULTI_CHAR: int
MIN_YEAR_SPACE: int
REFERENCE_YEAR: int

class _GuessesResult(TypedDict):
password: str
guesses: int
guesses_log10: float
sequence: list[_Match]

def nCk(n: int, k: int) -> float: ...
def most_guessable_match_sequence(password: str, matches: Iterable[_Match], _exclude_additive: bool = ...) -> _GuessesResult: ...
def estimate_guesses(match: _Match, password: str) -> Decimal: ...
def bruteforce_guesses(match: _Match) -> int: ...
def dictionary_guesses(match: _Match) -> int: ...
def repeat_guesses(match: _Match) -> Decimal: ...
def sequence_guesses(match: _Match) -> int: ...
def regex_guesses(match: _Match) -> int | None: ...
def date_guesses(match: _Match) -> int: ...

KEYBOARD_AVERAGE_DEGREE: float
KEYPAD_AVERAGE_DEGREE: float
KEYBOARD_STARTING_POSITIONS: int
KEYPAD_STARTING_POSITIONS: int

def spatial_guesses(match: _Match) -> int: ...

START_UPPER: Pattern[str]
END_UPPER: Pattern[str]
ALL_UPPER: Pattern[str]
ALL_LOWER: Pattern[str]

def uppercase_variations(match: _Match) -> int: ...
def l33t_variations(match: _Match) -> int: ...
24 changes: 24 additions & 0 deletions stubs/zxcvbn/zxcvbn/time_estimates.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from decimal import Decimal
from typing_extensions import Literal, TypedDict

class _TimeEstimate(TypedDict):
crack_times_seconds: _CrackTimeSeconds
crack_times_display: _CrackTimesDisplay
score: Literal[0, 1, 2, 3, 4]

class _CrackTimeSeconds(TypedDict):
online_throttling_100_per_hour: Decimal
online_no_throttling_10_per_second: Decimal
offline_slow_hashing_1e4_per_second: Decimal
offline_fast_hashing_1e10_per_second: Decimal

class _CrackTimesDisplay(TypedDict):
online_throttling_100_per_hour: str
online_no_throttling_10_per_second: str
offline_slow_hashing_1e4_per_second: str
offline_fast_hashing_1e10_per_second: str

def estimate_attack_times(guesses: Decimal | float) -> _TimeEstimate: ...
def guesses_to_score(guesses: Decimal) -> Literal[0, 1, 2, 3, 4]: ...
def display_time(seconds: float) -> str: ...
def float_to_decimal(f: float) -> Decimal: ...