Skip to content

Commit 4c75e63

Browse files
committed
fix: raise Invalid for non-string input in Replace validator
Replace.__call__ passed non-string values straight to re.Pattern.sub(), which raises an unhandled TypeError. Wrap it and raise MatchInvalid (honouring a custom msg), matching how Match reports the same case.
1 parent 44593ce commit 4c75e63

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

voluptuous/tests/tests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,3 +2375,16 @@ def test_complex_required_keys_with_specific_value_validation():
23752375
error_msg = str(exc_info.value)
23762376
assert "required" not in error_msg.lower() # No "required field missing" error
23772377
assert "value must be at most 100" in error_msg # Range validation error
2378+
2379+
2380+
def test_replace_non_string_input():
2381+
"""Verify that Replace raises Invalid for non-string input."""
2382+
replace = Replace('hello', 'goodbye')
2383+
assert replace('hello world') == 'goodbye world'
2384+
for value in (42, None, ['hello']):
2385+
with pytest.raises(Invalid, match='expected string or buffer'):
2386+
replace(value)
2387+
2388+
replace2 = Replace('x', 'y', msg='must be a string')
2389+
with pytest.raises(Invalid, match='must be a string'):
2390+
replace2(123)

voluptuous/validators.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,10 @@ def __init__(
469469
self.msg = msg
470470

471471
def __call__(self, v):
472-
return self.pattern.sub(self.substitution, v)
472+
try:
473+
return self.pattern.sub(self.substitution, v)
474+
except TypeError:
475+
raise MatchInvalid(self.msg or 'expected string or buffer')
473476

474477
def __repr__(self):
475478
return 'Replace(%r, %r, msg=%r)' % (

0 commit comments

Comments
 (0)