diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
index 11b97531109..20b0f50af6b 100644
--- a/.github/workflows/python.yml
+++ b/.github/workflows/python.yml
@@ -21,7 +21,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
- python-version: '3.13.7'
+ python-version: '3.14.0'
- name: Install all dependencies and tools
run: |
@@ -38,7 +38,7 @@ jobs:
run: pytest || true
- name: Run Ruff checks with ignored rules
- run: ruff check . --ignore B904,B905,EM101,EXE001,G004,ISC001,PLC0415,PLC1901,PLW060,PLW1641,PLW2901,PT011,PT018,PT028,S101,S311,SIM905,SLF001
+ run: ruff check . --ignore B904,B905,EM101,EXE001,G004,ISC001,PLC0415,PLC1901,PLW060,PLW1641,PLW2901,PT011,PT018,PT028,S101,S311,SIM905,SLF001,F405
- name: Run Mypy type checks
run: mypy . --ignore-missing-imports || true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 0f3717818e6..5d5134469d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,12 +16,10 @@ for i in string:
odd+=i
print(lower+upper+odd+even)
+.vscode
+__pycache__/
.venv
-# operating system-related files
-# file properties cache/storage on macOS
*.DS_Store
-
-# thumbnail cache on Windows
Thumbs.db
bankmanaging.db
\ No newline at end of file
diff --git a/BoardGame-CLI/python.py b/BoardGame-CLI/python.py
index 49929a775ce..5a28f5adf6f 100644
--- a/BoardGame-CLI/python.py
+++ b/BoardGame-CLI/python.py
@@ -87,4 +87,5 @@ def play_snakes_and_ladders():
# Start the game
-play_snakes_and_ladders()
+if __name__ == "__main__":
+ play_snakes_and_ladders()
diff --git a/BoardGame-CLI/snakeLadder.py b/BoardGame-CLI/snakeLadder.py
index ea605cab340..fd06dd64527 100644
--- a/BoardGame-CLI/snakeLadder.py
+++ b/BoardGame-CLI/snakeLadder.py
@@ -90,7 +90,7 @@ def play():
elif n == 2:
players = {} # stores player ans their locations
isReady = {}
- current_loc = 0 # vaiable for iterating location
+ current_loc = 1 # reset starting location to 1
player_input()
elif n == 3:
@@ -170,4 +170,5 @@ def ladder(a, i):
print("/" * 40)
-player_input()
+if __name__ == "__main__":
+ player_input()
diff --git a/BoardGame-CLI/uno.py b/BoardGame-CLI/uno.py
index f10f46c4ff8..dca5f1e10c1 100644
--- a/BoardGame-CLI/uno.py
+++ b/BoardGame-CLI/uno.py
@@ -1,16 +1,25 @@
# uno game #
import random
+from typing import List
"""
Generate the UNO deck of 108 cards.
-Parameters: None
-Return values: deck=>list
+
+Doctest examples:
+
+>>> deck = buildDeck()
+>>> len(deck)
+108
+>>> sum(1 for c in deck if 'Wild' in c)
+8
+
+Return: list of card strings (e.g. 'Red 7', 'Wild Draw Four')
"""
-def buildDeck():
- deck = []
+def buildDeck() -> List[str]:
+ deck: List[str] = []
# example card:Red 7,Green 8, Blue skip
colours = ["Red", "Green", "Yellow", "Blue"]
values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "Draw Two", "Skip", "Reverse"]
@@ -24,7 +33,6 @@ def buildDeck():
for i in range(4):
deck.append(wilds[0])
deck.append(wilds[1])
- print(deck)
return deck
@@ -35,10 +43,9 @@ def buildDeck():
"""
-def shuffleDeck(deck):
- for cardPos in range(len(deck)):
- randPos = random.randint(0, 107)
- deck[cardPos], deck[randPos] = deck[randPos], deck[cardPos]
+def shuffleDeck(deck: List[str]) -> List[str]:
+ # use Python's built-in shuffle which is efficient and correct
+ random.shuffle(deck)
return deck
@@ -48,10 +55,18 @@ def shuffleDeck(deck):
"""
-def drawCards(numCards):
- cardsDrawn = []
+def drawCards(numCards: int) -> List[str]:
+ """
+ Draw a number of cards from the top of the global `unoDeck`.
+
+ Raises ValueError if the deck runs out of cards.
+ """
+ cardsDrawn: List[str] = []
for x in range(numCards):
- cardsDrawn.append(unoDeck.pop(0))
+ try:
+ cardsDrawn.append(unoDeck.pop(0))
+ except IndexError:
+ raise ValueError("The deck is empty; cannot draw more cards")
return cardsDrawn
@@ -62,7 +77,7 @@ def drawCards(numCards):
"""
-def showHand(player, playerHand):
+def showHand(player: int, playerHand: List[str]) -> None:
print("Player {}'s Turn".format(players_name[player]))
print("Your Hand")
print("------------------")
@@ -80,7 +95,15 @@ def showHand(player, playerHand):
"""
-def canPlay(colour, value, playerHand):
+def canPlay(colour: str, value: str, playerHand: List[str]) -> bool:
+ """
+ Return True if any card in playerHand is playable on a discard with given colour and value.
+
+ >>> canPlay('Red','5',['Red 3','Green 5'])
+ True
+ >>> canPlay('Blue','7',['Green 1'])
+ False
+ """
for card in playerHand:
if "Wild" in card:
return True
@@ -89,101 +112,118 @@ def canPlay(colour, value, playerHand):
return False
+# --- Global deck and initial setup ---
unoDeck = buildDeck()
unoDeck = shuffleDeck(unoDeck)
unoDeck = shuffleDeck(unoDeck)
-discards = []
+discards: List[str] = []
-players_name = []
-players = []
+players_name: List[str] = []
+players: List[List[str]] = []
colours = ["Red", "Green", "Yellow", "Blue"]
-numPlayers = int(input("How many players?"))
-while numPlayers < 2 or numPlayers > 4:
- numPlayers = int(
- input("Invalid. Please enter a number between 2-4.\nHow many players?")
- )
-for player in range(numPlayers):
- players_name.append(input("Enter player {} name: ".format(player + 1)))
- players.append(drawCards(5))
-
-
-playerTurn = 0
-playDirection = 1
-playing = True
-discards.append(unoDeck.pop(0))
-splitCard = discards[0].split(" ", 1)
-currentColour = splitCard[0]
-if currentColour != "Wild":
- cardVal = splitCard[1]
-else:
- cardVal = "Any"
-
-while playing:
- showHand(playerTurn, players[playerTurn])
- print("Card on top of discard pile: {}".format(discards[-1]))
- if canPlay(currentColour, cardVal, players[playerTurn]):
- cardChosen = int(input("Which card do you want to play?"))
- while not canPlay(
- currentColour, cardVal, [players[playerTurn][cardChosen - 1]]
- ):
- cardChosen = int(input("Not a valid card. Which card do you want to play?"))
- print("You played {}".format(players[playerTurn][cardChosen - 1]))
- discards.append(players[playerTurn].pop(cardChosen - 1))
-
- # cheak if player won
- if len(players[playerTurn]) == 0:
- playing = False
- # winner = "Player {}".format(playerTurn+1)
- winner = players_name[playerTurn]
- else:
- # cheak for special cards
- splitCard = discards[-1].split(" ", 1)
- currentColour = splitCard[0]
- if len(splitCard) == 1:
- cardVal = "Any"
- else:
- cardVal = splitCard[1]
- if currentColour == "Wild":
- for x in range(len(colours)):
- print("{}) {}".format(x + 1, colours[x]))
- newColour = int(input("What colour would you like to choose? "))
- while newColour < 1 or newColour > 4:
- newColour = int(
- input("Invalid option. What colour would you like to choose")
- )
- currentColour = colours[newColour - 1]
- if cardVal == "Reverse":
- playDirection = playDirection * -1
- elif cardVal == "Skip":
- playerTurn += playDirection
- if playerTurn >= numPlayers:
- playerTurn = 0
- elif playerTurn < 0:
- playerTurn = numPlayers - 1
- elif cardVal == "Draw Two":
- playerDraw = playerTurn + playDirection
- if playerDraw == numPlayers:
- playerDraw = 0
- elif playerDraw < 0:
- playerDraw = numPlayers - 1
- players[playerDraw].extend(drawCards(2))
- elif cardVal == "Draw Four":
- playerDraw = playerTurn + playDirection
- if playerDraw == numPlayers:
- playerDraw = 0
- elif playerDraw < 0:
- playerDraw = numPlayers - 1
- players[playerDraw].extend(drawCards(4))
- print("")
+
+
+def main() -> None:
+ """Run interactive UNO game (keeps original behavior).
+
+ Note: main() is interactive and not exercised by doctest.
+ """
+ global players_name, players, discards
+
+ numPlayers = int(input("How many players?"))
+ while numPlayers < 2 or numPlayers > 4:
+ numPlayers = int(
+ input("Invalid. Please enter a number between 2-4.\nHow many players?")
+ )
+ for player in range(numPlayers):
+ players_name.append(input("Enter player {} name: ".format(player + 1)))
+ players.append(drawCards(5))
+
+ playerTurn = 0
+ playDirection = 1
+ playing = True
+ discards.append(unoDeck.pop(0))
+ splitCard = discards[0].split(" ", 1)
+ currentColour = splitCard[0]
+ if currentColour != "Wild":
+ cardVal = splitCard[1]
else:
- print("You can't play. You have to draw a card.")
- players[playerTurn].extend(drawCards(1))
+ cardVal = "Any"
+
+ while playing:
+ showHand(playerTurn, players[playerTurn])
+ print("Card on top of discard pile: {}".format(discards[-1]))
+ if canPlay(currentColour, cardVal, players[playerTurn]):
+ cardChosen = int(input("Which card do you want to play?"))
+ while not canPlay(
+ currentColour, cardVal, [players[playerTurn][cardChosen - 1]]
+ ):
+ cardChosen = int(
+ input("Not a valid card. Which card do you want to play?")
+ )
+ print("You played {}".format(players[playerTurn][cardChosen - 1]))
+ discards.append(players[playerTurn].pop(cardChosen - 1))
+
+ # cheak if player won
+ if len(players[playerTurn]) == 0:
+ playing = False
+ # winner = "Player {}".format(playerTurn+1)
+ winner = players_name[playerTurn]
+ else:
+ # cheak for special cards
+ splitCard = discards[-1].split(" ", 1)
+ currentColour = splitCard[0]
+ if len(splitCard) == 1:
+ cardVal = "Any"
+ else:
+ cardVal = splitCard[1]
+ if currentColour == "Wild":
+ for x in range(len(colours)):
+ print("{}) {}".format(x + 1, colours[x]))
+ newColour = int(input("What colour would you like to choose? "))
+ while newColour < 1 or newColour > 4:
+ newColour = int(
+ input(
+ "Invalid option. What colour would you like to choose"
+ )
+ )
+ currentColour = colours[newColour - 1]
+ if cardVal == "Reverse":
+ playDirection = playDirection * -1
+ elif cardVal == "Skip":
+ playerTurn += playDirection
+ if playerTurn >= numPlayers:
+ playerTurn = 0
+ elif playerTurn < 0:
+ playerTurn = numPlayers - 1
+ elif cardVal == "Draw Two":
+ playerDraw = playerTurn + playDirection
+ if playerDraw == numPlayers:
+ playerDraw = 0
+ elif playerDraw < 0:
+ playerDraw = numPlayers - 1
+ players[playerDraw].extend(drawCards(2))
+ elif cardVal == "Draw Four":
+ playerDraw = playerTurn + playDirection
+ if playerDraw == numPlayers:
+ playerDraw = 0
+ elif playerDraw < 0:
+ playerDraw = numPlayers - 1
+ players[playerDraw].extend(drawCards(4))
+ print("")
+ else:
+ print("You can't play. You have to draw a card.")
+ players[playerTurn].extend(drawCards(1))
+
+ playerTurn += playDirection
+ if playerTurn >= numPlayers:
+ playerTurn = 0
+ elif playerTurn < 0:
+ playerTurn = numPlayers - 1
+
+ print("Game Over")
+ print("{} is the Winner!".format(winner))
- playerTurn += playDirection
- if playerTurn >= numPlayers:
- playerTurn = 0
- elif playerTurn < 0:
- playerTurn = numPlayers - 1
-print("Game Over")
-print("{} is the Winner!".format(winner))
+if __name__ == "__main__":
+ main()
diff --git a/Industrial_developed_hangman/tests/test_hangman/test_main.py b/Industrial_developed_hangman/tests/test_hangman/test_main.py
index 9d377c7f9e9..6567e56b765 100644
--- a/Industrial_developed_hangman/tests/test_hangman/test_main.py
+++ b/Industrial_developed_hangman/tests/test_hangman/test_main.py
@@ -1,5 +1,3 @@
-import os
-from pathlib import Path
from typing import Callable, List
import pytest
@@ -8,7 +6,6 @@
from src.hangman.main import (
MainProcess,
Source,
- parse_word_from_local,
parse_word_from_site,
)
diff --git a/Password Manager Using Tkinter/PGV.py b/Password Manager Using Tkinter/PGV.py
new file mode 100644
index 00000000000..045625ea650
--- /dev/null
+++ b/Password Manager Using Tkinter/PGV.py
@@ -0,0 +1,18 @@
+import json
+
+new_data = {
+ website_input.get():{
+ "email": email_input.get(),
+ "password": passw_input.get()
+ }
+ }
+
+try:
+ with open("data.json", "r") as data_file:
+ data = json.load(data_file)
+except FileNotFoundError:
+ with open("data.json", "w") as data_file:
+ pass
+else:
+ with open("data.json", "w") as data_file:
+ json.dump(new_data, data_file, indent = 4)
\ No newline at end of file
diff --git a/Password Manager Using Tkinter/README.md b/Password Manager Using Tkinter/README.md
new file mode 100644
index 00000000000..a31bf876550
--- /dev/null
+++ b/Password Manager Using Tkinter/README.md
@@ -0,0 +1,68 @@
+# My Personal Password Manager
+
+Hello there! Welcome to my Password Manager project. I created this application to provide a simple and secure way **to manage all my website login credentials in one place**. It's a desktop application **built with Python**, and I've focused on making it both functional and easy on the eyes.
+
+---
+
+## What It Can Do
+
+- **Generate Strong Passwords**: One click = secure, random passwords (auto-copied to clipboard!).
+
+- **Save Credentials**: Store site name, email/username, and password safely.
+
+- **Quick Search**: Instantly find saved logins by website name.
+
+- **View All Passwords**: Unlock all saved entries with your master password — neatly organized in a table.
+
+- **One-Click Copy**: Copy email or password directly from the list for quick logins.
+
+---
+
+## How I Built It
+
+- **Python**: Powers the core logic behind the app.
+
+- **Tkinter**: Handles the clean and simple user interface.
+
+- **ttkbootstrap**: Adds a modern, professional theme to the UI.
+
+- **JSON**: Stores all password data securely in a local data.json file.
+
+---
+
+## How to Get Started
+
+1. Install Python 3 on your system.
+
+2. Download all project files (main.py, logo.png, requirements.txt).
+
+3. Open Terminal/CMD, navigate to the project folder, and run:
+```python
+pip install -r requirements.txt
+```
+
+4. Start the app with:
+```python
+python main.py
+```
+
+5. Enjoy!
+
+---
+
+## Screenshots
+
+
+
+ | Main Window where from where you can add credentials |
+  |
+
+
+ | Second window — where you can see all your saved passwords (but hey, you’ll need a password to see your passwords 😏).
+ |
+  |
+
+
+
+
+
diff --git a/Password Manager Using Tkinter/data.json b/Password Manager Using Tkinter/data.json
new file mode 100644
index 00000000000..399ea997575
--- /dev/null
+++ b/Password Manager Using Tkinter/data.json
@@ -0,0 +1,14 @@
+{
+ "Amazon": {
+ "email": "prashant123Amazon@gmail.com",
+ "password": "1mD%#Z555rF$&2aRpI"
+ },
+ "Facebook": {
+ "email": "prashant123Facebook@gmail.com",
+ "password": "qQ6#H7o&)i8S!3sO)c4"
+ },
+ "Flipkart": {
+ "email": "prashant123Flipkart@gmail.com",
+ "password": "1!+7NqmUZbN18K(3A+"
+ }
+}
\ No newline at end of file
diff --git a/Password Manager Using Tkinter/data.txt b/Password Manager Using Tkinter/data.txt
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/Password Manager Using Tkinter/logo.png b/Password Manager Using Tkinter/logo.png
new file mode 100644
index 00000000000..59b69165150
Binary files /dev/null and b/Password Manager Using Tkinter/logo.png differ
diff --git a/Password Manager Using Tkinter/main.py b/Password Manager Using Tkinter/main.py
new file mode 100644
index 00000000000..15d6fdc1d13
--- /dev/null
+++ b/Password Manager Using Tkinter/main.py
@@ -0,0 +1,207 @@
+import tkinter as tk
+from tkinter import messagebox, simpledialog
+import ttkbootstrap as ttk
+from ttkbootstrap.constants import *
+import pyperclip
+import json
+from random import choice, randint, shuffle
+
+# ---------------------------- CONSTANTS ------------------------------- #
+FONT_NAME = "Helvetica"
+# IMP: this is not a secure way to store a master password.
+# in a real application, this should be changed and stored securely (e.g., hashed and salted).
+MASTER_PASSWORD = "password123"
+
+# ---------------------------- PASSWORD GENERATOR ------------------------------- #
+def generate_password():
+ """generates a random strong password and copies it to clipboard."""
+ letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
+ numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
+ symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']
+
+ password_letters = [choice(letters) for _ in range(randint(8, 10))]
+ password_symbols = [choice(symbols) for _ in range(randint(2, 4))]
+ password_numbers = [choice(numbers) for _ in range(randint(2, 4))]
+
+ password_list = password_letters + password_symbols + password_numbers
+ shuffle(password_list)
+
+ password = "".join(password_list)
+ password_entry.delete(0, tk.END)
+ password_entry.insert(0, password)
+ pyperclip.copy(password)
+ messagebox.showinfo(title="Password Generated", message="Password copied to clipboard!")
+
+# ---------------------------- SAVE PASSWORD ------------------------------- #
+def save():
+ """saves the website, email, and password to a JSON file."""
+ website = website_entry.get()
+ email = email_entry.get()
+ password = password_entry.get()
+ new_data = {
+ website: {
+ "email": email,
+ "password": password,
+ }
+ }
+
+ if not website or not password:
+ messagebox.showerror(title="Oops", message="Please don't leave any fields empty!")
+ return
+
+ is_ok = messagebox.askokcancel(title=website, message=f"These are the details entered: \nEmail: {email} "
+ f"\nPassword: {password} \nIs it ok to save?")
+ if is_ok:
+ try:
+ with open("data.json", "r") as data_file:
+ data = json.load(data_file)
+ except (FileNotFoundError, json.JSONDecodeError):
+ data = {}
+
+ data.update(new_data)
+
+ with open("data.json", "w") as data_file:
+ json.dump(data, data_file, indent=4)
+
+ website_entry.delete(0, tk.END)
+ password_entry.delete(0, tk.END)
+
+# ---------------------------- FIND PASSWORD ------------------------------- #
+def find_password():
+ """finds and displays password for a given website."""
+ website = website_entry.get()
+ try:
+ with open("data.json", "r") as data_file:
+ data = json.load(data_file)
+ except (FileNotFoundError, json.JSONDecodeError):
+ messagebox.showerror(title="Error", message="No Data File Found.")
+ return
+
+ if website in data:
+ email = data[website]["email"]
+ password = data[website]["password"]
+ messagebox.showinfo(title=website, message=f"Email: {email}\nPassword: {password}")
+ pyperclip.copy(password)
+ messagebox.showinfo(title="Copied", message="Password for {} copied to clipboard.".format(website))
+ else:
+ messagebox.showerror(title="Error", message=f"No details for {website} exists.")
+
+# ---------------------------- VIEW ALL PASSWORDS ------------------------------- #
+def view_all_passwords():
+ """prompts for master password and displays all saved passwords if correct."""
+ password = simpledialog.askstring("Master Password", "Please enter the master password:", show='*')
+
+ if password == MASTER_PASSWORD:
+ show_passwords_window()
+ elif password is not None: # avoids error message if user clicks cancel
+ messagebox.showerror("Incorrect Password", "The master password you entered is incorrect.")
+
+def show_passwords_window():
+ """creates a new window to display all passwords in a table."""
+ all_passwords_window = tk.Toplevel(window)
+ all_passwords_window.title("All Saved Passwords")
+ all_passwords_window.config(padx=20, pady=20)
+
+ # a frame for the treeview and scrollbar
+ tree_frame = ttk.Frame(all_passwords_window)
+ tree_frame.grid(row=0, column=0, columnspan=2, sticky='nsew')
+
+ # a Treeview (table)
+ cols = ('Website', 'Email', 'Password')
+ tree = ttk.Treeview(tree_frame, columns=cols, show='headings')
+
+ # column headings and widths
+ tree.heading('Website', text='Website')
+ tree.column('Website', width=150)
+ tree.heading('Email', text='Email/Username')
+ tree.column('Email', width=200)
+ tree.heading('Password', text='Password')
+ tree.column('Password', width=200)
+
+ tree.grid(row=0, column=0, sticky='nsew')
+
+ # a scrollbar
+ scrollbar = ttk.Scrollbar(tree_frame, orient=tk.VERTICAL, command=tree.yview)
+ tree.configure(yscroll=scrollbar.set)
+ scrollbar.grid(row=0, column=1, sticky='ns')
+
+ # load data from JSON file
+ try:
+ with open("data.json", "r") as data_file:
+ data = json.load(data_file)
+
+ # insert data into the treeview
+ for website, details in data.items():
+ tree.insert("", "end", values=(website, details['email'], details['password']))
+
+ except (FileNotFoundError, json.JSONDecodeError):
+ # if file not found or empty, it will just show an empty table
+ pass
+
+ def copy_selected_info(column_index, info_type):
+ """copies the email or password of the selected row."""
+ selected_item = tree.focus()
+ if not selected_item:
+ messagebox.showwarning("No Selection", "Please select a row from the table first.", parent=all_passwords_window)
+ return
+
+ item_values = tree.item(selected_item, 'values')
+ info_to_copy = item_values[column_index]
+ pyperclip.copy(info_to_copy)
+ messagebox.showinfo("Copied!", f"The {info_type.lower()} for '{item_values[0]}' has been copied to your clipboard.", parent=all_passwords_window)
+
+ # a frame for the buttons
+ button_frame = ttk.Frame(all_passwords_window)
+ button_frame.grid(row=1, column=0, columnspan=2, pady=(10,0))
+
+ copy_email_button = ttk.Button(button_frame, text="Copy Email", style="success.TButton", command=lambda: copy_selected_info(1, "Email"))
+ copy_email_button.pack(side=tk.LEFT, padx=5)
+
+ copy_password_button = ttk.Button(button_frame, text="Copy Password", style="success.TButton", command=lambda: copy_selected_info(2, "Password"))
+ copy_password_button.pack(side=tk.LEFT, padx=5)
+
+ all_passwords_window.grab_set() # makes window modal
+
+# ---------------------------- UI SETUP ------------------------------- #
+window = ttk.Window(themename="superhero")
+window.title("Password Manager")
+window.config(padx=50, pady=50)
+
+# logo
+canvas = tk.Canvas(width=200, height=200, highlightthickness=0)
+logo_img = tk.PhotoImage(file="logo.png")
+canvas.create_image(100, 100, image=logo_img)
+canvas.grid(row=0, column=1, pady=(0, 20))
+
+# labels
+website_label = ttk.Label(text="Website:", font=(FONT_NAME, 12))
+website_label.grid(row=1, column=0, sticky="W")
+email_label = ttk.Label(text="Email/Username:", font=(FONT_NAME, 12))
+email_label.grid(row=2, column=0, sticky="W")
+password_label = ttk.Label(text="Password:", font=(FONT_NAME, 12))
+password_label.grid(row=3, column=0, sticky="W")
+
+# entries
+website_entry = ttk.Entry(width=32)
+website_entry.grid(row=1, column=1, pady=5, sticky="EW")
+website_entry.focus()
+email_entry = ttk.Entry(width=50)
+email_entry.grid(row=2, column=1, columnspan=2, pady=5, sticky="EW")
+email_entry.insert(0, "example@email.com")
+password_entry = ttk.Entry(width=32)
+password_entry.grid(row=3, column=1, pady=5, sticky="EW")
+
+# buttons
+search_button = ttk.Button(text="Search", width=14, command=find_password, style="info.TButton")
+search_button.grid(row=1, column=2, sticky="EW", padx=(5,0))
+generate_password_button = ttk.Button(text="Generate Password", command=generate_password, style="success.TButton")
+generate_password_button.grid(row=3, column=2, sticky="EW", padx=(5,0))
+add_button = ttk.Button(text="Add", width=43, command=save, style="primary.TButton")
+add_button.grid(row=4, column=1, columnspan=2, pady=(10,0), sticky="EW")
+
+view_all_button = ttk.Button(text="View All Passwords", command=view_all_passwords, style="secondary.TButton")
+view_all_button.grid(row=5, column=1, columnspan=2, pady=(10,0), sticky="EW")
+
+
+window.mainloop()
+
diff --git a/Password Manager Using Tkinter/requirements.txt b/Password Manager Using Tkinter/requirements.txt
new file mode 100644
index 00000000000..60ffacab8a4
--- /dev/null
+++ b/Password Manager Using Tkinter/requirements.txt
@@ -0,0 +1 @@
+ttkbootstrap
\ No newline at end of file
diff --git a/Tic-Tac-Toe Games/tic-tac-toe1.py b/Tic-Tac-Toe Games/tic-tac-toe1.py
index f9825207079..4f87c72b7c6 100644
--- a/Tic-Tac-Toe Games/tic-tac-toe1.py
+++ b/Tic-Tac-Toe Games/tic-tac-toe1.py
@@ -28,11 +28,13 @@ def print_board(board: Board) -> None:
def check_winner(board: Board, player: str) -> bool:
"""Return True if `player` has won."""
for i in range(3):
- if all(board[i][j] == player for j in range(3)) or \
- all(board[j][i] == player for j in range(3)):
+ if all(board[i][j] == player for j in range(3)) or all(
+ board[j][i] == player for j in range(3)
+ ):
return True
- if all(board[i][i] == player for i in range(3)) or \
- all(board[i][2 - i] == player for i in range(3)):
+ if all(board[i][i] == player for i in range(3)) or all(
+ board[i][2 - i] == player for i in range(3)
+ ):
return True
return False
@@ -86,5 +88,6 @@ def main() -> None:
if __name__ == "__main__":
import doctest
+
doctest.testmod()
main()
diff --git a/Tic-Tac-Toe Games/tic-tac-toe3.py b/Tic-Tac-Toe Games/tic-tac-toe3.py
index f7a4fe3d5b7..92c60d494e6 100644
--- a/Tic-Tac-Toe Games/tic-tac-toe3.py
+++ b/Tic-Tac-Toe Games/tic-tac-toe3.py
@@ -21,11 +21,13 @@
def check_winner(board: Board, player: str) -> bool:
"""Check if `player` has a winning line on `board`."""
for i in range(3):
- if all(board[i][j] == player for j in range(3)) or \
- all(board[j][i] == player for j in range(3)):
+ if all(board[i][j] == player for j in range(3)) or all(
+ board[j][i] == player for j in range(3)
+ ):
return True
- if all(board[i][i] == player for i in range(3)) or \
- all(board[i][2 - i] == player for i in range(3)):
+ if all(board[i][i] == player for i in range(3)) or all(
+ board[i][2 - i] == player for i in range(3)
+ ):
return True
return False
@@ -116,16 +118,19 @@ def ai_move() -> None:
# --- Initialize GUI ---
root = ctk.CTk()
root.title("Tic-Tac-Toe")
-board: Board = [[" "]*3 for _ in range(3)]
+board: Board = [[" "] * 3 for _ in range(3)]
buttons: List[List[ctk.CTkButton]] = []
for i in range(3):
row_buttons: List[ctk.CTkButton] = []
for j in range(3):
btn = ctk.CTkButton(
- root, text=" ", font=("normal", 30),
- width=100, height=100,
- command=lambda r=i, c=j: make_move(r, c)
+ root,
+ text=" ",
+ font=("normal", 30),
+ width=100,
+ height=100,
+ command=lambda r=i, c=j: make_move(r, c),
)
btn.grid(row=i, column=j, padx=2, pady=2)
row_buttons.append(btn)
@@ -133,5 +138,6 @@ def ai_move() -> None:
if __name__ == "__main__":
import doctest
+
doctest.testmod()
root.mainloop()
diff --git a/Tic-Tac-Toe Games/tic-tac-toe6.py b/Tic-Tac-Toe Games/tic-tac-toe6.py
index 329675be2c9..294f6fa0a17 100644
--- a/Tic-Tac-Toe Games/tic-tac-toe6.py
+++ b/Tic-Tac-Toe Games/tic-tac-toe6.py
@@ -62,9 +62,14 @@ def check_win(player_pos: Dict[str, List[int]], cur_player: str) -> bool:
False
"""
soln = [
- [1, 2, 3], [4, 5, 6], [7, 8, 9], # Rows
- [1, 4, 7], [2, 5, 8], [3, 6, 9], # Columns
- [1, 5, 9], [3, 5, 7] # Diagonals
+ [1, 2, 3],
+ [4, 5, 6],
+ [7, 8, 9], # Rows
+ [1, 4, 7],
+ [2, 5, 8],
+ [3, 6, 9], # Columns
+ [1, 5, 9],
+ [3, 5, 7], # Diagonals
]
return any(all(pos in player_pos[cur_player] for pos in combo) for combo in soln)
diff --git a/Timetable_Operations.py b/Timetable_Operations.py
index 18b9218f561..630ef597417 100644
--- a/Timetable_Operations.py
+++ b/Timetable_Operations.py
@@ -67,5 +67,6 @@ def calculate() -> None:
if __name__ == "__main__":
import doctest
+
doctest.testmod()
root.mainloop()
diff --git a/simple_calculator.py b/simple_calculator.py
index 3464389ca3e..8864d9b2f60 100644
--- a/simple_calculator.py
+++ b/simple_calculator.py
@@ -14,6 +14,7 @@
4.0
"""
+
def add(x: float, y: float) -> float:
"""Return the sum of x and y."""
return x + y
@@ -41,17 +42,17 @@ def calculator() -> None:
while True:
choice: str = input("Enter choice (1/2/3/4): ").strip()
- if choice in ('1', '2', '3', '4'):
+ if choice in ("1", "2", "3", "4"):
num1: float = float(input("Enter first number: "))
num2: float = float(input("Enter second number: "))
- if choice == '1':
+ if choice == "1":
print(f"{num1} + {num2} = {add(num1, num2)}")
- elif choice == '2':
+ elif choice == "2":
print(f"{num1} - {num2} = {subtract(num1, num2)}")
- elif choice == '3':
+ elif choice == "3":
print(f"{num1} * {num2} = {multiply(num1, num2)}")
- elif choice == '4':
+ elif choice == "4":
print(f"{num1} / {num2} = {divide(num1, num2)}")
break
else:
@@ -60,5 +61,6 @@ def calculator() -> None:
if __name__ == "__main__":
import doctest
+
doctest.testmod()
calculator()
diff --git a/smart_file_organizer.py b/smart_file_organizer.py
index 3150251678e..d9062c9fc93 100644
--- a/smart_file_organizer.py
+++ b/smart_file_organizer.py
@@ -68,7 +68,9 @@ def organize_files(base_path: str) -> None:
Args:
base_path: Path of the directory to organize.
"""
- files = [f for f in os.listdir(base_path) if os.path.isfile(os.path.join(base_path, f))]
+ files = [
+ f for f in os.listdir(base_path) if os.path.isfile(os.path.join(base_path, f))
+ ]
if not files:
print(f"[{datetime.now().strftime('%H:%M:%S')}] No files found in {base_path}")
return
@@ -82,9 +84,13 @@ def organize_files(base_path: str) -> None:
try:
shutil.move(source, os.path.join(target_folder, file_name))
- print(f"[{datetime.now().strftime('%H:%M:%S')}] Moved: {file_name} -> {category}/")
+ print(
+ f"[{datetime.now().strftime('%H:%M:%S')}] Moved: {file_name} -> {category}/"
+ )
except Exception as e:
- print(f"[{datetime.now().strftime('%H:%M:%S')}] Error moving {file_name}: {e}")
+ print(
+ f"[{datetime.now().strftime('%H:%M:%S')}] Error moving {file_name}: {e}"
+ )
def main() -> None:
@@ -92,16 +98,12 @@ def main() -> None:
parser = argparse.ArgumentParser(
description="Organize files in a directory into categorized subfolders."
)
- parser.add_argument(
- "--path",
- required=True,
- help="Directory path to organize."
- )
+ parser.add_argument("--path", required=True, help="Directory path to organize.")
parser.add_argument(
"--interval",
type=int,
default=0,
- help="Interval (in minutes) to repeat automatically (0 = run once)."
+ help="Interval (in minutes) to repeat automatically (0 = run once).",
)
args = parser.parse_args()
diff --git a/time_delta.py b/time_delta.py
index 9b46d34f79f..dc9d479303d 100644
--- a/time_delta.py
+++ b/time_delta.py
@@ -1,7 +1,7 @@
"""
Time Delta Calculator
-This module provides functionality to calculate the absolute difference
+This module provides functionality to calculate the absolute difference
in seconds between two timestamps in the format: Day dd Mon yyyy hh:mm:ss +xxxx
"""
# -----------------------------------------------------------------------------
@@ -31,7 +31,6 @@
# 88200
# ------------------------------------------------------------------------------
-
import datetime
from typing import List, Tuple
@@ -39,10 +38,10 @@
def parse_timestamp(timestamp: str) -> datetime.datetime:
"""
Parse a timestamp string into a datetime object.
-
+
Args:
timestamp: String in the format "Day dd Mon yyyy hh:mm:ss +xxxx"
-
+
Returns:
A datetime object with timezone information
"""
@@ -54,18 +53,18 @@ def parse_timestamp(timestamp: str) -> datetime.datetime:
def calculate_time_delta(t1: str, t2: str) -> int:
"""
Calculate the absolute time difference between two timestamps in seconds.
-
+
Args:
t1: First timestamp string
t2: Second timestamp string
-
+
Returns:
Absolute time difference in seconds as an integer
"""
# Parse both timestamps
dt1 = parse_timestamp(t1)
dt2 = parse_timestamp(t2)
-
+
# Calculate absolute difference and convert to seconds
time_difference = abs(dt1 - dt2)
return int(time_difference.total_seconds())
@@ -74,7 +73,7 @@ def calculate_time_delta(t1: str, t2: str) -> int:
def read_test_cases() -> Tuple[int, List[Tuple[str, str]]]:
"""
Read test cases from standard input.
-
+
Returns:
A tuple containing:
- Number of test cases
@@ -83,12 +82,12 @@ def read_test_cases() -> Tuple[int, List[Tuple[str, str]]]:
try:
num_test_cases = int(input().strip())
test_cases = []
-
+
for _ in range(num_test_cases):
timestamp1 = input().strip()
timestamp2 = input().strip()
test_cases.append((timestamp1, timestamp2))
-
+
return num_test_cases, test_cases
except ValueError as e:
raise ValueError("Invalid input format") from e
@@ -100,11 +99,11 @@ def main() -> None:
"""
try:
num_test_cases, test_cases = read_test_cases()
-
+
for t1, t2 in test_cases:
result = calculate_time_delta(t1, t2)
print(result)
-
+
except ValueError as e:
print(f"Error: {e}")
except Exception as e:
diff --git a/to check leap year.py b/to check leap year.py
index ece26a6ecca..c54b3719527 100644
--- a/to check leap year.py
+++ b/to check leap year.py
@@ -15,6 +15,7 @@
False
"""
+
def is_leap_year(year: int) -> bool:
"""
Return True if year is a leap year, False otherwise.
@@ -29,6 +30,7 @@ def is_leap_year(year: int) -> bool:
if __name__ == "__main__":
import doctest
+
doctest.testmod()
year_input = input("Enter a year: ").strip()