Skip to content

Commit

Permalink
🎨 Make HintsProvider Injectable (#21)
Browse files Browse the repository at this point in the history
* make hintsprovider injectable

* translate error message to english
  • Loading branch information
hf-kklein committed Sep 6, 2021
1 parent 3f44a81 commit 03ef11a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 26 deletions.
6 changes: 4 additions & 2 deletions src/ahbicht/condition_node_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import asyncio
from typing import Dict, List, Tuple, Union

import inject

from ahbicht.content_evaluation.rc_evaluators import RcEvaluator
from ahbicht.expressions.condition_nodes import Hint, RequirementConstraint, UnevaluatedFormatConstraint
from ahbicht.expressions.hints_provider import HintsProvider
Expand All @@ -18,8 +20,8 @@ class ConditionNodeBuilder:
It distinguishes between requirement constraint evaluation and format constraint evaluation.
"""

def __init__(self, condition_keys: List[str], hints_provider: HintsProvider, rc_evaluator: RcEvaluator):
self.hints_provider = hints_provider
def __init__(self, condition_keys: List[str], rc_evaluator: RcEvaluator):
self.hints_provider = inject.instance(HintsProvider)
self.rc_evaluator = rc_evaluator
self.condition_keys = condition_keys
(
Expand Down
2 changes: 1 addition & 1 deletion src/ahbicht/content_evaluation/fc_evaluators.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def evaluate_single_format_constraint(

# Fallback error message if there is no error message even though format constraint isn't fulfilled
if result.format_constraint_fulfilled is False and result.error_message is None:
result.error_message = f"Bedingung [{condition_key}] muss erfüllt werden."
result.error_message = f"Condition [{condition_key}] has to be fulfilled."

return result

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
UnevaluatedFormatConstraint,
)
from ahbicht.expressions.expression_builder import FormatConstraintExpressionBuilder, HintExpressionBuilder
from ahbicht.expressions.hints_provider import HintsProvider


# pylint: disable=no-self-use
Expand Down Expand Up @@ -245,14 +244,13 @@ def requirement_constraint_evaluation(condition_expression: str) -> RequirementC
Evaluation of the condition expression in regard to the requirement conditions (rc).
"""

hints_provider = inject.instance(HintsProvider)
rc_evaluator = inject.instance(RcEvaluator)

parsed_tree_rc: Tree = parse_condition_expression_to_tree(condition_expression)

# get all condition keys from tree
all_condition_keys: List[str] = [t.value for t in parsed_tree_rc.scan_values(lambda v: isinstance(v, Token))]
condition_node_builder = ConditionNodeBuilder(all_condition_keys, hints_provider, rc_evaluator)
condition_node_builder = ConditionNodeBuilder(all_condition_keys, rc_evaluator)
input_nodes: List[ConditionNode] = condition_node_builder.requirement_content_evaluation_for_all_condition_keys()

resulting_condition_node: ConditionNode = evaluate_requirement_constraint_tree(parsed_tree_rc, input_nodes)
Expand Down
47 changes: 27 additions & 20 deletions unittests/test_condition_node_builder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
""" Tests for Class Condition Node Builder"""
from pathlib import Path

import inject
import pytest

from ahbicht.condition_node_builder import ConditionNodeBuilder
Expand All @@ -13,7 +14,7 @@
RequirementConstraint,
UnevaluatedFormatConstraint,
)
from ahbicht.expressions.hints_provider import JsonFileHintsProvider
from ahbicht.expressions.hints_provider import HintsProvider, JsonFileHintsProvider


class DummyRcEvaluator(RcEvaluator):
Expand All @@ -33,22 +34,28 @@ class TestConditionNodeBuilder:
_edifact_format_version = EdifactFormatVersion.FV2104
_dummy_evaluatable_data = EvaluatableData(edifact_seed=dict())
_evaluator = DummyRcEvaluator(_dummy_evaluatable_data)
_hints_provider = JsonFileHintsProvider(
_edifact_format,
_edifact_format_version,
file_path=Path("unittests/resources_condition_hints/FV2104/Hints_FV2104_UTILMD.json"),
)

_h_583 = Hint(condition_key="583", hint="[583] Hinweis: Verwendung der ID der Marktlokation")
_h_584 = Hint(condition_key="584", hint="[584] Hinweis: Verwendung der ID der Messlokation")
_ufc_955 = UnevaluatedFormatConstraint(condition_key="955")
_ufc_907 = UnevaluatedFormatConstraint(condition_key="907")

