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.
Related
I've got an auto completion function that listen on key. There is an edge case in which the given list to complete from is way too long. So I want to limit the output of possible options and ask the user whether he wants to see the whole amount of possibilities.
Let's say I have this completion function and my_list has about 4000 items.
import readline
my_list = [...]
def completer(text, state):
options = [x for x in my_list if x.startswith(text)]
if state < len(options):
return options[state]
else:
return None
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)
while True:
ans = input("Please select one from the list above: ")
if ans == 'exit':
break
print(ans)
I tried to put the condition inside of def completer() like
def completer(text, state):
options = [x for x in my_list if x.startswith(text)]
if state < len(options):
if len(options) > 50:
question = input(f"Do you want to see all {len(options)} possibilities? ")
if question.lower(0) == "y":
return options[state]
else:
return None
else:
return options[state]
else:
return None
Unfortunately this doesn't work, because there is no way calling the input() function inside the input() function. Do you guys got an idea how to implement this?
I'm learning how to use Python. I have a function with a conditional inside of it, if an invalid input is provided, it should restart the loop until a valid input is provided.
Unfortunately, this "restarting" behavior is causing an infinite loop within my tests (it circularly provides the wrong input). How can I pause, or break, or limit the output to one instance so I can test the returned string?
function:
def confirm_user_choice(choice: str):
while True:
user_response = input(f"\nYou chose '{choice}', is this correct? y/n ")
if user_response == "y":
return True
elif user_response == "n":
return False
else:
print("\nSelect either 'y' (yes) or 'n' (no)")
test:
import unittest
from unittest import mock
from src.utils.utils import addValues, confirm_user_choice
class TestConfirmUserChoice(unittest.TestCase):
def test_yes(self):
with mock.patch("builtins.input", return_value="y"):
result = confirm_user_choice("y")
self.assertEqual(result, True)
def test_no(self):
with mock.patch("builtins.input", return_value="n"):
result = confirm_user_choice("n")
self.assertEqual(result, False)
def test_invalid_input(self):
with mock.patch("builtins.input", return_value="apple"): <-- triggers func else case
result = confirm_user_choice("apple")
self.assertEqual(result, False)
You have a partial function: on a proper input, it will return a Boolean value, but it may not return at all, and you can't test that an infinite loop is indeed infinite.
To make it more testable, allow the function to take an optional iterable value that defaults to sys.stdin, allowing you to control what the function reads (and how long it will attempt to do so.)
def confirm_user_choice(choice: str, responses: Optional[Iterable[str]] = None):
if responses is None:
# An infinite stream of calls to input()
responses = iter(lambda: input(f"\nYou chose '{choice}', is this correct? y/n "), None)
for user_response in responses:
if user_response == "y":
return True
elif user_response == "n":
return False
else:
print("\nSelect either 'y' (yes) or 'n' (no)")
else:
# Note: cannot be raised from the default value of responses
raise ValueError("Unexpected end of responses")
Now your test can simply pass canned lists of responses, and either catch the expected ValueError, or look at the returned Boolean value.
import unittest
from src.utils.utils import addValues, confirm_user_choice
class TestConfirmUserChoice(unittest.TestCase):
def test_yes(self):
result = confirm_user_choice("y", ["y"])
self.assertTrue(result)
def test_eventual_yes(self):
result = confirm_user_choice("y", ["apple", "pear", "y"])
self.assertTrue(result)
def test_no(self):
result = confirm_user_choice("y", ["n"])
self.assertFalse(result)
def test_no_valid_input(self):
with self.assertRaises(ValueError):
result = confirm_user_choice(["apple"])
continue does nothing in your code
continue alows you to ignore a part of the code for some instance of the loop.
For example :
for i in range(2):
if i < 1:
continue
print(i)
Output :
1
For what you want to do, don't forget while is suppose to end when a condition is meet. Hence bypassing the condition using while True: and then using a if to exit your loop is a bit counter productive.
Just use the while condition :
user_response = ""
while user_response not in ["y", "n"]:
user_response = input("y/n ? ")
print(user_response)
Happy programming
I'm new to Python myself but in my understanding, unit tests investigate how function handle different inputs based on the function's return value or exceptions raised (if any).
Your function only exits when the user inputs either "y" or "n" or when an error is raised (for instance, if the user provides Crtl-Z). Your while loop does not break when a user inputs 'apple.' There is no return value for pytest (or the like) to inspect.
If you really want to test this, you'd have to rewrite your function so that's a little more modular. It would have to feature at least three different return values, including one that implies that the input was invalid.
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'm writing my first program - it's an idiom generator, which combines individual elements from lists of random verbs, nouns, and pronouns (that I have entered) in Madlibs style and generates a humorous expression. This is a simplified version of my source code:
baseFunction = True
def mainFunction() :
import random
quest = input("Which language do you want it in? Type 'French' or 'English'. ")
if quest == "French" or "french":
verb =
#list of verbs I have manually entered
noun =
#list of nouns I have manually entered
pronoun =
#list of pronouns I have manually entered
morenouns =
#list of nouns I have manually entered
phrase = random.choice(verb) + random.choice(noun) + random.choice(pronoun) + random.choice(morenouns)
print(phrase)
print("Now, give it some meaning and use in the world!")
elif quest == "English" or "english":
verb =
#another list of verbs I have manually entered
noun =
#another list of nouns I have manually entered
pronoun =
#another list of pronouns I have manually entered
morenouns =
#another list of nouns I have manually entered
phrase = random.choice(verb) + random.choice(noun) + random.choice(pronoun) + random.choice(morenouns)
print(phrase)
print("Now, invent some meaning for it and use it in the world!")
f8 = input("Do you want to make another one? Say 'yes' if you do. ")
if f8 == "yes" or "Yes":
mainFunction()
else:
print("Thanks for playing!")
else:
print("Didn't quite catch that. Try again! (say yes!)")
mainFunction()
def malif() :
ques = input("Want to hear a funny idiom? Say 'yes' or 'no'. ")
if ques == "yes" or "Yes":
mainFunction()
elif ques == "no" or "No":
print("Wrong answer. Try again! (say yes)")
malif()
else:
print("Didn't quite catch that. Say 'yes' or 'no'.")
while baseFunction :
malif()
mainFunction()
Essentially, I am asking the user whether they want to make an idiom, offering them a choice of language, generating the expression for them, and then asking them if they want to repeat the process. When I run the script in PyCharm, it runs the two functions in order (meaning, malif() first and then mainFunction(), as I have it at the end) but it does not pay any attention to my input (ex. if I say 'no' it runs the mainFunction anyway and will always do it in French even if I say 'English').
I used some of the tips discussed in this entry (Python - How to make program go back to the top of the code instead of closing). I think the problem lies calling the functions in their own definitions (ex. calling malif() if I answer 'no' to input 'ques', which is defined in malif() ). Yet, I have followed the tips discussed in the question that I linked and it is still not working the way that I want it to. Am I doing something wrong in formatting the code (ex. in terms of indentation) or if it is not obvious what I am doing wrong, is there a way for me to loop functions back to the beginning that was not suggested in the original question?
Thanks!
First some tips when you work with strings as input. Python will make the difference between caps and non-caps letter, thus a good way to deal with strings is to lower() them first (or upper(), ...):
Example:
ques = input("Enter Yes or No: ")
ques = ques.lower()
if ques == "yes":
# do something
elif ques == "no":
# do something else
else:
# raise error
Now I feel like your code is build in a funny way. A good habit is to separate the import from the functions, from the main program. The 2 first will be imported if the module (file) is imported, while the last one will be played when the file is executed. To do so, you can use this:
# -*- coding: utf-8 -*-
"""
docstring of the module
"""
# Imports
import random
import os
# Functions
def f():
return "Hello world"
# Main program
if __name__ == '__main__':
# Calling the function, taking the inputs and so on
In the main program, it's rather useful to deal with the possibility that an exception is raised. Moreover, if you use the cmd to display your program, the cmd will close immediately when an error is raised. This syntax is quite useful:
if __name__ == '__main__':
try:
# Do stuff
except:
import sys
print (sys.exc_info()[0])
import traceback
print (traceback.format_exc())
os.system("pause") # for windows, else easy way is to have an empty input to freeze the cmd
Now your code. I would rework it this way:
# -*- coding: utf-8 -*-
"""
Docstring
"""
# Imports
import random
import os
# Functions
def build_a_phrase(language) :
if language == "french":
verb = ["vendre", "atterir", "attaquer", "jeter"]
#list of verbs I have manually entered
noun = ["arbre", "poisson", "chien"]
#list of nouns I have manually entered
pronoun = ["un", "les"]
#list of pronouns I have manually entered
morenouns = ["chat", "oiseau"]
#list of nouns I have manually entered
choices = [random.choice(verb), random.choice(noun), random.choice(pronoun), random.choice(morenouns)]
phrase = " ".join(choices) # Add a space between the words
return phrase
elif language == "english":
verb = ["...", "...", "..."]
#another list of verbs I have manually entered
noun = ["...", "...", "..."]
#another list of nouns I have manually entered
pronoun = ["...", "...", "..."]
#another list of pronouns I have manually entered
morenouns = ["...", "...", "..."]
#another list of nouns I have manually entered
choices = [random.choice(verb), random.choice(noun), random.choice(pronoun), random.choice(morenouns)]
phrase = " ".join(choices) # Add a space between the words
return phrase
if __name__ == '__main__':
try:
# Parameters
available_language = ["french", "english"]
available_answers = ["yes", "no"]
# Safety implementation of an input
quest = ""
i = 0
while quest.lower() not in available_answers:
quest = input("Want to hear a funny idiom? Say 'yes' or 'no'. ")
i += 1
if i == 2: # number of tries
break
if quest.lower() == "no":
print ("I'm sure you meant yes.")
language = ""
i = 0
while language.lower() not in available_language:
language = input("Which language do you want it in? Type 'French' or 'English'.\n")
i += 1
if i == 2: # number of tries
break
while True:
sentence = build_a_phrase(language)
print (sentence)
print ("Now, give it some meaning and use in the world!")
f8 = ""
i = 0
while f8.lower() not in available_answers:
f8 = input("Do you want to make another one? Say 'yes' if you do. ")
i += 1
if i == 2: # number of tries
break
if f8.lower() == "no":
print("Thanks for playing!")
break
except:
import sys
print (sys.exc_info()[0])
import traceback
print (traceback.format_exc())
os.system("pause")
Hope you'll get a few good tricks from this answer, and some good habits :)
Not complete yet, when the input is wrong, an Error should be raised rather than waiting for the error resulting in the wrong input (i.e. a raise statement should be placed instead of the breaks)
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)