import re


def find_clades_by_name(tree, terminal=True, contains=[], contains_all=False,
                        pattern=None):
    """Find clades by their name and whether or not they are terminal clades.

    Parameters
    ----------
    terminal : bool
        If True, only the terminal nodes of the `tree` are searched.
        If False, only the non-terminal nodes are searched.
        If None, all nodes are searched.
    contains : iterable of str
        Collection of strings whose presence will be checked in a clade name.
        If `contains` is given, then `pattern` should not be given.
    contains_all: bool
        If True, all str specified in `contains` must be present in the clade
        name.
        If False, any str specified in `contains` gives a name of interest.
    pattern : str
        Regular expression pattern to match the clade name.
        If `pattern` is given then `contains` should not be given.

    Returns
    -------
    generator expression
        Iterating over the returned generator will yield clades whose names
        match the given search criteria.

    Notes
    -----
    Slightly faster implementation than BioPython's Phylo package find_clades
    search functionality.
    """
    if contains:
        logic = all if contains_all else any
        return (clade for clade in tree.find_clades(terminal=terminal) if
                clade.name and
                logic(x in clade.name for x in contains))
    elif pattern:
        pattern = re.compile(pattern)
        return (clade for clade in tree.find_clades(terminal=terminal) if
                clade.name and
                pattern.match(clade.name))
    else:
        return (clade for clade in tree.find_clades(terminal=terminal))