def restoring(expr, clone=None):
    '''A context manager that evaluates an expression when entering the runtime
    context and restores its value when exiting.
    
    This context manager makes
    
    .. python::
        with restoring(expr, clone) as value:
            BODY        
    
    a shortcut for
    
    .. python::
        value = EXPR
        __cloned = clone(value) if clone is not None else value
        try:
            BODY
        finally:
            EXPR = __cloned
            del __cloned
    
    where ``__cloned`` is a temporary hidden name and ``EXPR`` is ``expr``
    substituted textually in the code snippet. Therefore ``expr`` can only be an
    assignable expression, i.e. an expression that is allowed on the left hand
    side of '=' (e.g. identifier, subscription, attribute reference, etc.).
        
    :param expr: The expression whose value is to be evaluated and restored.
    :type expr: str
    :param clone: A callable that takes the object ``expr`` evaluates to and
        returns an appropriate copy to be used for restoring. If None, the
        original object is used.        
    :type clone: callable or None
    '''
    f = sys._getframe(2)    # bypass the contextmanager frame
    # evaluate the expression and make a clone of the value to be restored
    value = eval(expr, f.f_globals, f.f_locals)
    restored_value = clone(value) if clone is not None else value
    try:
        yield value
    finally:
        if expr in f.f_locals:      # local or nonlocal name
            _update_locals(f, {expr:restored_value})
        elif expr in f.f_globals:   # global name
            f.f_globals[expr] = restored_value
        else:
            # make a copy of f_locals and bind restored_value to a new name
            tmp_locals = dict(f.f_locals)
            tmp_name = '__' + min(tmp_locals)
            tmp_locals[tmp_name] = restored_value
            exec '%s = %s' % (expr, tmp_name) in f.f_globals, tmp_locals
A context manager that evaluates an expression when entering the runtime
    context and restores its value when exiting.
    
    This context manager makes
    
    .. python::
        with restoring(expr, clone) as value:
            BODY        
    
    a shortcut for
    
    .. python::
        value = EXPR
        __cloned = clone(value) if clone is not None else value
        try:
            BODY
        finally:
            EXPR = __cloned
            del __cloned
    
    where ``__cloned`` is a temporary hidden name and ``EXPR`` is ``expr``
    substituted textually in the code snippet. Therefore ``expr`` can only be an
    assignable expression, i.e. an expression that is allowed on the left hand
    side of '=' (e.g. identifier, subscription, attribute reference, etc.).
        
    :param expr: The expression whose value is to be evaluated and restored.
    :type expr: str
    :param clone: A callable that takes the object ``expr`` evaluates to and
        returns an appropriate copy to be used for restoring. If None, the
        original object is used.        
    :type clone: callable or None
    
recipes/Python/576977_Context_manager_restoring/recipe-576977.py