Return the endpoints from an API implementation module.

    The results returned by this are used to populate your HTTP layer's
    route handler, as well as by the documentation generator.

def extract_endpoints(api_module):
    """Return the endpoints from an API implementation module.

    The results returned by this are used to populate your HTTP layer's
    route handler, as well as by the documentation generator.
    """
    if not hasattr(api_module, 'endpoints'):
        raise ValueError(("pale.extract_endpoints expected the passed in "
            "api_module to have an `endpoints` attribute, but it didn't!"))

    endpoints = api_module.endpoints
    if isinstance(endpoints, types.ModuleType):
        classes = [v for (k,v) in inspect.getmembers(endpoints,
                                                     inspect.isclass)]
    elif isinstance(endpoints, (list, tuple)):
        classes = endpoints
    else:
        raise ValueError("Endpoints is not a module or list type!")

    instances = []

    for cls in classes:
        if cls not in (Endpoint, PatchEndpoint, PutResourceEndpoint) and \
                Endpoint in inspect.getmro(cls):
            source_code = inspect.getsource(cls)
            if "@requires_permission" in source_code:
                permission_match = re.search(r"@requires_permission\(\[?[\'\"]+(\w+)[\'\"]+", source_code)
                if permission_match != None:
                    cls._requires_permission = permission_match.group(1)
            instances.append(cls())
    return instances