I'm trying to figure out the problem in this short paragraph of code. Any help would be appreciated. Regardless of what I specify User.email to be, it always returns false.
def add(self):
#1 -- VALIDATE EMAIL ADDRESS
#Check that e-mail has been completed
try:
#Validate if e-mail address is in correct format
if (isAddressValid(self.email) == 0):
self.errors['email'] = 'You have entered an invalid e-mail address';
return 0
except NameError:
self.errors['email'] = 'Please enter your e-mail'
return 0
>>> u = User()
>>> u.email = 'test#example.com'
>>> u.add()
0
>>> print u.errors
{'email': 'Please enter your e-mail'}
I have confirmed that the false being returned is coming from except NameError.
Also, isAddressValid() is just a method to check the structure of an e-mail address.
Thanks.
You haven't included a return statement for the positive case... Also, when a function doesn't include a return statement, the caller receives None instead...
def add(self):
#1 -- VALIDATE EMAIL ADDRESS
#Check that e-mail has been completed
try:
#Validate if e-mail address is in correct format
if (isAddressValid(self.email) == 0):
self.errors['email'] = 'You have entered an invalid e-mail address';
return False
except NameError:
self.errors['email'] = 'Please enter your e-mail'
return False
return True
Actually you have two values.
0
None
If you print the value instead of using it in an if-statement, you'll see the two conditions. Consider adding print statements to see what the value actually is.
if (isAddressValid(self.email) == 0):
If this is True, you get 0.
If this is False, you'll get None.
And the exception give 0.
If I were re-writing this code, I would go for something like this:
def add(self):
try:
if not isAddressValid(self.email):
self.errors['email'] = 'You have entered an invalid e-mail address';
except NameError:
self.errors['email'] = 'Please enter your e-mail'
return 'email' not in self.errors
Im not sure what problem you are talking about , but you are always returning 0
Try adding an else clause for the case of the Valid Email (which you are currently not considering)
def add(self):
#1 -- VALIDATE EMAIL ADDRESS
#Check that e-mail has been completed
try:
#Validate if e-mail address is in correct format
if (isAddressValid(self.email) == 0):
self.errors['email'] = 'You have entered an invalid e-mail address';
return 0
else
return 1
except NameError:
self.errors['email'] = 'Please enter your e-mail'
return 0
You said isAddressValid is a method, right? Since add is also a method, perhaps you have to prepend a self.:
if (self.isAddressValid(self.email) == 0):
This most probably will deal with your NameError.
After that, add an else clause when the check succeeds:
…
self.errors['email'] = 'You have entered an invalid e-mail address'
return 0
else:
return 1
Related
I have been doing an online Python course and the final exercise was to check a list of email addresses for invalid addresses.
The code is
def has_invalid_characters(string):
valid = "abcdefghijklmnopqrstuvwxyz0123456789."
# your code here
for i in string:
if i not in valid:
return True
else:
return False
def is_valid(email):
if email.count("#") != 1:
return False
prefix, domain = email.split("#")
if len(prefix) == 0:
return False
if domain.count(".") != 1:
return False
domain_name, extension = domain.split(".")
if len(domain_name) == 0 or len(extension) == 0:
return False
if has_invalid_characters(prefix) == True:
return False
if has_invalid_characters(domain) == True:
return False
else:
return True
emails = [
"test#example.com",
"valid#gmail.com",
"invalid#gmail",
"invalid",
"not an email",
"invalid#email",
"!#/",
"test##example.com",
"test#.com",
"test#site.",
"#example.com",
"an.example#test",
"te#st#example.com",
"test#exam!ple.com"
]
for i in emails:
is_valid(i)
if i == True:
print(i + " is valid")
else:
print(i + " is invalid")
When I run this I am told that the first two email addresses, which should be reported as valid, are invalid, but I cannot figure out why. I have gone over it a few times and cannot see an error in the logic. I have also run it on my laptop and I get the same result.
In the course this code was written in steps and with the last step to change the for loop from simply printing the email addresses to validating them and everything until I modified the for was marked as correct.
I would be grateful if someone could point out the issue with this code to me.
I found the issue. My call to the is_valid() function was not correct.
it should be
for i in emails:
result = is_valid(i)
if result == True:
.....
Sorry for troubling you with this.
I'm new to python I got a question that might be easy but i can't get it.
i wanted to make aprogram that user gives email as username and password as password ,the program should check if email is in corect format and if its not it should print something and get email again so i used regex (Im giving this inputs to database and i thought using LIKE query but i don't think that might help)
so whats the problem with my code?!it keeps wrong email
import re
regex = r'\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
def check(email):
if (re.fullmatch(regex, email)):
return
else:
print("corect format is like amireza#gmail.com")
return
while __name__ == '__main__':
username = input()
check(username)
password = input()
here is a working code for you:
import re
regex = r'\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
def check(email):
if (re.fullmatch(regex, email)):
return True
else:
print("invalid input! correct format is like amireza#gmail.com")
return False
while __name__ == '__main__':
while True:
username = input("please enter email\n")
if check(username) is True:
break
password = input("please enter password\n")
break
print("username: %s, password: %s" % (username, password))
key correction:
your helper should return a boolean which lets you know if the input is legit or not. thus I returned a boolean to outside scope
one more thing: since you run it as a standalone script, the outermost while condition (while __name__ == '__main__') will always be True, which means you have to break out of it when you want to end your program execution. For simplicity I'd suggest using if __name__ == '__main__' instead
You could change your function check to return a boolean output that tells you whether the check was successful, as in
def check(email):
if (re.fullmatch(regex, email)):
return True
else:
print("corect format is like amireza#gmail.com")
return False
And then add a loop to your main code:
if __name__ == '__main__':
username = input()
while not check(username):
username = input()
Note that I did not actually run your code, but this should work.
EDIT: Heh, right, as the other answer explains, you should change your while into an if, I edited my code correspondingly.
I've written a method for hashing passwords by using hashlib.
I allow the user to send a password through a POST method, which is received by Flask and the password is subsequently hashed so that the hash can be checked against a stored var to see if it's the same.
It works great both when a correct or an incorrect password is sent for the first time.
But if the user sends a wrong password on the first POST and then tries again with the correct password, it fails. (One could also think of it as failing if the first try was a success and the user keeps on trying, but I don't care about that for now.)
I was able to narrow the problem down to hashlibs update function
hash.update(arg)
Update the hash object with the string arg. Repeated calls are equivalent to a single call with the concatenation of all the arguments: m.update(a); m.update(b) is equivalent to m.update(a+b).
I wanted to know how can I disable the concatenation upon repeated calls.
It doesn't matter if it's a hacky workaround.
Here's my code in case it's useful:
h = hashlib.sha256()
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h.update(passwordBytes)
if h.hexdigest() != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
Additional notes:
the "r.set" line (above the last one) is just because it later does something with Redis.
i've checked that passwordBytes always returns the same encoding when the same password is provided (it's deterministic)
i've also checked that h.hexdigest() is returning something different if the same password is provided on the first try or on another try. So taking into account these two points, we can be sure that the problem lies in h.update(), probably because of the concatenation feature.
Just move the first line out of the global scope into the auth() function:
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h = hashlib.sha256()
h.update(passwordBytes)
if h.hexdigest() != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
or even better, refactor the hashing of the password to a different function:
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
def hash_password(password):
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h = hashlib.sha256()
h.update(passwordBytes)
return h.hexdigest()
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
if hash_password(password) != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
I have two files and I want to store in Username.txt, but my function just drops me a "None".
def username_input(user):
user_len = int(len(user))
while user_len > 12 or not (user.isalnum()):
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
user = input("Type a valid username: ")
user_len = int(len(user))
if user_len <= 12 and user.isalnum():
return user
with open("Username.txt", "a") as usr_txt:
usr = username_input(user = input("Type a username: "))
usr_txt.write(usr)
In python, no return or return means return None. If never enter the while user_len > 12 or not (user.isalnum()):, it will reach end and no return here, so it will get None from outside, when you call username_input.
Hope that will help you, and comment if you have further questions. : )
As #Michael Butscher said, if the username you pass the first time doesn't meet the while condition you're giving None back. To fix that you can remove the inner if check and return the username before leaving your function:
def username_input(user):
while len(user) > 12 or not (user.isalnum()):
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
user = input("Type a valid username: ")
return user
If I understand correctly, you want to ask the user for a username and then store their input in a file called Username.txt if it matches certain criteria.
The reason your code returns None at the moment is due to the conditions of the while loop not being satisfied. Because there is no default return statement after the while loop, if the while loop's conditions are not met, the function will exit and return None.
I suggest refactoring your code slightly:
def username_input():
while True:
user = input("Type a valid username: ")
if len(user) <= 12 and user.isalnum():
return user
else:
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
with open("Username.txt", "a") as usr_txt:
usr = username_input()
usr_txt.write(usr)
As a side note, this programming construct is called "loop-and-a-half". It is Python's equivalent of the "do-while" loop. See here for more information.
The task is to get a user to input a password then, using recursion, make sure it has no vowels in it. If it does then let the user re-enter the password. This is what i have so far:
def passwordCheck(pwd):
"""checks if pwd has any vowels in it."""#doc string
vowels = 'aeiou'#specifies the characters that aren't allowed
if pwd == '':
return 0
elif pwd == None:
return None#Shouldn't be necessary but just in case
elif pwd[0] not in vowels:#checks that the 1st(0th) character is not a vowel
return passwordCheck(pwd[1:])#gets rid of the 1st(0th) character and starts again
elif pwd[0] in vowels:#checks if the 1st(0th) character is a vowel
return 1#if it is, stops the function calls and returns a value
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
x = passwordCheck(password)#checks the password is valid, i.e. no vowels
while x == 1:#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
x = passwordCheck(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
I know this is probably not the most pythonic way of doing it but it works for me in most cases. I'd love to hear a better way but ideally someone can help in the same style. I don't want to just copy someones code without understanding it.
The question i have is dealing with the case where the user enters no password at all. The first if statement:
if pwd == '':
return 0
I thought it just dealt with the case when the string had been fully recursed through, i.e. no vowels, but after a minutes inspection it's obvious this applies to no password as well.
I had also tried using:
if pwd == None:
return something
Now i'm thinking the problem could be because i said:
password = str(input('######'))
but i've fiddled with that as well and still can't can't seem to make that work either! I've tried google and searching stackoverflow but no luck so if anyone has any ideas/solution they think might be helpful I'd be very grateful to hear them. Thank you very much.
My main question is:
How can i differentiate between a string that's empty because it's been recursed through and the user inputting nothing?
Solved.
ended up using
def passwordValid(pwd):
if len(pwd)>0 and passwordCheck(pwd)==0:
return pwd
else: return 'Fail'
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
y = passwordValid(password)#checks the password is valid, i.e. no vowels
while y == 'Fail':#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels or be empty.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
y = passwordValid(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
Thank you Wayne Werner for fixing the title and the main question.
This problem can be broken down into (at least) three distinct subproblems:
check whether a string contains vowels
check whether a string is a valid password (length > X and has vowels)
get a password from the user
Your code should reflect this structure. You could therefore use the following function layout:
def has_vowels(string):
if not string: # check for empty string
return False # empty strings never have vowels
# TODO we have a non-empty string at this point and can use recursion
def is_valid_password(string):
return len(string) > 0 and not has_vowels(string)
def request_password():
while True: # use an endless loop here, we don't won't to repeat
# the "input" statement. We could also change this to
# something like `for i in range(3)` to allow only a limited
# number of tries.
passwd = input('Please enter a password with no vowels in it: ')
# TODO check if input is valid, if yes, return, if no, print an error
Don't attempt to solve both problems with a single method. You have two ditinct critera: no vowels; minimum length.
def isPasswordValid(pwd):
return len(pwd) > 4 and not passwordCheck(password)
x = isPasswordValid(password)
...
You could solve this with recursion by adding another parameter which indicates how many characters have been looped through, but that is clumsy and offers no real benefit.
You can't differentiate between an empty string and an empty string. You can however set the variable to None, or to a string like "__no_string_entered_yet". That said, I don't see why you would need to, see the other answers.
I believe this does what your question asks for:
Not allow an empty password (different than a "blank" password?)
Not allow vowels in the password
I opted not use if/elif/else in favor of structuring it so that valid characters "fall through"
def pwd_check(s):
vowels = 'aeiou'
if len(s) == 0: return False # This is only valid in the first iteration
if s[0] in vowels: return False
if len(s) == 1: return True # Success: a 1 character pwd with no vowels
return pwd_check(s[1:])
I thought about putting checks in to make sure that a string like ' ' was not passed in, but I didn't see that explicitly asked for. pwd_check(password.strip()) solves this problem.
Here's how I like to do.
For the fun, I added conditions of minimum and maximum lengths for the password:
def passwordCheck(pwd,vowels = 'aeiou',minimum=5,maximum=12):
if pwd == '':
return 0,None,None
elif pwd[0] in vowels:
return -1,None,None
else:
y = passwordCheck(pwd[1:])[0]
if y==-1:
return -1,None,None
else:
return y + 1,minimum,maximum
mess = 'Please enter a password with no vowels in it: '
while True:
x,miin,maax = passwordCheckstr(input(mess))
if x==-1:
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif x==0:
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif x<miin:
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (miin,x))
elif x>maax:
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maax,x))
else:
print ('\nCongratulations, you have entered a valid password!\n'
'\nYou are now able to log on to the system with these '
'credentials.')
break
edit
Another kind of algorithm.
I wasn't satisfied to return such tuple as -1,None,None
def check_password(forbidden,minimum,maximum):
def passwordCheck(pwd,cnt=0,forbid = forbidden,
miin=minimum,maax = maximum):
# cnt is the number of preceding turns of recursion
# that have been already executed.
if pwd == '':
if cnt==0:
# cnt==0 means that it's the first turn of recursion
# since pwd is '', it means no entry has been done
return 0
elif cnt<miin:
return -3
elif cnt>maax:
return -2
elif pwd[0] in forbid:
return -1
else:
if cnt in (-3,-2,-1):
return cnt
else:
return passwordCheck( pwd[1:] , cnt+1 )
mess = 'Please enter a password with no vowels in it: '
while True:
x = str(raw_input(mess)).strip()
y = passwordCheck(x)
if y==0: # inexistent string
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif y==-1: # string contains a vowel
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif y==-2: # string too long
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maximum,len(x)))
elif y==-3: # string too short
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (minimum,len(x)))
else: # success
print ('\nCongratulations, you have entered a valid password!\n'
'You are now able to log on to the system with these credentials.')
break
# EXECUTION
check_password('aeiou',5,12)