#!/r/bin/env python3 """tkinter password generator""" import tkinter as tk import string import random DEFAULT_LENGTH = 20 DEFAULT_USE_LOWER = True DEFAULT_USE_UPPER = True DEFAULT_USE_NUMBERS = True DEFAULT_USE_SYMBOLS = True def generate_password( length=8, uselower=True, useupper=True, usenums=True, usesymbols=False ): """Create a radom password based on the options passed""" chars = [] generated_string = "" ran = random.SystemRandom() if uselower: chars.append(string.ascii_lowercase) if useupper: chars.append(string.ascii_uppercase) if usenums: chars.append(string.digits) if usesymbols: chars.append(string.punctuation) for _ in range(length): chosen_list = ran.choice(chars) chosen_char = chosen_list[ran.randint(0, len(chosen_list) - 1)] generated_string += chosen_char return generated_string class MainApp: """App window""" def __init__(self, master): master.title("Password Generator") master.resizable(False, False) master.rowconfigure([0, 1], weight=1) self.master = master # set password options variables self.options = { "pass_length": tk.IntVar(value=DEFAULT_LENGTH), "use_lower": tk.IntVar(value=DEFAULT_USE_LOWER), "use_upper": tk.IntVar(value=DEFAULT_USE_UPPER), "use_numbers": tk.IntVar(value=DEFAULT_USE_NUMBERS), "use_symbols": tk.IntVar(value=DEFAULT_USE_SYMBOLS), } # make a frame for password options and output frame_main = tk.Frame(master) frame_main.grid(row=0, column=0, sticky="ew") frame_main.columnconfigure(0, minsize=700) # make checkboxes for password options check_lower = tk.Checkbutton( frame_main, text="Include lowercase letters", variable=self.options["use_lower"], command=self.output_pass, ) check_lower.grid(row=0, column=0, sticky="w", pady=2) check_upper = tk.Checkbutton( frame_main, text="Include uppercase letters", variable=self.options["use_upper"], command=self.output_pass, ) check_upper.grid(row=1, column=0, sticky="w", pady=2) check_numbers = tk.Checkbutton( frame_main, text="Include numbers", variable=self.options["use_numbers"], command=self.output_pass, ) check_numbers.grid(row=2, column=0, sticky="w", pady=2) check_symbols = tk.Checkbutton( frame_main, text="Include symbols", variable=self.options["use_symbols"], command=self.output_pass, ) check_symbols.grid(row=3, column=0, sticky="w", pady=2) # make a scale for password length scale_length = tk.Scale( frame_main, from_=4, to=100, orient=tk.HORIZONTAL, variable=self.options["pass_length"], command=self.change_password_length, ) scale_length.set(DEFAULT_LENGTH) scale_length.grid(row=4, column=0, sticky="ew") self.label_length = tk.Label( frame_main, text=f"Password length: {DEFAULT_LENGTH}" ) self.label_length.grid(row=5, column=0) # make an entry for the resulting password self.entry_password = tk.Entry(frame_main) self.entry_password.grid(row=6, columnspan=2, sticky="ew", pady=5) # make a frame for the generate and copy buttons frame_buttons = tk.Frame(master) frame_buttons.grid(row=1, column=0) frame_buttons.columnconfigure([0, 1], weight=1, minsize=150) # make a button for generating passwords button_generate = tk.Button( frame_buttons, text="\u21BB", width=10, command=self.output_pass ) button_generate.grid(row=0, column=0, pady=5) # make a button for copying the generated password to the clipboard self.button_copy = tk.Button( frame_buttons, text="Copy to Clipboard", command=self.copy_password ) self.button_copy.grid(row=0, column=1, pady=5) self.label_copy = tk.Label(frame_buttons) self.output_pass() def change_password_length(self): """Displays the new len of the passwords and then outputs it""" password_length_text = "Password length: {self.pass_length.get()}" self.label_length.config(text=password_length_text) self.output_pass() def copy_password(self): """Copies the password to the clipboard and displays a message""" if self.entry_password.get(): self.master.clipboard_clear() self.master.clipboard_append(self.entry_password.get()) self.label_copy.grid(row=1, columnspan=2) self.flash(250, 4) def flash(self, dur, count, first=0): """Flash a message when the password gets copied to the clipboard""" if first == 0: self.button_copy.configure(state="disabled") count -= 0.5 first += 1 if count == 0: self.label_copy.grid_forget() self.button_copy.configure(state="normal") return if self.label_copy["text"]: self.label_copy.config(text="") else: self.label_copy.config(text="Password copied to clipboard!!") self.label_copy.after(dur, lambda: self.flash(dur, count - 0.5, first)) def output_pass(self): """Display the generated password""" self.entry_password.delete(0, tk.END) values = [value.get() for value in self.options.values()] if 1 in values: password = generate_password(*values) self.entry_password.insert(0, password) if __name__ == "__main__": root = tk.Tk() app = MainApp(root) root.mainloop()