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

# %% auto 0
__all__ = ['flatten_dict', 'most_common', 'set_dir', 'generate_time_id', 'get_node', 'apply_nested', 'resolve_path']

# %% ../nbs/utils.ipynb 3
import os
from contextlib import contextmanager
from pathlib import Path
from typing import Dict, Union

from fastcore.basics import patch

# %% ../nbs/utils.ipynb 4
@patch
def ls_sorted(self:Path):
    "ls but sorts files by name numerically"
    return self.ls().sorted(key=lambda f: int(f.with_suffix('').name))

# %% ../nbs/utils.ipynb 5
def flatten_dict(d: Dict) -> Dict:
    """flattens a nested dict one level"""
    def func(dct):
        for k, v in dct.items():
            if isinstance(v, dict):
                yield from v.items()
            else:
                yield k, v
    return dict(func(d))

# %% ../nbs/utils.ipynb 7
from collections import Counter

def most_common(lst):
    """returns the most common element of a collection"""
    return Counter(lst).most_common(1)[0][0]

# %% ../nbs/utils.ipynb 9
# ref: https://dev.to/teckert/changing-directory-with-a-python-context-manager-2bj8
@contextmanager
def set_dir(path: Union[Path, str]):
    """Sets the cwd within the context"""
    origin = Path().absolute()
    try:
        os.chdir(path)
        yield
    finally:
        os.chdir(origin)

# %% ../nbs/utils.ipynb 10
from datetime import datetime

def generate_time_id(dt=None):
    """generates a string id from given datetime or now"""
    return (dt or datetime.now()).isoformat().rsplit('.', 1)[0].replace(':', '-')

# %% ../nbs/utils.ipynb 12
def get_node(
    tree: Dict, # tree to traverse
    path: str, # path of node
    sep: str = '.' # separator used in path
): # the node
    """returns the node from a tree (dict) by path"""
    if path is None or path == '':
        return tree
    node = tree
    for field in path.split(sep):
        if field in node:
            node = node[field]
        else:
            return None
    return node


# %% ../nbs/utils.ipynb 14
def apply_nested(tree: dict, path: str, func, sep: str = '.'):
    parts = path.split(sep)
    parent_node = get_node(tree, sep.join(parts[:-1]))
    parent_node[parts[-1]] = func(parent_node[parts[-1]])
    return tree

# %% ../nbs/utils.ipynb 16
def resolve_path(config, field_path, sep='.'):
    func = lambda s: str(Path(s).resolve())
    return apply_nested(config, field_path, func, sep)
