Skip to content

Commit

Permalink
Zyp/Moksha/jq: Improve error reporting at MokshaTransformation.apply
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Sep 24, 2024
1 parent 6f75a10 commit f97c040
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
decode non-UUID binary values
- Zyp/Moksha/jq: `to_object` function now respects a `zap` option, that
removes the element altogether if it's empty
- Zyp/Moksha/jq: Improve error reporting at `MokshaTransformation.apply`

## 2024/09/22 v0.0.17
- MongoDB: Fixed edge case when decoding MongoDB Extended JSON elements
Expand Down
12 changes: 10 additions & 2 deletions src/zyp/model/moksha.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import collections
import logging
import typing as t

import jmespath
Expand All @@ -11,6 +12,8 @@
from zyp.model.bucket import ConverterBase, MokshaTransformer, TransonTemplate
from zyp.util.expression import compile_expression

logger = logging.getLogger(__name__)


@define
class MokshaRule:
Expand Down Expand Up @@ -69,7 +72,12 @@ def transon(self, expression: TransonTemplate) -> "MokshaTransformation":
self._add_rule(MokshaRule(type="transon", expression=expression))
return self

def apply(self, data: DictOrList) -> DictOrList:
def apply(self, data: t.Any) -> t.Any:
for rule in self._runtime_rules:
data = rule.evaluate(data)
try:
data = rule.evaluate(data)
except Exception:
logger.exception(f"Error evaluating rule: {rule}")
logger.debug(f"Error payload:\n{data}")
raise

Check warning on line 82 in src/zyp/model/moksha.py

View check run for this annotation

Codecov / codecov/patch

src/zyp/model/moksha.py#L79-L82

Added lines #L79 - L82 were not covered by tests
return data
55 changes: 43 additions & 12 deletions tests/zyp/moksha/test_model.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,65 @@
import re

import pytest
from jmespath.exceptions import ParseError

from zyp.model.moksha import MokshaRule, MokshaTransformation


def test_moksha_rule():
moksha = MokshaRule(type="jmes", expression="@").compile()
def test_moksha_rule_compile_success():
rule = MokshaRule(type="jmes", expression="@")
moksha = rule.compile()
assert moksha.transformer.expression == "@"
assert moksha.transformer.parsed == {"type": "current", "children": []}


def test_moksha_runtime_rule_success():
assert MokshaRule(type="jmes", expression="@").compile().evaluate(42.42) == 42.42


def test_moksha_runtime_rule_syntax_error():
def test_moksha_rule_compile_syntax_error_jmes():
with pytest.raises(ParseError) as ex:
MokshaRule(type="jmes", expression="@foo").compile()
assert ex.match("Unexpected token: foo")


def test_moksha_runtime_rule_invalid_transformer():
rule = MokshaRule(type="jmes", expression="@").compile()
rule.transformer = "foo"
def test_moksha_rule_compile_syntax_error_jq():
with pytest.raises(ValueError) as ex:
MokshaRule(type="jq", expression="foo").compile()
assert ex.match("jq: error: foo/0 is not defined at <top-level>, line 1")


def test_moksha_rule_evaluate_success_jmes():
rule = MokshaRule(type="jmes", expression="@")
assert rule.compile().evaluate(42.42) == 42.42


def test_moksha_rule_evaluate_success_jq():
rule = MokshaRule(type="jq", expression=".")
assert rule.compile().evaluate(42.42) == 42.42


def test_moksha_rule_evaluate_invalid_transformer():
rule = MokshaRule(type="jmes", expression="@")
compiled = rule.compile()
compiled.transformer = "foo"
with pytest.raises(TypeError) as ex:
rule.evaluate(42.42)
compiled.evaluate(42.42)
assert ex.match("Evaluation failed. Type must be either jmes or jq or transon: foo")


def test_moksha_empty():
def test_moksha_transformation_success_jq():
moksha = MokshaTransformation().jq(". /= 100")
assert moksha.apply(4242) == 42.42


def test_moksha_transformation_error_jq(caplog):
moksha = MokshaTransformation().jq(". /= 100")
with pytest.raises(ValueError) as ex:
moksha.apply("foo")
assert ex.match(re.escape('string ("foo") and number (100) cannot be divided'))

assert "Error evaluating rule: MokshaRuntimeRule(type='jq'" in caplog.text
assert "Error payload:\nfoo" in caplog.messages


def test_moksha_transformation_empty():
"""
Empty JSON Pointer expression means "root node".
"""
Expand Down

0 comments on commit f97c040

Please sign in to comment.