Skip to content

get_purity_results

Get the purity results of a package.

This function is the entry to the purity analysis of a package. It iterates over all modules in the package and infers the purity of the functions in the modules.

Parameters:

Name Type Description Default
src_dir_path Path

The path of the source directory of the package.

required

Returns:

Type Description
APIPurity

The purity results of the package.

Source code in src/library_analyzer/processing/api/purity_analysis/_infer_purity.py
def get_purity_results(
    src_dir_path: Path,
) -> APIPurity:
    """Get the purity results of a package.

    This function is the entry to the purity analysis of a package.
    It iterates over all modules in the package and infers the purity of the functions in the modules.

    Parameters
    ----------
    src_dir_path :
        The path of the source directory of the package.

    Returns
    -------
    APIPurity
        The purity results of the package.
    """
    modules = list(src_dir_path.glob("**/*.py"))
    module_names: list[str] = []
    package_purity = APIPurity()
    package_data = PackageData(src_dir_path.stem)

    for module in modules:
        posix_path = Path(module).as_posix()

        if _is_test_file(posix_path):
            continue

        module_name = __module_name(src_dir_path, Path(module))
        module_names.append(module_name)
        # Prepare the module data for all modules of the package.
        with module.open("r", encoding="utf-8") as file:
            code = file.read()
            package_data.modules.update({module_name: (posix_path, get_module_data(code, module_name, posix_path))})

    # Analyze the complete package.
    package_data.combine_modules()
    package_purity_results = infer_purity(code=None, results=package_purity.purity_results, package_data=package_data)

    # Group the results by file name.
    sorted_module_purity_results: dict[NodeID, dict[NodeID, PurityResult]] = {}
    for values in package_purity_results.values():
        for k, v in values.items():
            sorted_module_purity_results.setdefault(
                NodeID(None, "UNKNOWN" if k.module is None else k.module),
                {},
            ).update({k: v})

    # Add back empty files.
    for mod in module_names:
        if NodeID(None, mod) not in sorted_module_purity_results:
            sorted_module_purity_results[NodeID(None, mod)] = {}

    # Sort the functions by line number to make the results more readable.
    sorted_module_purity_results = {
        key: dict(
            sorted(
                value.items(),
                key=lambda item: item[0].line if item[0] is not None and item[0].line is not None else float("inf"),
            ),
        )
        for key, value in sorted_module_purity_results.items()
    }

    package_purity.purity_results.update(sorted_module_purity_results)

    # Clean the purity results by removing all modules that are not part of the package.
    for module_id in package_purity.purity_results.copy():
        if module_id.name not in module_names:
            package_purity.purity_results.pop(module_id)

    return package_purity