Skip to content

Commit 47eb581

Browse files
committed
Validator can now raise exceptions
1 parent 48b4246 commit 47eb581

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

optmanage/option.py

+28-7
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,24 @@
3838

3939
class Validator(Protocol[ValueT_contra]):
4040
"""
41-
Structura type for an option validator.
41+
Structural type for an option validator.
42+
There are two ways to signal that a value is invalid:
43+
44+
- returning :obj:`False`
45+
- raising any :class:`Exception`
46+
47+
There are two ways to signal that a value is valid:
48+
49+
- returning :obj:`True` (as opposed to :obj:`False`)
50+
- returning :obj:`None` (as opposed to raising an exception)
51+
52+
In the context of option validation, a :obj:`ValueError` will be raised
53+
if validation fails: if the validator raised an exception, the
54+
:obj:`ValueError` is re-raised from it.
55+
4256
"""
4357

44-
def __call__(self, value: ValueT_contra, /) -> bool:
58+
def __call__(self, value: ValueT_contra, /) -> bool|None:
4559
...
4660

4761

@@ -84,9 +98,7 @@ def __new__(
8498
8599
:param ty: The type of the option.
86100
:param default: The default value for the option.
87-
:param validator: A callable that takes a value and returns whether
88-
it is valid for this option. If not specified,
89-
defaults to :obj:`None` (no validation)
101+
:param validator: An optional validator function, see :class:`Validator`
90102
91103
:meta public:
92104
"""
@@ -151,16 +163,25 @@ def validate(self, value: ValueT) -> None:
151163
152164
- Checks that the value has the correct type.
153165
- If a validator is specified, checks that the value is valid.
166+
167+
If the value is not valid, :obj:`ValueError` is raised.
154168
"""
155169
validate(value, self.__type)
156170
if (validator := self.__validator) is not None:
157-
if not validator(value):
171+
validator_res: bool|None
172+
validator_err: Exception|None = None
173+
try:
174+
validator_res = validator(value)
175+
except Exception as e:
176+
validator_res = False
177+
validator_err = e
178+
if validator_res is False:
158179
name_str = (
159180
f" {self.__name!r}" if hasattr(self, "__name") else ""
160181
)
161182
raise ValueError(
162183
f"Invalid value for option{name_str}: " f"{value!r}."
163-
)
184+
) from validator_err
164185

165186
def reset(self, instance: OptionManager) -> ValueT:
166187
"""

0 commit comments

Comments
 (0)