def walk_controller(root_class, controller, hooks, seen=None):
    seen = seen or set()
    if type(controller) not in vars(six.moves.builtins).values():
        # Avoid recursion loops
        try:
            if controller in seen:
                return
            seen.add(controller)
        except __HOLE__:
            # If we discover an unhashable item (like a list), it's not
            # something that we want to traverse because it's not the sort of
            # thing we would add a hook to
            return

        for hook in getattr(controller, '__hooks__', []):
            # Append hooks from controller class definition
            hooks.add(hook)

        for name, value in getmembers(controller):
            if name == 'controller':
                continue
            if name.startswith('__') and name.endswith('__'):
                continue

            if iscontroller(value):
                for hook in hooks:
                    value._pecan.setdefault('hooks', set()).add(hook)
            elif hasattr(value, '__class__'):
                # Skip non-exposed methods that are defined in parent classes;
                # they're internal implementation details of that class, and
                # not actual routable controllers, so we shouldn't bother
                # assigning hooks to them.
                if (
                    isinstance(value, types.MethodType) and
                    any(filter(lambda c: value.__func__ in c.__dict__.values(),
                               value.__self__.__class__.mro()[1:]))
                ):
                    continue
                walk_controller(root_class, value, hooks, seen)
dataset/ETHPy150Open pecan/pecan/pecan/hooks.py/walk_controller