-2

I created a small script for generating password in python:

# LIBRARY IMPORTS
from datetime import datetime
import random

# VARIABLES
date = datetime.now()
dateFormat = str(date.strftime("%d-%m-%Y %H:%M:%S"))
lowerCase = "abcdefghijklmnopqrstuvwxyz"
upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
numbers = "0123456789"
symbols = "!?%&@#+*/()=<>-_"
passwordConstructor = lowerCase + upperCase + numbers + symbols
minPasswordLength: int = 8
maxPasswordLength: int = 20


# FUNCTIONS
def getUsername():
    global userName
    userName = str(input("Enter Username:"))


def getPasswordLength():
    global passwordLength
    passwordLength = input("Enter the length of password: ")


def generatePassword():
    global password
    password = "".join([random.choice(passwordConstructor) for i in range(passwordLength)])
    print("1." + password)
    password = ''.join(random.sample(password,len(password)))
    print("2." + password)
    password = ''.join(random.sample(password, len(password)))
    print("3." + password)


def generateTextFile():
    if userName != "":
        f = open(userName.upper() + " - " + dateFormat + ".txt", "w+")
        f.write("USERNAME: " + userName + "\nPASSWORD: " + password + "\n\nGENERATED ON: " + dateFormat)
    else:
        f = open("Password generated on " + dateFormat + ".txt", "w+")
        f.write("PASSWORD: " + password + "\n\nGENERATED ON: " + dateFormat)
    f.close()


def printPassword():
    generatePassword()
    print(password)


if getPasswordLength() == '':
        print("Please enter a value. This cannot be empty.")
else:
    if not getPasswordLength().isdigit():
        print("Length of password must be a number.")
    else:
        if getPasswordLength() > maxPasswordLength:
            print('Length of password is limited to ' + maxPasswordLength)
        elif getPasswordLength() < minPasswordLength:
            print('Length of password must be grater than ' + minPasswordLength)
        else:
            generatePassword()

But condition doesn't work and end up in an error. What I am doing wrong?

Conditions for User Input which should be covered:

  1. Cannot be empty.
  2. Must be number.
  3. Greater than minPasswordLength (8).
  4. Smaller than maxPasswordLength (20).
