Example #1
0
 def __init__(self, name=None, negative=False, obj=None):
     self._name = name
     self.negative = negative
     self.obj = obj
     self._callable_args = []
     self._callable_kw = {}
     self._that = AssertionHelper(self.obj)
Example #2
0
    def __call__(self, obj):
        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj

        self._that = AssertionHelper(self.obj)
        return self
Example #3
0
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
        else:
            args = [first] + list(rest)
            collection_should = AssertionHelper(range(*args))

        if self.negative:
            return collection_should.does_not_contain(self.obj)
        else:
            return collection_should.contains(self.obj)
Example #4
0
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj, with_args=self._callable_args, and_kwargs=self._callable_kw)

        if self.negative:
            msg = "{0} called with args {1} and kwargs {2} should " "not raise {3} but raised {4}"

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(self.obj, self._that._callable_args, self._that._callable_kw, exc, e)
                raise AssertionError(err)

        return _that.raises(*args, **kw)
Example #5
0
 def __init__(self, name=None, negative=False, obj=None):
     self._name = name
     self.negative = negative
     self.obj = obj
     self._callable_args = []
     self._callable_kw = {}
     self._that = AssertionHelper(self.obj)
Example #6
0
    def __call__(self, obj):
        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj

        self._that = AssertionHelper(self.obj)
        return self
Example #7
0
    def cool(self):
        _that = AssertionHelper(self.obj,
                     with_args=self._callable_args,
                     and_kwargs=self._callable_kw)
        if self.negative:
            try:
                return _that.raises(Exception)
            except AssertionError:
                raise AssertionError('The callable `{0}` was supposed to not be cool and throw an exception, but it is too cool for that'.format(self.obj.__name__))

        try:
            self.obj(*self._callable_args, **self._callable_kw)
        except Exception as e:
            raise AssertionError('The callable `{2}` should be cool but threw {0}: {1}'.format(
                e.__class__.__name__,
                str(e),
                self.obj.__name__
            ))

        return True
Example #8
0
    def cool(self):
        _that = AssertionHelper(self.obj,
                                with_args=self._callable_args,
                                and_kwargs=self._callable_kw)
        if self.negative:
            try:
                return _that.raises(Exception)
            except AssertionError:
                raise AssertionError(
                    'The callable `{0}` was supposed to not be cool and throw an exception, but it is too cool for that'
                    .format(self.obj.__name__))

        try:
            self.obj(*self._callable_args, **self._callable_kw)
        except Exception as e:
            raise AssertionError(
                'The callable `{2}` should be cool but threw {0}: {1}'.format(
                    e.__class__.__name__, str(e), self.obj.__name__))

        return True
Example #9
0
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
            if self.negative:
                return collection_should.does_not_contain(self.obj)
            else:
                return collection_should.contains(self.obj)

        elif len(rest) == 1:
            return self.within_range(first, rest[0])
        else:
            if self.negative:
                ppath = '{0}.should_not.be.within'.format(self.obj)
            else:
                ppath = '{0}.should.be.within'.format(self.obj)

            raise AssertionError(
                ('{0}({1}, {2}) must be called with either a iterable:\n'
                 '{0}([1, 2, 3, 4])\n'
                 'or with a range of numbers:'
                 '{0}(1, 3000)').format(ppath, first,
                                        ", ".join([repr(x) for x in rest])))
Example #10
0
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
            if self.negative:
                return collection_should.does_not_contain(self.obj)
            else:
                return collection_should.contains(self.obj)

        elif len(rest) == 1:
            return self.within_range(first, rest[0])
        else:
            if self.negative:
                ppath = '{0}.should_not.be.within'.format(self.obj)
            else:
                ppath = '{0}.should.be.within'.format(self.obj)

            raise AssertionError((
                '{0}({1}, {2}) must be called with either a iterable:\n'
                '{0}([1, 2, 3, 4])\n'
                'or with a range of numbers:'
                '{0}(1, 3000)'
            ).format(ppath, first, ", ".join([repr(x) for x in rest])))
Example #11
0
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj,
                                with_args=self._callable_args,
                                and_kwargs=self._callable_kw)

        if self.negative:
            msg = ("{0} called with args {1} and kwargs {2} should "
                   "not raise {3} but raised {4}")

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(
                    self.obj,
                    self._that._callable_args,
                    self._that._callable_kw,
                    exc,
                    e,
                )
                raise AssertionError(err)

        return _that.raises(*args, **kw)
Example #12
0
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
        else:
            args = [first] + list(rest)
            collection_should = AssertionHelper(list(range(*args)))

        if self.negative:
            return collection_should.does_not_contain(self.obj)
        else:
            return collection_should.contains(self.obj)
