def combine_parallel_data(
    data: CoverageData,
    aliases: PathAliases | None = None,
    data_paths: Iterable[str] | None = None,
    strict: bool = False,
    keep: bool = False,
    message: Callable[[str], None] | None = None,
) -> None:
    """Combine a number of data files together.

    `data` is a CoverageData.

    Treat `data.filename` as a file prefix, and combine the data from all
    of the data files starting with that prefix plus a dot.

    If `aliases` is provided, it's a `PathAliases` object that is used to
    re-map paths to match the local machine's.

    If `data_paths` is provided, it is a list of directories or files to
    combine.  Directories are searched for files that start with
    `data.filename` plus dot as a prefix, and those files are combined.

    If `data_paths` is not provided, then the directory portion of
    `data.filename` is used as the directory to search for data files.

    Unless `keep` is True every data file found and combined is then deleted
    from disk. If a file cannot be read, a warning will be issued, and the
    file will not be deleted.

    If `strict` is true, and no files are found to combine, an error is
    raised.

    `message` is a function to use for printing messages to the user.

    """
    files_to_combine = combinable_files(data.base_filename(), data_paths)

    if strict and not files_to_combine:
        raise NoDataError("No data to combine")

    if aliases is None:
        map_path = None
    else:
        map_path = functools.cache(aliases.map)

    file_hashes = set()
    combined_any = False

    for f in files_to_combine:
        if f == data.data_filename():
            # Sometimes we are combining into a file which is one of the
            # parallel files.  Skip that file.
            if data._debug.should("dataio"):
                data._debug.write(f"Skipping combining ourself: {f!r}")
            continue

        try:
            rel_file_name = os.path.relpath(f)
        except ValueError:
            # ValueError can be raised under Windows when os.getcwd() returns a
            # folder from a different drive than the drive of f, in which case
            # we print the original value of f instead of its relative path
            rel_file_name = f

        with open(f, "rb") as fobj:
            hasher = hashlib.new("sha3_256", usedforsecurity=False)
            hasher.update(fobj.read())
            sha = hasher.digest()
            combine_this_one = sha not in file_hashes

        delete_this_one = not keep
        if combine_this_one:
            if data._debug.should("dataio"):
                data._debug.write(f"Combining data file {f!r}")
            file_hashes.add(sha)
            try:
                new_data = CoverageData(f, debug=data._debug)
                new_data.read()
            except CoverageException as exc:
                if data._warn:
                    # The CoverageException has the file name in it, so just
                    # use the message as the warning.
                    data._warn(str(exc))
                if message:
                    message(f"Couldn't combine data file {rel_file_name}: {exc}")
                delete_this_one = False
            else:
                data.update(new_data, map_path=map_path)
                combined_any = True
                if message:
                    message(f"Combined data file {rel_file_name}")
        else:
            if message:
                message(f"Skipping duplicate data {rel_file_name}")

        if delete_this_one:
            if data._debug.should("dataio"):
                data._debug.write(f"Deleting data file {f!r}")
            file_be_gone(f)

    if strict and not combined_any:
        raise NoDataError("No usable data files")
Combine a number of data files together.

    `data` is a CoverageData.

    Treat `data.filename` as a file prefix, and combine the data from all
    of the data files starting with that prefix plus a dot.

    If `aliases` is provided, it's a `PathAliases` object that is used to
    re-map paths to match the local machine's.

    If `data_paths` is provided, it is a list of directories or files to
    combine.  Directories are searched for files that start with
    `data.filename` plus dot as a prefix, and those files are combined.

    If `data_paths` is not provided, then the directory portion of
    `data.filename` is used as the directory to search for data files.

    Unless `keep` is True every data file found and combined is then deleted
    from disk. If a file cannot be read, a warning will be issued, and the
    file will not be deleted.

    If `strict` is true, and no files are found to combine, an error is
    raised.

    `message` is a function to use for printing messages to the user.

    
coverage/data.py