import os from functools import reduce __all__ = [ 'get_project_path', 'deep_dict_update', 'dict_remove', 'equals_ignore_case', 'to_bool', ] def get_project_path(): for anchor in ['.idea', '.git', 'config.yml', 'requirements.txt']: path = os.path.realpath(os.curdir) while anchor not in os.listdir(path): parent = os.path.dirname(path) if parent == path: path = None break else: path = parent if path is not None: return path return None def deep_dict_update(d1, d2): for key in d1: if key not in d2: continue if isinstance(d1[key], dict) and isinstance(d2[key], dict): deep_dict_update(d1[key], d2[key]) else: d1[key] = d2[key] for key in d2: if key not in d1: d1[key] = d2[key] def dict_remove(d: dict, k) -> dict: result = d.copy() for key in tuple(k): del result[key] return result def equals_ignore_case(a, b) -> bool: return str(a).upper() == str(b).upper() if a and b else False _TRUE_STR = ['true', 't', 'yes', 'y', 'on'] _FALSE_STR = ['false', 'f', 'no', 'n', 'off'] def to_bool(v) -> bool: if isinstance(v, str): if reduce(lambda a, b: a or b, [equals_ignore_case(v, x) for x in _TRUE_STR]): return True if reduce(lambda a, b: a or b, [equals_ignore_case(v, x) for x in _FALSE_STR]): return False return bool(v)