def search_symbols()

in scripts/generate_api_docs.py [0:0]


def search_symbols(config):
    # Validate module name to document
    assert (
        "settings" in config
        and "search" in config["settings"]
        and (
            type(config["settings"]["search"]) is str
            or type(config["settings"]["search"]) is list
        )
    )

    # TODO: Try to import module, more validation, etc.

    # Construct regular expressions for includes and excludes
    # Default include/exclude rules
    patterns = {
        "include": {"modules": re.compile(r".+"), "symbols": re.compile(r".+")},
        "exclude": {"modules": re.compile(r""), "symbols": re.compile(r"")},
    }

    # Override rules based on configuration file
    if "filters" in config:
        filters = config["filters"]
        for clude, rules in filters.items():
            for rule, pattern in rules.items():
                if type(pattern) is list:
                    pattern = "|".join(pattern)
                patterns[clude][rule] = re.compile(pattern)

    # Read in all modules and symbols
    search = config["settings"]["search"]
    search = [search] if type(search) is str else search
    modules_and_symbols = {}
    for modname in set(search):
        modules_and_symbols = {**modules_and_symbols, **walk_packages(modname)}

    # Apply filtering
    # TODO: Would be slightly faster if we applied module filtering inside walk_packages
    tmp = {}
    for x, y in modules_and_symbols.items():
        if (
            patterns["include"]["modules"].fullmatch(x) is not None
            and patterns["exclude"]["modules"].fullmatch(x) is None
        ):

            new_y1 = [
                (a, b)
                for a, b in y[1]
                if patterns["include"]["symbols"].fullmatch(x + "." + a) is not None
                and patterns["exclude"]["symbols"].fullmatch(x + "." + a) is None
            ]

            tmp[x] = (y[0], new_y1)

    return tmp