Filesystem

Utilities for directory traversal, file metadata, and batch operations.

Overview

DirTree and FileMetadataReader are static utility classes under buvis.pybase.filesystem. Each exposes class-level helpers—no instantiation is required—to inspect directory depth, prune files, or read timestamps. DirTree bundles cleanup routines (counting files, normalizing extensions, removing empty folders, and merging Mac metadata), while FileMetadataReader surfaces creation and first-commit datetimes with platform-aware fallbacks.

Quick Start

from pathlib import Path
from buvis.pybase.filesystem import DirTree, FileMetadataReader

project_root = Path(__file__).resolve().parent

# Static utilities: no DirTree() or FileMetadataReader() instantiation.
total_files = DirTree.count_files(project_root / "src")
creation_dt = FileMetadataReader.get_creation_datetime(project_root / "pyproject.toml")
first_commit = FileMetadataReader.get_first_commit_datetime(project_root / "pyproject.toml")

print(total_files, creation_dt, first_commit)

API Reference

DirTree

class buvis.pybase.filesystem.DirTree

Bases: object

Utility with static directory operations.

Provides static methods for counting files, cleanup routines, and normalization helpers. No instantiation is required.

Example

>>> from buvis.pybase.filesystem import DirTree
>>> from pathlib import Path
>>> count = DirTree.count_files(Path('/data'))
static count_files(directory: Path) int

Count the number of files in the directory and its subdirectories.

Parameters:

directory – Path to the directory to process.

Returns:

Number of files in the directory and its subdirectories.

static delete_by_extension(directory: Path, extensions_to_delete: list[str]) None

Delete files with specific extensions in the given directory.

Parameters:
  • directory – Path to the directory to process.

  • extensions_to_delete – List of file extensions to delete.

Returns:

None. The function modifies the directory in place.

static get_max_depth(directory: Path) int

Determine the maximum depth of the directory tree.

Parameters:

directory – Path to the directory to process.

Returns:

Maximum depth of the directory tree.

static merge_mac_metadata(directory: Path) None

Restore macOS metadata from AppleDouble helper files.

Walks the directory tree for AppleDouble files (._*) and, when not on Windows, applies their extended attributes back to the corresponding originals before cleaning up any orphaned helper files. This serves as a post-copy cleanup for macOS metadata files.

Parameters:

directory – Directory containing files and AppleDouble metadata.

static normalize_file_extensions(directory: Path) None

Normalize file extensions in the given directory: 1) lowercase the extensions 2) replace equivalents

Parameters:

directory – Path to the directory to process.

Returns:

None. The function modifies the directory in place.

static remove_empty_directories(directory: Path) None

Recursively remove all empty directories.

Traverses bottom-up to remove directories that become empty after their children are removed.

Parameters:

directory – Root directory to clean.

Note

Modifies the directory tree in place. Non-empty directories and files are preserved.

FileMetadataReader

class buvis.pybase.filesystem.FileMetadataReader

Bases: object

Utility reader that exposes static helpers for file metadata.

The class is not meant to be instantiated; callers just need to invoke the static helpers to obtain timestamps such as the file creation datetime or the first commit datetime in a Git repository. Creation-time resolution is platform specific (Windows uses st_ctime while Unix systems prefer st_birthtime with a fallback to modification time).

Example

>>> FileMetadataReader.get_creation_datetime(Path("example.txt"))
datetime(2024, 7, 8, 12, 34, tzinfo=...)
static get_creation_datetime(file_path: Path) datetime

Retrieve the creation date of a file, falling back to modification date if creation date is unavailable.

Parameters:

file_path (Path) – Path to the file.

Returns:

Datetime when file was created.

Return type:

datetime

static get_first_commit_datetime(file_path: Path) datetime | None

Retrieve the date a file was first added to a Git repository located at the parent directory of file_path.

Parameters:

file_path (Path) – Path to the file.

Returns:

Datetime of the first commit involving the file

or None if the file wasn’t committed to any Git repository.

Return type:

datatime | None

Examples

DirTree Example

Use DirTree to profile and clean a release artifact directory before publishing.

from pathlib import Path
from buvis.pybase.filesystem import DirTree

project_root = Path(__file__).resolve().parent
artifacts_dir = project_root / "dist" / "artifacts"

file_count = DirTree.count_files(artifacts_dir)
max_depth = DirTree.get_max_depth(artifacts_dir)
print(f"Artifact tree: {file_count} files across {max_depth} levels.")

DirTree.delete_by_extension(artifacts_dir, [".tmp", ".log"])
DirTree.normalize_file_extensions(artifacts_dir)
DirTree.remove_empty_directories(artifacts_dir)
DirTree.merge_mac_metadata(artifacts_dir)

# The cleanup routine removes stray caches, coerces extensions to the
# project standard, prunes empty folders, and restores macOS metadata.

FileMetadataReader Example

FileMetadataReader can guard metadata-dependent builds while accounting for non-git working trees.

from pathlib import Path
from buvis.pybase.filesystem import FileMetadataReader

project_root = Path(__file__).resolve().parent
config_file = project_root / "pyproject.toml"

created = FileMetadataReader.get_creation_datetime(config_file)
print(f"{config_file.name} born at {created.isoformat()}")

first_commit = FileMetadataReader.get_first_commit_datetime(config_file)
if first_commit is None:
    raise RuntimeError(
        f"{config_file} lives outside a Git repository; commit metadata unavailable."
    )
print(f"First commit touching {config_file.name} occurred on {first_commit.date()}")