Skip to content

trestle.common.trash

trestle.common.trash ¤

Trestle trash module.

Attributes¤

TRESTLE_TRASH_DIR = '.trestle/_trash/' module-attribute ¤

TRESTLE_TRASH_DIR_EXT = '__bk' module-attribute ¤

TRESTLE_TRASH_FILE_EXT = '.bk' module-attribute ¤

Functions¤

get_trash_root(path) ¤

Find the trestle trash root path.

Source code in trestle/common/trash.py
62
63
64
65
66
67
68
69
70
71
72
73
74
def get_trash_root(path: pathlib.Path) -> Optional[pathlib.Path]:
    """Find the trestle trash root path."""
    if path is None or len(path.parts) <= 0:
        return None

    current = path
    while len(current.parts) > 1:  # it must not be the system root directory
        trash_dir = current / TRESTLE_TRASH_DIR
        if trash_dir.exists() and trash_dir.is_dir():
            return trash_dir
        current = current.parent

    return None

has_parent_path(sub_path, parent_path) ¤

Check if sub_path has the specified parent_dir path.

Source code in trestle/common/trash.py
219
220
221
222
223
224
225
226
227
228
def has_parent_path(sub_path: pathlib.Path, parent_path: pathlib.Path) -> bool:
    """Check if sub_path has the specified parent_dir path."""
    # sub_path should be longer than parent path
    if len(sub_path.parts) < len(parent_path.parts):
        return False

    for i, part in enumerate(parent_path.parts):
        if part != sub_path.parts[i]:
            return False
    return True

recover(dest_content_path, delete_trash=False) ¤

Recover the specified file or directory from the trash directory.

dest_content_path: destination content path that needs to be recovered from trash It recovers the latest path content from trash if exists

Source code in trestle/common/trash.py
208
209
210
211
212
213
214
215
216
def recover(dest_content_path: pathlib.Path, delete_trash: bool = False) -> None:
    """Recover the specified file or directory from the trash directory.

    dest_content_path: destination content path that needs to be recovered from trash
    It recovers the latest path content from trash if exists
    """
    if dest_content_path.suffix != '':
        return recover_file(dest_content_path, delete_trash)
    return recover_dir(dest_content_path, delete_trash)

recover_dir(dest_dir_path, delete_trash=False) ¤

Move the specified dir from the trash directory.

dest_dir_path: destination path of the directory inside a trestle workspace

It recovers the latest directory and contents from trash if exists

Source code in trestle/common/trash.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
def recover_dir(dest_dir_path: pathlib.Path, delete_trash: bool = False) -> None:
    """Move the specified dir from the trash directory.

    dest_dir_path: destination path of the directory inside a trestle workspace

    It recovers the latest directory and contents from trash if exists
    """
    trash_dir_path = to_trash_dir_path(dest_dir_path)
    if not (trash_dir_path.exists() and trash_dir_path.is_dir()):
        raise AssertionError(f'Specified path "{dest_dir_path}" could not be found in trash')

    # move all files/directories under sub_path
    for item_path in pathlib.Path.iterdir(trash_dir_path):
        if item_path.is_file():
            recover_file(to_origin_file_path(item_path), delete_trash)
        elif item_path.is_dir():
            recover_dir(to_origin_dir_path(item_path), delete_trash)

    if delete_trash:
        trash_dir_path.rmdir()

recover_file(file_path, delete_trash=False) ¤

Recover the specified file from the trash directory.

It recovers the latest file from trash if exists

Source code in trestle/common/trash.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def recover_file(file_path: pathlib.Path, delete_trash: bool = False) -> None:
    """Recover the specified file from the trash directory.

    It recovers the latest file from trash if exists
    """
    trash_file_path = to_trash_file_path(file_path)
    if not trash_file_path.exists():
        raise AssertionError(f'Specified path "{file_path}" could not be found in trash')

    file_path.parent.mkdir(exist_ok=True, parents=True)
    copyfile(trash_file_path, file_path)

    if delete_trash:
        trash_file_path.unlink()

store(content_path, delete_content=False) ¤

Move the specified file or directory to the trash directory.

It overwrites the previous file or directory if exists

Source code in trestle/common/trash.py
159
160
161
162
163
164
165
166
167
def store(content_path: pathlib.Path, delete_content: bool = False) -> None:
    """Move the specified file or directory to the trash directory.

    It overwrites the previous file or directory if exists
    """
    if content_path.is_file():
        return store_file(content_path, delete_content)
    if content_path.is_dir():
        return store_dir(content_path, delete_content)

store_dir(dir_path, delete_source=False) ¤

Move the specified dir to the trash directory.

It overwrites the previous directory and contents if exists

Source code in trestle/common/trash.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def store_dir(dir_path: pathlib.Path, delete_source: bool = False) -> None:
    """Move the specified dir to the trash directory.

    It overwrites the previous directory and contents if exists
    """
    if not dir_path.is_dir():
        raise AssertionError(f'Specified path "{dir_path}" is not a dir')

    # move all files/directories under sub_path
    for item_path in pathlib.Path.iterdir(dir_path):
        if item_path.is_file():
            store_file(item_path, delete_source)
        elif item_path.is_dir():
            store_dir(item_path, delete_source)

    if delete_source:
        dir_path.rmdir()

