FABulous.caching ================ .. py:module:: FABulous.caching .. autoapi-nested-parse:: Caching utilities for FABulous. Provides: - Cache: singleton file-backed cache (implemented via __new__) - cache_with: dependency-aware caching decorator Usage: # Initialize the cache directory Cache("/path/to/cache") # Use the decorator to cache a function @cache_with(files=lambda self: [self.config_path]) def build(self): ... Classes ------- .. py:class:: Cache(cache_dir = None) Singleton file-backed cache for function results. The first instantiation may specify cache_dir. Subsequent instantiations return the same instance; if cache_dir is provided it updates the path. Caching can be globally enabled/disabled using enable() and disable() methods, or temporarily controlled using the temporarily_disabled() context manager. :param cache_dir: The cache directory path. :type cache_dir: str | None :param Create or return the singleton Cache instance.: :param : :type : param cache_dir: The cache directory path. If provided on first call, sets the cache dir. :param : :type : type cache_dir: str | None :param : :type : returns: The singleton instance. :param : :type : rtype: Self :param : :type : raises RuntimeError: If attempting to reinitialize with a different cache_dir. **Properties:** .. py:property:: cache_dir The cache directory path. :returns: The path to the cache directory. :rtype: str **Methods:** .. py:method:: cache_disabled() Context manager to temporarily disable caching. :Yields: *None* .. rubric:: Examples >>> # Caching is normally enabled >>> result1 = cached_function() # Uses cache >>> with Cache.cache_disabled(): ... result2 = cached_function() # Bypasses cache >>> result3 = cached_function() # Uses cache again .. py:method:: cache_enabled() Context manager to temporarily enable caching. Useful when caching is globally disabled but you want to enable it for a specific code block. :Yields: *None* .. rubric:: Examples >>> Cache.disable() # Disable globally >>> with Cache.cache_enabled(): ... result = cached_function() # Uses cache .. py:method:: disable() Disable caching globally. When disabled, all cache checks will return cache miss, forcing functions to re- execute every time. .. py:method:: enable() Enable caching globally. .. py:method:: get(fn, args, kwargs) Get cached result or return _CACHE_MISS sentinel. :param fn: The function. :type fn: Callable :param args: Positional arguments. :type args: tuple :param kwargs: Keyword arguments. :type kwargs: dict :returns: The cached result or _CACHE_MISS. :rtype: Any .. py:method:: get_async(fn, args, kwargs) Get cached result or return _CACHE_MISS sentinel. :param fn: The function. :type fn: Callable :param args: Positional arguments. :type args: tuple :param kwargs: Keyword arguments. :type kwargs: dict :returns: The cached result or _CACHE_MISS. :rtype: Any .. py:method:: is_cache_hit(cache_key, files, params = None) Return True when stored metadata indicates dependencies are unchanged. :param cache_key: Unique key identifying the cached function call :type cache_key: str :param files: List of file paths that the function depends on :type files: list[Path] :param params: Optional dictionary of parameters affecting the function :type params: dict[str, Any] | None :returns: True if the cache is valid (hit), False if a cache miss :rtype: bool .. py:method:: is_enabled() Check if caching is currently enabled. :returns: True if enabled, False otherwise. :rtype: bool .. py:method:: reset() Clear all cached entries and reset the singleton state. .. py:method:: reset_async() Clear all cached entries and reset the singleton state. .. py:method:: set(fn, args, kwargs, value) Store a pickled cached value for the given function call. :param fn: The function. :type fn: Callable :param args: Positional arguments. :type args: tuple :param kwargs: Keyword arguments. :type kwargs: dict :param value: The value to cache. :type value: Any .. py:method:: set_async(fn, args, kwargs, value) Store a pickled cached value for the given function call. :param fn: The function. :type fn: Callable :param args: Positional arguments. :type args: tuple :param kwargs: Keyword arguments. :type kwargs: dict :param value: The value to cache. :type value: Any .. py:method:: update(cache_key, files, params = None) Write metadata for a cache key. :param cache_key: The cache key. :type cache_key: str :param files: List of dependent files. :type files: list[Path] :param params: Parameters. :type params: dict[str, Any] | None .. py:class:: DiscoveryHelper() Helper class for discovering file dependencies in config files. **Methods:** .. py:method:: expand_config_files(files) Expand list of files by recursively extracting paths from config files. For each configuration file in the input list, this method will: 1. Include the config file itself 2. Recursively extract and include any file paths referenced within it 3. Cache the expansion results to avoid recomputation :param files: List of file paths, may include config files. :type files: list[Path] :returns: Expanded list including all referenced files. :rtype: list[Path] .. py:method:: extract_file_paths_from_value(value, base_dir, visited) Recursively extract file paths from a configuration value. :param value: The value to extract paths from. :type value: Any :param base_dir: Base directory for resolving relative paths. :type base_dir: Path :param visited: Set of already visited paths to prevent loops. :type visited: set[Path] :returns: List of Path objects found in the value. :rtype: list[Path] .. py:method:: extract_paths_from_config(config_file, visited = None) Extract all file paths referenced in a configuration file. Recursively searches through JSON/YAML config files for string values that represent valid file paths. Prevents infinite loops by tracking visited files. :param config_file: Path to the configuration file. :type config_file: Path :param visited: Set of already visited config files (for loop prevention). :type visited: set[Path] | None :returns: List of Path objects found in the configuration. :rtype: list[Path] .. py:method:: is_config_file(file_path) Check if a file is a configuration file. Supported formats are JSON and YAML. :param file_path: The path to the file to check. :type file_path: Path :returns: True if the file is a config file, False otherwise. :rtype: bool .. py:class:: HashHelper() Helper class for hashing files and parameters. **Methods:** .. py:method:: hash_file_content(file_path) Return a SHA256 hash of a file's contents. Uses hashlib.file_digest() for efficient file hashing without loading the entire file into memory. :param file_path: The path to the file to hash. :type file_path: Path :returns: The SHA256 hash as a hexadecimal string. :rtype: str :raises FileNotFoundError: If the file does not exist. .. py:method:: hash_files(files) Return a combined hash for a list of files. The files are sorted by path to ensure stable ordering. :param files: List of file paths to hash. :type files: list[Path] :returns: The combined SHA256 hash as a hexadecimal string. :rtype: str .. py:method:: hash_params(params) Return a stable hash for the provided params mapping. Returns None if params cannot be serialized, and emits a warning. :param params: The parameters to hash. :type params: dict[str, Any] | None :returns: The SHA256 hash as a hexadecimal string, or None if serialization fails. :rtype: str | None Functions --------- .. py:function:: cache_with(*, param = True, files = None, return_cached = False) Return a dependency-aware caching decorator. :param param: Whether to include parameters in cache key. Defaults to True. :type param: bool :param files: Function to get file dependencies. :type files: Callable[..., list[Path | str]] | None :param return_cached: Whether to return cached value. Defaults to False. :type return_cached: bool :returns: The decorator function. :rtype: Callable[[Callable], Callable] .. rubric:: Examples >>> class Worker: ... def __init__(self, path: Path): ... self.path = path ... ... @cache_with(files=lambda self: [self.path]) ... def build(self): ... ... Module Attributes -----------------