Skip to content

Commit

Permalink
Merge pull request #1647 from Avaiga/feature/#1566-check-children-con…
Browse files Browse the repository at this point in the history
…fig-id-not-properties

Feature/#1566 - Check children config_id to make sure not overlapping the properties
  • Loading branch information
trgiangdo authored Aug 9, 2024
2 parents 4d0b874 + 5c01851 commit 3a6090e
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 1 deletion.
25 changes: 24 additions & 1 deletion taipy/core/config/checkers/_scenario_config_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,33 @@ def _check(self) -> IssueCollector:
self._check_addition_data_node_configs(scenario_config_id, scenario_config)
self._check_additional_dns_not_overlapping_tasks_dns(scenario_config_id, scenario_config)
self._check_tasks_in_sequences_exist_in_scenario_tasks(scenario_config_id, scenario_config)
self._check_if_children_config_id_is_overlapping_with_properties(scenario_config_id, scenario_config)
self._check_comparators(scenario_config_id, scenario_config)

return self._collector

def _check_if_children_config_id_is_overlapping_with_properties(
self, scenario_config_id: str, scenario_config: ScenarioConfig
):
if scenario_config.tasks:
for task in scenario_config.tasks:
if isinstance(task, TaskConfig) and task.id in scenario_config.properties:
self._error(
TaskConfig._ID_KEY,
task.id,
f"The id of the TaskConfig `{task.id}` is overlapping with the "
f"property `{task.id}` of ScenarioConfig `{scenario_config_id}`.",
)
if scenario_config.data_nodes:
for data_node in scenario_config.data_nodes:
if isinstance(data_node, DataNodeConfig) and data_node.id in scenario_config.properties:
self._error(
DataNodeConfig._ID_KEY,
data_node.id,
f"The id of the DataNodeConfig `{data_node.id}` is overlapping with the "
f"property `{data_node.id}` of ScenarioConfig `{scenario_config_id}`.",
)

def _check_task_configs(self, scenario_config_id: str, scenario_config: ScenarioConfig):
self._check_children(
ScenarioConfig,
Expand Down Expand Up @@ -78,7 +101,7 @@ def _check_comparators(self, scenario_config_id: str, scenario_config: ScenarioC
f"{ScenarioConfig._COMPARATOR_KEY} field of ScenarioConfig"
f" `{scenario_config_id}` must be populated with a dictionary value.",
)
else:
elif scenario_config.comparators is not None:
for data_node_id, comparator in scenario_config.comparators.items():
if data_node_id not in Config.data_nodes:
self._error(
Expand Down
11 changes: 11 additions & 0 deletions taipy/core/config/checkers/_task_config_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,19 @@ def _check(self) -> IssueCollector:
self._check_existing_function(task_config_id, task_config)
self._check_inputs(task_config_id, task_config)
self._check_outputs(task_config_id, task_config)
self._check_if_children_config_id_is_overlapping_with_properties(task_config_id, task_config)
return self._collector

def _check_if_children_config_id_is_overlapping_with_properties(self, task_config_id: str, task_config: TaskConfig):
for data_node in task_config.input_configs + task_config.output_configs:
if isinstance(data_node, DataNodeConfig) and data_node.id in task_config.properties:
self._error(
DataNodeConfig._ID_KEY,
data_node.id,
f"The id of the DataNodeConfig `{data_node.id}` is overlapping with the "
f"property `{data_node.id}` of TaskConfig `{task_config_id}`.",
)

def _check_if_config_id_is_overlapping_with_scenario_attributes(
self, task_config_id: str, task_config: TaskConfig, scenario_attributes: List[str]
):
Expand Down
41 changes: 41 additions & 0 deletions tests/core/config/checkers/test_scenario_config_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,47 @@ def test_check_if_entity_property_key_used_is_predefined(self, caplog):
)
assert expected_error_message in caplog.text

def test_check_if_children_id_is_used_in_properties(self, caplog):
config = Config._applied_config
Config._compile_configs()
input_dn_config = DataNodeConfig("input_dn")
output_dn_config = DataNodeConfig("output_dn")
test_dn_config = DataNodeConfig("test")
task_config = TaskConfig("bar", print, [input_dn_config], [output_dn_config])
test_task_config = TaskConfig("test", print, [test_dn_config], [output_dn_config])

config._sections[ScenarioConfig.name]["new"] = copy(config._sections[ScenarioConfig.name]["default"])
config._sections[ScenarioConfig.name]["new"]._properties["test"] = "test"
config._sections[ScenarioConfig.name]["new"]._tasks = [task_config]
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 0

config._sections[ScenarioConfig.name]["new"]._tasks = [test_task_config]
with pytest.raises(SystemExit):
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 2
assert (
"The id of the TaskConfig `test` is overlapping with the property `test` of ScenarioConfig `new`."
in caplog.text
)
assert (
"The id of the DataNodeConfig `test` is overlapping with the property `test` of ScenarioConfig `new`."
in caplog.text
)

config._sections[ScenarioConfig.name]["new"]._tasks = [task_config]
config._sections[ScenarioConfig.name]["new"]._additional_data_nodes = [test_dn_config]
with pytest.raises(SystemExit):
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 1
assert (
"The id of the DataNodeConfig `test` is overlapping with the property `test` of ScenarioConfig `new`."
in caplog.text
)

def test_check_task_configs(self, caplog):
Config._collector = IssueCollector()
config = Config._applied_config
Expand Down
34 changes: 34 additions & 0 deletions tests/core/config/checkers/test_task_config_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,40 @@ def test_check_config_id(self, caplog):
assert len(Config._collector.errors) == 1
assert len(Config._collector.warnings) == 2

def test_check_if_input_output_id_is_used_in_properties(self, caplog):
config = Config._applied_config
Config._compile_configs()
input_dn_config = DataNodeConfig("input_dn")
test_dn_config = DataNodeConfig("test")

config._sections[TaskConfig.name]["new"] = copy(config._sections[TaskConfig.name]["default"])
config._sections[TaskConfig.name]["new"].function = print
config._sections[TaskConfig.name]["new"]._properties["test"] = "test"
config._sections[TaskConfig.name]["new"]._inputs = [input_dn_config]
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 0

config._sections[TaskConfig.name]["new"]._inputs = [test_dn_config]
with pytest.raises(SystemExit):
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 1
assert (
"The id of the DataNodeConfig `test` is overlapping with the property `test` of TaskConfig `new`."
in caplog.text
)

config._sections[TaskConfig.name]["new"]._outputs = [test_dn_config]
with pytest.raises(SystemExit):
Config._collector = IssueCollector()
Config.check()
assert len(Config._collector.errors) == 2
assert (
"The id of the DataNodeConfig `test` is overlapping with the property `test` of TaskConfig `new`."
in caplog.text
)

def test_check_config_id_is_different_from_all_task_properties(self, caplog):
Config._collector = IssueCollector()
config = Config._applied_config
Expand Down

0 comments on commit 3a6090e

Please sign in to comment.