Source code for ahvn.utils.basic.path_utils

__all__ = [
    "pj",
    "get_file_ext",
    "get_file_name",
    "get_file_basename",
    "get_file_dir",
    "has_file_ext",
]

import re
import os
from typing import Union, List


[docs] def pj(*args: List[str], abs: bool = False) -> str: """\ Join a list of strings into a path. Platform-agnostic and user-expanding. Spaces and trailing slashes are stripped from each argument. Args: *args: Components of the path to join. Each argument should be a string. abs (bool, optional): If True, returns the absolute path. Defaults to False. Returns: str: The joined, normalized path. Expands '~' to the user's home directory. """ args = [arg.rstrip(" /").strip() for arg in args if arg.rstrip(" /").strip()] if not args: return "/" path = os.path.expanduser(os.path.join(*[arg for arg in args if arg])) return os.path.normpath(path if not abs else os.path.abspath(path))
[docs] def get_file_ext(path: str) -> str: """\ Get the file extension (without a dot) for a specified path. Args: path (str): The path to the file. Returns: str: The file extension without a dot. """ ext = os.path.splitext(pj(path, abs=True))[1] return ext[1:] if ext.startswith(".") else ext
[docs] def get_file_name(path: str, ext: Union[bool, str] = True, abs: bool = False) -> str: """\ Get the full file name from the specified path. When a file extension is provided (preferrably without a dot), it will be used instead of the file's original extension. Args: path: str: The path to the file. ext: Union[bool, str]: If True, returns the file name with its original extension. If False, returns the file name without any extension. If a string is provided, it will be used as the new extension. abs: bool: If True, returns the absolute path. Defaults to False. Returns: str: The file name with or without the specified extension. Examples: >>> get_file_name("A/B/C/file.txt") 'A/B/C/file.txt' >>> get_file_name("A/B/C/file.txt", ext=True) 'A/B/C/file.txt' >>> get_file_name("A/B/C/file.txt", ext=False) 'A/B/C/file' >>> get_file_name("A/B/C/file.txt", ext="md") 'A/B/C/file.md' >>> get_file_name("A/B/C/") 'C' """ path = pj(path, abs=abs) pfx, _ = os.path.splitext(path) if not ext: return pfx if ext is True: return path return pfx + ("" if ext.startswith(".") else ".") + ext
[docs] def get_file_basename(path: str, ext: Union[bool, str] = True) -> str: """\ Get the base name of the file from the specified path. When a file extension is provided (preferably without a dot), it will be used instead of the file's original extension. Args: path (str): The path to the file. ext (Union[bool, str]): If True, returns the file name with its original extension. If False, returns the file name without any extension. If a string is provided, it will be used as the new extension. Returns: str: The base name of the file. Examples: >>> get_file_basename("A/B/C/file.txt") 'file.txt' >>> get_file_basename("A/B/C/file.txt", ext=True) 'file.txt' >>> get_file_basename("A/B/C/file.txt", ext=False) 'file' >>> get_file_basename("A/B/C/file.txt", ext="md") 'file.md' """ return os.path.basename(get_file_name(path, ext=ext, abs=True))
[docs] def get_file_dir(path: str, abs: bool = False) -> str: """\ Get the directory of the specified file path. Args: path (str): The path to the file. abs (bool): If True, returns the absolute path. Defaults to False. Returns: str: The directory of the file. Examples: >>> get_file_dir("A/B/C/file.txt") 'A/B/C' >>> get_file_dir("/") '/' """ return os.path.dirname(pj(path, abs=abs))
[docs] def has_file_ext(path: str, ext: Union[None, str, List[str]] = None) -> bool: """\ Check if the specified file path has a given extension or any of the extensions in a list. Args: path (str): The path to the file. ext (Union[None, str, List[str]]): The extension to check for. If `None`, return whether the file has any extension. If a string, checks for that specific extension. A string may contain multiple extensions separated by commas or semicolons, which will be split into a list. If a list, checks if the file has any of the extensions in the list. Each list item may be `None`, which will check if the file has NO extension, or a string, which will check for that specific extension (preferably without a dot). Returns: bool: True if the file has the specified extension(s), False otherwise. Examples: >>> has_file_ext("A/B/C/file.txt", ext="txt") True >>> has_file_ext("A/B/C/file.txt", ext="md") False >>> has_file_ext("A/B/C/file.txt", ext=["txt", "md"]) True >>> has_file_ext("A/B/C/file.txt", ext=None) True >>> has_file_ext("A/B/C/file", ext=None) False >>> has_file_ext("A/B/C/file", ext=[None, "txt,md;py"]) True """ if ext is None: return bool(get_file_ext(path)) if isinstance(ext, str): ext = [ext] if (None in ext) and get_file_ext(path): return True ext = set(e for e in ext if e is not None) ext = set(e.strip() for expr in ext for e in re.split(r"[;,]", expr) if e.strip()) ext = set(e[1:] if e.startswith(".") else e for e in ext if e.strip()) return bool(get_file_ext(path) in ext)