From 879bfe58313d1f5cd181aa62082fd749496edc7e Mon Sep 17 00:00:00 2001 From: Marton Vago Date: Wed, 19 Nov 2025 15:11:22 +0000 Subject: [PATCH 1/3] feat: :sparkles: disallow intersection operator --- src/check_datapackage/internals.py | 18 ++++++++++++++++-- tests/test_extensions.py | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/check_datapackage/internals.py b/src/check_datapackage/internals.py index a44327d5..1a2479aa 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,20 @@ 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." ) + + if isinstance(jsonpath, CompoundJSONPath) and _filter( + jsonpath.paths, lambda path: path[0] == "&" + ): + raise ValueError( + f"The intersection operator (`&`) in the JSON path '{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, ) From 2bebec2e4ec81d2305248695d014c939f05514ea Mon Sep 17 00:00:00 2001 From: Marton Vago Date: Wed, 19 Nov 2025 15:41:21 +0000 Subject: [PATCH 2/3] refactor: :recycle: use intersection_token var --- src/check_datapackage/internals.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/check_datapackage/internals.py b/src/check_datapackage/internals.py index 1a2479aa..45f26905 100644 --- a/src/check_datapackage/internals.py +++ b/src/check_datapackage/internals.py @@ -72,12 +72,13 @@ def _is_jsonpath(value: str) -> str: "https://jg-rp.github.io/python-jsonpath/syntax/ for the expected syntax." ) + intersection_token = jsonpath.env.intersection_token if isinstance(jsonpath, CompoundJSONPath) and _filter( - jsonpath.paths, lambda path: path[0] == "&" + jsonpath.paths, lambda path: path[0] == intersection_token ): raise ValueError( - f"The intersection operator (`&`) in the JSON path '{value}' is not " - "supported." + f"The intersection operator (`{intersection_token}`) in the JSON path " + f"'{value}' is not supported." ) return value From 8c0465349f873b715bda8b66f8e953552f5861fe Mon Sep 17 00:00:00 2001 From: martonvago <57952344+martonvago@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:43:56 +0000 Subject: [PATCH 3/3] docs: :memo: add comment --- src/check_datapackage/internals.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/check_datapackage/internals.py b/src/check_datapackage/internals.py index 45f26905..0d87d97a 100644 --- a/src/check_datapackage/internals.py +++ b/src/check_datapackage/internals.py @@ -72,6 +72,7 @@ def _is_jsonpath(value: str) -> str: "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