Source code for mypythontools.paths.paths_internal

"""Module with functions for 'paths' subpackage."""

from __future__ import annotations
from typing import Sequence, Union
from pathlib import Path

from ..types import validate_sequence

PathLike = Union[Path, str]  # Path is included in PathLike
"""Str pr pathlib Path. It can be also relative to current working directory."""


[docs]def find_path( name: str, folder: PathLike | None = None, exclude_names: Sequence[str] = ("node_modules", "build", "dist", "venv"), exclude_paths: Sequence[PathLike] = (), levels: int = 5, ) -> Path: """Search for file or folder in defined folder (cwd() by default) and return it's path. Args: name (str): Name of folder or file that should be found. If using file, use it with extension e.g. "app.py". folder (PathLike | None, optional): Where to search. If None, then root is used (cwd by default). Defaults to None. exclude_names (Sequence[str], optional): List or tuple of ignored names. If this name is whenever in path, it will be ignored. Defaults to ('node_modules', 'build', 'dist', 'venv'). exclude_paths (Sequence[PathLike], optional): List or tuple of ignored paths. If defined path is subpath of found file, it will be ignored. If relative, it has to be from cwd. Defaults to (). levels (str, optional): Recursive number of analyzed folders. Defaults to 5. Returns: Path: Found path. Raises: FileNotFoundError: If file is not found. Example: >>> path = find_path("README.md", exclude_names=['venv']) >>> path.exists() True """ validate_sequence(exclude_names, "exclude_names") validate_sequence(exclude_paths, "exclude_paths") folder = Path.cwd() if not folder else validate_path(folder) for lev in range(levels): glob_file_str = f"{'*/' * lev}{name}" for i in folder.glob(glob_file_str): is_wanted_file = True for j in exclude_names: if j in i.parts: is_wanted_file = False break if is_wanted_file: for j in exclude_paths: excluded_name = Path(j).resolve() if i.as_posix().startswith(excluded_name.as_posix()): is_wanted_file = False break if is_wanted_file: return i # If not returned - not found raise FileNotFoundError(f"File `{name}` not found")
[docs]def get_desktop_path() -> Path: """Get desktop path. Returns: Path: Return pathlib Path object. If you want string, use `.as_posix()` Example: >>> desktop_path = get_desktop_path() >>> desktop_path.exists() True """ return Path.home() / "Desktop"
[docs]def validate_path( path: PathLike, error_prefix: None | str = None, error_file_name: None | str = None ) -> Path: """Convert to pathlib path, resolve to full path and check if exists. Args: path (PathLike): Validated path. error_prefix (None | str): Prefix for raised error if file nor folder found. Defaults to None. error_file_name (): In raised error it's the name of file or folder that should be found, so user understand what happened. Defaults to None. Raises: FileNotFoundError: If file nor folder do not exists. Returns: Path: Pathlib Path object. Example: >>> from pathlib import Path >>> existing_path = validate_path(Path.cwd()) >>> non_existing_path = validate_path("not_existing") Traceback (most recent call last): FileNotFoundError: ... """ path = Path(path).resolve() if not path.exists(): error_file_name = f"'{error_file_name}' not " if error_file_name else "Nothing" raise FileNotFoundError(f"{error_prefix}. Nothing found on defined path {path}") return path
[docs]def isFolderEmpty(path: PathLike) -> bool: """Check whether folder is empty. Args: path (PathLike): Path to folder Raises: RuntimeError: If there is no folder on path. Returns: bool: True or False Example: >>> from pathlib import Path >>> from shutil import rmtree >>> test_path = Path("isFolderEmptyFolder") >>> test_path.mkdir() >>> isFolderEmpty(test_path) True >>> isFolderEmpty(test_path.parent) False >>> rmtree("isFolderEmptyFolder") """ path = validate_path(path) if not path.is_dir(): raise RuntimeError("On defined path is not folder.") content = next(path.iterdir(), None) if content is None: return True else: return False
[docs]def is_path_free(path: PathLike): """Check whether path is available. It means that it doesn't exists yet or its a folder, but it's empty. Args: path (PathLike): Path to be verified. Returns: bool: True or False Example: >>> from pathlib import Path >>> from shutil import rmtree >>> is_path_free("non/existing/path") True >>> test_path = Path("isFolderEmptyFolder") >>> test_path.mkdir() >>> is_path_free(test_path) True >>> is_path_free(test_path.parent) False >>> rmtree("isFolderEmptyFolder") """ path = Path(path) if not Path(path).exists(): return True else: if path.is_dir: if isFolderEmpty(path): return True return False