Filesystem facts the scratch reasons with: tree sizes, free space, atomic promotion.
available_bytes(path)
The bytes free to an unprivileged writer on path's filesystem.
Source code in capturegraph-lib/capturegraph/recipes/scratch/fs.py
| def available_bytes(path: Path) -> int:
"""The bytes free to an unprivileged writer on ``path``'s filesystem."""
stats = os.statvfs(path)
return stats.f_bavail * stats.f_frsize
|
Move the tree source to destination atomically, unless one is already there.
Returns:
| Type |
Description |
bool
|
Whether source became destination; False means an equal tree
|
bool
|
was already present and source was discarded.
|
Source code in capturegraph-lib/capturegraph/recipes/scratch/fs.py
| def promote(source: Path, destination: Path) -> bool:
"""Move the tree ``source`` to ``destination`` atomically, unless one is already there.
Returns:
Whether ``source`` became ``destination``; ``False`` means an equal tree
was already present and ``source`` was discarded.
"""
if destination.exists():
remove_tree(source)
return False
try:
os.rename(source, destination)
except OSError as error:
if error.errno in (errno.EEXIST, errno.ENOTEMPTY):
remove_tree(source)
return False
raise
return True
|
remove_tree(path)
Delete path and everything under it; an absent path is fine.
Source code in capturegraph-lib/capturegraph/recipes/scratch/fs.py
| def remove_tree(path: Path) -> None:
"""Delete ``path`` and everything under it; an absent path is fine."""
shutil.rmtree(path, ignore_errors=True)
|
tree_size(path)
The bytes under path (a file's own size, a directory's recursive total).
Source code in capturegraph-lib/capturegraph/recipes/scratch/fs.py
| def tree_size(path: Path) -> int:
"""The bytes under ``path`` (a file's own size, a directory's recursive total)."""
status = os.lstat(path)
if not os.path.isdir(path):
return status.st_size
total = 0
for directory, _, names in os.walk(path):
for name in names:
total += os.lstat(os.path.join(directory, name)).st_size
return total
|