Example #1
0
    def test_no_cmp(self):
        """
        If `no_cmp` is set, ignore that attribute.
        """
        C = make_class("C", {"a": attr(no_cmp=True), "b": attr()})

        assert C(1, 2) == C(2, 2)
Example #2
0
    def test_hash(self):
        """
        If `hash` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(hash=False), "b": attr()})

        assert hash(C(1, 2)) == hash(C(2, 2))
Example #3
0
    def test_repr(self):
        """
        If `repr` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(repr=False), "b": attr()})

        assert "C(b=2)" == repr(C(1, 2))
Example #4
0
    def test_cmp(self):
        """
        If `cmp` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(cmp=False), "b": attr()})

        assert C(1, 2) == C(2, 2)
Example #5
0
    def test_no_repr(self):
        """
        If `no_repr` is set, ignore that attribute.
        """
        C = make_class("C", {"a": attr(no_repr=True), "b": attr()})

        assert "C(b=2)" == repr(C(1, 2))
Example #6
0
    def test_no_hash(self):
        """
        If `no_hash` is set, ignore that attribute.
        """
        C = make_class("C", {"a": attr(no_hash=True), "b": attr()})

        assert hash(C(1, 2)) == hash(C(2, 2))
Example #7
0
    def test_repr(self, slots):
        """
        If `repr` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(repr=False), "b": attr()}, slots=slots)

        assert "C(b=2)" == repr(C(1, 2))
Example #8
0
    def test_hash(self, slots):
        """
        If `hash` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(hash=False), "b": attr()}, slots=slots)

        assert hash(C(1, 2)) == hash(C(2, 2))
Example #9
0
 def test_success(self):
     """
     If the validator suceeds, nothing gets raised.
     """
     C = make_class("C", {"x": attr(validator=lambda *a: None),
                          "y": attr()})
     validate(C(1, 2))
Example #10
0
    def test_cmp(self, slots):
        """
        If `cmp` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(cmp=False), "b": attr()}, slots=slots)

        assert C(1, 2) == C(2, 2)
Example #11
0
    def test_hash_attribute(self, slots):
        """
        If `hash` is False on an attribute, ignore that attribute.
        """
        C = make_class("C", {"a": attr(hash=False), "b": attr()},
                       slots=slots, hash=True)

        assert hash(C(1, 2)) == hash(C(2, 2))
Example #12
0
 def test_convert(self):
     """
     Return value of convert is used as the attribute's value.
     """
     C = make_class("C", {"x": attr(convert=lambda v: v + 1), "y": attr()})
     c = C(1, 2)
     assert c.x == 2
     assert c.y == 2
Example #13
0
    def test_multiple_empty(self):
        """
        Empty list/tuple for validator is the same as None.
        """
        C1 = make_class("C", {"x": attr(validator=[])})
        C2 = make_class("C", {"x": attr(validator=None)})

        assert inspect.getsource(C1.__init__) == inspect.getsource(C2.__init__)
Example #14
0
    def test_multiple_empty(self):
        """
        Empty list/tuple for validator is the same as None.
        """
        C1 = make_class("C", {"x": attr(validator=[])})
        C2 = make_class("C", {"x": attr(validator=None)})

        assert inspect.getsource(C1.__init__) == inspect.getsource(C2.__init__)
Example #15
0
 def test_no_init_order(self):
     """
     If an attribute is `init=False`, it's legal to come after a mandatory
     attribute.
     """
     make_class("C", {
         "a": attr(default=Factory(list)),
         "b": attr(init=False),
     })
 def test_no_init_order(self, slots, frozen):
     """
     If an attribute is `init=False`, it's legal to come after a mandatory
     attribute.
     """
     make_class("C", {
         "a": attr(default=Factory(list)),
         "b": attr(init=False),
     }, slots=slots, frozen=frozen)
Example #17
0
 def test_convert(self):
     """
     Return value of convert is used as the attribute's value.
     """
     C = make_class("C", {"x": attr(convert=lambda v: v + 1),
                          "y": attr()})
     c = C(1, 2)
     assert c.x == 2
     assert c.y == 2
