import mimetypes import os from typing import Dict, Optional def merge_dicts(dict_a: Dict, dict_b: Dict) -> Dict: """Merge two dictionaries (shallow). Arguments: dict_a (dict): The dictionary to use as the base. dict_b (dict): The dictionary to update the values with. Returns: dict: A new merged dictionary. """ dict_z = dict_a.copy() dict_z.update(dict_b) return dict_z def deep_merge_dicts(dict_a: Dict, dict_b: Dict, _path=None) -> Dict: """Merge two dictionaries (deep). https://stackoverflow.com/questions/7204805/how-to-merge-dictionaries-of-dictionaries/7205107#7205107 Arguments: dict_a (dict): The dictionary to use as the base. dict_b (dict): The dictionary to update the values with. _path (list): internal use. Returns: dict: A new merged dictionary. """ if _path is None: _path = [] for key in dict_b: if key in dict_a: if isinstance(dict_a[key], dict) and isinstance(dict_b[key], dict): deep_merge_dicts(dict_a[key], dict_b[key], _path + [str(key)]) elif dict_a[key] == dict_b[key]: pass # same leaf value else: raise Exception('Conflict at %s' % '.'.join(_path + [str(key)])) else: dict_a[key] = dict_b[key] return dict_a def guess_mime(path: str) -> Optional[str]: """Guess the mime type for a given path. Arguments: root (str): the root path of the file tree path (str): the sub-path within the file tree Returns: str: the guessed mime-type """ mtypes = mimetypes.guess_type(path) ftype = None if os.path.isdir(path): ftype = "directory" elif os.access(path, os.F_OK) and mtypes[0]: ftype = mtypes[0] else: ftype = "application/octet-stream" return ftype