diff --git a/src/check_datapackage/internals.py b/src/check_datapackage/internals.py index a44327d5..0d87d97a 100644 --- a/src/check_datapackage/internals.py +++ b/src/check_datapackage/internals.py @@ -2,7 +2,13 @@ from itertools import chain from typing import Annotated, Any, Callable, Iterable, TypeVar -from jsonpath import JSONPathMatch, JSONPathSyntaxError, compile, finditer +from jsonpath import ( + CompoundJSONPath, + JSONPathMatch, + JSONPathSyntaxError, + compile, + finditer, +) from pydantic import AfterValidator @@ -59,12 +65,22 @@ def _flat_map(items: Iterable[In], fn: Callable[[In], Iterable[Out]]) -> list[Ou def _is_jsonpath(value: str) -> str: try: - compile(value) + jsonpath = compile(value) except JSONPathSyntaxError: raise ValueError( f"'{value}' is not a correct JSON path. See " "https://jg-rp.github.io/python-jsonpath/syntax/ for the expected syntax." ) + + # Doesn't allow intersection paths (e.g. `$.resources & $.name`). + intersection_token = jsonpath.env.intersection_token + if isinstance(jsonpath, CompoundJSONPath) and _filter( + jsonpath.paths, lambda path: path[0] == intersection_token + ): + raise ValueError( + f"The intersection operator (`{intersection_token}`) in the JSON path " + f"'{value}' is not supported." + ) return value diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 98f97ce5..6c9a2c32 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -168,6 +168,8 @@ def test_required_check_array_wildcard(): "..resources", "$.resources[0].*", "$.resources[*]", + "$.no & $.intersection", + "$.no & $.intersection | $.operator", ], ) def test_required_check_cannot_apply_to_bad_or_ambiguous_path(jsonpath): @@ -178,10 +180,18 @@ def test_required_check_cannot_apply_to_bad_or_ambiguous_path(jsonpath): ) -def test_custom_check_cannot_apply_to_bad_path(): +@mark.parametrize( + "jsonpath", + [ + "<><>bad.path", + "$.no & $.intersection", + "$.no & $.intersection | $.operator", + ], +) +def test_custom_check_cannot_apply_to_bad_path(jsonpath): with raises(ValueError): CustomCheck( - jsonpath="<><>bad.path", + jsonpath=jsonpath, message="A message.", check=lambda _: True, )