Example #13
0
class AssertionBuilder(object):
    def __init__(self, name=None, negative=False, obj=None):
        self._name = name
        self.negative = negative
        self.obj = obj
        self._callable_args = []
        self._callable_kw = {}
        self._that = AssertionHelper(self.obj)

    def __call__(self, obj):
        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj

        self._that = AssertionHelper(self.obj)
        return self

    def __getattr__(self, attr):
        special_case = False
        special_case = attr in (POSITIVES + NEGATIVES)

        negative = attr in NEGATIVES

        if special_case:
            return AssertionBuilder(attr, negative=negative, obj=self.obj)

        return super(AssertionBuilder, self).__getattribute__(attr)

    @assertionproperty
    def callable(self):
        if self.negative:
            assert not callable(self.obj), "expected `{0}` to not be callable but it is".format(safe_repr(self.obj))
        else:
            assert callable(self.obj), "expected {0} to be callable".format(safe_repr(self.obj))

        return True

    @assertionproperty
    def be(self):
        import os

        if os.getenv("DEBUG"):
            import ipdb

            ipdb.set_trace()

        return IdentityAssertion(self)

    being = be

    @assertionproperty
    def not_be(self):
        return IdentityAssertion(self.should_not)

    not_being = not_be

    @assertionproperty
    def not_have(self):
        return self.should_not

    @assertionproperty
    def to_not(self):
        return self.should_not

    @assertionproperty
    def to(self):
        return self

    @assertionproperty
    def when(self):
        return self

    @assertionproperty
    def have(self):
        return self

    @assertionproperty
    def with_value(self):
        return self

    def property(self, name):
        has_it = hasattr(self.obj, name)
        if self.negative:
            assert not has_it, "%r should not have the property `%s`, " "but it is %r" % (
                self.obj,
                name,
                getattr(self.obj, name),
            )
            return True

        assert has_it, "%r should have the property `%s` but does not" % (self.obj, name)
        return expect(getattr(self.obj, name))

    def key(self, name):
        has_it = name in self.obj
        if self.negative:
            assert not has_it, "%r should not have the key `%s`, " "but it is %r" % (self.obj, name, self.obj[name])
            return True

        assert has_it, "%r should have the key `%s` but does not" % (self.obj, name)
        return expect(self.obj[name])

    @assertionproperty
    def empty(self):
        representation = safe_repr(self.obj)
        length = len(self.obj)
        if self.negative:
            assert length > 0, "expected `{0}` to not be empty".format(representation)
        else:
            assert length == 0, "expected `{0}` to be empty but it has {1} items".format(representation, length)

        return True

    @assertionproperty
    def ok(self):
        if self.negative:
            msg = "expected `{0}` to be falsy".format(self.obj)
            assert not bool(self.obj), msg
        else:
            msg = "expected `{0}` to be truthy".format(self.obj)
            assert bool(self.obj), msg

        return True

    truthy = ok
    true = ok

    @assertionproperty
    def falsy(self):
        if self.negative:
            msg = "expected `{0}` to be truthy".format(self.obj)
            assert bool(self.obj), msg
        else:
            msg = "expected `{0}` to be falsy".format(self.obj)
            assert not bool(self.obj), msg

        return True

    false = falsy

    @assertionproperty
    def none(self):
        if self.negative:
            assert self.obj is not None, r"expected `{0}` to not be None".format(self.obj)
        else:
            assert self.obj is None, r"expected `{0}` to be None".format(self.obj)

        return True

    @assertionmethod
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
        else:
            args = [first] + list(rest)
            collection_should = AssertionHelper(list(range(*args)))

        if self.negative:
            return collection_should.does_not_contain(self.obj)
        else:
            return collection_should.contains(self.obj)

    @assertionmethod
    def equal(self, what):
        try:
            comparison = DeepComparison(self.obj, what).compare()
            error = False
        except AssertionError as e:
            error = e
            comparison = None

        if isinstance(comparison, DeepExplanation):
            error = comparison.get_assertion(self.obj, what)

        if self.negative:
            if error:
                return True

            msg = "%s should differ to %s, but is the same thing"
            raise AssertionError(msg % (safe_repr(self.obj), safe_repr(what)))

        else:
            if not error:
                return True
            raise error

    eql = equal
    equals = equal
    equal_to = equal

    @assertionmethod
    def an(self, klass):
        if isinstance(klass, type):
            class_name = klass.__name__
        elif isinstance(klass, string_types):
            class_name = klass.strip()
        else:
            class_name = text_type(klass)

        is_vowel = class_name[0] in "aeiou"

        if isinstance(klass, string_types):
            if "." in klass:
                items = klass.split(".")
                first = items.pop(0)
                if not items:
                    items = [first]
                    first = "_abcoll"
            else:
                if sys.version_info <= (3, 0, 0):
                    first = "__builtin__"
                else:
                    first = "builtins"
                items = [klass]

            klass = reduce(getattr, items, __import__(first))

        suffix = is_vowel and "n" or ""

        if self.negative:
            assert not isinstance(self.obj, klass), "expected `{0}` to not be a{1} {2}".format(
                self.obj, suffix, class_name
            )

        else:
            assert isinstance(self.obj, klass), "expected `{0}` to be a{1} {2}".format(self.obj, suffix, class_name)
        return True

    a = an

    @assertionmethod
    def greater_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than `{1}`".format(self.obj, dest)

            assert not self.obj > dest, msg

        else:
            msg = "expected `{0}` to be greater than `{1}`".format(self.obj, dest)
            assert self.obj > dest, msg

        return True

    @assertionmethod
    def greater_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than or equal to `{1}`".format(self.obj, dest)

            assert not self.obj >= dest, msg

        else:
            msg = "expected `{0}` to be greater than or equal to `{1}`".format(self.obj, dest)
            assert self.obj >= dest, msg

        return True

    @assertionmethod
    def lower_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than `{1}`".format(self.obj, dest)

            assert not self.obj < dest, msg

        else:
            msg = "expected `{0}` to be lower than `{1}`".format(self.obj, dest)
            assert self.obj < dest, msg

        return True

    @assertionmethod
    def lower_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than or equal to `{1}`".format(self.obj, dest)

            assert not self.obj <= dest, msg

        else:
            msg = "expected `{0}` to be lower than or equal to `{1}`".format(self.obj, dest)
            assert self.obj <= dest, msg

        return True

    @assertionmethod
    def below(self, num):
        if self.negative:
            msg = "{0} should not be below {1}".format(self.obj, num)
            assert not self.obj < num, msg
        else:
            msg = "{0} should be below {1}".format(self.obj, num)
            assert self.obj < num, msg

        return True

    @assertionmethod
    def above(self, num):
        if self.negative:
            msg = "{0} should not be above {1}".format(self.obj, num)
            assert not self.obj > num, msg
        else:
            msg = "{0} should be above {1}".format(self.obj, num)
            assert self.obj > num, msg
        return True

    @assertionmethod
    def length_of(self, num):
        if self.negative:
            return self._that.len_is_not(num)

        return self._that.len_is(num)

    @assertionmethod
    def called_with(self, *args, **kw):
        self._callable_args = args
        self._callable_kw = kw
        return self

    called = builtins.property(called_with)

    @assertionmethod
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj, with_args=self._callable_args, and_kwargs=self._callable_kw)

        if self.negative:
            msg = "{0} called with args {1} and kwargs {2} should " "not raise {3} but raised {4}"

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(self.obj, self._that._callable_args, self._that._callable_kw, exc, e)
                raise AssertionError(err)

        return _that.raises(*args, **kw)

    @assertionmethod
    def return_value(self, value):
        return_value = self.obj(*self._callable_args, **self._callable_kw)
        return this(return_value).should.equal(value)

    @assertionmethod
    def look_like(self, value):
        if self.negative:
            try:
                self._that.looks_like(value)
            except AssertionError:
                return True
            else:
                msg = "%r should not look like %r but does"
                raise AssertionError(msg % (self.obj, value))

        return self._that.looks_like(value)

    @assertionmethod
    def contain(self, what):
        if self.negative:
            return expect(what).to.not_be.within(self.obj)
        else:
            return expect(what).to.be.within(self.obj)

    @assertionmethod
    def match(self, regex, *args):
        obj_repr = repr(self.obj)
        assert isinstance(self.obj, basestring), "{0} should be a string in order to compare using .match()".format(
            obj_repr
        )
        matched = re.search(regex, self.obj, *args)

        modifiers_map = {re.I: "i", re.L: "l", re.M: "m", re.S: "s", re.U: "u"}
        modifiers = "".join([modifiers_map.get(x, "") for x in args])
        regex_representation = "/{0}/{1}".format(regex, modifiers)

        if self.negative:
            assert matched is None, "{0} should not match the regular expression {1}".format(
                obj_repr, regex_representation
            )

        else:
            assert matched is not None, "{0} doesn't match the regular expression {1}".format(
                obj_repr, regex_representation
            )

        return True
