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