Skip to content

Commit

Permalink
Improve the error message informing the type that it got it
Browse files Browse the repository at this point in the history
  • Loading branch information
williamjamir committed May 30, 2019
1 parent 45adbb9 commit 58ddbfc
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ Validators
>>> C("not a callable")
Traceback (most recent call last):
...
TypeError: 'x' must be callable
TypeError: 'x' must be callable (got 'not a callable' that is a <class 'str'>).


.. autofunction:: attr.validators.deep_iterable
Expand Down
10 changes: 8 additions & 2 deletions src/attr/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,12 @@ def __call__(self, inst, attr, value):
We use a callable class to be able to change the ``__repr__``.
"""
if not callable(value):
raise TypeError("'{name}' must be callable".format(name=attr.name))
raise TypeError(
"'{name}' must be callable (got {value!r} that is a "
"{actual!r}).".format(
name=attr.name, value=value, actual=value.__class__
)
)

def __repr__(self):
return "<is_callable validator>"
Expand All @@ -200,7 +205,8 @@ def is_callable():
.. versionadded:: 19.1.0
:raises TypeError: With a human readable error message containing the
attribute (of type :class:`attr.Attribute`) name.
attribute (of type :class:`attr.Attribute`) name, and the value it
got.
"""
return _IsCallableValidator()

Expand Down
15 changes: 12 additions & 3 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,10 @@ def test_noncallable_validators(
with pytest.raises(TypeError) as e:
deep_iterable(member_validator, iterable_validator)

e.match(r"\w* must be callable")
assert (
"must be callable (got 42 that is a <type 'int'>)."
in e.value.args[0]
)

def test_fail_invalid_member(self):
"""
Expand Down Expand Up @@ -466,7 +469,10 @@ def test_noncallable_validators(
with pytest.raises(TypeError) as e:
deep_mapping(key_validator, value_validator, mapping_validator)

e.match(r"\w* must be callable")
assert (
"must be callable (got 42 that is a <type 'int'>)."
in e.value.args[0]
)

def test_fail_invalid_mapping(self):
"""
Expand Down Expand Up @@ -550,7 +556,10 @@ def test_fail(self):
with pytest.raises(TypeError) as e:
v(None, a, None)

e.match("'test' must be callable")
assert (
"must be callable (got None that is a <type 'NoneType'>)."
in e.value.args[0]
)

def test_repr(self):
"""
Expand Down

0 comments on commit 58ddbfc

Please sign in to comment.