On May 11, 11:16 am, samwyse <samw...@gmail.com> wrote: > I'm writing a class that derives it's functionality from mix-ins. > Here's the code: > > def boilerplate(what): # This used to be a decorator, but all of > the > ##what = f.__name__ # function bodies turned out to be > 'pass'. > 'Validate the user, then call the appropriate plug-in.' > def template(self, which, username, password, *args): > if not self.security.isAuthorised(username, password, > which, what): > raise Exception('Unauthorised access') > return getattr(self.blog, what)(which, *args) > template.__name__ = what > template.__doc__ = getattr(self.blog, what).__doc__ > return template > > class MetaWeblog(object): > def __init__(self, > securityHandler=SimpleSecurityHandler, > blogHandler=SimpleBlogHandler): > self.security = securityHandler() > self.blog = blogHandler() > newPost = boilerplate('newPost') > editPost = boilerplate('editPost') > getPost = boilerplate('getPost') > # etc, etc, etc > > I'd like to replace the method definitions with a loop: > for what in attr_list: > setattr(klass, what, boilerplate(what)) > > That begs the question of where I define 'klass' and 'attr_list'. > Should I use a class decorator, or a metaclass?
Here's the thing: unless you have advance knowledge of the methods defined by self.blog, you can't get the attr_list at class definition time, which means neither the metaclass nor the decorator would be a good approach. If that's the case, you should define newPost, editPost, and whatever other methods of self.blog as ordinary attributes of self, within the init function. boilerplate would be the same except you would pass self to it and allow template to use it from its nested scope (it would no longer be an instance method since it's an ordinary attribute). If you do know what the methods of self.blog will be, then that's where you get attr_list from. So, for instance, if blogHandler always returns an object of type Blog, then you could inspect Blog's type dict to see what methods are defined in it; in fact you probably want to check the whole MRO for Blog, like this (untested): attr_list = [] for cls in Blog.__mro__: for value in cls.__dict__: if is_wrapped_method(value): attr_list.append(value) A metaclass is probably overkill to assign the wrapped blog methods. I probably wouldn't even bother with the decorator, and just write the loop after the class definition. Then you can use MetaBlog directly for klass. class MetaBlog(object): ... for what in attr_list: setattr(MetaBlog, what, boilerplate(what)) If it were the kind of thing I found myself doing often I'd refactor into a decorator. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list