@contextlib.contextmanager<EOL>def swap_attr(obj, attr, new_val):
if hasattr(obj, attr):<EOL><INDENT>real_val = getattr(obj, attr)<EOL>setattr(obj, attr, new_val)<EOL>try:<EOL><INDENT>yield<EOL><DEDENT>finally:<EOL><INDENT>setattr(obj, attr, real_val)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>setattr(obj, attr, new_val)<EOL>try:<EOL><INDENT>yield<EOL><DEDENT>finally:<EOL><INDENT>delattr(obj, attr)<EOL><DEDENT><DEDENT>
Temporary swap out an attribute with a new object.

    Usage:
        with swap_attr(obj, "attr", 5):
            ...

        This will set obj.attr to 5 for the duration of the with: block,
        restoring the old value at the end of the block. If `attr` doesn't
        exist on `obj`, it will be created and then deleted at the end of the
        block.