fix: validate default answers #2145
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I've fixed a bug that prevented default answers from being validated against the
validatorexpression.Before, using a default answer through
--defaultsdid not apply validation. Now, theQuestion.get_default()method not only casts the answer but also validates it. Initially, this change caused an infinite recursion becauseQuestion._formatted_choicesused the default answer to pre-select choices for multi-select questions andQuestion.parse_answer()usesQuestion._formatted_choicesto retain the order of choice items in a multi-select question answer, so there was a cycle. To avoid this cycle, I've moved the snippet for pre-selecting choices toQuestion.get_questionary_structure(), as it's only important to add this information for prompting. AsQuestion._formatted_choicesis a cached property, I've decided to deep-copy this list ofChoiceobjects to avoid mutating them, risking potentially hard-to-debug side effects.As it turned out, one test case I added to
tests/test_copy.py::test_validate_default_valuein #1770 was silently incorrect and would have caught this bug already back then. 🫣 This is fixed now as well.To avoid duplicate error logic and message code,
Question.validate_answer()now raises aValueErrorwhen validation fails instead of returning the error message string. This way, we raise the same exception wherever answer validation fails.Hands down, this isn't pretty, but it works for now.
Fixes #2143.