mirror of
https://github.com/rjNemo/pass-gen
synced 2026-06-12 13:26:42 +00:00
feat: control numbers
This commit is contained in:
parent
6d890aedf0
commit
69f1a801de
5 changed files with 37 additions and 14 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
- [x] As a user I want to generate a random secure password to protect my personal accounts
|
- [x] As a user I want to generate a random secure password to protect my personal accounts
|
||||||
- [x] Minimal length
|
- [x] Minimal length
|
||||||
- [x] Include symbols
|
- [x] Include symbols
|
||||||
- [ ] Include numbers
|
- [x] Include numbers
|
||||||
- [ ] Include lowercase characters
|
- [ ] Include lowercase characters
|
||||||
- [ ] Include uppercase characters
|
- [ ] Include uppercase characters
|
||||||
- [ ] As a user I want the generated password to be copied to the clipboard
|
- [ ] As a user I want the generated password to be copied to the clipboard
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,16 @@ app = typer.Typer()
|
||||||
def main(
|
def main(
|
||||||
random: bool = True,
|
random: bool = True,
|
||||||
length: int = typer.Option(8, help="Length of the generated password."),
|
length: int = typer.Option(8, help="Length of the generated password."),
|
||||||
|
numbers: bool = typer.Option(
|
||||||
|
True, help="If the generated password should include numeric characters."
|
||||||
|
),
|
||||||
symbols: bool = typer.Option(
|
symbols: bool = typer.Option(
|
||||||
False, help="If the generated password should includes special characters."
|
False, help="If the generated password should include special characters."
|
||||||
),
|
),
|
||||||
) -> None:
|
) -> None:
|
||||||
seed = r.randint(0, 100) if random else 0
|
seed = r.randint(0, 100) if random else 0
|
||||||
typer.echo(generate_password(seed, length, symbols))
|
typer.echo(generate_password(seed, length, symbols, numbers))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app()
|
app() # pragma nocover
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,14 @@ def test_cli_can_set_symbols() -> None:
|
||||||
args = ["--symbols"]
|
args = ["--symbols"]
|
||||||
result = _run_cli(*args)
|
result = _run_cli(*args)
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
assert "X1fH$!ZM" in result.stdout
|
assert """X"fH.+ZM""" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli_can_set_numbers() -> None:
|
||||||
|
args = ["--no-numbers"]
|
||||||
|
result = _run_cli(*args)
|
||||||
|
print(result.stdout)
|
||||||
|
assert "yWAcqGFz" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
def _run_cli(*args) -> Result:
|
def _run_cli(*args) -> Result:
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ import string
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
def generate_password(seed: int, length: int = 8, symbols: bool = False) -> str:
|
def generate_password(
|
||||||
characters = _build_characters(symbols)
|
seed: int, length: int = 8, symbols: bool = False, numbers: bool = True
|
||||||
|
) -> str:
|
||||||
|
characters = _build_characters(symbols=symbols, numbers=numbers)
|
||||||
|
|
||||||
random_generator = _new_random_generator(seed)
|
random_generator = _new_random_generator(seed)
|
||||||
|
|
||||||
|
|
@ -20,15 +22,15 @@ def _new_random_generator(seed: int) -> RandomSampler:
|
||||||
return random.Random(seed)
|
return random.Random(seed)
|
||||||
|
|
||||||
|
|
||||||
def _build_characters(symbols: bool) -> str:
|
def _build_characters(symbols: bool, numbers: bool) -> str:
|
||||||
lowercase = string.ascii_lowercase
|
lowercase = string.ascii_lowercase
|
||||||
uppercase = string.ascii_uppercase
|
uppercase = string.ascii_uppercase
|
||||||
digits = string.digits
|
|
||||||
punctuation = string.punctuation
|
|
||||||
|
|
||||||
characters = lowercase + uppercase + digits
|
characters = lowercase + uppercase
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
characters += punctuation
|
characters += string.punctuation
|
||||||
|
if numbers:
|
||||||
|
characters += string.digits
|
||||||
|
|
||||||
return characters
|
return characters
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,20 @@ def test_control_password_length(seed: int, length: int, expected: str) -> None:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("seed", "symbols", "expected"),
|
("seed", "symbols", "expected"),
|
||||||
[
|
[
|
||||||
(0, True, "X1fH$!ZM"),
|
(0, True, """X"fH.+ZM"""),
|
||||||
(1, True, """r+iGp"58"""),
|
(1, True, """r?iGp,&)"""),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -> None:
|
def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -> None:
|
||||||
assert generate_password(seed, symbols=symbols) == expected
|
assert generate_password(seed, symbols=symbols) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("seed", "numbers", "expected"),
|
||||||
|
[
|
||||||
|
(0, False, "yWAcqGFz"),
|
||||||
|
(1, False, "iKWeqhFC"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_password_can_contain_numbers(seed: int, numbers: bool, expected: str) -> None:
|
||||||
|
assert generate_password(seed, numbers=numbers) == expected
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue