Although I tend to agree that you probably don't want to reinvent the wheel on this, below is version of your attempt that appears to work AFAIK.
Basically, I first I had switch to explicit new-style classes by making them derived from object
so that the super()
call would work, then second, I changed the self.roles = roles
initialization in the MultiRoleUser
class to create the instances needed. Lastly I changed how the MultiRoleUser.__getattr__()
used them to handle role classes that didn't have the sought permission attribute.
def not_allowed(*args, **kwargs): return False
class User(object):
def __init__(self, userid):
self.userid = userid
def __getattr__(self, attr):
return not_allowed
def view_profile(self):
return True
class Admin(User):
def edit_comment(self):
return True
class Expert(User):
def delete_post(self):
return True
class MultiRoleUser(User):
"""A multirole user has all the power of all the roles together"""
def __init__(self, userid, roles):
super(MultiRoleUser, self).__init__(userid)
self.roles = [role(userid) for role in roles] # create instances needed
def __getattr__(self, attr):
all_funcs = [getattr(x, attr, None) for x in self.roles]
return any(x() for x in all_funcs if x) # check permission if there was one
u = MultiRoleUser('userid', [Admin, Expert])
print 'u.edit_comment:', u.edit_comment
print 'u.delete_post:', u.delete_post
BTW, I think a better Python implementation would use sets
and operations with them to accomplish what you're trying to do.