Skip to content

pathutils

sleap.io.pathutils

Utilities for working with file paths.

Functions:

Name Description
filenames_prefix_change

Finds missing files by changing the initial part of paths.

find_changed_subpath

Finds the smallest initial section of path that was changed.

list_file_missing

Given a list of filenames, returns list of whether file exists.

filenames_prefix_change(filenames, old_prefix, new_prefix, missing=None, confirm_callback=None)

Finds missing files by changing the initial part of paths.

Parameters:

Name Type Description Default
filenames

The list of filenames, needn't all be missing.

required
old_prefix

Initial part of path to replace.

required
new_prefix

Initial part with which to replace it.

required
missing bool

List of which files are known to be missing; if not given, then we'll check each file.

None
confirm_callback Optional[Callable]

If given, then we'll call this before applying change to confirm that user wants to apply the change.

None

Returns:

Type Description

None; filenames (and missing, if given) have new data.

Source code in sleap/io/pathutils.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def filenames_prefix_change(
    filenames,
    old_prefix,
    new_prefix,
    missing: bool = None,
    confirm_callback: Optional[Callable] = None,
):
    """
    Finds missing files by changing the initial part of paths.

    Args:
        filenames: The list of filenames, needn't all be missing.
        old_prefix: Initial part of path to replace.
        new_prefix: Initial part with which to replace it.
        missing: List of which files are known to be missing; if not given,
            then we'll check each file.
        confirm_callback: If given, then we'll call this before applying
            change to confirm that user wants to apply the change.

    Returns:
        None; `filenames` (and `missing`, if given) have new data.
    """

    if not filenames or not old_prefix or not new_prefix:
        return

    # Ask for confirmation if there's a confirmation callback given
    need_to_ask = True if callable(confirm_callback) else False

    # Try changing every filename unless we're given list of which are missing
    check = missing if missing else [True] * len(filenames)

    # Just to be on the safe side, make sure this list covers all filenames
    if len(check) < len(filenames):
        check.extend([True] * (len(filenames) - len(check)))

    for i, filename in enumerate(filenames):
        if check[i]:
            if filename.startswith(old_prefix):
                try_filename = filename.replace(old_prefix, new_prefix)
                try_filename = fix_path_separator(try_filename)

                if os.path.exists(try_filename):
                    # Check if user would like to apply change to all paths
                    # with the same initial segment.
                    if need_to_ask and not confirm_callback():
                        return

                    # We're still here, so we can go ahead and replace
                    need_to_ask = False
                    filenames[i] = try_filename
                    check[i] = False

                    # Save prefix change in config file so that it can be used
                    # automatically in the future
                    save_path_prefix_replacement(old_prefix, new_prefix)

find_changed_subpath(old_path, new_path)

Finds the smallest initial section of path that was changed.

Parameters:

Name Type Description Default
old_path str

Old path

required
new_path str

New path

required

Returns:

Type Description
Tuple[str, str]

(initial part of old path), (corresponding replacement in new path)

Source code in sleap/io/pathutils.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
def find_changed_subpath(old_path: str, new_path: str) -> Tuple[str, str]:
    """Finds the smallest initial section of path that was changed.

    Args:
        old_path: Old path
        new_path: New path

    Returns:
        (initial part of old path), (corresponding replacement in new path)
    """
    seps = ("/", "\\")

    # Find overlap at end of paths
    old_common = ""
    new_char_idx = -1
    for old_char_idx in range(len(old_path) - 1, 0, -1):
        old_char = old_path[old_char_idx]
        new_char = new_path[new_char_idx]
        if old_char == new_char or old_char in seps and new_char in seps:
            old_common = old_char + old_common
            new_char_idx -= 1
        else:
            break

    # Get the initial part of the old path which was replaced, and the
    # initial part of the new path which replaced it.
    old_initial = old_path[: old_char_idx + 1]
    new_inital = new_path[: new_char_idx + 1] if new_char_idx < -1 else new_path

    return (old_initial, new_inital)

list_file_missing(filenames)

Given a list of filenames, returns list of whether file exists.

Source code in sleap/io/pathutils.py
11
12
13
def list_file_missing(filenames):
    """Given a list of filenames, returns list of whether file exists."""
    return [not os.path.exists(filename) for filename in filenames]