Skip to content
Closed
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
6 changes: 2 additions & 4 deletions care/emr/utils/compute_observation_interpretation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ def compute_observation_interpretation(model_instance, metrics_cache):
interpretation, ranges = evaluator.evaluate(
evaluation_context, model_instance.value
)
model_instance.reference_range = ranges
if interpretation is not None:
model_instance.interpretation = interpretation
model_instance.reference_range = ranges
else:
model_instance.interpretation = {}
model_instance.reference_range = []
metrics_cache = evaluator.metric_cache
# Handle Components
if not model_instance.observation_definition.component:
Expand All @@ -43,12 +42,11 @@ def compute_observation_interpretation(model_instance, metrics_cache):
interpretation, ranges = evaluator.evaluate(
evaluation_context, component.get("value")
)
component["reference_range"] = ranges
if interpretation is not None:
component["interpretation"] = interpretation
component["reference_range"] = ranges
else:
component["interpretation"] = {}
component["reference_range"] = []
metrics_cache = evaluator.metric_cache
except Exception as e:
raise e
Expand Down
77 changes: 39 additions & 38 deletions care/utils/evaluators/interpretation_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,44 +59,44 @@ def get_interpretation(self, rule: dict, value: Any): # noqa PLR0911 PLR0912

if Decimal(str(min_val)) <= value <= Decimal(str(max_val)):
return value_range.get("interpretation"), rule.get("ranges", [])
else:
# Handle Valueset based interpretation
if "coding" not in value:
raise ValueError("Coding not found")
if rule.get("normal_coded_value_set"):
interpretation = self.check_valueset(
rule.get("normal_coded_value_set"),
value.get("coding"),
NORMAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
if rule.get("critical_coded_value_set"):
interpretation = self.check_valueset(
rule.get("critical_coded_value_set"),
value.get("coding"),
CRITICAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
if rule.get("abnormal_coded_value_set"):
interpretation = self.check_valueset(
rule.get("abnormal_coded_value_set"),
value.get("coding"),
ABNORMAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
for valueset_interpretation in rule.get("valueset_interpretation", []):
if not valueset_interpretation.get("valuset"):
continue
interpretation = self.check_valueset(
valueset_interpretation.get("valuset"),
value.get("coding"),
valueset_interpretation.get("interpretation"),
)
if interpretation:
return interpretation, []
return False, rule.get("ranges", [])
# Handle Valueset based interpretation
if "coding" not in value:
raise ValueError("Coding not found")
Comment on lines +63 to +65
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider a more defensive check before accessing value.

If value is not a dict (e.g., an unexpected primitive type that didn't match any range conditions), the "coding" not in value check on line 64 could raise a TypeError. While this path should only be reached for coded values, a defensive type check would be safer.

Additionally, the static analysis tool flags the inline message as a minor style issue (TRY003).

🛡️ Proposed defensive fix
         # Handle Valueset based interpretation
+        if not isinstance(value, dict) or "coding" not in value:
+            raise ValueError("Coding not found")
-        if "coding" not in value:
-            raise ValueError("Coding not found")
🧰 Tools
🪛 Ruff (0.15.4)

[warning] 65-65: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@care/utils/evaluators/interpretation_evaluator.py` around lines 63 - 65, The
check assumes value is a dict and does "if 'coding' not in value" which can
raise TypeError for non-dict values; update the Valueset-based interpretation
branch (the block under the comment "Handle Valueset based interpretation" that
inspects variable value) to first verify isinstance(value, dict) and raise a
clear ValueError if it's not a dict, then check for the 'coding' key and raise a
distinct, descriptive ValueError if missing (use a full sentence message rather
than an inline snippet to satisfy the TRY003 style flag).

if rule.get("normal_coded_value_set"):
interpretation = self.check_valueset(
rule.get("normal_coded_value_set"),
value.get("coding"),
NORMAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
if rule.get("critical_coded_value_set"):
interpretation = self.check_valueset(
rule.get("critical_coded_value_set"),
value.get("coding"),
CRITICAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
if rule.get("abnormal_coded_value_set"):
interpretation = self.check_valueset(
rule.get("abnormal_coded_value_set"),
value.get("coding"),
ABNORMAL_INTERPRETATION,
)
if interpretation:
return interpretation, []
for valueset_interpretation in rule.get("valueset_interpretation", []):
if not valueset_interpretation.get("valuset"):
continue
interpretation = self.check_valueset(
valueset_interpretation.get("valuset"),
value.get("coding"),
valueset_interpretation.get("interpretation"),
)
if interpretation:
return interpretation, []

return False, False

Expand Down Expand Up @@ -136,4 +136,5 @@ def evaluate(self, context: dict, value: Any) -> str:
interpretation, ranges = self.get_interpretation(rule, value)
if interpretation:
return interpretation, ranges
return None, ranges
return None, []