0

My problem is to design a Python script which requires the user to input a password, and let Python validate the password is suitable for the conditions or not.

Here are conditions for the password input by users:

  1. Begin with letters
  2. at least 6 characters
  3. only allowed letters, numbers, - and _ in password

If the conditions match, output Yes. Or else, No.

These are what I have tried:

from sys import exit

def check_alpha(input):
   alphas = 0
   alpha_list = "A B C D E F G H I J K L M N I O P Q R S T U V W X Y Z".split()
   for char in input:
    if char in alpha_list:
        alphas += 1
if alphas > 0:
    return True
else:
    return False

def check_number(input):
numbers = 0
number_list = "1 2 3 4 5 6 7 8 9 0".split()
for char in input:
    if char in number_list:
        numbers += 1
    if numbers > 0:
        return True
    else:
        return False

def check_special(input):
specials = 0
special_list = "_-"
for char in input:
    if char in special_list:
        specials += 1
    if specials > 0:
        return True
    else:
        return False

def check_len(input):
    if len(input) >= 6:
        return True
    else:
        return False

def validate_password(input):
check_dict ={
    'alpha':check_alpha(input),
    'number':check_number(input),
    'special':check_special(input),
    'len':check_len(input)

}
    if check_alpha(input) & check_number(input) & check_sprcial(input) & check_len(input)
    return True
else:
    print"No"

    while True:
    password = raw_input("Enter password:")
    print
    if validate_password(password):
        print("Yes")
    else
        print("No")

or alternatively:

import re

while True:
    user_input = input("Please enter password:")
    is_valid = False

    if(len(user_input)<6):
        print("No")
        continue
    elif not re.search("[a-z]",user_input):
        print("No")
        continue
    elif not re.search("[0-9]",user_input):
        print("No")
        continue
    elif re.search("[~!@#$%^&*`+=|\;:><,.?/]",user_input):
        print("No")
        continue
    else:
        is_valid = True
        break

    if(is_valid):
    print("Yes")
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
Hann
  • 21
  • 1
  • 4
  • 4
    You should start to show what you tried so we can help you in improving your skills and not doing your homework :) – Joe Nov 30 '18 at 08:02
  • So, the assignment is supposed to contain three things: 1) make the user input a password, 2) validate it according to the conditions, 3) print the result. Which part are you stuck with? – bereal Nov 30 '18 at 08:04
  • 1
    We don't object to *helping* with homework, if you've had a go and are really stuck somewhere. We do object to "do my homework for me", which is what this question seems to be asking. – Daniel Roseman Nov 30 '18 at 08:04
  • @Hann, Did you try [this](https://stackoverflow.com/questions/41117733/validation-a-password-python) post? – S.Sakthybaalan Nov 30 '18 at 08:08
  • import re while True: user_input = input("Please enter password:") is_valid = False if(len(user_input)<6): print("No") continue elif not re.search("[a-z]",user_input): print("No") continue elif not re.search("[0-9]",user_input): print("No") continue elif re.search("[~!@#$%^&*`+=|\;:><,.?/]",user_input): print("No") continue else: is_valid = True break if(is_valid): print("Yes") – Hann Nov 30 '18 at 08:30
  • @Hann you should edit that into your question so it's possible to read – Adam Smith Nov 30 '18 at 08:34
  • 1
    Yeah sure I am sorry :) – Hann Nov 30 '18 at 08:38
  • @S.Sakthybaalan Yeah I have read that before :) Thanks – Hann Nov 30 '18 at 08:44

8 Answers8

1

I enjoy this particular solution because I find validation to be such a good use of decorators.

def require(pred):
    def wrapper(f):
        def wrapped(*args, **kwargs):
            while True:
                result = f(*args, **kwargs)
                ok = pred(result)
                if ok:
                    return result
        return wrapped
    return wrapper

def begin_with_letters(s):
    return s[0].isalpha()

def length_over_six(s):
    return len(s) >= 6

def no_letters_outside_of_whitelist(s):
    WHITELIST = set(string.ascii_letters + string.digits + '-_')
    return all(c in WHITELIST for c in s)

@require(begin_with_letters)
@require(length_over_six)
@require(no_letters_outside_of_whitelist)
def get_password():
    user_pass = input("Enter a password: ")
    return user_pass

This architecture can be grown by building a Validator class.

class Validator(abc.ABC):
    errormsg = NotImplemented

    def __init__(self, value):
        self.__value = value

    @property
    def value(self):
        return self.__value

    @abc.abstractmethod
    def validate(self) -> bool:
        """Uses self.value and validates it in some way, returning a bool."""

    @staticmethod
    def require(validator)
        def wrapper(f):
            def wrapped(*args, **kwargs):
                while True:
                    result = f(*args, **kwargs)
                    v = validator(result)
                    ok = v.validate()
                    if ok:
                        return result
                    print(v.errormsg)
            return wrapped
        return wrapper

class BeginWithLetters(Validator):
    errormsg = "Your password must begin with letters."

    def validate(self):
        return self.value[0].isalpha()

