Fork me on GitHub

Source code for attest.deprecated

import inspect

from contextlib import contextmanager

from attest import statistics


__all__ = (
    'Loader',
    'assert_',
    'Assert',
)


[docs]class Loader(object): """Run tests with Attest via distribute. .. deprecated:: 0.5 :meth:`~attest.reporters.AbstractReporter.test_loader` is preferred. """ def loadTestsFromNames(self, names, module=None): mod, collection = names[0].rsplit('.', 1) mod = __import__(mod, fromlist=[collection]) collection = getattr(mod, collection) collection.run() raise SystemExit
[docs]def assert_(expr, msg=None): """Like `assert`, but counts the assertion. .. deprecated:: 0.5 :func:`~attest.eval.assert_hook` is preferred. """ statistics.assertions += 1 if not expr: if msg is None: raise AssertionError raise AssertionError(msg) return expr
[docs]class Assert(object): """Wrap an object such that boolean operations on it fails with an :exc:`AssertionError` if the operation results in :const:`False`, with more helpful error messages on failure than `assert`. A test failure is simply an unhandled exception, so it is completely optional to use this class. Examples:: Assert(1 + 1) == 2 2 in Assert([1, 2, 3]) Attributes are proxied to the wrapped object, returning the result wrapped as well:: hello = Assert('hello') hello == 'hello' hello.upper() == 'HELLO' hello.capitalize() == 'Hello' Used in boolean context, fails if non-true. These all fail:: bool(Assert(0)) if Assert(0): pass assert Assert(0) Identical to, except for the more helpful failure message:: Assert(bool(0)) == True If you pass more than one argument, the first is assumed to be a predicate callable to which the rest of the arguments are passed. These are identical:: Assert.isinstance(0, int) Assert(isinstance, 0, int) .. deprecated:: 0.5 :func:`~attest.eval.assert_hook` is preferred. """ #: The wrapped object obj = None def __init__(self, *args): if len(args) == 1: obj = args[0] if isinstance(obj, Assert): self.obj = obj.obj else: self.obj = obj elif len(args) > 1: args = list(args) predicate = args.pop(0) name = predicate.__name__ arglist = ', '.join(map(_repr, args)) self.obj = assert_(predicate(*args), 'not %s(%s)' % (name, arglist)) @property def __class__(self): return Assert(self.obj.__class__) def __str__(self): """Wrapped proxy to the wrapped object's *__str__*, can be used for testing the string adaption of the object:: Assert(1).__str__() == '1' .. warning:: :func:`str` on :class:`Assert` objects does not work. """ return Assert(self.obj.__str__()) def __getattr__(self, name): """Proxy all attributes to the wrapped object, wrapping the result. """ return Assert(getattr(self.obj, name)) def __call__(self, *args, **kwargs): """Allow calling of wrapped callables, wrapping the return value. Useful for testing methods on a wrapped object via attribute proxying:: Assert('Hello').upper() == 'HELLO' """ return Assert(self.obj(*args, **kwargs)) def __getitem__(self, key): """Access an item on the wrapped object and return the result wrapped as well. :: Assert([1, 2, 3])[1] == 2 """ return Assert(self.obj[key]) def __eq__(self, obj): """Test for equality with ``==``.""" return assert_(self.obj == obj, '%r != %r' % (self.obj, obj)) def __ne__(self, obj): """Test for inequality with ``!=``.""" return assert_(self.obj != obj, '%r == %r' % (self.obj, obj))
[docs] def is_(self, obj): """The `is` operator is not overridable, for good reasons (that would defeat its purpose), so you can use this method for asserting identity:: Assert(True).is_(True) .. versionchanged:: 0.3 Checks the wrapped object for :class:`Assert` instances. """ if isinstance(obj, Assert): obj = obj.obj return assert_(self.obj is obj, '%r is not %r' % (self.obj, obj))
[docs] def is_not(self, obj): """The negated form of :meth:`is_`, corresponding to the ``is not`` operation:: Assert([]).is_not([]) .. versionchanged:: 0.3 Checks the wrapped object for :class:`Assert` instances. """ if isinstance(obj, Assert): obj = obj.obj return assert_(self.obj is not obj, '%r is %r' % (self.obj, obj))
def __contains__(self, obj): """Test for membership with `in`.""" return assert_(obj in self.obj, '%r not in %r' % (obj, self.obj))
[docs] def in_(self, obj): """Assert membership. While you can use the `in` operator, its order is inconsistent with the rest of the operators and doesn't work with the ``not in`` operation. :: 2 in Assert([1, 2, 3]) Assert(2).in_([1, 2, 3]) """ return assert_(self.obj in obj, '%r not in %r' % (self.obj, obj))
[docs] def not_in(self, obj): """The negated form of :meth:`in_`, corresponding to the ``not in`` operation:: Assert(0).not_in([1, 2, 3]) """ return assert_(self.obj not in obj, '%r in %r' % (self.obj, obj))
def __lt__(self, obj): """Test for lesserness with ``<``.""" return assert_(self.obj < obj, '%r >= %r' % (self.obj, obj)) def __le__(self, obj): """Test for lesserness or equality with ``<=``.""" return assert_(self.obj <= obj, '%r > %r' % (self.obj, obj)) def __gt__(self, obj): """Test for greaterness with ``>``.""" return assert_(self.obj > obj, '%r <= %r' % (self.obj, obj)) def __ge__(self, obj): """Test for greaterness or equality with ``>=``.""" return assert_(self.obj >= obj, '%r < %r' % (self.obj, obj)) def __nonzero__(self): """Test for truthiness in boolean context.""" return bool(assert_(self.obj, 'not %r' % self.obj)) @staticmethod @contextmanager
[docs] def raises(*exceptions): """Context manager that fails if *none* of the `exceptions` are raised. Yields the captured exception as an :term:`assertive object`. :: with Assert.raises(IOError) as error: open('/etc/passwd', 'w') error.errno == 13 :param exceptions: Expected exception classes. """ statistics.assertions += 1 proxy = Assert() try: yield proxy except exceptions, error: proxy.obj = error else: if len(exceptions) > 1: errors = '(' + ', '.join(e.__name__ for e in exceptions) + ')' else: errors = exceptions[0].__name__ raise AssertionError("didn't raise %s" % errors)
@staticmethod @contextmanager
[docs] def not_raising(exception): """Context manager that fails if a particular exception is raised. A raised exception constitutes a failure anyway and this is mainly used for testing Attest itself. :: with Assert.not_raising(IOError): open('/etc/passwd', 'r') :param exception: An exception class. """ statistics.assertions += 1 try: yield except exception: raise AssertionError('raised %s' % exception.__name__)
@staticmethod
[docs] def isinstance(obj, classinfo): """Test that an object is an instance of a class or a :func:`tuple` of classes. Corresponds to :func:`.isinstance`. .. versionadded:: 0.4 """ if isinstance(obj, Assert): obj = obj.obj return assert_(isinstance(obj, classinfo), 'not isinstance(%r, %s)' % (obj, _repr(classinfo)))
@staticmethod
[docs] def not_isinstance(obj, classinfo): """Negated version of :meth:`isinstance`. .. versionadded:: 0.4 """ if isinstance(obj, Assert): obj = obj.obj return assert_(not isinstance(obj, classinfo), 'isinstance(%r, %s)' % (obj, _repr(classinfo)))
@staticmethod
[docs] def issubclass(obj, cls): """Test that `obj` is a subclass of `cls` or a subclass of a class inside `cls`. Corresponds to :func:`.issubclass`. .. versionadded:: 0.4 """ if isinstance(obj, Assert): obj = obj.obj return assert_(issubclass(obj, cls), 'not issubclass(%s, %s)' % (_repr(obj), _repr(cls)))
@staticmethod
[docs] def not_issubclass(obj, cls): """Negated version of :meth:`issubclass`. .. versionadded:: 0.4 """ if isinstance(obj, Assert): obj = obj.obj return assert_(not issubclass(obj, cls), 'issubclass(%s, %s)' % (_repr(obj), _repr(cls)))
@property
[docs] def json(self): """Parse the wrapped object as JSON. Requires Python 2.6 or the simplejson package. .. versionadded:: 0.4 """ try: import simplejson as json except ImportError: import json return Assert(json.loads(self.obj))
[docs] def css(self, selector): """Parse the wrapped object as :abbr:`HTML (HyperText Markup Language)` and return an :term:`assertive <assertive object>` list of elements matching the :abbr:`CSS (Cascading Style Sheets)` `selector`. Requires lxml 2.0 or newer. .. note:: Not tested on Python 2.5 and PyPy due to difficulties installing lxml for these implementations. .. versionadded:: 0.4 """ from lxml import html return Assert(html.fromstring(self.obj).cssselect(selector))
[docs] def xpath(self, path): """Parse the wrapped object as :abbr:`XML (eXtensible Markup Language)` and return an :term:`assertive <assertive object>` list of elements matching the :abbr:`XPath (XML Path Language)` *path*. Requires lxml 2.0 or newer. .. note:: Not tested on Python 2.5 and PyPy due to difficulties installing lxml for these implementations. .. versionadded:: 0.4 """ from lxml import etree return Assert(etree.fromstring(self.obj).xpath(path))
[docs] def passed_to(self, func, *args, **kwargs): """Pass the unwrapped object to a function and return its result as an :term:`assertive object`. These are identical:: Assert(len([1, 2, 3])) == 3 Assert([1, 2, 3]).passed_to(len) == 3 Mainly useful with Assert objects that comes from the outside, e.g. yielded from a context, from methods like :meth:`css` etc. .. versionadded:: 0.4 """ return Assert(func(self.obj, *args, **kwargs))
[docs] def attr(self, name): """Safely get an attribute from the wrapped object. .. versionadded:: 0.4 """ return Assert(getattr(self.obj, name))
def __repr__(self): """Not proxied to the wrapped object. To test that do something like:: Assert(repr(obj)) == 'expectation' """ return 'Assert(%r)' % self.obj
def _repr(obj): """Internal :func:`repr` that tries to be more close to original code. """ if inspect.isclass(obj): return obj.__name__ elif type(obj) is tuple: return '(%s)' % ', '.join(map(_repr, obj)) return repr(obj)