Skip to content

Instantly share code, notes, and snippets.

@aaronlelevier
Created July 22, 2014 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronlelevier/57891806f7b41cc65da5 to your computer and use it in GitHub Desktop.
Save aaronlelevier/57891806f7b41cc65da5 to your computer and use it in GitHub Desktop.
metaclass example of looping through classes of password validation in python
class PluginMount(type):
"""
A Meta Class plugin mount location for a list of plugin classes.
By creating this, on all subclasses of PluginMount, python will
instantiate a plugin attribute list and maintain it for the Class
using this Meta Class.
"""
def __init__(cls, name, bases, attrs):
if not hasattr(cls, 'plugins'):
cls.plugins = []
else:
cls.plugins.append(cls)
class PasswordValidator(metaclass=PluginMount):
"""
Plugins extending this class will be used to validate passwords.
Valid plugins must provide the following method.
validate(self, password)
Receives a password to test, and either finishes silently or raises a
ValueError if the password was invalid. The exception may be displayed
to the user, so make sure it adequately describes what's wrong.
"""
def is_valid_password(password):
"""
Returns True if the password was fine, False if there was a problem.
"""
for plugin in PasswordValidator.plugins:
try:
plugin().validate(password)
except ValueError:
return False
return True
def get_password_errors(password):
"""
Returns a list of messages indicating any problems that were found
with the password. If it was fine, this returns an empty list.
"""
errors = []
for plugin in PasswordValidator.plugins:
try:
plugin().validate(password)
except ValueError as e:
errors.append(str(e))
return errors
class MinimumLength(PasswordValidator):
def validate(self, password):
"Raises ValueError if the password is too short."
if len(password) < 6:
raise ValueError('Passwords must be at least 6 characters.')
class SpecialCharacters(PasswordValidator):
def validate(self, password):
"Raises ValueError if the password doesn't contain any special characters."
if password.isalnum():
raise ValueError('Passwords must contain at least one special character.')
def run():
"""
Call run() function to demonstrate metaclass password usage
"""
for password in ('pass', 'password', 'p@ssword!'):
print(('Checking %r...' % password), end=' ')
if is_valid_password(password):
print('valid!')
else:
print() # Force new line
for error in get_password_errors(password):
print(' %s ' % error)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment