Source code for scitools.redirect_io
#!/usr/bin/env python
r"""
Example usage:
--------------
Redirect stderr using the 'with'-statement:
>>> from __future__ import with_statement
>>> from redirect_io import *
>>> with hidden_stderr():
... print >> sys.stderr, 'Divide By Cucumber Error'
>>>
Redirect stderr to stout:
>>> with hidden_stderr(sys.stdout):
... print >> sys.stderr, 'Where am I ?'
Where am I ?
>>>
Optinal usage without 'with'-statement:
>>> _redirect_err()
>>> try:
... print >> sys.stderr, " +++ Divide by Cucumber Error, "\
... "Please ReInstall Universe And Reboot +++"
... finally:
... _return_err()
>>>
Fetch previous error messages:
>>> print _tmp_err.getvalue()
Divide By Cucumber Error
+++ Divide by Cucumber Error, Please ReInstall Universe And Reboot +++
<BLANKLINE>
>>>
"""
from __future__ import with_statement # Comment to run _test_with_statement
__author__ = 'Rolv Erlend Bredesen <rolv@simula.no>'
__all__ = ['sys', '_tmp_err', 'hidden_stderr', '_redirect_err', '_return_err']
import __future__
import StringIO
import sys
from contextlib import contextmanager
if float(sys.version[:3]) < 2.5:
raise ImportError("This module requires version >= 2.5 of python")
_std_err = sys.stderr
_tmp_err = StringIO.StringIO() # stream for hidden stderr
_tmp_err.__exit__ = _tmp_err.flush # Add __exit__ method
@contextmanager # 'with' requires __enter__ and __exit__
[docs]def hidden_stderr(stream=_tmp_err):
sys.stderr = stream
try:
yield None
finally:
sys.stderr = _std_err
# For error stream with python version < 2.5
def _redirect_err():
sys.stderr = _tmp_err
def _return_err():
sys.stderr = _std_err
def _test_with_statement():
"""
If the word 'with', which is a reserved keyword from python version 2.6,
is used in python2.5 code then a warning will be printed to sys.stderr
when the code is bytecompiled.
In this example we look at capturing the warning messages
"""
assert 'with_statement' not in globals()
assert sys.version[:3] == '2.5'
# Force Error
statement = 'with=3'
try:
c = compile(statement, '/dev/null', 'exec',
__future__.with_statement.compiler_flag)
except SyntaxError:
print "Success: '%s' did not compile" %statement
else:
raise Exception("Statement: '%s' should not have been compiled" \
% statement)
# Setup error redirection
std_err = sys.stderr
tmp_err = StringIO.StringIO()
if float(sys.version[:3]) < 2.5:
raise ImportError, "This module requires version 2.5 of python"
# Compile with error redirection
statement1 = 'with=3'
statement2 = 'print "with>>", with'
print '>>>', statement1
print '>>>', statement2
# Test compilation of code using the reserved keyword with
# Redirection standard error under compilation to prevent warning
_redirect_err()
try:
c = compile(statement1, '/dev/null', 'single')
finally:
_return_err()
# No warning here
exec c in {}, locals()
_redirect_err()
try:
# This one will give a warning
exec statement2
finally:
_return_err()
print "Here is the redirected error stream:\n", tmp_err.getvalue()
# 'with'-example
print "Testing the use of the 'with'-statement"
c = compile(
r"""'''In this example we test the use of the 'with'-statement'''
#from __future__ import with_statement # using proper compile flag instead
from contextlib import contextmanager # 'with' requires __enter__ and __exit__
err_ = StringIO.StringIO()
@contextmanager
def stderr_redirected(stream):
err = sys.stderr
sys.stderr = stream
try:
yield None
finally:
sys.stderr = err
statement = 'with_=3' # we have imported the with_statement
with stderr_redirected(err_):
print >> sys.stderr, "Can you see me?"
c_ = compile(statement, '/dev/null', 'single', 0, 0)
""", '/dev/null', 'exec', __future__.with_statement.compiler_flag)
exec c
print "\nIt appears the with_statement worked."
print "Here is the redirected error stream:\n", err_.getvalue()
if __name__ == '__main__':
if 'with_statement' in globals():
import doctest
import unittest
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite())
runner = unittest.TextTestRunner(sys.stdout, verbosity=1)
runner.run(suite)
else:
# To run you must comment
# 'from __future__ import with_statement ' at start of file
_test_with_statement()