Example #18
0
    def test_no_init(self):
        """
        If `no_init` is set, ignore that attribute.
        """
        C = make_class("C", {"a": attr(no_init=True), "b": attr()})
        with pytest.raises(TypeError) as e:
            C(a=1, b=2)

        msg = e.value if PY26 else e.value.args[0]
        assert "__init__() got an unexpected keyword argument 'a'" == msg
Example #19
0
    def test_init(self):
        """
        If `init` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(init=False), "b": attr()})
        with pytest.raises(TypeError) as e:
            C(a=1, b=2)

        msg = e.value if PY26 else e.value.args[0]
        assert "__init__() got an unexpected keyword argument 'a'" == msg
Example #20
0
    def test_init(self, slots):
        """
        If `init` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(init=False), "b": attr()}, slots=slots)
        with pytest.raises(TypeError) as e:
            C(a=1, b=2)

        assert ("__init__() got an unexpected keyword argument 'a'" ==
                e.value.args[0])
Example #21
0
 def test_convert_property(self, val, init):
     """
     Property tests for attributes with convert.
     """
     C = make_class("C", {"y": attr(),
                          "x": attr(init=init, default=val,
                                    convert=lambda v: v + 1),
                          })
     c = C(2)
     assert c.x == val + 1
     assert c.y == 2
Example #22
0
    def test_dict(self):
        """
        Passing a dict of name: _CountingAttr creates an equivalent class.
        """
        C1 = make_class("C1", {"a": attr(default=42), "b": attr(default=None)})

        @attributes
        class C2(object):
            a = attr(default=42)
            b = attr(default=None)

        assert C1.__attrs_attrs__ == C2.__attrs_attrs__
Example #23
0
 def test_convert_before_validate(self):
     """
     Validation happens after conversion.
     """
     def validator(inst, attr, val):
         raise RuntimeError("foo")
     C = make_class(
         "C",
         {"x": attr(validator=validator, convert=lambda v: 1 / 0),
          "y": attr()})
     with pytest.raises(ZeroDivisionError):
         C(1, 2)
Example #24
0
    def test_dict(self):
        """
        Passing a dict of name: _CountingAttr creates an equivalent class.
        """
        C1 = make_class("C1", {"a": attr(default=42), "b": attr(default=None)})

        @attributes
        class C2(object):
            a = attr(default=42)
            b = attr(default=None)

        assert C1.__attrs_attrs__ == C2.__attrs_attrs__
Example #25
0
    def test_init(self, slots, frozen):
        """
        If `init` is False, ignore that attribute.
        """
        C = make_class("C", {"a": attr(init=False), "b": attr()},
                       slots=slots, frozen=frozen)
        with pytest.raises(TypeError) as e:
            C(a=1, b=2)

        assert (
            "__init__() got an unexpected keyword argument 'a'" ==
            e.value.args[0]
        )
Example #26
0
    def test_multiple_validators(self):
        """
        If a list is passed as a validator, all of its items are treated as one
        and must pass.
        """
        def v1(_, __, value):
            if value == 23:
                raise TypeError("omg")

        def v2(_, __, value):
            if value == 42:
                raise ValueError("omg")

        C = make_class("C", {"x": attr(validator=[v1, v2])})

        validate(C(1))

        with pytest.raises(TypeError) as e:
            C(23)

        assert "omg" == e.value.args[0]

        with pytest.raises(ValueError) as e:
            C(42)

        assert "omg" == e.value.args[0]
Example #27
0
    def test_returns_Attr(self):
        """
        Returns an instance of _CountingAttr.
        """
        a = attr()

        assert isinstance(a, _CountingAttr)
Example #28
0
    def _test_validator_none_is_empty_tuple(self):
        """
        If validator is None, it's transformed into an empty tuple.
        """
        a = attr(validator=None)

        assert () == a._validator
Example #29
0
    def test_returns_Attr(self):
        """
        Returns an instance of _CountingAttr.
        """
        a = attr()

        assert isinstance(a, _CountingAttr)
Example #30
0
    def _test_validator_none_is_empty_tuple(self):
        """
        If validator is None, it's transformed into an empty tuple.
        """
        a = attr(validator=None)

        assert () == a._validator
