# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/cache/dictc.ipynb.

# %% auto 0
__all__ = ['sizeof_fmt', 'save', 'load', 'append', 'rename', 'compute_or_load', 'decorator']

# %% ../../nbs/cache/dictc.ipynb 2
from pathlib import Path
from typing import Dict
import pickle
import json
from functools import wraps

# %% ../../nbs/cache/dictc.ipynb 4
def sizeof_fmt(num, suffix="B"):
    for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
        if abs(num) < 1024.0:
            return f"{num:3.1f}{unit}{suffix}"
        num /= 1024.0
    return f"{num:.1f}Yi{suffix}"

def save(_dict: Dict, dict_path: Path, verbose=True):
    file_type = dict_path.suffix
    if _dict is not None and dict_path is not None:
        dict_path.parent.mkdir(parents=True, exist_ok=True)
        if file_type == ".pkl":
            with open(dict_path, "wb") as fp:
                pickle.dump(_dict, fp)
        elif file_type == ".json":
            with open(dict_path, "w") as fp:
                return json.dump(_dict, fp)
        if verbose:
            print(f"Saved {sizeof_fmt(dict_path.stat().st_size)} KB")
    else:
        print("WARN: save dict with one None parameter (path or dict)")

# %% ../../nbs/cache/dictc.ipynb 9
def load(dict_path: Path):
    file_type = dict_path.suffix
    if dict_path.exists():
        if file_type == ".pkl":
            with open(dict_path, "rb") as fp:
                return pickle.load(fp)
        elif file_type == ".json":
            with open(dict_path, "r") as fp:
                return json.load(fp)
    return {}

# %% ../../nbs/cache/dictc.ipynb 14
def append(_dict: Dict, dict_path: Path, verbose=True):
    if not dict_path.exists():
        return save(_dict, dict_path, verbose)

    return save(
        {
            **load(dict_path),  # old
            **_dict,  # new
        },
        dict_path,
        verbose,
    )


# %% ../../nbs/cache/dictc.ipynb 19
def rename(dict_path: Path, old_key: str, new_key: str):
    """Rename a key in a dict saved under dict_path"""
    if not dict_path.exists():
        raise Exception("dict path does not exist")
    _dict = load(dict_path)
    if old_key not in _dict:
        raise Exception(f"old key {old_key} does not exist")
    _dict[new_key] = _dict.pop(old_key)
    save(_dict, dict_path)

# %% ../../nbs/cache/dictc.ipynb 24
def compute_or_load(fn, fn_params, dict_path: Path):
    if dict_path.exists():
        return load(dict_path)

    dict_result = fn(**fn_params)
    save(dict_result, dict_path)
    return dict_result

# %% ../../nbs/cache/dictc.ipynb 30
def decorator(dict_path: Path):
    def decorate(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            if dict_path.exists():
                return load(dict_path)

            dict_result = fn(*args, **kwargs)
            save(dict_result, dict_path)
            return dict_result

        return wrapper

    return decorate

