def _drop_nones(d: dict) -> dict:
    """Recursively drop Nones in dict d and return a new dict"""
    dd = {}
    for k, v in d.items():
        if isinstance(v, dict):
            dd[k] = _drop_nones(v)
        elif isinstance(v, (list, set, tuple)):
            # note: Nones in lists are not dropped
            dd[k] = type(v)(_drop_nones(vv) if isinstance(vv, dict) else vv for vv in v)
        elif isinstance(v, str) and v:
            dd[k] = v
        elif v is not None:
            dd[k] = v
    return dd