Skip to content

Commit

Permalink
[ASP-4228] Avoid name conflicts on BooleanLis (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
fschuch authored Dec 8, 2023
2 parents a50ddfe + 67ddfdd commit e87dc39
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
1 change: 1 addition & 0 deletions jobbergate-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This file keeps track of all notable changes to jobbergate-cli
## Unreleased

- Fixed the setting `CACHE_DIR` to expand the user home directory, allowing more flexibility on the path [ASP-4053]
- Fixed the question `BooleanList` to allow subquestion to have the same name [ASP-4228]

## 4.2.0a3 -- 2023-11-30

Expand Down
27 changes: 9 additions & 18 deletions jobbergate-cli/jobbergate_cli/subapps/applications/questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from copy import deepcopy
from functools import partial
from itertools import chain
from typing import Any, Callable, Dict, Optional, Type, TypeVar, cast

import inquirer
Expand Down Expand Up @@ -243,8 +244,8 @@ def __init__(
:param whentrue: List of questions to show if user answers 'false' on this question
"""
super().__init__(variablename, message, **kwargs)
self.whentrue_child_map = {c.variablename: c for c in (whentrue if whentrue is not None else [])}
self.whenfalse_child_map = {c.variablename: c for c in (whenfalse if whenfalse is not None else [])}
self.whentrue_child = whentrue or list()
self.whenfalse_child = whenfalse or list()

def ignore_child(self, child: QuestionBase, answers: Dict[str, Any]) -> bool:
"""
Expand All @@ -258,20 +259,11 @@ def ignore_child(self, child: QuestionBase, answers: Dict[str, Any]) -> bool:
my_answer is not None,
"Questions were asked out of order. Please check your Application for consistency",
)
if my_answer is True:
if child.variablename in self.whentrue_child_map:
return False
elif child.variablename in self.whenfalse_child_map:
return True
else:
return False # This child wasn't registered. This should not happen. But, don't ignore to be safe.
else:
if child.variablename in self.whentrue_child_map:
return True
elif child.variablename in self.whenfalse_child_map:
return False
else:
return False # This child wasn't registered. This should not happen. But, don't ignore to be safe.
if (my_answer is True and child in self.whenfalse_child) or (
my_answer is False and child in self.whentrue_child
):
return True
return False

def make_ignore_partial(self, child: QuestionBase) -> Callable[[Dict[str, Any]], bool]:
"""
Expand All @@ -289,8 +281,7 @@ def make_prompts(self, **override_kwargs):
"""

retval = super().make_prompts(**override_kwargs)
all_children = [*self.whentrue_child_map.values(), *self.whenfalse_child_map.values()]
for child in all_children:
for child in chain(self.whentrue_child, self.whenfalse_child):
retval.extend(child.make_prompts(ignore=self.make_ignore_partial(child)))
return retval

Expand Down
21 changes: 21 additions & 0 deletions jobbergate-cli/tests/subapps/applications/test_questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,27 @@ def test_BooleanList__success(dummy_render_class, mocker):
)


@pytest.mark.parametrize("parent_answer", [True, False])
def test_BooleanList__same_variable_name(dummy_render_class, parent_answer):
"""Assert that BooleanList works when multiple children have the same variable name."""
variablename = "child"
question_a = Text(variablename, message="Question A")
question_b = Text(variablename, message="Question B")

question = BooleanList("parent", message="Parent", whentrue=[question_a], whenfalse=[question_b], default=False)
prompts = question.make_prompts()

expected_answers = {"parent": parent_answer, variablename: "any-answer"}
dummy_render_class.prepared_input = expected_answers

actual_answers = prompt(prompts, answers=expected_answers, render=dummy_render_class())
assert actual_answers == expected_answers

expected_ignored_questions = [False, not parent_answer, parent_answer]
actual_ignored_questions = [q.ignore for q in prompts]
assert actual_ignored_questions == expected_ignored_questions


def test_gather_config_values__basic(dummy_render_class, mocker):
variablename1 = "foo"
question1 = Text(variablename1, message="gimme the foo!")
Expand Down

0 comments on commit e87dc39

Please sign in to comment.