# Buggy code
def __enter__(self):
    if self._active:
        raise RuntimeError("Can't re-enter the same log_output!")

    if self.file_like is None:
        raise RuntimeError("file argument must be set by either __init__ or __call__")

    # set up a stream for the daemon to write to
    self.close_log_in_parent = True
    self.write_log_in_parent = False
    if isinstance(self.file_like, string_types):
        self.log_file = open(self.file_like, "w")

    elif _file_descriptors_work(self.file_like):
        self.log_file = self.file_like
        self.close_log_in_parent = False

    else:
        self.log_file = StringIO()
        self.write_log_in_parent = True

    # record parent color settings before redirecting.  We do this
    # because color output depends on whether the *original* stdout
    # is a TTY.  New stdout won't be a TTY so we force colorization.
    self._saved_color = tty.color._force_color
    forced_color = tty.color.get_color_when()

    # also record parent debug settings -- in case the logger is
    # forcing debug output.
    self._saved_debug = tty._debug

    # OS-level pipe for redirecting output to logger
    self.read_fd, self.write_fd = os.pipe()

    # Multiprocessing pipe for communication back from the daemon
    # Currently only used to save echo value between uses
    self.parent, self.child = multiprocessing.Pipe()

    # Sets a daemon that writes to file what it reads from a pipe
    try:
        # need to pass this b/c multiprocessing closes stdin in child.
        try:
            input_stream = os.fdopen(os.dup(sys.stdin.fileno()))
        except BaseException:
            input_stream = None  # just don't forward input if this fails

        self.process = multiprocessing.Process(
            target=self._writer_daemon, args=(input_stream,)
        )
        self.process.daemon = True  # must set before start()
        self.process.start()
        os.close(self.read_fd)  # close in the parent process

    finally:
        if input_stream:
            input_stream.close()

    # Flush immediately before redirecting so that anything buffered
    # goes to the original stream
    sys.stdout.flush()
    sys.stderr.flush()

    # Now do the actual output rediction.
    self.use_fds = _file_descriptors_work(sys.stdout, sys.stderr)
    if self.use_fds:
        # We try first to use OS-level file descriptors, as this
        # redirects output for subprocesses and system calls.

        # Save old stdout and stderr file descriptors
        self._saved_stdout = os.dup(sys.stdout.fileno())
        self._saved_stderr = os.dup(sys.stderr.fileno())

        # redirect to the pipe we created above
        os.dup2(self.write_fd, sys.stdout.fileno())
        os.dup2(self.write_fd, sys.stderr.fileno())
        os.close(self.write_fd)

    else:
        # Handle I/O the Python way. This won't redirect lower-level
        # output, but it's the best we can do, and the caller
        # shouldn't expect any better, since *they* have apparently
        # redirected I/O the Python way.

        # Save old stdout and stderr file objects
        self._saved_stdout = sys.stdout
        self._saved_stderr = sys.stderr

        # create a file object for the pipe; redirect to it.
        pipe_fd_out = os.fdopen(self.write_fd, "w")
        sys.stdout = pipe_fd_out
        sys.stderr = pipe_fd_out

    # Unbuffer stdout and stderr at the Python level
    if not self.buffer:
        sys.stdout = Unbuffered(sys.stdout)
        sys.stderr = Unbuffered(sys.stderr)

    # Force color and debug settings now that we have redirected.
    tty.color.set_color_when(forced_color)
    tty._debug = self.debug

    # track whether we're currently inside this log_output
    self._active = True

    # return this log_output object so that the user can do things
    # like temporarily echo some ouptut.
    return self


# Traceback (KeyError)
Traceback (most recent call last):
File "/u/sciteam/stewart1/spack/bin/spack", line 64, in <module>
sys.exit(spack.main.main())
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/main.py", line 770, in main
if spack.config.get('config:debug'):
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 671, in get
return config.get(path, default, scope)
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 552, in __getattr__
return getattr(self.instance, name)
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 548, in instance
self._instance = self.factory()
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 653, in _config
_add_platform_scope(cfg, ConfigScope, name, path)
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 606, in _add_platform_scope
platform = spack.architecture.platform().name
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 178, in _memoized_function
func.cache[args] = func(*args)
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/architecture.py", line 516, in platform
return platform_cls()
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/platforms/cray.py", line 63, in __init__
_target = self._default_target_from_env()
File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/platforms/cray.py", line 121, in _default_target_from_env
env={'TERM': os.environ['TERM']},
File "/usr/lib64/python2.6/UserDict.py", line 22, in __getitem__
raise KeyError(key)
KeyError: 'TERM'

