Skip to content
Open
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 .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.venv/
4 changes: 2 additions & 2 deletions Password_Manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ To use this password manager, follow these steps:
2. Make sure you have Python 3.x installed.
3. Install the required libraries by running the following command in your terminal or command prompt:
```bash
pip install colorama
pip install rich
4. Run the password_manager.py script:
```bash
python password_manager.py
python main.py

# Usage

Expand Down
155 changes: 155 additions & 0 deletions Password_Manager/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import csv
import random
import string
from pathlib import Path
from typing import Literal

from rich import box
from rich.console import Console
from rich.prompt import Prompt
from rich.table import Table

STRING_LENGTH = 6
PUNCTUATION_LENGTH = 4
PASSWORD_FILE = Path("password.csv").resolve()
console = Console()


def display_message(message: str, color: Literal["green", "red", "white", "blue"]) -> None:
"""Display a message in the specified color."""
console.print(f"[{color}]{message}[/]")


def show_main_menu(last_output: str | None = None) -> int:
table = Table(
"[bold]Password Manager App[/]", box=box.SQUARE, caption=last_output, width=50, caption_justify="left"
)
table.add_row("1. Create password")
table.add_row("2. Show password")
table.add_row("3. Edit password")
table.add_row("4. Delete password")
table.add_row("5. Exit")
console.print(table)

choice = Prompt.ask(
"[bold]Select an option[/]", choices=["1", "2", "3", "4", "5"], default="5", show_choices=False, console=console
)
return int(choice)


def read_csv_file() -> dict[str, str]:
"""Read the CSV file and return the data as a dict[aim, password]"""
with PASSWORD_FILE.open("r", encoding="utf-8", newline="") as csvfile:
return {data[0]: data[1] for data in csv.reader(csvfile) if data}


def write_csv_file(data: dict[str, str]) -> None:
"""Write the data to the CSV file."""
with PASSWORD_FILE.open("w", encoding="utf-8", newline="") as csvfile:
writer = csv.writer(csvfile)
writer.writerows([[k, v] for k, v in data.items()])


def validate_aim(aim: str) -> bool:
if not aim or aim in read_csv_file():
return False
return True


def password_generator() -> str:
"""Generate a random password with lowercase, uppercase, punctuation, and numeric characters."""
char_sets = [string.ascii_lowercase, string.ascii_uppercase, string.punctuation, string.digits]
password = [random.choice(char_set) for char_set in char_sets]
password.extend(random.choices("".join(char_sets), k=STRING_LENGTH + PUNCTUATION_LENGTH + 4 - len(char_sets)))
random.shuffle(password)
return "".join(password)


def process_creation() -> str:
"""Create the password for a given aim in the CSV file."""
console.clear()
display_message("Creation mode", "blue")

if not validate_aim(aim := Prompt.ask("Enter aim", console=console)):
return "This aim is empty or already taken. Try again"

data = read_csv_file()
password = password_generator()
data[aim] = password
write_csv_file(data)
return "Password successfully created"


def process_checking() -> str:
"""Show the password for a given aim in the CSV file."""
console.clear()
display_message("Checking mode", "blue")
data = read_csv_file()

if not (aim := Prompt.ask("Enter aim", console=console)) or aim not in data:
return "This aim is empty or not found. Try again"

password = data.get(aim)
if password:
return password
return "Aim not found"


def process_editing() -> str:
"""Edit the password for a given aim in the CSV file."""
console.clear()
display_message("Editing mode", "blue")
data = read_csv_file()

if not (aim := Prompt.ask("Enter aim", console=console)) or aim not in data:
return "This aim is empty or not found. Try again"

new_password = Prompt.ask("Enter the new password", console=console)
if new_password != Prompt.ask("Re-enter the new password", console=console):
return "Passwords do not match. Try again"
data[aim] = new_password
write_csv_file(data)
return "Password updated successfully"


def process_deleting() -> str:
"""Delete a password entry for a given aim from the CSV file."""
console.clear()
display_message("Deleting mode", "blue")
data = read_csv_file()

if not (aim := Prompt.ask("Enter aim", console=console)) or aim not in data:
return "This aim is empty or not found. Try again"

del data[aim]
write_csv_file(data)
return "Password removed successfully"


def process_exit() -> None:
console.clear()
display_message("Exiting the Password Manager App. Goodbye!", "green")
exit(0)


def main() -> None:
last_output = None
while True:
console.clear()
selected = show_main_menu(last_output)
last_output = None
match selected:
case 1:
last_output = process_creation()
case 2:
last_output = process_checking()
case 3:
last_output = process_editing()
case 4:
last_output = process_deleting()
case 5:
process_exit()


if __name__ == "__main__":
main()
2 changes: 0 additions & 2 deletions Password_Manager/password.csv
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
aim,password

139 changes: 0 additions & 139 deletions Password_Manager/project.py

This file was deleted.

34 changes: 34 additions & 0 deletions Password_Manager/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[project]
name = "password-manager"
version = "0.1.0"
description = "Simply password manager"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"rich>=14.1.0",
]

[tool.ruff]
line-length = 120
target-version = "py312"
src = ["."]
exclude = ["migrations", ".venv", "__pycache__"]

[tool.ruff.lint]
select = ["E", "F", "B", "ANN", "ASYNC", "I"]
ignore = ["E501", "E701"]
fixable = ["ALL"]
unfixable = []

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "native"
docstring-code-format = true
skip-magic-trailing-comma = false

[tool.taskipy.tasks]
lint = "ruff check --no-cache --fix ."
format = "ruff format --no-cache ."
precommit = "task format && task lint"
clean = "cleaner -u python --delete"
6 changes: 1 addition & 5 deletions Password_Manager/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
random
string
csv
os
colorama
rich
Loading