In my opinion, there is no need to use this kind of regular expression. They are scary, difficult to understand and difficult to customize. If you need to validate email and password, then why not break it down into several steps? Yes, there will probably be more code, but further interaction with it will become easier. If necessary, you can remove one of the checks or add a new one without touching the others. Read something about the principle of "Divide and Conquer".
Here is one of the easily customizable and readable solutions to your problem:
import re
def email_is_valid(email:str) -> bool:
''' Returns True if email is valid and False if it's not
'''
conditions = [
# Checking for correct ending and forbidden characters
re.fullmatch(r'[a-z0-9$]{1,}((@google.com)|(\.go))$', email),
# Checking for at least three digits
re.search(r'(?=(?:.*\d){3,})', email),
# Checking for only one '$'
email.count('$') == 1,
]
for condition in conditions:
if not condition:
return False
return True
def password_is_valid(password:str) -> bool:
''' Returns True if password is valid and False if it's not
'''
conditions = [
# Checking the length and presence of forbidden characters
re.fullmatch(r'[A-Za-z0-9!@#$%^]{8,}', password),
# Looking for at least one of these characters !@#$%^
re.search(r'[!@#$%^]{1,}', password),
# Looking for at least one Uppercase letter
re.search(r'[A-Z]{1,}', password),
]
for condition in conditions:
if not condition:
return False
return True
And here is how the use of these functions will look like. Easy to read.
import email_is_valid, password_id_valid
if email_is_valid(your_email):
...
if password_id_valid(your_password):
...