store_file(file_path, delete_source=False) ¤

Move the specified file to the trash directory.

It overwrites the previous file if exists

Source code in trestle/common/trash.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def store_file(file_path: pathlib.Path, delete_source: bool = False) -> None:
    """Move the specified file to the trash directory.

    It overwrites the previous file if exists
    """
    if not file_path.is_file():
        raise AssertionError(f'Specified path "{file_path}" is not a file')

    trash_file_path = to_trash_file_path(file_path)
    trash_file_path.parent.mkdir(exist_ok=True, parents=True)
    copyfile(file_path, trash_file_path)

    if delete_source:
        file_path.unlink()

to_origin_dir_path(trash_dir_path) ¤

Convert trash content path to origin path.

Source code in trestle/common/trash.py
 77
 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
def to_origin_dir_path(trash_dir_path: pathlib.Path) -> pathlib.Path:
    """Convert trash content path to origin path."""
    if trash_dir_path.suffix != '' and trash_dir_path.suffix.endswith(TRESTLE_TRASH_FILE_EXT):
        raise AssertionError(f'Given path "{trash_dir_path}" is a trash file, not a valid trash directory')

    trestle_root = file_utils.extract_trestle_project_root(trash_dir_path)
    if trestle_root is None:
        raise AssertionError(f'Directory path "{trash_dir_path}" is not in a valid trestle project path')

    trash_root = get_trash_root(trash_dir_path)
    if trash_root is None:
        raise AssertionError(f'Directory path "{trash_dir_path}" is not in a valid trestle trash path')

    if not has_parent_path(trash_dir_path, trash_root):
        raise AssertionError(f'Directory path "{trash_dir_path}" is not a valid trash dir path')

    relative_path = trash_dir_path.relative_to(str(trash_root))

    origin_path_parts: List[str] = []
    for item in relative_path.parts:
        parts = item.split(TRESTLE_TRASH_DIR_EXT)
        origin_path_parts.append(parts[0])

    origin_relative_path = pathlib.Path('/'.join(origin_path_parts))
    origin_path = trestle_root / origin_relative_path
    return origin_path

to_origin_file_path(trash_file_path) ¤

Convert trash file path to origin file path.

Source code in trestle/common/trash.py
105
106
107
108
109
110
111
112
113
114
def to_origin_file_path(trash_file_path: pathlib.Path) -> pathlib.Path:
    """Convert trash file path to origin file path."""
    if trash_file_path.suffix != TRESTLE_TRASH_FILE_EXT:
        raise AssertionError(f'File path "{trash_file_path}" is not a valid trash file path')

    origin_dir = to_origin_dir_path(trash_file_path.parent)
    file_parts = trash_file_path.name.split(TRESTLE_TRASH_FILE_EXT)
    origin_file_path = origin_dir / file_parts[0]

    return origin_file_path

to_origin_path(trash_content_path) ¤

Convert the trash path to origin path.

Source code in trestle/common/trash.py
117
118
119
120
121
def to_origin_path(trash_content_path: pathlib.Path) -> pathlib.Path:
    """Convert the trash path to origin path."""
    if trash_content_path.suffix == TRESTLE_TRASH_FILE_EXT:
        return to_origin_file_path(trash_content_path)
    return to_origin_dir_path(trash_content_path)

to_trash_dir_path(dir_path) ¤

Construct the path to the trashed file.

Source code in trestle/common/trash.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def to_trash_dir_path(dir_path: pathlib.Path) -> pathlib.Path:
    """Construct the path to the trashed file."""
    absolute_path = dir_path.resolve()
    root_path = file_utils.extract_trestle_project_root(absolute_path)
    if root_path is None:
        raise AssertionError(f'Directory path "{absolute_path}" is not in a valid trestle project')

    trestle_trash_path = root_path / TRESTLE_TRASH_DIR

    relative_path = absolute_path.relative_to(str(root_path))
    if len(relative_path.parts) == 0:
        trash_dir = trestle_trash_path
    else:
        trash_dir = trestle_trash_path / f'{relative_path}{TRESTLE_TRASH_DIR_EXT}'

    return trash_dir

to_trash_file_path(file_path) ¤

Construct the path to the trashed file.

Source code in trestle/common/trash.py
47
48
49
50
51
52
def to_trash_file_path(file_path: pathlib.Path) -> pathlib.Path:
    """Construct the path to the trashed file."""
    trash_file_dir = to_trash_dir_path(file_path.parent)
    trash_file_path = trash_file_dir / f'{file_path.name}{TRESTLE_TRASH_FILE_EXT}'

    return trash_file_path

to_trash_path(path) ¤

Convert the dir or file path to apporpriate trash file or dir path.

Source code in trestle/common/trash.py
55
56
57
58
59
def to_trash_path(path: pathlib.Path) -> pathlib.Path:
    """Convert the dir or file path to apporpriate trash file or dir path."""
    if path.suffix != '':
        return to_trash_file_path(path)
    return to_trash_dir_path(path)

handler: python