Example #31
0
    def test_multiple_validators(self):
        """
        If a list is passed as a validator, all of its items are treated as one
        and must pass.
        """
        def v1(_, __, value):
            if value == 23:
                raise TypeError("omg")

        def v2(_, __, value):
            if value == 42:
                raise ValueError("omg")

        C = make_class("C", {"x": attr(validator=[v1, v2])})

        validate(C(1))

        with pytest.raises(TypeError) as e:
            C(23)

        assert "omg" == e.value.args[0]

        with pytest.raises(ValueError) as e:
            C(42)

        assert "omg" == e.value.args[0]
Example #32
0
    def test_no_init_default(self):
        """
        If `init` is False but a Factory is specified, don't allow passing that
        argument but initialize it anyway.
        """
        C = make_class("C", {
            "_a": attr(init=False, default=42),
            "_b": attr(init=False, default=Factory(list)),
            "c": attr()
        })
        with pytest.raises(TypeError):
            C(a=1, c=2)
        with pytest.raises(TypeError):
            C(b=1, c=2)

        i = C(23)
        assert (42, [], 23) == (i._a, i._b, i.c)
    def test_no_init_default(self, slots, frozen):
        """
        If `init` is False but a Factory is specified, don't allow passing that
        argument but initialize it anyway.
        """
        C = make_class("C", {
            "_a": attr(init=False, default=42),
            "_b": attr(init=False, default=Factory(list)),
            "c": attr()
        }, slots=slots, frozen=frozen)
        with pytest.raises(TypeError):
            C(a=1, c=2)
        with pytest.raises(TypeError):
            C(b=1, c=2)

        i = C(23)
        assert (42, [], 23) == (i._a, i._b, i.c)
Example #34
0
 def test_validator_others(self):
     """
     Does not interfere when setting non-attrs attributes.
     """
     C = make_class("C", {"a": attr("a", validator=instance_of(int))})
     i = C(1)
     i.b = "foo"
     assert 1 == i.a
     assert "foo" == i.b
Example #35
0
 def test_validator_others(self):
     """
     Does not interfere when setting non-attrs attributes.
     """
     C = make_class("C", {"a": attr("a", validator=instance_of(int))})
     i = C(1)
     i.b = "foo"
     assert 1 == i.a
     assert "foo" == i.b
Example #36
0
    def test_these(self):
        """
        If these is passed, use it and ignore body.
        """
        class C(object):
            y = attr()

        _transform_attrs(C, {"x": attr()})
        assert (simple_attr("x"), ) == C.__attrs_attrs__
        assert isinstance(C.y, _CountingAttr)
Example #37
0
    def test_validator_decorator_single(self):
        """
        """
        a = attr()

        @a.validator
        def v():
            pass

        assert _AndValidator((v, )) == a._validator
Example #38
0
    def test_default_decorator_already_set(self):
        """
        Raise DefaultAlreadySetError if the decorator is used after a default
        has been set.
        """
        a = attr(default=42)

        with pytest.raises(DefaultAlreadySetError):
            @a.default
            def f(self):
                pass
Example #39
0
    def test_factory_takes_self(self):
        """
        If takes_self on factories is True, self is passed.
        """
        C = make_class("C", {"x": attr(default=Factory(
            (lambda self: self), takes_self=True
        ))})

        i = C()

        assert i is i.x
Example #40
0
    def test_these(self):
        """
        If these is passed, use it and ignore body.
        """
        class C(object):
            y = attr()

        _transform_attrs(C, {"x": attr()})
        assert (
            simple_attr("x"),
        ) == C.__attrs_attrs__
        assert isinstance(C.y, _CountingAttr)
Example #41
0
    def test_default_decorator_sets(self):
        """
        Decorator wraps the method in a Factory with pass_self=True and sets
        the default.
        """
        a = attr()

        @a.default
        def f(self):
            pass

        assert Factory(f, True) == a._default
Example #42
0
    def test_validator_decorator_single(self):
        """
        If _CountingAttr.validator is used as a decorator and there is no
        decorator set, the decorated method is used as the validator.
        """
        a = attr()

        @a.validator
        def v():
            pass

        assert v == a._validator
