Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/27.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update QuestionComputed and QuestionConstant to respect existing answers if provided in the context, preventing unnecessary recomputations when overrides are intended. @erral
16 changes: 12 additions & 4 deletions src/tui_forms/form/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ def _render_variable(
self, env: Environment, answers: dict[str, Any], value: Any, root_key: str = ""
) -> Any:
key = self.key
current_value = (answers.get(root_key, {}) if root_key else answers).get(
key, _NOVALUE
)
current_answers = answers.get(root_key, {}) if root_key else answers
current_value = current_answers.get(key, _NOVALUE)
if current_value is _NOVALUE:
value = template.render_variable(env, value, answers)
value = template.render_variable(
env, value, current_answers, root_key=root_key
)
else:
value = current_value
return value
Expand All @@ -90,6 +91,10 @@ class QuestionComputed(QuestionHidden):
def default_value(
self, env: Environment, answers: dict[str, Any], root_key: str = ""
) -> Any:
current_answers = answers.get(root_key, {}) if root_key else answers
if (current_value := current_answers.get(self.key, _NOVALUE)) is not _NOVALUE:
return current_value

val = (
self.default["default"] if isinstance(self.default, dict) else self.default
)
Expand All @@ -115,6 +120,9 @@ def default_value(
self, env: Environment, answers: dict[str, Any], root_key: str = ""
) -> Any:
"""Return the raw constant value without rendering."""
current_answers = answers.get(root_key, {}) if root_key else answers
if (current_value := current_answers.get(self.key, _NOVALUE)) is not _NOVALUE:
return current_value
return self.default


Expand Down
74 changes: 74 additions & 0 deletions tests/form/test_question_overrides.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from jinja2 import Environment
from tui_forms.form.question import QuestionComputed
from tui_forms.form.question import QuestionConstant


def test_question_computed_respects_existing_answer():
"""Verify that QuestionComputed uses an existing answer if provided."""
env = Environment(autoescape=True)
q = QuestionComputed(
key="test_key",
type="string",
title="Test",
description="",
default="computed-{{ base }}",
)
answers = {"base": "value", "test_key": "user-override"}
# Should use 'user-override' instead of computing 'computed-value'
assert q.default_value(env, answers) == "user-override"


def test_question_computed_computes_when_missing():
"""Verify that QuestionComputed computes the value when answer is missing."""
env = Environment(autoescape=True)
q = QuestionComputed(
key="test_key",
type="string",
title="Test",
description="",
default="computed-{{ base }}",
)
answers = {"base": "value"}
assert q.default_value(env, answers) == "computed-value"


def test_question_constant_respects_existing_answer():
"""Verify that QuestionConstant uses an existing answer if provided."""
env = Environment(autoescape=True)
q = QuestionConstant(
key="test_key",
type="string",
title="Test",
description="",
default="constant-value",
)
answers = {"test_key": "user-override"}
assert q.default_value(env, answers) == "user-override"


def test_question_constant_uses_default_when_missing():
"""Verify that QuestionConstant uses the default when answer is missing."""
env = Environment(autoescape=True)
q = QuestionConstant(
key="test_key",
type="string",
title="Test",
description="",
default="constant-value",
)
answers = {}
assert q.default_value(env, answers) == "constant-value"


def test_question_computed_with_root_key():
"""Verify QuestionComputed works with root_key nesting."""
env = Environment(autoescape=True)
q = QuestionComputed(
key="test_key",
type="string",
title="Test",
description="",
default="computed-{{ base }}",
)
answers = {"myroot": {"base": "value", "test_key": "user-override"}}
assert q.default_value(env, answers, root_key="myroot") == "user-override"
Loading