From 944917c76287fd178353ea4ee76e014fd21a40d7 Mon Sep 17 00:00:00 2001 From: frmdstryr Date: Fri, 1 May 2026 08:42:16 -0400 Subject: [PATCH] Handle errors in range_handler comparisons --- atom/src/validatebehavior.cpp | 18 ++++++++++++++++-- tests/test_validators.py | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/atom/src/validatebehavior.cpp b/atom/src/validatebehavior.cpp index 8c3584b2..e6da684b 100644 --- a/atom/src/validatebehavior.cpp +++ b/atom/src/validatebehavior.cpp @@ -881,23 +881,37 @@ range_handler( Member* member, CAtom* atom, PyObject* oldvalue, PyObject* newval PyObject* high = PyTuple_GET_ITEM( member->validate_context, 1 ); if( low != Py_None ) { - if( PyObject_RichCompareBool( low , newvalue, Py_GT ) ) + switch (PyObject_RichCompareBool( low , newvalue, Py_GT )) + { + case 0: + break; + case 1: return PyErr_Format( PyExc_ValueError, "range value for '%s' of '%s' too small", PyUnicode_AsUTF8( member->name ), Py_TYPE( pyobject_cast( atom ) )->tp_name ); + default: + return 0; + } } if( high != Py_None ) { - if( PyObject_RichCompareBool( high , newvalue, Py_LT ) ) + switch( PyObject_RichCompareBool( high , newvalue, Py_LT ) ) + { + case 0: + break; + case 1: return PyErr_Format( PyExc_ValueError, "range value for '%s' of '%s' too large", PyUnicode_AsUTF8( member->name ), Py_TYPE( pyobject_cast( atom ) )->tp_name ); + default: + return 0; + } } return cppy::incref( newvalue ); } diff --git a/tests/test_validators.py b/tests/test_validators.py index c178c81d..53d37ca2 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -434,3 +434,28 @@ def test_custom_validate(mode, factory): with pytest.raises(TypeError) as excinfo: type(v).v.set_validate_mode(getattr(Validate, mode), 1) assert "str" in excinfo.exconly() + + +def test_validate_range_error(): + class CustomInt(int): + def __gt__(self, other): + raise TypeError("Cannot be compared") + + def __lt__(self, other): + raise TypeError("Cannot be compared") + + class Obj(Atom): + x = Range(low=0) + y = Range(high=10) + + o = Obj() + o.x = 1 + o.y = 9 + with pytest.raises(ValueError): + o.x = -1 + with pytest.raises(ValueError): + o.y = 11 + with pytest.raises(TypeError): + o.x = CustomInt(-1) + with pytest.raises(TypeError): + o.y = CustomInt(11)