first commit
This commit is contained in:
commit
9bc37aeae8
12
Pipfile
Normal file
12
Pipfile
Normal file
@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
pyperclip = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.12"
|
28
Pipfile.lock
generated
Normal file
28
Pipfile.lock
generated
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "8ceead135ee6991bd49b68802a159c7b7d7cfe2f2218d7a71d7a5d55b1d4cd6e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.12"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"pyperclip": {
|
||||
"hashes": [
|
||||
"sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.8.2"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
146
main.py
Normal file
146
main.py
Normal file
@ -0,0 +1,146 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import random
|
||||
import json
|
||||
import pyperclip
|
||||
from tkinter import messagebox
|
||||
from tkinter import filedialog
|
||||
|
||||
# Constants for password characters
|
||||
UPPERCASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
LOWERCASE_CHARS = 'abcdefghijklmnopqrstuvwxyz'
|
||||
DIGITS = '0123456789'
|
||||
SPECIAL_CHARS = '!@#$%^&*()-_=+[]{}|;:",.<>?/~'
|
||||
AMBIGUOUS_CHARS = 'lI1oO0'
|
||||
|
||||
class PasswordGeneratorApp:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Password Generator")
|
||||
|
||||
# Variables for password generation
|
||||
self.include_uppercase = tk.BooleanVar(value=True)
|
||||
self.include_lowercase = tk.BooleanVar(value=True)
|
||||
self.include_digits = tk.BooleanVar(value=True)
|
||||
self.include_special = tk.BooleanVar(value=True)
|
||||
self.exclude_ambiguous = tk.BooleanVar(value=False)
|
||||
self.include_every_category = tk.BooleanVar(value=False)
|
||||
self.password_length = tk.IntVar(value=12)
|
||||
|
||||
# Configure the main grid
|
||||
self.root.columnconfigure(0, weight=1)
|
||||
|
||||
# Create and place widgets
|
||||
self.create_widgets()
|
||||
|
||||
def create_widgets(self):
|
||||
# Password entry
|
||||
self.password_entry = ttk.Entry(self.root, font=('Arial', 14), width=40)
|
||||
self.password_entry.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
|
||||
|
||||
# Password settings frame
|
||||
settings_frame = ttk.LabelFrame(self.root, text="Settings", padding=10)
|
||||
settings_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")
|
||||
|
||||
# Character type checkboxes
|
||||
ttk.Checkbutton(settings_frame, text="A-Z", variable=self.include_uppercase, command=self.update_password).grid(row=0, column=0, sticky="w")
|
||||
ttk.Checkbutton(settings_frame, text="a-z", variable=self.include_lowercase, command=self.update_password).grid(row=0, column=1, sticky="w")
|
||||
ttk.Checkbutton(settings_frame, text="0-9", variable=self.include_digits, command=self.update_password).grid(row=0, column=2, sticky="w")
|
||||
ttk.Checkbutton(settings_frame, text="Special", variable=self.include_special, command=self.update_password).grid(row=0, column=3, sticky="w")
|
||||
ttk.Checkbutton(settings_frame, text="Exclude look-alike (lI1oO0)", variable=self.exclude_ambiguous, command=self.update_password).grid(row=1, column=0, columnspan=2, sticky="w")
|
||||
ttk.Checkbutton(settings_frame, text="Include every category", variable=self.include_every_category, command=self.update_password).grid(row=1, column=2, columnspan=2, sticky="w")
|
||||
|
||||
# Password length slider
|
||||
ttk.Label(settings_frame, text="Password Length:").grid(row=2, column=0, columnspan=2, sticky="w")
|
||||
self.length_slider = ttk.Scale(settings_frame, from_=4, to_=32, orient='horizontal', variable=self.password_length, command=lambda event: self.update_password())
|
||||
self.length_slider.grid(row=2, column=2, columnspan=2, sticky="ew")
|
||||
|
||||
# Buttons
|
||||
button_frame = ttk.Frame(self.root)
|
||||
button_frame.grid(row=2, column=0, padx=10, pady=10, sticky="ew")
|
||||
button_frame.columnconfigure((0, 1, 2), weight=1)
|
||||
|
||||
ttk.Button(button_frame, text="Copy", command=self.copy_to_clipboard).grid(row=0, column=0, padx=5, pady=5, sticky="ew")
|
||||
ttk.Button(button_frame, text="Save Settings", command=self.save_settings).grid(row=0, column=1, padx=5, pady=5, sticky="ew")
|
||||
ttk.Button(button_frame, text="Load Settings", command=self.load_settings).grid(row=0, column=2, padx=5, pady=5, sticky="ew")
|
||||
|
||||
# Initial password generation
|
||||
self.update_password()
|
||||
|
||||
def generate_password(self):
|
||||
# Collect selected character types
|
||||
chars = ''
|
||||
if self.include_uppercase.get():
|
||||
chars += UPPERCASE_CHARS
|
||||
if self.include_lowercase.get():
|
||||
chars += LOWERCASE_CHARS
|
||||
if self.include_digits.get():
|
||||
chars += DIGITS
|
||||
if self.include_special.get():
|
||||
chars += SPECIAL_CHARS
|
||||
if self.exclude_ambiguous.get():
|
||||
chars = ''.join(filter(lambda x: x not in AMBIGUOUS_CHARS, chars))
|
||||
|
||||
# Ensure the password includes at least one character from each selected category if required
|
||||
password = ''
|
||||
if self.include_every_category.get():
|
||||
if self.include_uppercase.get():
|
||||
password += random.choice(UPPERCASE_CHARS)
|
||||
if self.include_lowercase.get():
|
||||
password += random.choice(LOWERCASE_CHARS)
|
||||
if self.include_digits.get():
|
||||
password += random.choice(DIGITS)
|
||||
if self.include_special.get():
|
||||
password += random.choice(SPECIAL_CHARS)
|
||||
random_chars = [random.choice(chars) for _ in range(self.password_length.get() - len(password))]
|
||||
password += ''.join(random_chars)
|
||||
else:
|
||||
password = ''.join(random.choice(chars) for _ in range(self.password_length.get()))
|
||||
|
||||
return ''.join(random.sample(password, len(password)))
|
||||
|
||||
def update_password(self):
|
||||
new_password = self.generate_password()
|
||||
self.password_entry.delete(0, tk.END)
|
||||
self.password_entry.insert(0, new_password)
|
||||
|
||||
def copy_to_clipboard(self):
|
||||
password = self.password_entry.get()
|
||||
pyperclip.copy(password)
|
||||
messagebox.showinfo("Password Generator", "Password copied to clipboard!")
|
||||
|
||||
def save_settings(self):
|
||||
settings = {
|
||||
'include_uppercase': self.include_uppercase.get(),
|
||||
'include_lowercase': self.include_lowercase.get(),
|
||||
'include_digits': self.include_digits.get(),
|
||||
'include_special': self.include_special.get(),
|
||||
'exclude_ambiguous': self.exclude_ambiguous.get(),
|
||||
'include_every_category': self.include_every_category.get(),
|
||||
'password_length': self.password_length.get()
|
||||
}
|
||||
filename = filedialog.asksaveasfilename(defaultextension='.json', filetypes=[("JSON files", "*.json")])
|
||||
if filename:
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(settings, f)
|
||||
messagebox.showinfo("Password Generator", "Settings saved successfully!")
|
||||
|
||||
def load_settings(self):
|
||||
filename = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")])
|
||||
if filename:
|
||||
with open(filename, 'r') as f:
|
||||
settings = json.load(f)
|
||||
self.include_uppercase.set(settings['include_uppercase'])
|
||||
self.include_lowercase.set(settings['include_lowercase'])
|
||||
self.include_digits.set(settings['include_digits'])
|
||||
self.include_special.set(settings['include_special'])
|
||||
self.exclude_ambiguous.set(settings['exclude_ambiguous'])
|
||||
self.include_every_category.set(settings['include_every_category'])
|
||||
self.password_length.set(settings['password_length'])
|
||||
self.update_password()
|
||||
messagebox.showinfo("Password Generator", "Settings loaded successfully!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = PasswordGeneratorApp(root)
|
||||
root.mainloop()
|
Loading…
x
Reference in New Issue
Block a user