Example #14
0
class AssertionBuilder(object):
    def __init__(self,
                 name=None,
                 negative=False,
                 obj=None,
                 callable_args=None,
                 callable_kw=None):
        self._name = name
        self.negative = negative

        self.obj = obj
        self._callable_args = callable_args or []
        self._callable_kw = callable_kw or {}
        self._that = AssertionHelper(self.obj)

    def __call__(self, obj):

        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj
            self._callable_args = obj._callable_args
            self._callable_kw = obj._callable_kw

        self._that = AssertionHelper(self.obj)
        return self

    def __getattr__(self, attr):
        special_case = False
        special_case = attr in (POSITIVES + NEGATIVES)

        negative = attr in NEGATIVES

        if special_case:
            return AssertionBuilder(attr,
                                    negative=negative,
                                    obj=self.obj,
                                    callable_args=self._callable_args,
                                    callable_kw=self._callable_kw)

        return super(AssertionBuilder, self).__getattribute__(attr)

    @assertionproperty
    def callable(self):
        if self.negative:
            assert not callable(self.obj), (
                'expected `{0}` to not be callable but it is'.format(
                    safe_repr(self.obj)))
        else:
            assert callable(self.obj), ('expected {0} to be callable'.format(
                safe_repr(self.obj)))

        return True

    @assertionproperty
    def be(self):
        return IdentityAssertion(self)

    being = be

    @assertionproperty
    def not_be(self):
        return IdentityAssertion(self.should_not)

    not_being = not_be

    @assertionproperty
    def not_have(self):
        return self.should_not

    @assertionproperty
    def to_not(self):
        return self.should_not

    @assertionproperty
    def to(self):
        return self

    which = to

    @assertionproperty
    def when(self):
        return self

    @assertionproperty
    def have(self):
        return self

    @assertionproperty
    def with_value(self):
        return self

    def property(self, name):
        has_it = hasattr(self.obj, name)
        if self.negative:
            assert not has_it, ('%r should not have the property `%s`, '
                                'but it is %r' %
                                (self.obj, name, getattr(self.obj, name)))
            return True

        assert has_it, ("%r should have the property `%s` but does not" %
                        (self.obj, name))
        return expect(getattr(self.obj, name))

    def key(self, name):
        has_it = name in self.obj
        if self.negative:
            assert not has_it, ('%r should not have the key `%s`, '
                                'but it is %r' %
                                (self.obj, name, self.obj[name]))
            return True

        assert has_it, ("%r should have the key `%s` but does not" %
                        (self.obj, name))

        return expect(self.obj[name])

    @assertionproperty
    def empty(self):
        representation = safe_repr(self.obj)
        length = len(self.obj)
        if self.negative:
            assert length > 0, (
                "expected `{0}` to not be empty".format(representation))
        else:
            assert length == 0, (
                "expected `{0}` to be empty but it has {1} items".format(
                    representation, length))

        return True

    @assertionproperty
    def ok(self):
        if self.negative:
            msg = 'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg
        else:
            msg = 'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg

        return True

    truthy = ok
    true = ok

    @assertionproperty
    def falsy(self):
        if self.negative:
            msg = 'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg
        else:
            msg = 'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg

        return True

    false = falsy

    @assertionproperty
    def none(self):
        if self.negative:
            assert self.obj is not None, (
                r"expected `{0}` to not be None".format(self.obj))
        else:
            assert self.obj is None, (r"expected `{0}` to be None".format(
                self.obj))

        return True

    @assertionmethod
    def within_range(self, start, end):
        start = ensure_type('within_range', int, start)
        end = ensure_type('within_range', int, end)
        subject = ensure_type('within_range', int, self.obj)
        is_within_range = subject >= start and subject <= end

        if self.negative:
            if is_within_range:
                raise AssertionError(
                    'expected {0} to NOT be within {1} and {2}'.format(
                        subject, start, end))
            return not is_within_range

        else:
            if not is_within_range:
                raise AssertionError(
                    'expected {0} to be within {1} and {2}'.format(
                        subject, start, end))
            return is_within_range

    @assertionmethod
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
            if self.negative:
                return collection_should.does_not_contain(self.obj)
            else:
                return collection_should.contains(self.obj)

        elif len(rest) == 1:
            return self.within_range(first, rest[0])
        else:
            if self.negative:
                ppath = '{0}.should_not.be.within'.format(self.obj)
            else:
                ppath = '{0}.should.be.within'.format(self.obj)

            raise AssertionError(
                ('{0}({1}, {2}) must be called with either a iterable:\n'
                 '{0}([1, 2, 3, 4])\n'
                 'or with a range of numbers:'
                 '{0}(1, 3000)').format(ppath, first,
                                        ", ".join([repr(x) for x in rest])))

    @assertionmethod
    def equal(self, what, epsilon=None):
        try:
            comparison = DeepComparison(self.obj, what, epsilon).compare()
            error = False
        except AssertionError as e:
            error = e
            comparison = None

        if isinstance(comparison, DeepExplanation):
            error = comparison.get_assertion(self.obj, what)

        if self.negative:
            if error:
                return True

            msg = '%s should differ from %s, but is the same thing'
            raise AssertionError(msg % (safe_repr(self.obj), safe_repr(what)))

        else:
            if not error:
                return True
            raise error

    eql = equal
    equals = equal
    equal_to = equal

    @assertionmethod
    def different_of(self, what):
        differ = difflib.Differ()

        source = self.obj.strip().splitlines(True)
        destination = what.strip().splitlines(True)
        result = differ.compare(source, destination)
        difference = "".join(result)
        if self.negative:
            if self.obj != what:
                assert not difference, "Difference:\n\n{0}".format(difference)
        else:
            if self.obj == what:
                raise AssertionError("{0} should be different of {1}".format(
                    self.obj, what))

        return True

    @assertionmethod
    def an(self, klass):
        if isinstance(klass, type):
            class_name = klass.__name__
        elif isinstance(klass, string_types):
            class_name = klass.strip()
        else:
            class_name = text_type(klass)

        is_vowel = class_name[0] in 'aeiou'

        if isinstance(klass, string_types):
            if '.' in klass:
                items = klass.split('.')
                first = items.pop(0)
                if not items:
                    items = [first]
                    first = '_abcoll'
            else:
                if sys.version_info <= (3, 0, 0):
                    first = '__builtin__'
                else:
                    first = 'builtins'
                items = [klass]

            klass = reduce(getattr, items, __import__(first))

        suffix = is_vowel and "n" or ""

        if self.negative:
            assert not isinstance(
                self.obj, klass), ('expected `{0}` to not be a{1} {2}'.format(
                    self.obj, suffix, class_name))

        else:
            assert isinstance(self.obj,
                              klass), ('expected `{0}` to be a{1} {2}'.format(
                                  self.obj, suffix, class_name))
        return True

    a = an

    @assertionmethod
    def greater_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than `{1}`".format(
                self.obj, dest)

            assert not self.obj > dest, msg

        else:
            msg = "expected `{0}` to be greater than `{1}`".format(
                self.obj, dest)
            assert self.obj > dest, msg

        return True

    @assertionmethod
    def greater_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj >= dest, msg

        else:
            msg = "expected `{0}` to be greater than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj >= dest, msg

        return True

    @assertionmethod
    def lower_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than `{1}`".format(
                self.obj, dest)

            assert not self.obj < dest, msg

        else:
            msg = "expected `{0}` to be lower than `{1}`".format(
                self.obj, dest)
            assert self.obj < dest, msg

        return True

    @assertionmethod
    def lower_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj <= dest, msg

        else:
            msg = "expected `{0}` to be lower than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj <= dest, msg

        return True

    @assertionmethod
    def below(self, num):
        if self.negative:
            msg = "{0} should not be below {1}".format(self.obj, num)
            assert not self.obj < num, msg
        else:
            msg = "{0} should be below {1}".format(self.obj, num)
            assert self.obj < num, msg

        return True

    @assertionmethod
    def above(self, num):
        if self.negative:
            msg = "{0} should not be above {1}".format(self.obj, num)
            assert not self.obj > num, msg
        else:
            msg = "{0} should be above {1}".format(self.obj, num)
            assert self.obj > num, msg
        return True

    @assertionmethod
    def length_of(self, num):
        if self.negative:
            return self._that.len_is_not(num)

        return self._that.len_is(num)

    def called_with(self, *args, **kw):
        self._callable_args = args
        self._callable_kw = kw
        return self

    called = builtins.property(called_with)

    @assertionmethod
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj,
                                with_args=self._callable_args,
                                and_kwargs=self._callable_kw)

        if self.negative:
            msg = ("{0} called with args {1} and kwargs {2} should "
                   "not raise {3} but raised {4}")

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(
                    self.obj,
                    self._that._callable_args,
                    self._that._callable_kw,
                    exc,
                    e,
                )
                raise AssertionError(err)

        return _that.raises(*args, **kw)

    thrown = throw
    raised = thrown

    @assertionmethod
    def return_value(self, value):
        return_value = self.obj(*self._callable_args, **self._callable_kw)
        return this(return_value).should.equal(value)

    returned_the_value = return_value

    @assertionmethod
    def look_like(self, value):
        if self.negative:
            try:
                self._that.looks_like(value)
            except AssertionError:
                return True
            else:
                msg = '%r should not look like %r but does'
                raise AssertionError(msg % (self.obj, value))

        return self._that.looks_like(value)

    @assertionmethod
    def contain(self, what):
        obj = self.obj
        if self.negative:
            return expect(what).to.not_be.within(obj)
        else:
            return expect(what).to.be.within(obj)

    @assertionmethod
    def match(self, regex, *args):
        obj_repr = repr(self.obj)
        assert isinstance(self.obj, basestring), (
            "{0} should be a string in order to compare using .match()".format(
                obj_repr))
        matched = re.search(regex, self.obj, *args)

        modifiers_map = {
            re.I: "i",
            re.L: "l",
            re.M: "m",
            re.S: "s",
            re.U: "u",
        }
        modifiers = "".join([modifiers_map.get(x, "") for x in args])
        regex_representation = '/{0}/{1}'.format(regex, modifiers)

        if self.negative:
            assert matched is None, (
                "{0} should not match the regular expression {1}".format(
                    obj_repr, regex_representation))

        else:
            assert matched is not None, (
                "{0} doesn't match the regular expression {1}".format(
                    obj_repr, regex_representation))

        return True
