from __future__ import annotations from dataclasses import dataclass from pathlib import Path @dataclass(frozen=True, slots=True) class DirectoryEntry: """Directory metadata used by the navigator layer.""" name: str path: Path has_children: bool def list_directories(path: Path, show_hidden: bool = False) -> list[DirectoryEntry]: """Return direct child directories sorted by name.""" directory_path = path.expanduser().resolve() entries: list[DirectoryEntry] = [] try: children = list(directory_path.iterdir()) except PermissionError: return [] for child in children: try: is_directory = child.is_dir() except OSError: continue if not is_directory: continue if not show_hidden and child.name.startswith("."): continue entries.append( DirectoryEntry( name=child.name, path=child, has_children=has_subdirectories(child, show_hidden=show_hidden), ) ) return sorted(entries, key=lambda entry: entry.name.casefold()) def has_subdirectories(path: Path, show_hidden: bool = False) -> bool: """Return whether the directory contains at least one subdirectory.""" directory_path = path.expanduser().resolve() try: children = list(directory_path.iterdir()) except PermissionError: return False for child in children: try: is_directory = child.is_dir() except OSError: continue if not is_directory: continue if not show_hidden and child.name.startswith("."): continue return True return False