| | 3 | |
|---|
| | 4 | class NoMatchFound(Exception): pass |
|---|
| | 5 | |
|---|
| | 6 | class HasPermission(object): |
|---|
| | 7 | """ |
|---|
| | 8 | Function that supports multiple implementations via a type registry. The |
|---|
| | 9 | implemetation called depends on the argument types. |
|---|
| | 10 | """ |
|---|
| | 11 | def __init__(self): |
|---|
| | 12 | self.registry = {} |
|---|
| | 13 | |
|---|
| | 14 | def __call__(self, user, permission, obj=None): |
|---|
| | 15 | # TODO: this isn't very robust. Only matches on exact types. Support |
|---|
| | 16 | # for matching subclasses and caching registry hits would be helpful, |
|---|
| | 17 | # but we'll add that later |
|---|
| | 18 | types = (type(user), type(permission), type(obj)) |
|---|
| | 19 | func = self.registry.get(types) |
|---|
| | 20 | if func is not None: |
|---|
| | 21 | return func(user, permission, obj) |
|---|
| | 22 | else: |
|---|
| | 23 | raise NoMatchFound, "%s\n%s" % (self.registry, types) |
|---|
| | 24 | |
|---|
| | 25 | def register(self, user_type, permission_type, obj_type, func): |
|---|
| | 26 | types = (user_type, permission_type, obj_type) |
|---|
| | 27 | self.registry[types] = func |
|---|
| | 28 | |
|---|
| | 29 | has_permission = HasPermission() |
|---|