Example #15
0
class AssertionBuilder(object):
    def __init__(self, name=None, negative=False, obj=None):
        self._name = name
        self.negative = negative
        self.obj = obj
        self._callable_args = []
        self._callable_kw = {}
        self._that = AssertionHelper(self.obj)

    def __call__(self, obj):
        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj

        self._that = AssertionHelper(self.obj)
        return self

    def __getattr__(self, attr):
        special_case = False
        special_case = attr in (POSITIVES + NEGATIVES)

        negative = attr in NEGATIVES

        if special_case:
            return AssertionBuilder(attr, negative=negative, obj=self.obj)

        return super(AssertionBuilder, self).__getattribute__(attr)

    @assertionproperty
    def callable(self):
        if self.negative:
            assert not callable(self.obj), (
                'expected `{0}` to not be callable but it is'.format(
                    safe_repr(self.obj)))
        else:
            assert callable(self.obj), ('expected {0} to be callable'.format(
                safe_repr(self.obj)))

        return True

    @assertionproperty
    def be(self):
        import os
        if os.getenv("DEBUG"):
            import ipdb
            ipdb.set_trace()

        return IdentityAssertion(self)

    being = be

    @assertionproperty
    def not_be(self):
        return IdentityAssertion(self.should_not)

    not_being = not_be

    @assertionproperty
    def not_have(self):
        return self.should_not

    @assertionproperty
    def to_not(self):
        return self.should_not

    @assertionproperty
    def to(self):
        return self

    @assertionproperty
    def when(self):
        return self

    @assertionproperty
    def have(self):
        return self

    @assertionproperty
    def with_value(self):
        return self

    def property(self, name):
        has_it = hasattr(self.obj, name)
        if self.negative:
            assert not has_it, ('%r should not have the property `%s`, '
                                'but it is %r' %
                                (self.obj, name, getattr(self.obj, name)))
            return True

        assert has_it, ("%r should have the property `%s` but does not" %
                        (self.obj, name))
        return expect(getattr(self.obj, name))

    def key(self, name):
        has_it = name in self.obj
        if self.negative:
            assert not has_it, ('%r should not have the key `%s`, '
                                'but it is %r' %
                                (self.obj, name, self.obj[name]))
            return True

        assert has_it, ("%r should have the key `%s` but does not" %
                        (self.obj, name))
        return expect(self.obj[name])

    @assertionproperty
    def empty(self):
        representation = safe_repr(self.obj)
        length = len(self.obj)
        if self.negative:
            assert length > 0, (
                u"expected `{0}` to not be empty".format(representation))
        else:
            assert length == 0, (
                u"expected `{0}` to be empty but it has {1} items".format(
                    representation, length))

        return True

    @assertionproperty
    def ok(self):
        if self.negative:
            msg = u'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg
        else:
            msg = u'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg

        return True

    truthy = ok
    true = ok

    @assertionproperty
    def falsy(self):
        if self.negative:
            msg = u'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg
        else:
            msg = u'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg

        return True

    false = falsy

    @assertionproperty
    def none(self):
        if self.negative:
            assert self.obj is not None, (
                r"expected `{0}` to not be None".format(self.obj))
        else:
            assert self.obj is None, (r"expected `{0}` to be None".format(
                self.obj))

        return True

    @assertionmethod
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
        else:
            args = [first] + list(rest)
            collection_should = AssertionHelper(list(range(*args)))

        if self.negative:
            return collection_should.does_not_contain(self.obj)
        else:
            return collection_should.contains(self.obj)

    @assertionmethod
    def equal(self, what):
        try:
            comparison = DeepComparison(self.obj, what).compare()
            error = False
        except AssertionError as e:
            error = e
            comparison = None

        if isinstance(comparison, DeepExplanation):
            error = comparison.get_assertion(self.obj, what)

        if self.negative:
            if error:
                return True

            msg = '%s should differ to %s, but is the same thing'
            raise AssertionError(msg % (safe_repr(self.obj), safe_repr(what)))

        else:
            if not error:
                return True
            raise error

    eql = equal
    equals = equal
    equal_to = equal

    @assertionmethod
    def an(self, klass):
        if isinstance(klass, type):
            class_name = klass.__name__
        elif isinstance(klass, string_types):
            class_name = klass.strip()
        else:
            class_name = text_type(klass)

        is_vowel = class_name[0] in 'aeiou'

        if isinstance(klass, string_types):
            if '.' in klass:
                items = klass.split('.')
                first = items.pop(0)
                if not items:
                    items = [first]
                    first = '_abcoll'
            else:
                if sys.version_info <= (3, 0, 0):
                    first = u'__builtin__'
                else:
                    first = u'builtins'
                items = [klass]

            klass = reduce(getattr, items, __import__(first))

        suffix = is_vowel and "n" or ""

        if self.negative:
            assert not isinstance(
                self.obj, klass), ('expected `{0}` to not be a{1} {2}'.format(
                    self.obj, suffix, class_name))

        else:
            assert isinstance(self.obj,
                              klass), ('expected `{0}` to be a{1} {2}'.format(
                                  self.obj, suffix, class_name))
        return True

    a = an

    @assertionmethod
    def greater_than(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be greater than `{1}`".format(
                self.obj, dest)

            assert not self.obj > dest, msg

        else:
            msg = u"expected `{0}` to be greater than `{1}`".format(
                self.obj, dest)
            assert self.obj > dest, msg

        return True

    @assertionmethod
    def greater_than_or_equal_to(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be greater than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj >= dest, msg

        else:
            msg = u"expected `{0}` to be greater than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj >= dest, msg

        return True

    @assertionmethod
    def lower_than(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be lower than `{1}`".format(
                self.obj, dest)

            assert not self.obj < dest, msg

        else:
            msg = u"expected `{0}` to be lower than `{1}`".format(
                self.obj, dest)
            assert self.obj < dest, msg

        return True

    @assertionmethod
    def lower_than_or_equal_to(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be lower than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj <= dest, msg

        else:
            msg = u"expected `{0}` to be lower than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj <= dest, msg

        return True

    @assertionmethod
    def below(self, num):
        if self.negative:
            msg = u"{0} should not be below {1}".format(self.obj, num)
            assert not self.obj < num, msg
        else:
            msg = u"{0} should be below {1}".format(self.obj, num)
            assert self.obj < num, msg

        return True

    @assertionmethod
    def above(self, num):
        if self.negative:
            msg = u"{0} should not be above {1}".format(self.obj, num)
            assert not self.obj > num, msg
        else:
            msg = u"{0} should be above {1}".format(self.obj, num)
            assert self.obj > num, msg
        return True

    @assertionmethod
    def length_of(self, num):
        if self.negative:
            return self._that.len_is_not(num)

        return self._that.len_is(num)

    @assertionmethod
    def called_with(self, *args, **kw):
        self._callable_args = args
        self._callable_kw = kw
        return self

    called = builtins.property(called_with)

    @assertionmethod
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj,
                                with_args=self._callable_args,
                                and_kwargs=self._callable_kw)

        if self.negative:
            msg = (u"{0} called with args {1} and kwargs {2} should "
                   "not raise {3} but raised {4}")

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(
                    self.obj,
                    self._that._callable_args,
                    self._that._callable_kw,
                    exc,
                    e,
                )
                raise AssertionError(err)

        return _that.raises(*args, **kw)

    @assertionmethod
    def return_value(self, value):
        return_value = self.obj(*self._callable_args, **self._callable_kw)
        return this(return_value).should.equal(value)

    @assertionmethod
    def look_like(self, value):
        if self.negative:
            try:
                self._that.looks_like(value)
            except AssertionError:
                return True
            else:
                msg = '%r should not look like %r but does'
                raise AssertionError(msg % (self.obj, value))

        return self._that.looks_like(value)

    @assertionmethod
    def contain(self, what):
        if self.negative:
            return expect(what).to.not_be.within(self.obj)
        else:
            return expect(what).to.be.within(self.obj)

    @assertionmethod
    def match(self, regex, *args):
        obj_repr = repr(self.obj)
        assert isinstance(self.obj, basestring), (
            "{0} should be a string in order to compare using .match()".format(
                obj_repr))
        matched = re.search(regex, self.obj, *args)

        modifiers_map = {
            re.I: "i",
            re.L: "l",
            re.M: "m",
            re.S: "s",
            re.U: "u",
        }
        modifiers = "".join([modifiers_map.get(x, "") for x in args])
        regex_representation = '/{0}/{1}'.format(regex, modifiers)

        if self.negative:
            assert matched is None, (
                "{0} should not match the regular expression {1}".format(
                    obj_repr, regex_representation))

        else:
            assert matched is not None, (
                "{0} doesn't match the regular expression {1}".format(
                    obj_repr, regex_representation))

        return True
Example #16
0
class AssertionBuilder(object):
    def __init__(self, name=None, negative=False, obj=None, callable_args=None, callable_kw=None):
        self._name = name
        self.negative = negative

        self.obj = obj
        self._callable_args = callable_args or []
        self._callable_kw = callable_kw or {}
        self._that = AssertionHelper(self.obj)

    def __call__(self, obj):

        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj
            self._callable_args = obj._callable_args
            self._callable_kw = obj._callable_kw

        self._that = AssertionHelper(self.obj)
        return self

    def __getattr__(self, attr):
        special_case = False
        special_case = attr in (POSITIVES + NEGATIVES)

        negative = attr in NEGATIVES

        if special_case:
            return AssertionBuilder(attr, negative=negative, obj=self.obj,
                 callable_args=self._callable_args, callable_kw=self._callable_kw)

        return super(AssertionBuilder, self).__getattribute__(attr)

    @assertionproperty
    def callable(self):
        if self.negative:
            assert not callable(self.obj), (
                'expected `{0}` to not be callable but it is'.format(safe_repr(self.obj)))
        else:
            assert callable(self.obj), (
                'expected {0} to be callable'.format(safe_repr(self.obj)))

        return True

    @assertionproperty
    def be(self):
        return IdentityAssertion(self)

    being = be

    @assertionproperty
    def not_be(self):
        return IdentityAssertion(self.should_not)

    not_being = not_be

    @assertionproperty
    def not_have(self):
        return self.should_not

    @assertionproperty
    def to_not(self):
        return self.should_not

    @assertionproperty
    def to(self):
        return self

    which = to

    @assertionproperty
    def when(self):
        return self

    @assertionproperty
    def have(self):
        return self

    @assertionproperty
    def with_value(self):
        return self

    def property(self, name):
        has_it = hasattr(self.obj, name)
        if self.negative:
            assert not has_it, (
                '%r should not have the property `%s`, '
                'but it is %r' % (self.obj, name, getattr(self.obj, name)))
            return True

        assert has_it, (
            "%r should have the property `%s` but does not" % (
                self.obj, name))
        return expect(getattr(self.obj, name))

    def key(self, name):
        has_it = name in self.obj
        if self.negative:
            assert not has_it, (
                '%r should not have the key `%s`, '
                'but it is %r' % (self.obj, name, self.obj[name]))
            return True

        assert has_it, (
            "%r should have the key `%s` but does not" % (
                self.obj, name))

        return expect(self.obj[name])

    @assertionproperty
    def empty(self):
        representation = safe_repr(self.obj)
        length = len(self.obj)
        if self.negative:
            assert length > 0, (
                "expected `{0}` to not be empty".format(representation))
        else:
            assert length == 0, (
                "expected `{0}` to be empty but it has {1} items".format(representation, length))

        return True

    @assertionproperty
    def ok(self):
        if self.negative:
            msg = 'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg
        else:
            msg = 'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg

        return True

    truthy = ok
    true = ok

    @assertionproperty
    def falsy(self):
        if self.negative:
            msg = 'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg
        else:
            msg = 'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg

        return True

    false = falsy

    @assertionproperty
    def none(self):
        if self.negative:
            assert self.obj is not None, (
                r"expected `{0}` to not be None".format(self.obj))
        else:
            assert self.obj is None, (
                r"expected `{0}` to be None".format(self.obj))

        return True

    @assertionmethod
    def within_range(self, start, end):
        start = ensure_type('within_range', int, start)
        end = ensure_type('within_range', int, end)
        subject = ensure_type('within_range', int, self.obj)
        is_within_range = subject >= start and subject <= end

        if self.negative:
            if is_within_range:
                raise AssertionError('expected {0} to NOT be within {1} and {2}'.format(subject, start, end))
            return not is_within_range

        else:
            if not is_within_range:
                raise AssertionError('expected {0} to be within {1} and {2}'.format(subject, start, end))
            return is_within_range

    @assertionmethod
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
            if self.negative:
                return collection_should.does_not_contain(self.obj)
            else:
                return collection_should.contains(self.obj)

        elif len(rest) == 1:
            return self.within_range(first, rest[0])
        else:
            if self.negative:
                ppath = '{0}.should_not.be.within'.format(self.obj)
            else:
                ppath = '{0}.should.be.within'.format(self.obj)

            raise AssertionError((
                '{0}({1}, {2}) must be called with either a iterable:\n'
                '{0}([1, 2, 3, 4])\n'
                'or with a range of numbers:'
                '{0}(1, 3000)'
            ).format(ppath, first, ", ".join([repr(x) for x in rest])))

    @assertionmethod
    def equal(self, what, epsilon=None):
        try:
            comparison = DeepComparison(self.obj, what, epsilon).compare()
            error = False
        except AssertionError as e:
            error = e
            comparison = None

        if isinstance(comparison, DeepExplanation):
            error = comparison.get_assertion(self.obj, what)

        if self.negative:
            if error:
                return True

            msg = '%s should differ from %s, but is the same thing'
            raise AssertionError(msg % (safe_repr(self.obj), safe_repr(what)))

        else:
            if not error:
                return True
            raise error

    eql = equal
    equals = equal
    equal_to = equal

    @assertionmethod
    def different_of(self, what):
        differ = difflib.Differ()

        source = self.obj.strip().splitlines(True)
        destination = what.strip().splitlines(True)
        result = differ.compare(source, destination)
        difference = "".join(result)
        if self.negative:
            if self.obj != what:
                assert not difference, "Difference:\n\n{0}".format(difference)
        else:
            if self.obj == what:
                raise AssertionError("{0} should be different of {1}".format(self.obj, what))

        return True

    @assertionmethod
    def an(self, klass):
        if isinstance(klass, type):
            class_name = klass.__name__
        elif isinstance(klass, string_types):
            class_name = klass.strip()
        else:
            class_name = text_type(klass)

        is_vowel = class_name[0] in 'aeiou'

        if isinstance(klass, string_types):
            if '.' in klass:
                items = klass.split('.')
                first = items.pop(0)
                if not items:
                    items = [first]
                    first = '_abcoll'
            else:
                if sys.version_info <= (3, 0, 0):
                    first = '__builtin__'
                else:
                    first = 'builtins'
                items = [klass]

            klass = reduce(getattr, items, __import__(first))

        suffix = is_vowel and "n" or ""

        if self.negative:
            assert not isinstance(self.obj, klass), (
                'expected `{0}` to not be a{1} {2}'.format(
                    self.obj, suffix, class_name))

        else:
            assert isinstance(self.obj, klass), (
                'expected `{0}` to be a{1} {2}'.format(
                    self.obj, suffix, class_name))
        return True

    a = an

    @assertionmethod
    def greater_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than `{1}`".format(
                self.obj, dest)

            assert not self.obj > dest, msg

        else:
            msg = "expected `{0}` to be greater than `{1}`".format(
                self.obj, dest)
            assert self.obj > dest, msg

        return True

    @assertionmethod
    def greater_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be greater than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj >= dest, msg

        else:
            msg = "expected `{0}` to be greater than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj >= dest, msg

        return True

    @assertionmethod
    def lower_than(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than `{1}`".format(
                self.obj, dest)

            assert not self.obj < dest, msg

        else:
            msg = "expected `{0}` to be lower than `{1}`".format(
                self.obj, dest)
            assert self.obj < dest, msg

        return True

    @assertionmethod
    def lower_than_or_equal_to(self, dest):
        if self.negative:
            msg = "expected `{0}` to not be lower than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj <= dest, msg

        else:
            msg = "expected `{0}` to be lower than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj <= dest, msg

        return True

    @assertionmethod
    def below(self, num):
        if self.negative:
            msg = "{0} should not be below {1}".format(self.obj, num)
            assert not self.obj < num, msg
        else:
            msg = "{0} should be below {1}".format(self.obj, num)
            assert self.obj < num, msg

        return True

    @assertionmethod
    def above(self, num):
        if self.negative:
            msg = "{0} should not be above {1}".format(self.obj, num)
            assert not self.obj > num, msg
        else:
            msg = "{0} should be above {1}".format(self.obj, num)
            assert self.obj > num, msg
        return True

    @assertionmethod
    def length_of(self, num):
        if self.negative:
            return self._that.len_is_not(num)

        return self._that.len_is(num)

    def called_with(self, *args, **kw):
        self._callable_args = args
        self._callable_kw = kw
        return self

    called = builtins.property(called_with)

    @assertionmethod
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj,
                     with_args=self._callable_args,
                     and_kwargs=self._callable_kw)

        if self.negative:
            msg = ("{0} called with args {1} and kwargs {2} should "
                   "not raise {3} but raised {4}")

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception as e:
                err = msg.format(
                    self.obj,
                    self._that._callable_args,
                    self._that._callable_kw,
                    exc,
                    e,
                )
                raise AssertionError(err)

        return _that.raises(*args, **kw)

    thrown = throw
    raised = thrown

    @assertionmethod
    def return_value(self, value):
        return_value = self.obj(*self._callable_args, **self._callable_kw)
        return this(return_value).should.equal(value)

    returned_the_value = return_value

    @assertionmethod
    def look_like(self, value):
        if self.negative:
            try:
                self._that.looks_like(value)
            except AssertionError:
                return True
            else:
                msg = '%r should not look like %r but does'
                raise AssertionError(msg % (self.obj, value))

        return self._that.looks_like(value)

    @assertionmethod
    def contain(self, what):
        obj = self.obj
        if self.negative:
            return expect(what).to.not_be.within(obj)
        else:
            return expect(what).to.be.within(obj)

    @assertionmethod
    def match(self, regex, *args):
        obj_repr = repr(self.obj)
        assert isinstance(self.obj, basestring), (
            "{0} should be a string in order to compare using .match()".format(obj_repr)
        )
        matched = re.search(regex, self.obj, *args)

        modifiers_map = {
            re.I: "i",
            re.L: "l",
            re.M: "m",
            re.S: "s",
            re.U: "u",
        }
        modifiers = "".join([modifiers_map.get(x, "") for x in args])
        regex_representation = '/{0}/{1}'.format(regex, modifiers)

        if self.negative:
            assert matched is None, (
                "{0} should not match the regular expression {1}".format(
                    obj_repr, regex_representation))

        else:
            assert matched is not None, (
                "{0} doesn't match the regular expression {1}".format(
                    obj_repr, regex_representation))

        return True
