Source code for ochanticipy.utils.check_file_existence

"""Function for checking file existence."""
import logging
from typing import Any, Callable, Optional, TypeVar

import wrapt

from ochanticipy.datasources.datasource import DataSource

logger = logging.getLogger(__name__)

# For typing the decorator
F = TypeVar("F", bound=Callable[..., Any])


[docs] @wrapt.decorator def check_file_existence( wrapped: F, instance: Optional[DataSource], args: list, kwargs: dict ) -> F: """ Don't overwrite existing data. Avoid recreating data if it already exists and if clobber not toggled by user. Used to wrap functions that accept filepath as a keyword argument. Parameters ---------- wrapped : function The function to wrap. The function must have "filepath" as a keyword parameter, and it can also have an optional "clobber" boolean keyword parameter. instance : Optional[DataSource] Object the wrapped function is bound to. Not used within, but ensures that instance methods do not pass `self` to args. args : list List of positional arguments. kwargs : dict Dictionary of keyword arguments Returns ------- If filepath exists and clobber is False, returns filepath. Otherwise, returns the result of the decorated function. Raises ------ KeyError If `filepath` or `clobber` are not passed as kwargs. """ try: filepath = kwargs["filepath"] clobber = kwargs["clobber"] except KeyError as err: raise KeyError( ( "`filepath` and `clobber` must be passed as keyword " "arguments for the `check_file_existence`" " decorator to work." ) ) from err # check existence exist_dict = {True: "exists", False: "does not exist"} # check filepath exists -> clobber usage_dict = { True: {True: "overwriting existing", False: "using existing"}, False: {True: "creating new", False: "creating new"}, } fp_exists = filepath.exists() logger.info( f"File {filepath} {exist_dict[fp_exists]} and clobber " f"set to {clobber}, {usage_dict[fp_exists][clobber]} file." ) if fp_exists and not clobber: return filepath else: return wrapped(*args, **kwargs)