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.
Related
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.
def specificChecker(someThing, checker):
if checker == None:
return someThing
elif checker == True:
return not someThing
else:
return None
def whatDoesTheCheckerSay(someThing):
if specificChecker(someThing) == someThing:
return 'The checker value was False on that one.'
elif specificChecker(someThing) == not someThing:
return 'The checker value was True on that one.'
elif specificChecker(someThing) == None:
return 'Something irregular happend. The checker value wasn\'t None or True.'
else:
return 'Something went really wrong. This doesn\'t even not work.'
reallySomeThing = input('Type in really some thing: ')
theChecker = input('Set the checker to something: ')
print(specificChecker(reallySomeThing, theChecker))
print(whatDoesTheCheckerSay(reallySomeThing)) # This can be made more efficient, right?
def one(someShit):
return someShit + ' AWWW YEAH!'
def two(someShit):
return one(someShit)
print(two(input('Type in some kind of stuff: ')))
I'm a self-taught beginner, so surely it's something awkwardly basic. I'm using the IDLE shell and have repeatedly gotten a syntax error at the second definition statement of my codes. Please help?
You cannot use the line:
elif specificChecker(someThing) == not someThing:
This must be written
elif specificChecker(someThing) != someThing:
to be valid Python.
This is also valid but is perhaps less readable:
elif (specificChecker(someThing)) == (not someThing):
After OP edit:
The new error is the mismatch in arguments (always 1) to a function that requires 2 arguments. You have to pass two arguments to specificChecker not one
Line 12: elif specificChecker(someThing) == not someThing:
If you want to check if some variable is not some variable, used is not for boolean or != for values and strings
I'm often tasked with asking users for input. I've always just written my prompts "as-needed" in my main execution scripts. This is kind of ugly, and because I often ask for the same types of input across multiple scripts, a ton of my code is just copy/pasted prompt loops. Here's what I've done in the past:
while True:
username = input("Enter New Username: ")
if ldap.search(username):
print " [!] Username already taken."
if not validator.validate_username(username):
print " [!] Invalid Username."
else:
break
I'd like to create something that can be called like:
username = prompt(prompt="Enter New Username: ",
default=None,
rules=["user_does_not_exist",
"valid_username"])
Then the prompt function looks like:
def prompt(prompt, default, rules):
while True:
retval = input(prompt)
if default and retval == "":
break
return default
if not rule_match(retval, rules):
continue
break
return retval
def rule_match(value, rules):
if "user_does_not_exist" in rules:
if not user.user_exists(value):
return False
if "valid_username" in rules:
if not validator.username(value):
return False
if "y_n_or_yes_no" in rules:
if "ignore_case" in rules:
if value.lower() not in ["y", "yes", "n", "no"]:
return False
else:
if value not in ["y", "yes", "n", "no"]:
return False
return True
An alternative I'm considering is to make a Prompt class, which would allow for more flexibility with the results. For example, if I want to convert the "y" or "n" to True or False, the above doesn't really work.
create_another = Prompt(prompt="Create another user? (y/n): ,"
default=False,
rules=["y_n_or_yes_no",
"ignore_case"]).prompt().convert_to_bool()
The other alternative I'm considering is just making individualized prompts and naming them, with each one written similar to my very original code. This doesn't actually change anything. It just serves to get these loops out of my main execution code which makes the main execution code easier to browse:
username = prompt("get_new_username")
def prompt(prompt_name):
if prompt_name == "get_new_username":
while True:
username = input("Enter New Username: ")
if ldap.search(username):
print " [!] Username already taken."
if not validator.validate_username(username):
print " [!] Invalid Username."
else:
break
return username
if prompt_name == "y_n_yes_no_ignore_case":
# do prompt
if prompt_name == "y_n_yes_no":
# do prompt
if prompt_name == "y_n":
# do prompt
if prompt_name == "y_n_ignore_case":
# do prompt
if prompt_name == "yes_no":
# do prompt
if prompt_name == "yes_no_ignore_case":
# do prompt
I realize that it's probably just a good idea to settle on one accepted "y/n" format for all of my programs, and I will. This is just for the sake of showing that, in cases where I would need a very similar but slightly different prompt, it would result in a lot of copy/pasted code (no flexibility with this method at all).
What is a good approach to writing clean, flexible, and easy-to-maintain user prompts?
(I've seen this: Asking the user for input until they give a valid response and some other responses. My question is not about how to get input and validate it, it's about how to make a flexible input system that can be reused with across multiple programs).
I once wrote a function for something similar. The explanation is in the doc-string:
def xory(question = "", setx = ["yes"], sety = ["no"], setz = [], strict = False):
"""xory([question][, setx][, sety][, setz][, strict]) -> string
Asks question. If the answer is equal to one of the elements in setx,
returns True. If the answer is equal to one of the elements in sety,
returns False. If the answer is equal to one of the elements in setz,
returns the element in setz that answer is equal to. If the answer is
not in any of the sets, reasks the question. Strict controls whether
the answer is case-sensitive. If show is True, an indication of the
acceptable answers will be displayed next to the prompt."""
if isinstance(setx, str):
setx = [setx]
if isinstance(sety, str):
sety = [sety]
if isinstance(setz, str):
setz = [setz]
if (setx[0])[0] != (sety[0])[0]:
setx = [(setx[0])[0]] + setx
sety = [(sety[0])[0]] + sety
question = question.strip(" ") + " "
while True:
if show:
shows = "[%s/%s] " % (setx[0], sety[0])
else:
shows = ""
user_input = raw_input(question + shows)
for y in [setx, sety, setz]:
for x in y:
if (user_input == x) or ((not strict) and (user_input.lower() == x.lower())):
if y is setx:
return True
elif y is sety:
return False
else:
return x
question = ""
show = True
Examples:
>>> response = xory("1 or 0?", ["1", "one", "uno"], ["0", "zero", "null"], ["quit", "exit"])
1 or 0? x
[1/0] eante
[1/0] uno
>>> print(response)
True
>>> response = xory("Is that so?")
Is that so? Who knows?
[y/n] no
>>> print(response)
False
>>> response = xory("Will you do it?", setz=["quit", "exit", "restart"])
Will you do it? hm
[y/n] quit
>>> print(response)
quit
I'd advise to write a library that contains a number of very clearly defined building blocks, each one as small and light-weight as possible, without too many assumptions baked in about how you're going to put the pieces together.
That is, I'd include one function that does the loop, but instead of passing in a set of rules, I'd allow for exactly one function to be passed in that either returns a value (if a valid input was given and after converting it in any way necessary) or raises a ValueError if the input wasn't usable. Other building blocks would implement certain checks or transformations (like resolution of 'y' and 'n' into boolean values).
This way, you would leave it completely up to the user to assemble the stuff in a way suitable for the use case.
# library:
def prompt(prompt, default, postprocess):
value = input('{} ({}): '.format(prompt, default)) or default
try:
return postprocess(value)
except ValueError:
continue
def check_lower(value):
if not value.islower():
raise ValueError()
def to_bool(value):
return value in 'yes'
# using the library:
def postprocess(value):
check_lower(value)
return to_bool(value)
prompt('Really?', 'n', postprocess)
I would create a prompt function as such:
def prompt(prompt, default=None, rules=[]):
while True:
response = input(prompt)
if response:
valid = [rule(response) for rule in rules]
if not(False in valid):
return response
else:
print('Invalid input')
else:
return default
You could then create different validation functions such as
def filterValidEmail(string):
if '#' in string:
if '.' in string.split('#')[1]:
return True
else:
return False
else:
return False
And call these functions like so:
prompt('What is your email? ', rules=[filterValidEmail])
You could also tweak this so that you can tell the user what verification they failed or disallow blank inputs.
When the Condition matches, It is printing the proper output as expected. But when the condition does not match the "if not found" part is not working.
here If condition checks the username and password both. If it satisfies, It executes the code below it, But when It does not match, It displays blank , I mean there is no Invalid Login printed , though It should get printed
passwd = {}
actual_user = {}
found = False
for row in prsnobj.result:
actual_user[row[0]] = row[1]
for i in range(1, 100):
passwd[row[0]] = row[2]
for i in range(1, 100):
if login == actual_user[i] and password == passwd[i]:
found = True
print "WELCOME !!"
if not found:
print "<h4>Invalid Login</h4>"
You can write this without a flag, using for/else:
for u, p in zip(actual_user.values(), passwd.values()):
if login == u and password == p:
print "WELCOME !!"
break
else:
print "<h4>Invalid Login</h4>"
But it may be better to use a dictionary:
logindb = {row[1]:row[2] for row in prsnobj.result}
if login in logindb and logindb[login] == password:
print "WELCOME !!"
else:
print "<h4>Invalid Login</h4>"
The relevant part of your code could be more simple expressed as this:
if a == 1:
found = True
if not found:
print "not found"
The problem with this is that you never set found to false. Even if a is not equal to 1, found is still true from the last time you found something.
So the solution is something like this:
found = False
if a == 1:
found = True
if not found:
print "not found"
for row in prsnobj.result:
logindb = {row[1]:row[2]}
#print logindb
if login in logindb and logindb[login] == password:
print "Welcome"
break
else:
print "Invalid"
break
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