Example #17
0
class AssertionBuilder(object):
    def __init__(self, name=None, negative=False):
        self._name = name
        self.negative = negative
        self._callable_args = []
        self._callable_kw = {}

    def __call__(self, obj):
        self.obj = obj

        if isinstance(obj, self.__class__):
            self.obj = obj.obj

        self._that = AssertionHelper(self.obj)
        return self

    def __getattr__(self, attr):
        special_case = False
        special_case = attr in (POSITIVES + NEGATIVES)

        self.negative = attr in NEGATIVES

        if attr in POSITIVES:
            self.negative = False
            special_case = True

        if attr in NEGATIVES:
            self.negative = True
            special_case = True

        if special_case:
            return self

        return super(AssertionBuilder, self).__getattribute__(attr)

    @assertionproperty
    def callable(self):
        if self.negative:
            assert not callable(self.obj), (
                'expected `{0}` to not be callable but it is'.format(safe_repr(self.obj)))
        else:
            assert callable(self.obj), (
                'expected {0} to be callable'.format(safe_repr(self.obj)))

        return True

    @assertionproperty
    def be(self):
        return self

    @assertionproperty
    def being(self):
        return self

    @assertionproperty
    def not_being(self):
        return self.should_not

    @assertionproperty
    def not_be(self):
        return self.obj.should_not

    @assertionproperty
    def not_have(self):
        return self.obj.should_not

    @assertionproperty
    def to_not(self):
        return self.obj.should_not

    @assertionproperty
    def to(self):
        return self

    @assertionproperty
    def when(self):
        return self

    @assertionproperty
    def have(self):
        return self

    @assertionproperty
    def with_value(self):
        return self

    def property(self, name):
        has_it = hasattr(self.obj, name)
        if self.negative:
            assert not has_it, (
                '%r should not have the property `%s`, '
                'but it is %r' % (self.obj, name, getattr(self.obj, name)))
            return True

        assert has_it, (
            "%r should have the property `%s` but doesn't" % (
                self.obj, name))
        return expect(getattr(self.obj, name))

    def key(self, name):
        has_it = name in self.obj
        if self.negative:
            assert not has_it, (
                '%r should not have the key `%s`, '
                'but it is %r' % (self.obj, name, self.obj[name]))
            return True

        assert has_it, (
            "%r should have the key `%s` but doesn't" % (
                self.obj, name))
        return expect(self.obj[name])

    @assertionproperty
    def empty(self):
        representation = safe_repr(self.obj)
        length = len(self.obj)
        if self.negative:
            assert length > 0, (
                u"expected `{0}` to not be empty".format(representation))
        else:
            assert length is 0, (
                u"expected `{0}` to be empty but it has {1} items".format(representation, length))

        return True

    @assertionproperty
    def ok(self):
        if self.negative:
            msg = u'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg
        else:
            msg = u'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg

        return True

    truthy = ok
    true = ok

    @assertionproperty
    def falsy(self):
        if self.negative:
            msg = u'expected `{0}` to be truthy'.format(self.obj)
            assert bool(self.obj), msg
        else:
            msg = u'expected `{0}` to be falsy'.format(self.obj)
            assert not bool(self.obj), msg

        return True

    false = falsy

    @assertionproperty
    def none(self):
        if self.negative:
            assert self.obj is not None, (
                ur"expected `{0}` to not be None".format(self.obj))
        else:
            assert self.obj is None, (
                ur"expected `{0}` to be None".format(self.obj))

        return True

    @assertionmethod
    def within(self, first, *rest):
        if isinstance(first, Iterable):
            collection_should = AssertionHelper(first)
        else:
            args = [first] + list(rest)
            collection_should = AssertionHelper(range(*args))

        if self.negative:
            return collection_should.does_not_contain(self.obj)
        else:
            return collection_should.contains(self.obj)

    @assertionmethod
    def equal(self, what):
        try:
            comparison = DeepComparison(self.obj, what).compare()
            error = False
        except AssertionError as e:
            error = e
            comparison = None

        if isinstance(comparison, DeepExplanation):
            error = comparison.get_assertion(self.obj, what)

        if self.negative:
            if error:
                return True

            msg = '%r should differ to %r, but is the same thing'
            raise AssertionError(msg % (self.obj, what))

        else:
            if not error:
                return True
            raise error

    eql = equal
    equals = equal

    @assertionmethod
    def an(self, klass):
        if isinstance(klass, type):
            class_name = klass.__name__
        elif isinstance(klass, basestring):
            class_name = klass.strip()
        else:
            class_name = unicode(klass)

        is_vowel = class_name[0] in 'aeiou'

        if isinstance(klass, basestring):
            if '.' in klass:
                items = klass.split('.')
                first = items.pop(0)
                if not items:
                    items = [first]
                    first = '_abcoll'
            else:
                if sys.version_info <= (3, 0, 0):
                    first = u'__builtin__'
                else:
                    first = u'builtins'
                items = [klass]

            klass = reduce(getattr, items, __import__(first))

        suffix = is_vowel and "n" or ""

        if self.negative:
            assert not isinstance(self.obj, klass), (
                'expected `{0}` to not be a{1} {2}'.format(
                    self.obj, suffix, class_name))

        else:
            assert isinstance(self.obj, klass), (
                'expected `{0}` to be a{1} {2}'.format(
                    self.obj, suffix, class_name))
        return True

    a = an

    @assertionmethod
    def greater_than(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be greater than `{1}`".format(
                self.obj, dest)

            assert not self.obj > dest, msg

        else:
            msg = u"expected `{0}` to be greater than `{1}`".format(
                self.obj, dest)
            assert self.obj > dest, msg

        return True

    @assertionmethod
    def greater_than_or_equal_to(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be greater than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj >= dest, msg

        else:
            msg = u"expected `{0}` to be greater than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj >= dest, msg

        return True

    @assertionmethod
    def lower_than(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be lower than `{1}`".format(
                self.obj, dest)

            assert not self.obj < dest, msg

        else:
            msg = u"expected `{0}` to be lower than `{1}`".format(
                self.obj, dest)
            assert self.obj < dest, msg

        return True

    @assertionmethod
    def lower_than_or_equal_to(self, dest):
        if self.negative:
            msg = u"expected `{0}` to not be lower than or equal to `{1}`".format(
                self.obj, dest)

            assert not self.obj <= dest, msg

        else:
            msg = u"expected `{0}` to be lower than or equal to `{1}`".format(
                self.obj, dest)
            assert self.obj <= dest, msg

        return True

    @assertionmethod
    def below(self, num):
        if self.negative:
            msg = u"{0} should not be below {1}".format(self.obj, num)
            assert not self.obj < num, msg
        else:
            msg = u"{0} should be below {1}".format(self.obj, num)
            assert self.obj < num, msg

        return True

    @assertionmethod
    def above(self, num):
        if self.negative:
            msg = u"{0} should not be above {1}".format(self.obj, num)
            assert not self.obj > num, msg
        else:
            msg = u"{0} should be above {1}".format(self.obj, num)
            assert self.obj > num, msg
        return True

    @assertionmethod
    def length_of(self, num):
        if self.negative:
            return self._that.len_is_not(num)

        return self._that.len_is(num)

    @assertionmethod
    def called_with(self, *args, **kw):
        self._callable_args = args
        self._callable_kw = kw
        return self

    called = builtins.property(called_with)

    @assertionmethod
    def throw(self, *args, **kw):
        _that = AssertionHelper(self.obj,
                     with_args=self._callable_args,
                     and_kwargs=self._callable_kw)

        if self.negative:
            msg = (u"{0} called with args {1} and kwargs {2} should "
                   "not raise {3} but raised {4}")

            exc = args and args[0] or Exception
            try:
                self.obj(*self._callable_args, **self._callable_kw)
                return True
            except Exception, e:
                err = msg.format(
                    self.obj,
                    self._that._callable_args,
                    self._that._callable_kw,
                    exc,
                    e,
                )
                raise AssertionError(err)

        return _that.raises(*args, **kw)