# Fixed code
def __enter__(self):
    if self._active:
        raise RuntimeError("Can't re-enter the same log_output!")

    if self.file_like is None:
        raise RuntimeError("file argument must be set by either __init__ or __call__")

    # set up a stream for the daemon to write to
    self.close_log_in_parent = True
    self.write_log_in_parent = False
    if isinstance(self.file_like, string_types):
        self.log_file = open(self.file_like, "w")

    elif _file_descriptors_work(self.file_like):
        self.log_file = self.file_like
        self.close_log_in_parent = False

    else:
        self.log_file = StringIO()
        self.write_log_in_parent = True

    # record parent color settings before redirecting.  We do this
    # because color output depends on whether the *original* stdout
    # is a TTY.  New stdout won't be a TTY so we force colorization.
    self._saved_color = tty.color._force_color
    forced_color = tty.color.get_color_when()

    # also record parent debug settings -- in case the logger is
    # forcing debug output.
    self._saved_debug = tty._debug

    # OS-level pipe for redirecting output to logger
    read_fd, write_fd = os.pipe()

    # Multiprocessing pipe for communication back from the daemon
    # Currently only used to save echo value between uses
    self.parent_pipe, child_pipe = multiprocessing.Pipe()

    # Sets a daemon that writes to file what it reads from a pipe
    try:
        # need to pass this b/c multiprocessing closes stdin in child.
        try:
            input_stream = os.fdopen(os.dup(sys.stdin.fileno()))
        except BaseException:
            input_stream = None  # just don't forward input if this fails

        self.process = multiprocessing.Process(
            target=_writer_daemon,
            args=(
                input_stream,
                read_fd,
                write_fd,
                self.echo,
                self.log_file,
                child_pipe,
            ),
        )
        self.process.daemon = True  # must set before start()
        self.process.start()
        os.close(read_fd)  # close in the parent process

    finally:
        if input_stream:
            input_stream.close()

    # Flush immediately before redirecting so that anything buffered
    # goes to the original stream
    sys.stdout.flush()
    sys.stderr.flush()

    # Now do the actual output rediction.
    self.use_fds = _file_descriptors_work(sys.stdout, sys.stderr)
    if self.use_fds:
        # We try first to use OS-level file descriptors, as this
        # redirects output for subprocesses and system calls.

        # Save old stdout and stderr file descriptors
        self._saved_stdout = os.dup(sys.stdout.fileno())
        self._saved_stderr = os.dup(sys.stderr.fileno())

        # redirect to the pipe we created above
        os.dup2(write_fd, sys.stdout.fileno())
        os.dup2(write_fd, sys.stderr.fileno())
        os.close(write_fd)

    else:
        # Handle I/O the Python way. This won't redirect lower-level
        # output, but it's the best we can do, and the caller
        # shouldn't expect any better, since *they* have apparently
        # redirected I/O the Python way.

        # Save old stdout and stderr file objects
        self._saved_stdout = sys.stdout
        self._saved_stderr = sys.stderr

        # create a file object for the pipe; redirect to it.
        pipe_fd_out = os.fdopen(write_fd, "w")
        sys.stdout = pipe_fd_out
        sys.stderr = pipe_fd_out

    # Unbuffer stdout and stderr at the Python level
    if not self.buffer:
        sys.stdout = Unbuffered(sys.stdout)
        sys.stderr = Unbuffered(sys.stderr)

    # Force color and debug settings now that we have redirected.
    tty.color.set_color_when(forced_color)
    tty._debug = self.debug

    # track whether we're currently inside this log_output
    self._active = True

    # return this log_output object so that the user can do things
    # like temporarily echo some ouptut.
    return self