def bytes_iter(obj): """Turn a complex object into an iterator of byte strings. The resulting iterator can be used for caching. """ if obj is None: return elif isinstance(obj, six.binary_type): yield obj elif isinstance(obj, six.text_type): yield obj elif isinstance(obj, (date, datetime)): yield obj.isoformat() elif is_mapping(obj): for key in sorted(obj.keys()): for out in chain(bytes_iter(key), bytes_iter(obj[key])): yield out elif is_sequence(obj): if isinstance(obj, set): obj = sorted(obj) for item in obj: for out in bytes_iter(item): yield out elif isinstance( obj, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType)): yield getattr(obj, 'func_name', '') else: yield unicode(obj)
def bytes_iter(obj) -> Iterable[bytes]: """Turn a complex object into an iterator of byte strings. The resulting iterator can be used for caching. """ if obj is None: return elif isinstance(obj, (bytes, str)): yield _bytes_str(obj) elif isinstance(obj, (date, datetime)): yield _bytes_str(obj.isoformat()) elif is_mapping(obj): for key in sorted(obj.keys()): for out in chain(bytes_iter(key), bytes_iter(obj[key])): yield out elif is_sequence(obj): if isinstance(obj, (list, set)): try: obj = sorted(obj) except Exception: pass for item in obj: for out in bytes_iter(item): yield out elif isinstance(obj, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType)): yield _bytes_str(getattr(obj, 'func_name', '')) else: yield _bytes_str(str(obj))
def clean_dict(data): """Remove None-valued keys from a dictionary, recursively.""" if is_mapping(data): out = {} for k, v in data.items(): if v is not None: out[k] = clean_dict(v) return out elif is_sequence(data): return [clean_dict(d) for d in data if d is not None] return data