Skip to content

Commit

Permalink
feat: detail kwarg for list_files
Browse files Browse the repository at this point in the history
  • Loading branch information
phil65 committed Feb 22, 2025
1 parent f7df960 commit 9b1ac15
Showing 1 changed file with 74 additions and 18 deletions.
92 changes: 74 additions & 18 deletions src/upathtools/async_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from itertools import batched
import logging
import os
from typing import TYPE_CHECKING, Literal, overload
from typing import TYPE_CHECKING, Any, Literal, overload


if TYPE_CHECKING:
Expand Down Expand Up @@ -206,6 +206,20 @@ async def read_folder(
return result


@overload
async def list_files(
path: StrPath,
*,
pattern: str = "**/*",
recursive: bool = True,
include_dirs: bool = False,
exclude: list[str] | None = None,
max_depth: int | None = None,
detail: Literal[False] = False,
) -> list[UPath]: ...


@overload
async def list_files(
path: StrPath,
*,
Expand All @@ -214,7 +228,20 @@ async def list_files(
include_dirs: bool = False,
exclude: list[str] | None = None,
max_depth: int | None = None,
) -> list[UPath]:
detail: Literal[True],
) -> list[dict[str, Any]]: ...


async def list_files(
path: StrPath,
*,
pattern: str = "**/*",
recursive: bool = True,
include_dirs: bool = False,
exclude: list[str] | None = None,
max_depth: int | None = None,
detail: bool = False,
) -> list[UPath] | list[dict[str, Any]]:
"""List files in a folder matching a pattern.
Args:
Expand All @@ -224,6 +251,7 @@ async def list_files(
include_dirs: Whether to include directories in results
exclude: List of patterns to exclude (uses fnmatch against relative paths)
max_depth: Maximum directory depth for recursive search
detail: Include file details in the result
Returns:
List of UPath objects for matching files
Expand All @@ -241,32 +269,60 @@ async def list_files(
raise FileNotFoundError(msg)

fs = await get_async_fs(base_path)
matching_files: list[UPath] = []
matching_files: list[UPath | dict[str, Any]] = []

# Get all matching paths
if recursive:
paths = await fs._glob(str(base_path / pattern), maxdepth=max_depth)
paths = await fs._glob(
str(base_path / pattern), maxdepth=max_depth, detail=detail
)
else:
paths = await fs._glob(str(base_path / pattern))
paths = await fs._glob(str(base_path / pattern), detail=detail)

# Filter and collect paths

# Filter and collect paths
for file_path in paths:
path_obj = UPath(file_path)
rel_path = os.path.relpath(file_path, str(base_path)) # type: ignore
if detail:
assert isinstance(paths, dict)
for file_path, file_info in paths.items():
assert isinstance(file_path, str)
rel_path = os.path.relpath(file_path, str(base_path))

# Skip excluded patterns
if exclude and any(fnmatch(rel_path, pat) for pat in exclude):
continue

# Skip directories unless explicitly included
is_dir = await fs._isdir(file_path)
if is_dir and not include_dirs:
continue

if not is_dir:
matching_files.append({
**file_info,
"name": os.path.basename(file_path), # noqa: PTH119
"path": file_path,
})
else:
for file_path in paths:
assert isinstance(file_path, str)

path_obj = UPath(file_path)
rel_path = os.path.relpath(file_path, str(base_path))

# Skip excluded patterns
if exclude and any(fnmatch(rel_path, pat) for pat in exclude):
continue
# Skip excluded patterns
if exclude and any(fnmatch(rel_path, pat) for pat in exclude):
continue

# Skip directories unless explicitly included
is_dir = await fs._isdir(file_path)
if is_dir and not include_dirs:
continue
# Skip directories unless explicitly included
is_dir = await fs._isdir(file_path)
if is_dir and not include_dirs:
continue

if not is_dir:
matching_files.append(path_obj)
if not is_dir:
matching_files.append(path_obj)

return matching_files
return matching_files # type: ignore


if __name__ == "__main__":
Expand Down

0 comments on commit 9b1ac15

Please sign in to comment.