Example #43
0
    def test_validators_lists_to_wrapped_tuples(self):
        """
        If a list is passed as validator, it's just converted to a tuple.
        """
        def v1(_, __):
            pass

        def v2(_, __):
            pass

        a = attr(validator=[v1, v2])

        assert _AndValidator((v1, v2,)) == a._validator
Example #44
0
    def test_hash_attribute_mirrors_cmp(self, cmp):
        """
        If `hash` is None, the hash generation mirrors `cmp`.
        """
        C = make_class("C", {"a": attr(cmp=cmp)}, cmp=True, frozen=True)

        if cmp:
            assert C(1) != C(2)
            assert hash(C(1)) != hash(C(2))
            assert hash(C(1)) == hash(C(1))
        else:
            assert C(1) == C(2)
            assert hash(C(1)) == hash(C(2))
Example #45
0
    def test_hash_attribute_mirrors_cmp(self, cmp):
        """
        If `hash` is None, the hash generation mirrors `cmp`.
        """
        C = make_class("C", {"a": attr(cmp=cmp)}, cmp=True, frozen=True)

        if cmp:
            assert C(1) != C(2)
            assert hash(C(1)) != hash(C(2))
            assert hash(C(1)) == hash(C(1))
        else:
            assert C(1) == C(2)
            assert hash(C(1)) == hash(C(2))
Example #46
0
 def test_validator_others(self, slots):
     """
     Does not interfere when setting non-attrs attributes.
     """
     C = make_class("C", {"a": attr("a", validator=instance_of(int))},
                    slots=slots)
     i = C(1)
     assert 1 == i.a
     if not slots:
         i.b = "foo"
         assert "foo" == i.b
     else:
         with pytest.raises(AttributeError):
             i.b = "foo"
Example #47
0
    def test_propagates(self):
        """
        The exception of the validator is handed through.
        """
        def raiser(_, __, value):
            if value == 42:
                raise FloatingPointError

        C = make_class("C", {"x": attr(validator=raiser)})
        i = C(1)
        i.x = 42

        with pytest.raises(FloatingPointError):
            validate(i)
Example #48
0
    def test_propagates(self):
        """
        The exception of the validator is handed through.
        """
        def raiser(_, __, value):
            if value == 42:
                raise FloatingPointError

        C = make_class("C", {"x": attr(validator=raiser)})
        i = C(1)
        i.x = 42

        with pytest.raises(FloatingPointError):
            validate(i)
Example #49
0
 def test_validator_others(self, slots):
     """
     Does not interfere when setting non-attrs attributes.
     """
     C = make_class("C", {"a": attr("a", validator=instance_of(int))},
                    slots=slots)
     i = C(1)
     assert 1 == i.a
     if not slots:
         i.b = "foo"
         assert "foo" == i.b
     else:
         with pytest.raises(AttributeError):
             i.b = "foo"
Example #50
0
    def test_validator_decorator(self, wrap):
        """
        If _CountingAttr.validator is used as a decorator and there is already
        a decorator set, the decorators are composed using `and_`.
        """
        def v(_, __):
            pass

        a = attr(validator=wrap(v))

        @a.validator
        def v2(self, _, __):
            pass

        assert _AndValidator((v, v2,)) == a._validator
Example #51
0
    def test_validator(self):
        """
        If a validator is passed, call it with the preliminary instance, the
        Attribute, and the argument.
        """
        class VException(Exception):
            pass

        def raiser(*args):
            raise VException(*args)

        C = make_class("C", {"a": attr("a", validator=raiser)})
        with pytest.raises(VException) as e:
            C(42)
        assert (C.a, 42,) == e.value.args[1:]
        assert isinstance(e.value.args[0], C)
Example #52
0
    def test_enforces_type(self):
        """
        The `hash` argument to both attrs and attrib must be None, True, or
        False.
        """
        exc_args = ("Invalid value for hash.  Must be True, False, or None.",)

        with pytest.raises(TypeError) as e:
            make_class("C", {}, hash=1),

        assert exc_args == e.value.args

        with pytest.raises(TypeError) as e:
            make_class("C", {"a": attr(hash=1)}),

        assert exc_args == e.value.args