diff options
author | boredpasta <boredpasta@tutanota.com> | 2025-01-14 23:49:07 +0200 |
---|---|---|
committer | boredpasta <boredpasta@tutanota.com> | 2025-01-15 01:08:54 +0200 |
commit | fd9c657133aa6ad65b3ef679d121b53795c7bd60 (patch) | |
tree | 2be1fc6010d2a8d550388d5583f148d9a1b45ee7 | |
parent | 38cc25d6d53d3ce3cbf403ae8cb9225cd31de9e3 (diff) |
-rw-r--r-- | LICENSE | 13 | ||||
-rw-r--r-- | README | 3 | ||||
-rwxr-xr-x | passgen.py | 171 |
3 files changed, 187 insertions, 0 deletions
@@ -0,0 +1,13 @@ +Copyright (c) 2025 boredpasta <boredpasta@tutanota.com> + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. @@ -0,0 +1,3 @@ +passgen - a password generator in python+tkinter + +that's all, folks (isc license) diff --git a/passgen.py b/passgen.py new file mode 100755 index 0000000..085cb98 --- /dev/null +++ b/passgen.py @@ -0,0 +1,171 @@ +#!/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() |