0

I'm currently working on v1 of a password generator. I've been working on the visual elements, and now started working on the actual password generation. I've been coding this on my android device using pydroid 3 and tkinter.

I made the program to have three tickboxes for uppercase, numbers and special characters; along with an input field for the desired password length. I created the first if-statement that is executed when all the tickboxes are selected, but testing it results in a "PY_VAR4" result when tapping the Generation button, the 4 increasing every time the button is pressed (PY_VAR4, PY_VAR5, etc).

Do y'all have any suggestions for how I can fix this? I tried playing around with different ways to change the text of the result label using variables or a label["text"] = "text" code but that doesn't seem to resolve the issue. I also tested the password length variable (plugging it directly into the result label) and the tick box variables and it seems to work. I've come to the conclusion that it must be something within the if statement or generation code, but I haven't been able to figure out what it might be. I'm not sure what else to test and play around with at this point.

Here's the code:

import tkinter as tk
import random
import string


#randomized password based on ticked boxes
def final(event):
    password = tk.StringVar(value="")
    password_length = size.get()    
    if uppercase_on == True and special_chars_on == True and numbers_on == True:
        characters = string.ascii_letters + string.digits + string.punctuation
        password = "".join(secret.choice(characters) for i in range(password_length))
    result["textvariable"] = password

        
        
# start of gui
window = tk.Tk()

# some variables.
no_result = tk.StringVar(value="")

# title
title_text = tk.Label(
text="Aero's Pawsword Generator",
fg="brown",
bg="grey",
height=5
)

# Action prompt text
action_descriptor = tk.Label(
text="Select the appropriate option and tap Generate!",
height=5
)

#size input field + text
size_text = tk.Label(text="Size")
size = tk.Entry(
width=3,
fg="grey"
)

# uppercase tick box + variable
uppercase_on = tk.BooleanVar(value=False)
upper = tk.Checkbutton(
text="Uppercase Included",
variable=uppercase_on,
onvalue=True,
offvalue=False,
height=3
)

# special characters tick box + variable
special_chars_on = tk.BooleanVar(value=False)
special_chars = tk.Checkbutton(
text = "Special Characters Included",
variable=special_chars_on,
onvalue=True,
offvalue=False,
height=3
)

# numbers tick box + variable
numbers_on = tk.BooleanVar(value=False)
numbers = tk.Checkbutton(
text="Numbers Included",
variable=numbers_on,
onvalue=True,
offvalue=False,
height=3
)

# generate button
generate = tk.Button(
text="Generate",
width=5,
height=2,
bg="grey",
fg="brown"
)

# results label, empty until something has been generated
result = tk.Label(
textvariable=no_result,
height=5
)

# pack all elements
title_text.pack(fill=tk.X)
action_descriptor.pack(fill=tk.X)
size_text.pack(fill=tk.X)
size.pack()
upper.pack()
special_chars.pack()
numbers.pack()
generate.pack()
result.pack(fill=tk.X)

generate.bind("<Button-1>", final)

window.mainloop()
  • I'm running your code on Windows and don't see that error. I also don't see any password generated either. Are you sure you posted the latest version of your code? – GaryMBloom Nov 28 '21 at 15:11
  • Your code doesn't run the way you think it should. But I can tell you in your function call you start by setting "password" to be a StringVar and then inside the if you overwrite it to be a strong instead of assigning the result to the StringVar – GaryMBloom Nov 28 '21 at 15:16

2 Answers2

0

you have missed some ...

def final():
    password = tk.StringVar(value="")
    password_length = size.get()
    if uppercase_on.get() == True and special_chars_on.get() == True and numbers_on.get() == True:
        characters = string.ascii_letters + string.digits + string.punctuation
    for i in range(int(password_length)) :
        password.set(str(password.get())+random.choice(characters))
    no_result.set(str(password.get()))

and

# generate button
generate = tk.Button(
    text="Generate",
    width=5,
    height=2,
    bg="grey",
    fg="brown",
    command=final
)

and at last removed binding

upper.pack()
special_chars.pack()
numbers.pack()
generate.pack()
result.pack()

window.mainloop()
kaleintesh
  • 38
  • 6
  • 1
    This answer could do with an explanation. The code is too long to make it worth while to go through and check every line of code to see what you've changed. Also, an answer is less valuable without an explanation, because future users who have similar problems will have to guess at what fixed this. See [answer] for more information. – Sylvester Kruin Nov 28 '21 at 15:33
  • Thanks for the feedback, I'll keep the differences in mind ♥ – Aero Hyena Nov 28 '21 at 16:56
0

You do have issues with your final(). Here is a version that works:

#randomized password based on ticked boxes
def final(event):
    password = "" # tk.StringVar(value="")
    password_length = size.get()
    password_length = int(password_length) if password_length else 8
    characters = string.ascii_lowercase
    if uppercase_on.get():
        characters += string.ascii_uppercase
    if special_chars_on.get():
        characters += string.punctuation
    if numbers_on.get():
        characters += string.digits
    password = "".join(random.choice(characters) for i in range(password_length))
    no_result.set(password)
    # result["textvariable"] = password

A few changes to note:

  1. You were changing the type of password in your function. You started it as a StringVar and then changed it to a string inside the if. Be careful about using the same variable for more than one purpose. It makes the code harder to follow and debug. And it leads to errors.

  2. Your if was always satisfied because you have to access the value of a StringVar (or other Tkinter variable) using the .get() method. Otherwise you're getting the actual Tkinter variable which Python treats as a logical True.

  3. You needed to separate out the different components of your password. So, I assumed the default password would be 8 characters, all lower case. Then, you can override that with the checkboxes and Entry widget (for password length).

GaryMBloom
  • 5,350
  • 1
  • 24
  • 32
  • Thank you so much for this response! I'll definitely be more wary with multi-purpose variable usage! I didn't realize I jad to use the get() every time I need to access a value, thanks for clearing that up. I really appreciate the feedback and help ♥ – Aero Hyena Nov 28 '21 at 16:55
  • Also based on this I just figured out how to code with less if-arguments, thanks again for this brilliant response ♥ ♥ ♥ – Aero Hyena Nov 28 '21 at 17:01