def findRootsWithPredicate(c, root, predicate=None):
    """
    Commands often want to find one or more **roots**, given a position p.
    A root is the position of any node matching a predicate.

    This function formalizes the search order used by the black,
    pylint, pyflakes and the rst3 commands, returning a list of zero
    or more found roots.
    """
    seen = []
    roots = []
    if predicate is None:

        def predicate(p):
            return p.isAnyAtFileNode() and p.h.strip().endswith('.py')
    for p in root.self_and_subtree(copy=False):
        if predicate(p) and p.v not in seen:
            seen.append(p.v)
            roots.append(p.copy())
    if roots:
        return roots
    for p in root.parents():
        if predicate(p):
            return [p.copy()]
    clones = []
    for p in root.self_and_parents(copy=False):
        if p.isCloned():
            clones.append(p.v)
    if clones:
        for p in c.all_positions(copy=False):
            if predicate(p):
                for p2 in p.self_and_subtree():
                    if p2.v in clones:
                        return [p.copy()]
    return []
