Is this a good use of __metaclass__?
Joel.Hedlund at gmail.com
Joel.Hedlund at gmail.com
Sat May 6 13:36:14 EDT 2006
I played around with my old code before I saw your post, and I believe
I've found a solution that's a bit neater than what I had before. I
thought I could just as well post it if you're interested and have the
time. This one uses multiple inheritance, but it's legal and there's
only one metaclass.
When executed, this prints:
Validating admin.
Scary stuff done.
Cheers!
/Joel
Here ya go!
--------------------------------------------------------------------------
from decorator import decorator
# Metaclass for decorating public methods:
class DecoratePublicMethods(type):
"""Equip public methods of a class with a specified decorator.
Class data members:
decorator_attribute = '_public_method_decorator': <str>
If this attribute of the class exists and evaluates to True,
then
it is used to decorate all public methods of the class.
no_decoration_attribute = '_do_not_decorate': <str>
If this attribute of the class exists it should contain a list
of
names of public methods that should not be decorated.
"""
decorator_attribute = '_public_method_decorator'
no_decoration_attribute = '_do_not_decorate'
def __new__(cls, classname, bases, classdict):
decorator = classdict.get(cls.decorator_attribute, None)
if not decorator:
return type.__new__(cls,classname,bases,classdict)
do_not_decorate = classdict.get(cls.no_decoration_attribute,
[])
for attr,item in classdict.items():
if not callable(item):
continue
if attr in do_not_decorate or attr.startswith('_'):
continue
classdict[attr] = decorator(item)
return type.__new__(cls, classname, bases, classdict)
# Some decorators:
@decorator
def validate_job(func, self, id, response, *pargs, **kwargs):
"""Bogus authentiction routine"""
print "Validating job."
return func(self, id, response, *pargs, **kwargs)
@decorator
def validate_user(func, self, id, response, *pargs, **kwargs):
"""Bogus authentiction routine"""
print "Validating user."
return func(self, id, response, *pargs, **kwargs)
@decorator
def validate_admin(func, self, id, response, *pargs, **kwargs):
"""Bogus authentiction routine"""
print "Validating admin."
return func(self, id, response, *pargs, **kwargs)
# My API:
class BaseAPI(object):
__metaclass__ = DecoratePublicMethods
class JobValidatedAPI(BaseAPI):
_public_method_decorator = validate_job
def do_routine_stuff(self, clientid, response, foo):
print "Routine stuff done."
class UserValidatedAPI(BaseAPI):
_public_method_decorator = validate_user
def do_mundane_stuff(self, clientid, response, moo):
print "Mundane stuff done."
class AdminValidatedAPI(BaseAPI):
_public_method_decorator = validate_admin
def do_scary_stuff(self, clientid, response, moose):
print "Scary stuff done."
## FIXED: Multiple inheritance now legal.
class FullAPI(JobValidatedAPI, UserValidatedAPI, AdminValidatedAPI):
_public_method_decorator = None
# Now this works:
b = FullAPI()
b.do_scary_stuff('bofh', 2, 3)
--------------------------------------------------------------------------
More information about the Python-list
mailing list