def bunchify(x):
    """ Recursively transforms a dictionary into a Bunch via copy.
        
        >>> b = bunchify({'urmom': {'sez': {'what': 'what'}}})
        >>> b.urmom.sez.what
        'what'
        
        bunchify can handle intermediary dicts, lists and tuples (as well as 
        their subclasses), but ymmv on custom datatypes.
        
        >>> b = bunchify({ 'lol': ('cats', {'hah':'i win again'}), 
        ...         'hello': [{'french':'salut', 'german':'hallo'}] })
        >>> b.hello[0].french
        'salut'
        >>> b.lol[1].hah
        'i win again'
        
        nb. As dicts are not hashable, they cannot be nested in sets/frozensets.
    """
    if isinstance(x, dict):
        return Bunch( (k, bunchify(v)) for k,v in iteritems(x) )
    elif isinstance(x, (list, tuple)):
        return type(x)( bunchify(v) for v in x )
    else:
        return x
Recursively transforms a dictionary into a Bunch via copy.
        
        >>> b = bunchify({'urmom': {'sez': {'what': 'what'}}})
        >>> b.urmom.sez.what
        'what'
        
        bunchify can handle intermediary dicts, lists and tuples (as well as 
        their subclasses), but ymmv on custom datatypes.
        
        >>> b = bunchify({ 'lol': ('cats', {'hah':'i win again'}), 
        ...         'hello': [{'french':'salut', 'german':'hallo'}] })
        >>> b.hello[0].french
        'salut'
        >>> b.lol[1].hah
        'i win again'
        
        nb. As dicts are not hashable, they cannot be nested in sets/frozensets.