diff --git a/CHANGELOG.md b/CHANGELOG.md index 41be77c..3bc8488 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ These breaking changes apply to Python JSONPath in its default configuration. We - Added the [Keys filter selector](https://jg-rp.github.io/python-jsonpath/syntax/#keys-filter-selector). - Added the [Singular query selector](https://jg-rp.github.io/python-jsonpath/syntax/#singular-query-selector). - We now use the [regex] package, if available, instead of `re` for match and search function extensions. See [optional dependencies](https://jg-rp.github.io/python-jsonpath/#optional-dependencies). -- Added the `strict` argument to all [convenience functions](https://jg-rp.github.io/python-jsonpath/convenience/), the CLI and the `JSONPathEnvironment` constructor. When `strict=True`, all extensions to RFC 9535 and any lax parsing rules will be disabled. +- Added the `strict` argument to all [convenience functions](https://jg-rp.github.io/python-jsonpath/convenience/), the CLI and the `JSONPathEnvironment` constructor. When `strict=True`, all extensions to RFC 9535, any non-standard function extensions and any lax parsing rules will be disabled. - Added class variable `JSONPathEnvironment.max_recursion_depth` to control the maximum recursion depth of descendant segments. - Added pretty exception messages. diff --git a/docs/functions.md b/docs/functions.md index 4ddf99f..72eb5f9 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -2,6 +2,10 @@ A filter function is a named function that can be called as part of a [filter selector](syntax.md#filter-selector). Here we describe built in filters. You can [define your own function extensions](advanced.md#function-extensions) too. +!!! note + + If you pass `strict=True` when calling [`findall()`](convenience.md#jsonpath.findall), [`finditer()`](convenience.md#jsonpath.finditer), etc., Only standard functions - those defined by RFC 9535 - will be enabled. The standard functions are `count`, `length`, `match`, `search` and `value`. + ## `count()` ```text diff --git a/jsonpath/env.py b/jsonpath/env.py index ee674ed..048b050 100644 --- a/jsonpath/env.py +++ b/jsonpath/env.py @@ -450,11 +450,13 @@ def setup_function_extensions(self) -> None: self.function_extensions["match"] = function_extensions.Match() self.function_extensions["search"] = function_extensions.Search() self.function_extensions["value"] = function_extensions.Value() - self.function_extensions["isinstance"] = function_extensions.IsInstance() - self.function_extensions["is"] = self.function_extensions["isinstance"] - self.function_extensions["typeof"] = function_extensions.TypeOf() - self.function_extensions["type"] = self.function_extensions["typeof"] - self.function_extensions["startswith"] = function_extensions.StartsWith() + + if not self.strict: + self.function_extensions["isinstance"] = function_extensions.IsInstance() + self.function_extensions["is"] = self.function_extensions["isinstance"] + self.function_extensions["typeof"] = function_extensions.TypeOf() + self.function_extensions["type"] = self.function_extensions["typeof"] + self.function_extensions["startswith"] = function_extensions.StartsWith() def validate_function_extension_signature( self, token: Token, args: List[Any] diff --git a/tests/test_strictness.py b/tests/test_strictness.py index d4fe39a..5344b1e 100644 --- a/tests/test_strictness.py +++ b/tests/test_strictness.py @@ -1,6 +1,7 @@ import pytest from jsonpath import JSONPathEnvironment +from jsonpath import JSONPathNameError @pytest.fixture() @@ -73,3 +74,34 @@ def test_singular_path_selector_without_root_identifier( } assert env.findall(query, data) == [{"q": [4, 5, 6]}] + + +def test_isinstance_is_disabled_in_strict_mode() -> None: + env = JSONPathEnvironment(strict=True) + + query = "$.some[?is(@.thing, 'string')]" + with pytest.raises(JSONPathNameError): + env.compile(query) + + query = "$.some[?isinstance(@.thing, 'string')]" + with pytest.raises(JSONPathNameError): + env.compile(query) + + +def test_typeof_is_disabled_in_strict_mode() -> None: + env = JSONPathEnvironment(strict=True) + + query = "$.some[?type(@.thing) == 'string']" + with pytest.raises(JSONPathNameError): + env.compile(query) + + query = "$.some[?typeof(@.thing) == 'string']" + with pytest.raises(JSONPathNameError): + env.compile(query) + + +def test_startswith_is_disabled_in_strict_mode() -> None: + env = JSONPathEnvironment(strict=True) + query = "$[?startswith(@, 'ab')]" + with pytest.raises(JSONPathNameError): + env.compile(query)