Fork me on GitHub

Source code for attest.contexts

import sys

from contextlib import contextmanager
from shutil     import rmtree
from tempfile   import mkdtemp

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO  import StringIO

from attest            import statistics
from attest.deprecated import _repr


__all__ = (
    'capture_output',
    'disable_imports',
    'Error',
    'raises',
    'tempdir',
)


@contextmanager
[docs]def capture_output(): """Captures standard output and error during the context. Returns a tuple of the two streams as lists of lines, added after the context has executed. .. testsetup:: from attest import capture_output >>> with capture_output() as (out, err): ... print 'Captured' ... >>> out ['Captured'] """ stdout, stderr = sys.stdout, sys.stderr sys.stdout, sys.stderr = StringIO(), StringIO() out, err = [], [] try: yield out, err finally: out.extend(sys.stdout.getvalue().splitlines()) err.extend(sys.stderr.getvalue().splitlines()) sys.stdout, sys.stderr = stdout, stderr
@contextmanager
[docs]def disable_imports(*names): """Blocks the given `names` from being imported inside the context. This is useful for testing import-dependent fallbacks. .. testsetup:: from attest import disable_imports >>> with disable_imports('sys'): ... import sys ... Traceback (most recent call last): ImportError: 'sys' is disabled .. versionadded:: 0.4 """ import __builtin__ import_ = __builtin__.__import__ def __import__(name, *args, **kwargs): if name in names: raise ImportError('%r is disabled' % name) return import_(name, *args, **kwargs) __builtin__.__import__ = __import__ try: yield finally: __builtin__.__import__ = import_
[docs]class Error(object): """Container of metadata for an exception caught by :func:`raises`. Attribute access and string adaption is forwarded to the exception object. To test the type however you need to use the :attr:`exc` attribute directly. .. versionadded:: 0.5 """ #: The actual exception instance. exc = None def __getattr__(self, name): return getattr(self.exc, name) def __str__(self): return str(self.exc) def __repr__(self): return '<Error %s>' % repr(self.exc)
@contextmanager
[docs]def raises(*exceptions): """Fails if none of the `exceptions` are raised inside the context. This reverses failure semantics and is useful for testing code that uses exceptions as part of its API. .. testsetup:: from attest import raises >>> with raises(IOError) as error: ... open('/etc/passwd', 'w') ... >>> error.errno 13 :param exceptions: Expected exception classes. :returns: An :class:`Error` on which the caught exception is set after the context has executed, if one was raised. :raises AssertionError: If none of the expected exceptions are raised in the context. .. versionadded:: 0.5 .. autoclass:: Error :members: """ statistics.assertions += 1 error = Error() try: yield error except exceptions, e: error.exc = e else: exceptions = exceptions[0] if len(exceptions) == 1 else exceptions raise AssertionError("didn't raise %s when expected" % _repr(exceptions))
@contextmanager
[docs]def tempdir(*args, **kwargs): """Creates a temporary directory, removing it and everything in it when the context exits. For files you can use :func:`~tempfile.TemporaryFile` as a context manager. Returns the path to the directory. Arguments are passed to :func:`~tempfile.mkdtemp`. .. versionadded:: 0.6 """ d = mkdtemp(*args, **kwargs) try: yield d finally: rmtree(d)