petezurich
  • 9,280
  • 9
  • 43
  • 57
  • 1
    You are missing `return` statements in your functions. – Axe319 Sep 06 '22 at 19:08
  • What is the error? Have you done any [debugging](//ericlippert.com/2014/03/05/how-to-debug-small-programs/)? [Step through your code in a debugger](/q/25385173/843953), observe how your variables change, identify where your program diverges from your expectations, and work backwards from there. Please take the [tour], read [what's on-topic here](/help/on-topic), [ask], and the [question checklist](//meta.stackoverflow.com/q/260648/843953), and provide a [mre]. – Pranav Hosangadi Sep 06 '22 at 19:08
  • 1
    There are multiple issues here but from a cursory glance: `getPasswordLength() > maxPasswordLength` is going to raise exceptions because you're comparing a `None` to an `int`. Also, you keep asking for password length every time, which is probably not what you want to do. – wkl Sep 06 '22 at 19:09
  • 1
    It is a [bad idea to use global variables](/q/19158339/843953) when better options exist (such as @Axe319's `return` suggestion) – Pranav Hosangadi Sep 06 '22 at 19:11
  • 1
    @Axe319 fair, that comparison of `None` to `int` will raise exceptions as well anywya. – wkl Sep 06 '22 at 19:12
  • How this should look like, so it works? – Stephan Koenig Sep 06 '22 at 19:15

3 Answers3

1

When you add the max and min password length to the string at the end you must declare them to be a string. It should look like this:

print('Length of password is limited to ' + str(maxPasswordLength))

That's the only immediate issue that I can see, however from my experience I know that it has to be done every time an integer or numeric value is added to a string so you will have to amend any other instances where this happens.

Hope this works :)

iced
  • 317
  • 3
  • 12
0

There are a couple issues here in your code, as others have mentioned, including issues of comparisons between different types, namely comparing the input provided by the user and the min and max password lengths.

You also do not have a loop to re-prompt the user to enter a password length again if it does not satisfy the constraints, which I am not sure was your intended aim. I have adapted your existing code below and enclosed the modified logic in a while loop so that the user will continue to be prompted to enter a password length that satisfies the constraints.

# LIBRARY IMPORTS
from datetime import datetime
import random

# VARIABLES
date = datetime.now()
dateFormat = str(date.strftime("%d-%m-%Y %H:%M:%S"))
lowerCase = "abcdefghijklmnopqrstuvwxyz"
upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
numbers = "0123456789"
symbols = "!?%&@#+*/()=<>-_"
passwordConstructor = lowerCase + upperCase + numbers + symbols
minPasswordLength: int = 8
maxPasswordLength: int = 20


# FUNCTIONS
def getUsername():
    global userName
    userName = str(input("Enter Username:"))


def getPasswordLength():
    global passwordLength
    passwordLength = input("Enter the length of password: ")


def generatePassword():
    global password
    password = "".join([random.choice(passwordConstructor) for i in range(passwordLength)])
    print("1." + password)
    password = ''.join(random.sample(password,len(password)))
    print("2." + password)
    password = ''.join(random.sample(password, len(password)))
    print("3." + password)


def generateTextFile():
    if userName != "":
        f = open(userName.upper() + " - " + dateFormat + ".txt", "w+")
        f.write("USERNAME: " + userName + "\nPASSWORD: " + password + "\n\nGENERATED ON: " + dateFormat)
    else:
        f = open("Password generated on " + dateFormat + ".txt", "w+")
        f.write("PASSWORD: " + password + "\n\nGENERATED ON: " + dateFormat)
    f.close()


def printPassword():
    generatePassword()
    print(password)

while True:

    getPasswordLength()

    if passwordLength == "":
        print("Please enter a value. This cannot be empty.")
        continue

    try:
        passwordLength = int(passwordLength)
    
    except ValueError:
        print("Length of password must be an integer.")
        continue

    if passwordLength > maxPasswordLength:
        print(f"Length of password is limited to {maxPasswordLength}")
        
    elif passwordLength < minPasswordLength:
        print(f'Length of password must be grater than {minPasswordLength}')
        
    else:
        generatePassword()
        break

As mentioned by other users, global variables should be avoided if possible, and for your code the same result can be achieved in perhaps a more "pythonic" way without using global variables. I have not changed it in my answer but could be something to think about.

H_Boofer
  • 413
  • 1
  • 3
  • 13
  • Wow, now I got it. This was what I was looking for. Like all of you advised, I try to avoid global variable and switched to return. Please look my answer. – Stephan Koenig Sep 06 '22 at 21:38
  • And also whats "f'" means eg in: print(f'Length of password must be grater than {minPasswordLength}') – Stephan Koenig Sep 06 '22 at 21:56
  • @StephanKoenig, the `f` at the beginning of the string is to indicate that it is an f-string (formatted string literal). Have a look here at the docs for how it is used https://docs.python.org/3/tutorial/inputoutput.html. Essentially it's a way of using variable values in a string; as has also been suggested you can also do something like `"..." + str(minPasswordLength)"`. Also, if the answer has solved your issue please mark it as accepted. – H_Boofer Sep 06 '22 at 22:21
0

I switched from global variable to return and ended up with:

# Simple password generator created by akatsuki

# LIBRARY IMPORTS
from datetime import datetime
import random

# VARIABLES
date = datetime.now()
dateFormat = str(date.strftime("%d-%m-%Y %H:%M:%S"))
lowerCase = "abcdefghijklmnopqrstuvwxyz"
upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
numbers = "0123456789"
symbols = "!?%&@#+*/()=<>-_"
passwordConstructor = lowerCase + upperCase + numbers + symbols
minPasswordLength: int = 8
maxPasswordLength: int = 20


# FUNCTIONS
def getUsername():
    userName = str(input("Enter Username:"))
    return userName


def getPasswordLength():
    passwordLength: str = input("Enter the length of password: ")
    return passwordLength


def generatePassword():
    password = "".join([random.choice(passwordConstructor) for i in range(getPasswordLength())])
    print("1." + password)
    password = ''.join(random.sample(password,len(password)))
    print("2." + password)
    password = ''.join(random.sample(password, len(password)))
    print("3." + password)
    return password


def generateTextFile():
    if getUsername() != "":
        f = open(getUsername().upper() + " - " + dateFormat + ".txt", "w+")
        f.write("USERNAME: " + getUsername() + "\nPASSWORD: " + generatePassword() + "\n\nGENERATED ON: " + dateFormat)
    else:
        f = open("Password generated on " + dateFormat + ".txt", "w+")
        f.write("PASSWORD: " + generatePassword() + "\n\nGENERATED ON: " + dateFormat)
    f.close()


def printPassword():
    generatePassword()
    print(generatePassword())


while True:
    getUsername()
    getPasswordLength()

    if getPasswordLength() == "":
        print("Please enter a value. This cannot be empty.")
        continue

    try:
        getPasswordLength() = int(getPasswordLength())

    except ValueError:
        print("Length of password must be an integer.")
        continue

    if getPasswordLength() > maxPasswordLength:
        print(f"Length of password is limited to {maxPasswordLength}")

    elif getPasswordLength() < minPasswordLength:
        print(f'Length of password must be grater than {minPasswordLength}')

    else:
        generatePassword()
        generateTextFile()
        break

But in line:

    try:
        getPasswordLength() = int(getPasswordLength())

I got following error: "Cannot assign to function call"

How this can be solved?

  • I know the error is thrown, because I try to assign a variable to a function. But I also tried something like that: pass1 = getPasswordLength() try: pass1 = int(getPasswordLength()) and vice versa. But it didn't solve it. – Stephan Koenig Sep 06 '22 at 22:19
  • The problem is that you keep calling your function, which will ask the user again for a different password length. You should store the return value of the function in a variable as you have, then test if this value satisfies your constraint. So for example, once you have `pass1 = getPasswordLength()`, then you should use this variable, so `try: pass1 = int(pass1)` and `if pass1 > maxPasswordLength` for example. This will also have to be addressed throughout your other functions. I suggest reading some basic resources on how Python functions work. – H_Boofer Sep 06 '22 at 22:29