Skip to content

Commit

Permalink
Reduces code complexity in one part of weather_symbols.py. (metoppv#1391
Browse files Browse the repository at this point in the history
)

* Reduces code complexity in one part of weather_symbols.py.

* Refactors the dict definition so it is only performed once.

* Adds unit test for new error message.

* Removes == from list of invertible conditions, as it was wrong and isn't used anyway.

* Proves == raises the error too

* Improves doc-string
  • Loading branch information
MoseleyS authored Dec 17, 2020
1 parent e1e42c1 commit a33598a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 20 deletions.
55 changes: 35 additions & 20 deletions improver/wxcode/weather_symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@
)


def _define_invertible_conditions():
"""Returns a dictionary of boolean comparator strings where the value is the
logical inverse of the key."""
invertible_conditions = {
">=": "<",
">": "<=",
"OR": "AND",
"": "",
}
# Add reverse {value: key} entries to invertible_conditions
reverse_inversions = {}
for k, v in invertible_conditions.items():
reverse_inversions[v] = k
invertible_conditions.update(reverse_inversions)
return invertible_conditions


INVERTIBLE_CONDITIONS = _define_invertible_conditions()


class WeatherSymbols(BasePlugin):
"""
Definition and implementation of a weather symbol decision tree. This
Expand Down Expand Up @@ -228,12 +248,20 @@ def check_input_cubes(self, cubes):
return optional_node_data_missing

@staticmethod
def invert_condition(test_conditions):
def _invert_comparator(comparator):
"""Inverts a single comparator string."""
try:
return INVERTIBLE_CONDITIONS[comparator]
except KeyError:
raise KeyError(f"Unexpected condition {comparator}, cannot invert it.")

def invert_condition(self, condition):
"""
Invert a comparison condition to select the negative case.
Invert a comparison condition to allow positive identification of conditions
satisfying the negative ('fail') case.
Args:
test_conditions (dict):
condition (dict):
A single query from the decision tree.
Returns:
(tuple): tuple containing:
Expand All @@ -242,23 +270,10 @@ def invert_condition(test_conditions):
**inverted_combination** (str):
A string representing the inverted combination
"""
threshold = test_conditions["threshold_condition"]
inverted_threshold = threshold
if threshold == ">=":
inverted_threshold = "<"
elif threshold == "<=":
inverted_threshold = ">"
elif threshold == "<":
inverted_threshold = ">="
elif threshold == ">":
inverted_threshold = "<="
combination = test_conditions["condition_combination"]
inverted_combination = combination
if combination == "OR":
inverted_combination = "AND"
elif combination == "AND":
inverted_combination = "OR"

inverted_threshold = self._invert_comparator(condition["threshold_condition"])
inverted_combination = self._invert_comparator(
condition["condition_combination"]
)
return inverted_threshold, inverted_combination

@staticmethod
Expand Down
11 changes: 11 additions & 0 deletions improver_tests/wxcode/wxcode/test_WeatherSymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ def test_invert_combination_correctly(self):
result = plugin.invert_condition(node)
self.assertEqual(result[1], inverse_outputs[i])

def test_error(self):
"""Test that the _invert_comparator method raises an error when the condition
cannot be inverted."""
plugin = WeatherSymbols()
possible_inputs = ["==", "!=", "NOT", "XOR"]
for val in possible_inputs:
with self.assertRaisesRegex(
KeyError, f"Unexpected condition {val}, cannot invert it."
):
plugin._invert_comparator(val)


class Test_construct_condition(IrisTest):

Expand Down

0 comments on commit a33598a

Please sign in to comment.