Validating input to follow a specific order - python

I have to make sure that an email address that is inputted is valid. An email address must:
Start with a string of alphanumeric characters
followed by the # symbol
another string of alphanumeric characters
followed by a .
then a string of alphanumeric characters.
For example, a#b.c and ab23#f45.d3 are both valid, but #bc.d and 123.c#cvb are not valid. How would I program something that would make sure the input follows this order?

Use Regular Expression
An example:
import re
if re.search(r'[\w.-]+#[\w.-]+.\w+', email):
do stuff
else
do other stuff

I would split the string at the # character into two new strings and check if the string to the left of # only contains alphanumeric characters. Then I would split the string on the right at the . character and check if both left and right string contain only alphanumeric characters.
def test(email):
left, right = email.split('#') # 'abc123#mail1.com' -> left = 'abc123', right = 'mail1.com'
if not left.isalnum(): # If characters to the left of '#' is not alphanumeric or is empty, return False.
return False
left, rest = right.split('.') # 'mail1.com' -> left = 'mail1, right = 'com'
if not (left.isalnum() and rest.isalnum()): # If characters to the left and right of '.' is not alphanumeric or is empty, return False.
return False
return True # If it haven't returned False, return True.
# To test if it works as you intended. It works for the cases you provided.
while True:
print(test(input('Email: ')))

This is my take on this:
def email_valid(email_str):
if email_str.count('#') != 1 or email_str.count('.') != 1:
return False
if len(min(email_str.split('#'))) == 0 or len(min(email_str.split('#')[1].split('.'))) == 0:
return False
parts = email_str.split('#')[1].split('.') + [email_str.split('#')[0]]
return True if all(x.isalnum() for x in parts) else False
check = False
while not check:
check = email_valid(input('Please provide an email:\t'))
print('Email accepted!')
Checks to make sure '#', '.' can be found exactly once in the provided string and the string parts before and after them are alphanumeric & non empty.
However, the rules implemented here are not the rules generally applied to email accounts. For a list of those, see the syntax paragraph of this article.

Here's another non-regex way to do it:
def validate_email(email):
user, sep, domain = email.partition('#')
parts = [user]
parts.extend(domain.split('.'))
return len(parts) == 3 and all(part.isalnum() for part in parts)
>>> for email in 'a#b.c', 'ab23#f45.d3', 'a_b#p_q.com', '#bc.d', '123.c#cvb', '', '#', 'a#b#c', '#.', 'abc&**&#test.com':
... print(validate_email(email))
True
True
False
False
False
False
False
False
False
False
The domain part of the email address is restricted to two parts separated by a .. Valid email domains can have at least three parts so, if you want to support that, remove the len(parts) == 3 test.
And here is a regex pattern that works:
import re
def validate_email(email):
return re.match(r'[a-zA-Z\d]+#[a-zA-Z\d]+\.[a-zA-Z\d]+$', email) != None
>>> for email in 'a#b.c', 'ab23#f45.d3', 'a_b#p_q.com', '#bc.d', '123.c#cvb', '', '#', 'a#b#c', '#.', 'abc&**&#test.com':
... print(validate_email(email))
True
True
False
False
False
False
False
False
False
False
You can't use \w in the pattern because this will match the underscore character and this is not normally considered alphanumeric. The $ is required at the end of the pattern to ensure that the last segment of the email address ends with alphanumeric characters only. With out this extraneous invalid characters appearing at the end of the string after a sequence of valid characters will match.
In this case I'd opt for the first method using just basic string functions because it is (arguably) easier to read and maintain than a regex.

Related

Why my code not working in return value for Python Regex

