Improve error for in_(a_string) with a non-string value (#383)

* Improve error for in_(a_string) with a non-string value

* Tighten exception handling and test description

* Improve changelog for Hynek

* Final changelog edit
This commit is contained in:
Zac Hatfield-Dodds 2018-05-25 18:32:13 +10:00 committed by Hynek Schlawack
parent 8274c9fdbc
commit a3dbdfc687
3 changed files with 21 additions and 1 deletions

View File

@ -0,0 +1,2 @@
``attr.validators.in_()`` now raises a ``ValueError`` with a useful message even if the options are a string and the value is not a string.
This previously raised a ``TypeError``, like ``1 in "abc"``.

View File

@ -135,7 +135,12 @@ class _InValidator(object):
options = attrib()
def __call__(self, inst, attr, value):
if value not in self.options:
try:
in_options = value in self.options
except TypeError as e: # e.g. `1 in "abc"`
in_options = False
if not in_options:
raise ValueError(
"'{name}' must be in {options!r} (got {value!r})"
.format(name=attr.name, options=self.options, value=value)

View File

@ -243,6 +243,19 @@ class TestIn_(object):
"'test' must be in [1, 2, 3] (got None)",
) == e.value.args
def test_fail_with_string(self):
"""
Raise ValueError if the value is outside our options when the
options are specified as a string and the value is not a string.
"""
v = in_("abc")
a = simple_attr("test")
with pytest.raises(ValueError) as e:
v(None, a, None)
assert (
"'test' must be in 'abc' (got None)",
) == e.value.args
def test_repr(self):
"""
Returned validator has a useful `__repr__`.