def timestamps_from_paths(paths, ignore_fn=None):
    """
    From a list of paths, recursively return the timestamps
    from all non-hidden and non-ignored paths

    args:
        A list of paths to recursively explore
        ignore_fn: Ignore paths where this callback returns True

    returns:
        a list of timestamps
    """

    if not isinstance(paths, list):
        paths = [paths]

    def keep(f):
        return f.name[0] != "." and not (ignore_fn is not None and ignore_fn(f))

    def recurse_times(path):
        times = []
        if path.exists() and keep(path):
            if path.is_dir():
                for f in path.list():
                    times += recurse_times(f)
            else:
                times += [(path, path.stat().st_mtime)]
        return times

    times = []
    for path in paths:
        times += recurse_times(path)

    return sorted(times, key=lambda i: i[0])