r"""
    Searches module functions, classes, and constants for members matching a
    pattern.

    Args:
        mod (module): live python module
        pat (str): regular expression

    Returns:
        list: found_list

    CommandLine:
        python -m utool.util_dev --exec-search_module --mod=utool --pat=module
        python -m utool.util_dev --exec-search_module --mod=opengm --pat=cut
        python -m utool.util_dev --exec-search_module --mod=opengm --pat=multi
        python -m utool.util_dev --exec-search_module --mod=plottool --pat=networkx
        python -m utool.util_dev --exec-search_module --mod=utool --pat=Levenshtein

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_dev import *  # NOQA
        >>> import utool as ut
        >>> recursive = True
        >>> ignore_case = True
        >>> modname = ut.get_argval('--mod', type_=str, default='utool')
        >>> pat = ut.get_argval('--pat', type_=str, default='search')
        >>> mod = ut.import_modname(modname)
        >>> print('pat = %r' % (pat,))
        >>> print('mod = %r' % (mod,))
        >>> found_list = search_module(mod, pat, recursive=recursive)
        >>> result = ('found_list = %s' % (ut.repr2(found_list),))
        >>> print(result)

    Ignore:
        mod = cv2
        pat = 'freak'

def search_module(mod, pat, ignore_case=True, recursive=False, _seen=None):
    r"""
    Searches module functions, classes, and constants for members matching a
    pattern.

    Args:
        mod (module): live python module
        pat (str): regular expression

    Returns:
        list: found_list

    CommandLine:
        python -m utool.util_dev --exec-search_module --mod=utool --pat=module
        python -m utool.util_dev --exec-search_module --mod=opengm --pat=cut
        python -m utool.util_dev --exec-search_module --mod=opengm --pat=multi
        python -m utool.util_dev --exec-search_module --mod=plottool --pat=networkx
        python -m utool.util_dev --exec-search_module --mod=utool --pat=Levenshtein

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_dev import *  # NOQA
        >>> import utool as ut
        >>> recursive = True
        >>> ignore_case = True
        >>> modname = ut.get_argval('--mod', type_=str, default='utool')
        >>> pat = ut.get_argval('--pat', type_=str, default='search')
        >>> mod = ut.import_modname(modname)
        >>> print('pat = %r' % (pat,))
        >>> print('mod = %r' % (mod,))
        >>> found_list = search_module(mod, pat, recursive=recursive)
        >>> result = ('found_list = %s' % (ut.repr2(found_list),))
        >>> print(result)

    Ignore:
        mod = cv2
        pat = 'freak'
    """
    if _seen is not None and mod in _seen:
        return []
    import utool as ut
    reflags = re.IGNORECASE * ignore_case
    found_list = [name for name in dir(mod) if re.search(pat, name, flags=reflags)]
    if recursive:
        if _seen is None:
            _seen = set()
        _seen.add(mod)
        module_attrs = [getattr(mod, name) for name in dir(mod)]
        submodules = [
            submod for submod in module_attrs
            if isinstance(submod, types.ModuleType) and submod not in _seen and
            ut.is_defined_by_module(submod, mod)
        ]
        for submod in submodules:
            found_list += search_module(submod, pat, ignore_case=ignore_case, recursive=recursive, _seen=_seen)
    # found_list = [name for name in dir(mod) if name.find(pat) >= 0]
    found_list = ut.unique_ordered(found_list)
    return found_list