1 24fae870 2025-06-12 noodle #!/usr/local/bin/python3
2 fd9c6571 2025-01-14 boredpast """tkinter password generator"""
3 fd9c6571 2025-01-14 boredpast import tkinter as tk
4 fd9c6571 2025-01-14 boredpast import string
5 fd9c6571 2025-01-14 boredpast import random
7 fd9c6571 2025-01-14 boredpast DEFAULT_LENGTH = 20
8 fd9c6571 2025-01-14 boredpast DEFAULT_USE_LOWER = True
9 fd9c6571 2025-01-14 boredpast DEFAULT_USE_UPPER = True
10 fd9c6571 2025-01-14 boredpast DEFAULT_USE_NUMBERS = True
11 fd9c6571 2025-01-14 boredpast DEFAULT_USE_SYMBOLS = True
14 fd9c6571 2025-01-14 boredpast def generate_password(
15 fd9c6571 2025-01-14 boredpast length=8, uselower=True, useupper=True, usenums=True, usesymbols=False
17 fd9c6571 2025-01-14 boredpast """Create a radom password based on the options passed"""
18 fd9c6571 2025-01-14 boredpast chars = []
19 fd9c6571 2025-01-14 boredpast generated_string = ""
20 fd9c6571 2025-01-14 boredpast ran = random.SystemRandom()
21 fd9c6571 2025-01-14 boredpast if uselower:
22 fd9c6571 2025-01-14 boredpast chars.append(string.ascii_lowercase)
23 fd9c6571 2025-01-14 boredpast if useupper:
24 fd9c6571 2025-01-14 boredpast chars.append(string.ascii_uppercase)
25 fd9c6571 2025-01-14 boredpast if usenums:
26 fd9c6571 2025-01-14 boredpast chars.append(string.digits)
27 fd9c6571 2025-01-14 boredpast if usesymbols:
28 fd9c6571 2025-01-14 boredpast chars.append(string.punctuation)
29 fd9c6571 2025-01-14 boredpast for _ in range(length):
30 fd9c6571 2025-01-14 boredpast chosen_list = ran.choice(chars)
31 fd9c6571 2025-01-14 boredpast chosen_char = chosen_list[ran.randint(0, len(chosen_list) - 1)]
32 fd9c6571 2025-01-14 boredpast generated_string += chosen_char
33 fd9c6571 2025-01-14 boredpast return generated_string
36 fd9c6571 2025-01-14 boredpast class MainApp:
37 fd9c6571 2025-01-14 boredpast """App window"""
39 fd9c6571 2025-01-14 boredpast def __init__(self, master):
40 fd9c6571 2025-01-14 boredpast master.title("Password Generator")
41 fd9c6571 2025-01-14 boredpast master.resizable(False, False)
42 fd9c6571 2025-01-14 boredpast master.rowconfigure([0, 1], weight=1)
43 fd9c6571 2025-01-14 boredpast self.master = master
45 fd9c6571 2025-01-14 boredpast # set password options variables
46 fd9c6571 2025-01-14 boredpast self.options = {
47 fd9c6571 2025-01-14 boredpast "pass_length": tk.IntVar(value=DEFAULT_LENGTH),
48 fd9c6571 2025-01-14 boredpast "use_lower": tk.IntVar(value=DEFAULT_USE_LOWER),
49 fd9c6571 2025-01-14 boredpast "use_upper": tk.IntVar(value=DEFAULT_USE_UPPER),
50 fd9c6571 2025-01-14 boredpast "use_numbers": tk.IntVar(value=DEFAULT_USE_NUMBERS),
51 fd9c6571 2025-01-14 boredpast "use_symbols": tk.IntVar(value=DEFAULT_USE_SYMBOLS),
54 fd9c6571 2025-01-14 boredpast # make a frame for password options and output
55 fd9c6571 2025-01-14 boredpast frame_main = tk.Frame(master)
56 fd9c6571 2025-01-14 boredpast frame_main.grid(row=0, column=0, sticky="ew")
57 fd9c6571 2025-01-14 boredpast frame_main.columnconfigure(0, minsize=700)
59 fd9c6571 2025-01-14 boredpast # make checkboxes for password options
60 fd9c6571 2025-01-14 boredpast check_lower = tk.Checkbutton(
61 fd9c6571 2025-01-14 boredpast frame_main,
62 fd9c6571 2025-01-14 boredpast text="Include lowercase letters",
63 fd9c6571 2025-01-14 boredpast variable=self.options["use_lower"],
64 fd9c6571 2025-01-14 boredpast command=self.output_pass,
66 fd9c6571 2025-01-14 boredpast check_lower.grid(row=0, column=0, sticky="w", pady=2)
67 fd9c6571 2025-01-14 boredpast check_upper = tk.Checkbutton(
68 fd9c6571 2025-01-14 boredpast frame_main,
69 fd9c6571 2025-01-14 boredpast text="Include uppercase letters",
70 fd9c6571 2025-01-14 boredpast variable=self.options["use_upper"],
71 fd9c6571 2025-01-14 boredpast command=self.output_pass,
73 fd9c6571 2025-01-14 boredpast check_upper.grid(row=1, column=0, sticky="w", pady=2)
74 fd9c6571 2025-01-14 boredpast check_numbers = tk.Checkbutton(
75 fd9c6571 2025-01-14 boredpast frame_main,
76 fd9c6571 2025-01-14 boredpast text="Include numbers",
77 fd9c6571 2025-01-14 boredpast variable=self.options["use_numbers"],
78 fd9c6571 2025-01-14 boredpast command=self.output_pass,
80 fd9c6571 2025-01-14 boredpast check_numbers.grid(row=2, column=0, sticky="w", pady=2)
81 fd9c6571 2025-01-14 boredpast check_symbols = tk.Checkbutton(
82 fd9c6571 2025-01-14 boredpast frame_main,
83 fd9c6571 2025-01-14 boredpast text="Include symbols",
84 fd9c6571 2025-01-14 boredpast variable=self.options["use_symbols"],
85 fd9c6571 2025-01-14 boredpast command=self.output_pass,
87 fd9c6571 2025-01-14 boredpast check_symbols.grid(row=3, column=0, sticky="w", pady=2)
89 fd9c6571 2025-01-14 boredpast # make a scale for password length
90 fd9c6571 2025-01-14 boredpast scale_length = tk.Scale(
91 fd9c6571 2025-01-14 boredpast frame_main,
92 fd9c6571 2025-01-14 boredpast from_=4,
93 fd9c6571 2025-01-14 boredpast to=100,
94 fd9c6571 2025-01-14 boredpast orient=tk.HORIZONTAL,
95 fd9c6571 2025-01-14 boredpast variable=self.options["pass_length"],
96 fd9c6571 2025-01-14 boredpast command=self.change_password_length,
98 fd9c6571 2025-01-14 boredpast scale_length.set(DEFAULT_LENGTH)
99 fd9c6571 2025-01-14 boredpast scale_length.grid(row=4, column=0, sticky="ew")
100 fd9c6571 2025-01-14 boredpast self.label_length = tk.Label(
101 fd9c6571 2025-01-14 boredpast frame_main, text=f"Password length: {DEFAULT_LENGTH}"
103 fd9c6571 2025-01-14 boredpast self.label_length.grid(row=5, column=0)
105 fd9c6571 2025-01-14 boredpast # make an entry for the resulting password
106 fd9c6571 2025-01-14 boredpast self.entry_password = tk.Entry(frame_main)
107 fd9c6571 2025-01-14 boredpast self.entry_password.grid(row=6, columnspan=2, sticky="ew", pady=5)
109 fd9c6571 2025-01-14 boredpast # make a frame for the generate and copy buttons
110 fd9c6571 2025-01-14 boredpast frame_buttons = tk.Frame(master)
111 fd9c6571 2025-01-14 boredpast frame_buttons.grid(row=1, column=0)
112 fd9c6571 2025-01-14 boredpast frame_buttons.columnconfigure([0, 1], weight=1, minsize=150)
114 fd9c6571 2025-01-14 boredpast # make a button for generating passwords
115 fd9c6571 2025-01-14 boredpast button_generate = tk.Button(
116 fd9c6571 2025-01-14 boredpast frame_buttons, text="\u21BB", width=10, command=self.output_pass
118 fd9c6571 2025-01-14 boredpast button_generate.grid(row=0, column=0, pady=5)
120 fd9c6571 2025-01-14 boredpast # make a button for copying the generated password to the clipboard
121 fd9c6571 2025-01-14 boredpast self.button_copy = tk.Button(
122 fd9c6571 2025-01-14 boredpast frame_buttons, text="Copy to Clipboard", command=self.copy_password
124 fd9c6571 2025-01-14 boredpast self.button_copy.grid(row=0, column=1, pady=5)
125 fd9c6571 2025-01-14 boredpast self.label_copy = tk.Label(frame_buttons)
127 fd9c6571 2025-01-14 boredpast self.output_pass()
129 4e6ae475 2025-06-12 noodle def change_password_length(self, newval):
130 fd9c6571 2025-01-14 boredpast """Displays the new len of the passwords and then outputs it"""
131 4e6ae475 2025-06-12 noodle self.label_length.config(text=f"Password length: {newval}")
132 fd9c6571 2025-01-14 boredpast self.output_pass()
134 fd9c6571 2025-01-14 boredpast def copy_password(self):
135 fd9c6571 2025-01-14 boredpast """Copies the password to the clipboard and displays a message"""
136 fd9c6571 2025-01-14 boredpast if self.entry_password.get():
137 fd9c6571 2025-01-14 boredpast self.master.clipboard_clear()
138 fd9c6571 2025-01-14 boredpast self.master.clipboard_append(self.entry_password.get())
139 fd9c6571 2025-01-14 boredpast self.label_copy.grid(row=1, columnspan=2)
140 fd9c6571 2025-01-14 boredpast self.flash(250, 4)
142 fd9c6571 2025-01-14 boredpast def flash(self, dur, count, first=0):
143 fd9c6571 2025-01-14 boredpast """Flash a message when the password gets copied to the clipboard"""
144 fd9c6571 2025-01-14 boredpast if first == 0:
145 fd9c6571 2025-01-14 boredpast self.button_copy.configure(state="disabled")
146 fd9c6571 2025-01-14 boredpast count -= 0.5
147 fd9c6571 2025-01-14 boredpast first += 1
148 fd9c6571 2025-01-14 boredpast if count == 0:
149 fd9c6571 2025-01-14 boredpast self.label_copy.grid_forget()
150 fd9c6571 2025-01-14 boredpast self.button_copy.configure(state="normal")
151 fd9c6571 2025-01-14 boredpast return
152 fd9c6571 2025-01-14 boredpast if self.label_copy["text"]:
153 fd9c6571 2025-01-14 boredpast self.label_copy.config(text="")
155 fd9c6571 2025-01-14 boredpast self.label_copy.config(text="Password copied to clipboard!!")
156 fd9c6571 2025-01-14 boredpast self.label_copy.after(dur, lambda: self.flash(dur, count - 0.5, first))
158 fd9c6571 2025-01-14 boredpast def output_pass(self):
159 fd9c6571 2025-01-14 boredpast """Display the generated password"""
160 fd9c6571 2025-01-14 boredpast self.entry_password.delete(0, tk.END)
161 fd9c6571 2025-01-14 boredpast values = [value.get() for value in self.options.values()]
162 fd9c6571 2025-01-14 boredpast if 1 in values:
163 fd9c6571 2025-01-14 boredpast password = generate_password(*values)
164 fd9c6571 2025-01-14 boredpast self.entry_password.insert(0, password)
167 fd9c6571 2025-01-14 boredpast if __name__ == "__main__":
168 fd9c6571 2025-01-14 boredpast root = tk.Tk()
169 fd9c6571 2025-01-14 boredpast app = MainApp(root)
170 fd9c6571 2025-01-14 boredpast root.mainloop()