A function as on_fail
Lessons 9 to 11 picked from a fixed list. When none of them fits, on_fail takes a function, and the function decides what the Guard hands back.
def to_store_credit(value, fail_result):
return value.replace("refund", "store credit")
desk = Guard().use(NoRefunds(on_fail=to_store_credit))
outcome = desk.validate("We can refund order 8821 in full.")
print(outcome.validation_passed)
print(outcome.validated_output)The signature is fixed: the value that failed, then the FailResult the validator returned. Whatever the function returns becomes validated_output. The validator itself did not change and still has no fix_value; the repair moved out to the place that knows what this particular desk wants.
Reading the failure
The second argument is the object from lesson 7, so the function can use anything the validator recorded.
def explain(value, fail_result):
return f"[held back: {fail_result.error_message}]"
desk = Guard().use(NoRefunds(on_fail=explain))
print(desk.validate("We can refund order 8821 in full.").validated_output)
print(desk.validate("Order 8821 ships today.").validated_output)It counts as resolved
A custom handler and a noop both hand a value back, and the Guard treats them completely differently.
quiet = Guard().use(NoRefunds(on_fail="noop"))
handled = Guard().use(NoRefunds(on_fail=explain))
text = "We can refund order 8821 in full."
print("noop ", quiet.validate(text).validation_passed, quiet.history.last.status)
print("function", handled.validate(text).validation_passed, handled.history.last.status)noop leaves the failure unresolved, so the call stays a failure and validation_passed is False. A function is treated as a repair, like fix, so the call passes. The validator failed in both runs, and history.last.validator_logs says so in both runs.
Inside Guardrails the function shows up as the action named custom, which is the entry in lesson 9's enum you never set by hand.
- Return
Nonefrom the function and see whatvalidated_outputbecomes. - Raise an exception inside the function instead of returning. That is a third way to get
exceptionbehaviour, with your own message. - Use
fail_result.error_spansin the function to cut only the offending characters out of the reply.
You understood something today that you didn't yesterday.