I wrote one program to find the matches. its working fine. If the string is not proper it has to return false. example if my string_ contains 2 commas or instead of reject or any if some other string came it has to return false. My string only expect string as reject or any
import re
string_ = '''192.168.1.1,192.168.1.2/32,192.168.1.5-192.168.1.7,reject,any,
reject,192.168.1.1/32,reject,any,
172.168.1.4-172.168.1.4,reject'''
result = re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/?\d{0,}|[any|reject]+', string_)
#print(result)
if result :
print (True)
Expecting false for the string below
test = '''192.168.1.1,192.168.1.2/32,192.168.1.5-192.168.1.7,reject,any,ip_address
reject,192.168.1.1/32,reject,any,
172.168.1.4-172.168.1.4,reject'''
bool(re.search('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/?\d{0,}|[any|reject]+', test))
Expected Out is False, My Out is True
test1 = '''192.168.1.1,192.168.1.2/32,192.168.1.5-192.168.1.7,reject,any,,,,
reject,192.168.1.1/32,reject,any,
172.168.1.4-172.168.1.4,reject'''
bool(re.search('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/?\d{0,}|[any|reject]+', test1))
Expected Out is False, My Out is True
Expected Out
False
You may use
^(?:\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?(?:-\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?)?|reject|any)(?:\s*,\s*(?:\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?(?:-\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?)?|reject|any))*$
Since the regex is composed of blocks, it is easier to build it dynamically in the code:
import re
string_ = '''192.168.1.1,192.168.1.2/32,192.168.1.5-192.168.1.7,reject,any,ip_address
reject,192.168.1.1/32,reject,any,
172.168.1.4-172.168.1.4,reject'''
ip_rx = r'\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?'
# More precise:
# ip_rx = r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}'
block=r"(?:{0}(?:-{0})?|reject|any)".format(ip_rx)
print(bool(re.search(r'^{0}(?:\s*,\s*{0})*$'.format(block), string_))) # => False
See the Python demo
Details
^{0}(?:\s*,\s*{0})*$ - matches a string that fully matches a block pattern that is followed with 0 or more occurrences of , and block pattern
(?:{0}(?:-{0})?|reject|any) is the block pattern that matches either an ip pattern that can be optionally followed with - and an ip pattern or reject or any substrings
\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)? is the ip pattern that can be improved to only match valid IPs, (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}.

A check text numbers, alphabets, letters upper case and lower case except symbols

I need guys your help.
I can't understand what to use either list or set. List is more efficient. dictionary also need index. but my problem is text should be string so variable must equal to text as string. I can't D=['a','b','c'].
text gives me error because it can't compare them all except individual and i must create such as abc or word example as _success and confirm its in the list to be true.
This is my code so far but i have problem which is now it accepts numbers and letters and symbols. Symbols such as !##$% should be returning False.
Having it as own function works but i need it in the if statement.
return text.isalnum() doesn't work in the if statement. Thats my problem symbols should be false.
def check(text):
if text== '':
return False
if text.isalpha() == text.isdigit():
return True
else:
return text.isalnum()
def main():
text = str(raw_input("Enter text: "))
print(check(text))
main()
output problem.
Enter text: _
False
_ is suppose to be one of the symbols True. Example _success123 is True
!##$% is suppose to be false but its showing as True as output Another example is !##A123. This output is False.
The code up there does accept the underscore and letter and number
output:
_success123
but problem is also accepts !##$ as True.
return text.isalnum() Does deny the symbols but its not working in the if statement.
It's an overkill, but you can use Regex. It's easy to add new chars (e.g. symbols):
import re
def check(text):
return re.match('^[a-zA-Z0-9_!]*$', text)
text = str(raw_input("Enter text: "))
print(check(text))
If you want to avoid a regular expression, you could use Python sets:
allowed = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789')
def check(text):
return not len(set(text) - allowed)
for text in ['_success123', '!##$%']:
print(text, check(text))
This converts your text into a set of characters and removes all the characters that are allowed. If any characters remain then you know it is invalid. For two examples, this gives:
_success123 True
!##$% False

Python Regex for string matching