class LengthOverSix(Validator):
    errormsg = "Your password must be six characters or longer."

    def validate(self):
        return len(self.value) >= 6

class WhiteListCharacters(Validator):
    WHITELIST = set(string.ascii_letters + string.digits + "-_")
    errormsg = "Your password must only contain letters, digits, - and _"

    def validate(self):
        return all(c in self.WHITELIST for c in self.value)

@Validator.require(BeginWithLetters)
@Validator.require(LengthOverSix)
@Validator.require(WhiteListCharacters)
def get_password():
    return input("Enter a password: ")
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • For what it's worth, this isn't a *bad* solution per say but it's DEFINITELY over-engineered for a homework assignment (thus why it's 50 lines long instead of 6). Sometimes it's fun to over-engineer a solution to something simple so it could be used at the Enterprise level (consider that building new validators and validating new functions with this architecture is very easy and straightforward!) but I don't recommend you turn this in to your professor, or even attempt with any great effort to understand the code I've written here. – Adam Smith Nov 30 '18 at 09:04
  • Thanks so much! This is such an amazing answer :D – Hann Nov 30 '18 at 09:29
0

I suggest you have a look at getpass module. To help you get started, take a look at the following links:getpass (examples series 1) and examples series 2

eapetcho
  • 527
  • 3
  • 10
  • 2
    `getpass` is to get input without having it show on the command line, but it seems pretty useless for OP's use case. It's homework, and I'm guessing they are mostly having trouble on the validation part, not getting input (which is trivially easy). – iz_ Nov 30 '18 at 08:20
0

Try this:

import re

pw = raw_input('Type a password: ') # get input from user

if any([not pw[0].isalpha(),            # check if first char is a letter
       len(pw) < 6,                     # check if len is greater than or equal to 6
       not re.match(r'^[\w-]*$', pw)]): # check if all chars are alphanumeric, underscores, or dashes
    print 'No'
else:
    print 'Yes'

Sample output for a few test cases:

Type a password: qwer
No

Type a password: qwerty
Yes

Type a password: 1a2b3c
No

Type a password: ASDF1234!!!!
No

Type a password: a.a.a.a
No
iz_
  • 15,923
  • 3
  • 25
  • 40
  • Thank you! After read through your suggestion, I found that I have compliacating the question, your suggestion is simple and nice! – Hann Nov 30 '18 at 09:32
0

You can join the 3 conditions in one line, and avoid the variable is_valid. You also missed the condition of the first character:

import re
user_input = raw_input('Please enter password:')
if len(user_input)>=6 and user_input[0].isalpha() and re.match(r"^[\w-]*$", user_input):
    print('Yes')
else:
    print('No')
Joe
  • 12,057
  • 5
  • 39
  • 55
  • I thought the conditions cant be joined but now I learned :D Thank you! – Hann Nov 30 '18 at 09:30
  • You are welcome :) dont forget to accept the answer that you found most useful https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Joe Nov 30 '18 at 09:34
0
import re

def validate(password):
    if len(password) < 6  or re.search('^[A-Za-z][A-Za-z0-9-_]*$',password) is None:
        print("password not accepted")
    else:
        print("Your password seems fine")
  • 2
    why not get the whole thing in the regex? `if re.match(r"[A-Za-z][A-Za-z0-9-_]{5,}$", password) is None: ... ` – Adam Smith Nov 30 '18 at 08:56
  • 1
    regex stands for `regular expressions` and uses the library `re` to work with srings, characters etc(see https://docs.python.org/3/library/re.html). `validate` is a function written by the user – Joe Nov 30 '18 at 09:42
  • @Hann Great to know and happy to help. Can you mark answer this accepted so that its benificial for others as well. – saurav omar Dec 02 '18 at 07:21
0
import re

user_input = raw_input('Please enter password:')

if len(user_input)>=6 and user_input[0].isalpha() and re.match(r"^[\w-]*$", user_input):
      print('Yes')
else:
      print('No')
Hann
  • 21
  • 1
  • 4
-1

Ideal solution for your problem is Regular Expression. Try to validate it in the front-end. Something like javascript.

For your knowledge, Check the following link in Python Docs. https://docs.python.org/3/howto/regex.html

  • This answer has no substance at all. "Something like javascript?" What does that mean? Why do we think this is running in a browser? How would you use a regex to solve this problem? – Adam Smith Nov 30 '18 at 08:27
-1
Import re
Password = (input("enter password here:"))
flag = 0
while True:
          if (len(password)<7):
                flag = -1
                break
          elif not re.search("[a-z]",  password):
                flag = -1
                break
           elif not re.search("[A-Z]",  password):
                 flag = -1
                 break
           elif not re.search("[0-9]",  password):
                 flag = -1
                 break  
            elif not re.search("[#@$&*_]",  password):
                 flag = -1
                 break
            else:
                     flag = 0
                     print("strong")
                     break
if flag == -1:
      print("weak")
DavidW
  • 29,336
  • 6
  • 55
  • 86
dave
  • 1
  • 1