From 704e0fd7d565117b7707f82119e6096b51c65230 Mon Sep 17 00:00:00 2001 From: rohan Date: Wed, 4 Mar 2026 15:32:10 +0530 Subject: [PATCH] fix: guard TypeDef.check_value() against constraint exceptions Wrap constraint predicate calls in try/except so user-supplied constraints that raise (e.g., ZeroDivisionError, TypeError) return False instead of propagating uncaught through verification paths. Also guard ParameterDef.check_value() bounds comparison. Closes #86 --- packages/gds-framework/gds/parameters.py | 7 ++++-- packages/gds-framework/gds/types/typedef.py | 7 +++++- packages/gds-framework/tests/test_types.py | 28 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/gds-framework/gds/parameters.py b/packages/gds-framework/gds/parameters.py index 8899fba..ca4ba34 100644 --- a/packages/gds-framework/gds/parameters.py +++ b/packages/gds-framework/gds/parameters.py @@ -37,8 +37,11 @@ def check_value(self, value: Any) -> bool: if not self.typedef.check_value(value): return False if self.bounds is not None: - low, high = self.bounds - if not (low <= value <= high): + try: + low, high = self.bounds + if not (low <= value <= high): + return False + except Exception: return False return True diff --git a/packages/gds-framework/gds/types/typedef.py b/packages/gds-framework/gds/types/typedef.py index 78e56a1..dae0336 100644 --- a/packages/gds-framework/gds/types/typedef.py +++ b/packages/gds-framework/gds/types/typedef.py @@ -32,7 +32,12 @@ def check_value(self, value: Any) -> bool: """Check if a value satisfies this type definition.""" if not isinstance(value, self.python_type): return False - return self.constraint is None or self.constraint(value) + if self.constraint is None: + return True + try: + return bool(self.constraint(value)) + except Exception: + return False # ── Built-in types ────────────────────────────────────────── diff --git a/packages/gds-framework/tests/test_types.py b/packages/gds-framework/tests/test_types.py index 8e914a2..d54cf61 100644 --- a/packages/gds-framework/tests/test_types.py +++ b/packages/gds-framework/tests/test_types.py @@ -180,6 +180,34 @@ def test_frozen(self): with pytest.raises(ValidationError): t.name = "Other" # type: ignore[misc] + def test_constraint_exception_returns_false(self): + """Constraint that raises should return False, not propagate.""" + t = TypeDef( + name="Bad", + python_type=float, + constraint=lambda x: 1 / 0, # ZeroDivisionError + ) + assert t.check_value(1.0) is False + + def test_constraint_type_error_returns_false(self): + """Constraint that raises TypeError should return False.""" + t = TypeDef( + name="Bad", + python_type=float, + constraint=lambda x: x > "not a number", # TypeError + ) + assert t.check_value(1.0) is False + + def test_constraint_returns_truthy_non_bool(self): + """Constraint returning truthy non-bool value should work.""" + t = TypeDef( + name="Truthy", + python_type=str, + constraint=lambda x: x, # non-empty string is truthy + ) + assert t.check_value("hello") is True + assert t.check_value("") is False + # ── Built-in types ───────────────────────────────────────────