There are 2 rules that I am trying to match with regex. I've tried testing on various cases, giving me unwanted results.
Rules are as follows:
Find all strings that are numbers (integer, decimal, and negative values included)
Find all strings that have no numeric value. This is referring to special characters like !##$%^&*()
So in my attempt to match these rules, I got this:
def rule(word):
if re.match("\W", word):
return True
elif re.match("[-.\d]", word):
return True
else:
return False
Input: output tests are as follows
word = '972.2' : True
word = '-88.2' : True
word = '8fdsf' : True
word = '86fdsf' : True I want this to be False
word = '&^(' : True
There were some more tests, but I just wanted to show that one I want to return False. It seems like it's matching just the first character, so I tried changing the regex epressions, but that made things worse.
As the documentation says, re.match will return a MatchObject which always evaluates to True whenever the start of the string is matched to the regex.
Thus, you need to use anchors in regex to make sure only whole string match counts, e.g. [-.\d]$ (note the dollar sign).
EDIT: plus what Max said - use + so your regex won't just match a single letter.
Your regexes (both of them) only look at the first character of your string. Change them to add +$ at the end in order to make sure your string is only made of the target characters.
As i understand, you need to exclude all except 1 and 2.
Try this:
import re
def rule(word):
return True if re.search("[^\W\d\-\.]+", word) is None else False
Results on provided samples:
972.2: True
-88.2: True
8fdsf: False
86fdsf: False
&^(: True

I want to check if password and username contain at least one symbol?

I want this function to work in my is_password_good function.
def is_ascii(some_string) :
for each_letter in some_string:
if ord(each_letter) < 128:
return False
return True
The is_good_password function makes certain the user's password is at least 10 characters long and that at least one uppercase and lowercase exists.
How can I pass my ASCII function to check if the user creates a passwords using at least one symbol by ASCII standards?
def is_good_password(password):
count_upper, count_lower = 0, 0
for characters in password:
if characters.isupper():
count_upper += 1
if characters.islower():
count_lower += 1
is_password_good = True
if len(password) <= 10:
print "Password is too weak, must be more than 10 characters long!"
is_password_good = False
if count_upper < 1 or count_lower < 1:
print "Password must contain at least one uppercase and one lowercase character!"
is_password_good = False
create_user(database)
print "Welcome! Username & Password successfully created!"
return is_password_good
You can check string.punctuation exist in string or not.
>>>string.punctuation
'!"#$%&\'()*+,-./:;<=>?#[\\]^_`{|}~'
import re
def getmix(password):
Upper=len(set(re.findall(r'[A-Z]',password)))
Lower=len(set(re.findall(r'[a-z]',password)))
Nums=len(set(re.findall(r'[0-9]',password)))
Symb=len(set(re.findall(r'[~!##$%^&\*()_+=-`]')))
return (Upper, Lower, Nums, Symb)
Should give you a good starting point.
The function somestring.isalnum() will return False if not all characters in the string are alphabetics or numbers.
The precise definition of these categories are locale-dependent; make sure you know which locale you are using.
By the by, ASCII is only defined up to character code 127. If you go above 127, you need to know which character set and encoding you are dealing with. However, characters like # and ! are indeed defined in ASCII, and have character codes in the 30-something range. You are better off using library functions which abstract away the precise character codes, anyway.
has_symbol = False
for c in '~!##$%^&*()_+=-`':
if c in password:
has_symbol = True
break
if not has_symbol:
print "Password must contain at least one uppercase and one lowercase character!"
is_password_good = False
Always use the builtins, don't roll your own, so in that spirit, use the string module for a canonical list of symbols:
import string
symbols = string.punctuation
and printing symbols shows us these characters:
!"#$%&'()*+,-./:;<=>?#[\]^_`{|}~
You can pass to any the "one iterable in another" construction:
if any(char in symbols for char in some_string):
print 'password good'
However, I actually prefer the set methods instead of the above construction:
if set(symbols).intersection(some_string):
print 'password good'
but Triplee's advice on isalnum is just as potent, doesn't require importing the string module, and quite shorter.
if not some_string.isalnum():
print 'password good'

Python alphanumeric Validation server side using regular expression

I have this code in python.
Actually i wanted to validate the password field at server side using python. i want password to be alphanumeric in nature and thats what i have done so far
def valid():
num = "[a-zA-Z0-9]"
pwd = "asdf67AA"
match = re.match(pwd, num)
if match:
return True
else:
return False
its always returning false . It does not hit the IF condition. whats that i am missing
You reversed the arguments of match
re.match(pattern, string, flags=0)
It should be
match = re.match(num, pwd)
You can do this to find out if the string is alphanumeric
pwd = "asdf67AA"
if pwd.isalnum():
# password is alpha numeric
else:
# password is not alpha numeric
You have miss placed the argument in method reverse it .
it will work.
But this also matched if you set symbol in your string.
so, i suggest you apply this things :
pwd ="test5456"
pwd.isalnum():
This method will only work for if your string contain string or digit.
if you want strongly want your password contain both numeric and string than this code will help you.
test = "anil13##"
new = tuple(test)
data = list(new)
is_symb =False
is_digit = False
is_alpha = False
for d in data :
if d.isdigit() :
is_digit = True
if d.isalpha():
is_alpha = True
if not d.isdigit() and not d.isalpha():
is_symb =True
break
if is_symb == False and is_digit == True and is_alpha == True:
print "pwd matchd::::"
else :
print "pwd dosen't match..."
Note :This code strongly work for numeric & symbol
Regards,
Anil
This is very simple answer and it is better to use regex for validation instead of wired if else condition.
import re
password = raw_input("Enter Your password: ")
if re.match(r'[A-Za-z0-9##$%^&+=]{6,}', password):
print "Password is match...."
else:
print "Password is not match...."
#6 means length of password must be atleast 6
you can do it by using isalnum() method of python
just by doing
pwd.isalnum()
it will tell wthether a number is alphanumeric or not and then will hit the if condiion

Categories

Resources