def test_initiating_condition_node_builder(self):
@pytest.fixture()
def setup_and_teardown_injector(self):
_hints_provider = JsonFileHintsProvider(
TestConditionNodeBuilder._edifact_format,
TestConditionNodeBuilder._edifact_format_version,
file_path=Path("unittests/resources_condition_hints/FV2104/Hints_FV2104_UTILMD.json"),
)
inject.clear_and_configure(lambda binder: binder.bind(HintsProvider, _hints_provider))
yield
inject.clear()

def test_initiating_condition_node_builder(self, setup_and_teardown_injector):
"""Tests if condition node builder is initiated correctly."""

condition_keys = ["501", "12", "903"]
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)

assert condition_node_builder.hints_provider.edifact_format == self._edifact_format
assert condition_node_builder.rc_evaluator.edifact_format_version == self._edifact_format_version
Expand All @@ -57,38 +64,38 @@ def test_initiating_condition_node_builder(self):
assert condition_node_builder.hints_condition_keys == ["501"]
assert condition_node_builder.format_constraints_condition_keys == ["903"]

def test_invalid_initiating_condition_node_builder(self):
def test_invalid_initiating_condition_node_builder(self, setup_and_teardown_injector):
"""Test that correct error is shown if condition keys are out of range."""
condition_keys = ["5", "1011"]

with pytest.raises(ValueError) as excinfo:
_ = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
_ = ConditionNodeBuilder(condition_keys, self._evaluator)

assert "Condition key is not in valid number range." in str(excinfo.value)

def test_build_hint_nodes(self):
def test_build_hint_nodes(self, setup_and_teardown_injector):
"""Tests that hint nodes are build correctly."""
condition_keys = ["584", "583"]
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)
hint_nodes = condition_node_builder._build_hint_nodes()
excepted_hints_nodes = {"583": self._h_583, "584": self._h_584}
assert hint_nodes == excepted_hints_nodes

def test_invalid_hint_nodes(self):
def test_invalid_hint_nodes(self, setup_and_teardown_injector):
"""Tests that correct error is shown, when hint is not implemented."""
condition_keys = ["500"]
# it is possible that a hint with [500] will be implemented in the future as not all hints are collected yet.
# If test fails, look up if hint exist. And if hint list is completed take one that does not exist.
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)
with pytest.raises(KeyError) as excinfo:
_ = condition_node_builder._build_hint_nodes()

assert "There seems to be no hint implemented with condition key '500'." in str(excinfo.value)

def test_build_unevaluated_format_constraint_nodes(self):
def test_build_unevaluated_format_constraint_nodes(self, setup_and_teardown_injector):
"""Tests that unevaluated format constraints nodes are build correctly."""
condition_keys = ["907", "955"]
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)
unevaluated_fc_nodes = condition_node_builder._build_unevaluated_format_constraint_nodes()
expected_unevaluated_fc_nodes = {"907": self._ufc_907, "955": self._ufc_955}
assert unevaluated_fc_nodes == expected_unevaluated_fc_nodes
Expand All @@ -101,7 +108,7 @@ def test_build_unevaluated_format_constraint_nodes(self):
],
)
def test_build_requirement_constraint_nodes(
self, mocker, expected_conditions_fulfilled_11, expected_conditions_fulfilled_78
self, mocker, expected_conditions_fulfilled_11, expected_conditions_fulfilled_78, setup_and_teardown_injector
):
"""Tests that requirement constraint nodes are build correctly."""

Expand All @@ -111,7 +118,7 @@ def test_build_requirement_constraint_nodes(
)

condition_keys = ["11", "78"]
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)

evaluated_requirement_constraints = condition_node_builder._build_requirement_constraint_nodes()

Expand All @@ -121,14 +128,14 @@ def test_build_requirement_constraint_nodes(
}
assert evaluated_requirement_constraints == expected_requirement_constraints

def test_requirement_evaluation_for_all_condition_keys(self, mocker):
def test_requirement_evaluation_for_all_condition_keys(self, mocker, setup_and_teardown_injector):
mocker.patch(
"ahbicht.content_evaluation.rc_evaluators.RcEvaluator.evaluate_single_condition",
side_effect=[ConditionFulfilledValue.FULFILLED, ConditionFulfilledValue.UNFULFILLED],
)

condition_keys = ["78", "907", "11", "583"]
condition_node_builder = ConditionNodeBuilder(condition_keys, self._hints_provider, self._evaluator)
condition_node_builder = ConditionNodeBuilder(condition_keys, self._evaluator)

evaluated_requirement_constraints = (
condition_node_builder.requirement_content_evaluation_for_all_condition_keys()
Expand Down

0 comments on commit 03ef11a

Please sign in to comment.