diff --git a/CHANGELOG.md b/CHANGELOG.md index 296fc04..4bbb9be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Version 0.9.0 (unreleased) +**Breaking Changes** + +- `CompoundJSONPath` instances are no longer updated in-place when using `.union()` and `.intersection()`. Instead, a new `CompoundJSONPath` is returned. `CompoundJSONPath.paths` is now a tuple instead of a list. + **Fixes** - Fixed a bug with the parsing of JSON Pointers. When given an arbitrary string without slashes, `JSONPointer` would resolve to the document root. The empty string is the only valid pointer that should resolve to the document root. We now raise a `JSONPointerError` in such cases. See [#27](https://github.com/jg-rp/python-jsonpath/issues/27). diff --git a/jsonpath/env.py b/jsonpath/env.py index 7b38360..3937f74 100644 --- a/jsonpath/env.py +++ b/jsonpath/env.py @@ -161,7 +161,7 @@ def compile(self, path: str) -> Union[JSONPath, CompoundJSONPath]: # noqa: A003 if stream.current.kind == TOKEN_UNION: stream.next_token() - _path.union( + _path = _path.union( JSONPath( env=self, selectors=self.parser.parse(stream), @@ -169,7 +169,7 @@ def compile(self, path: str) -> Union[JSONPath, CompoundJSONPath]: # noqa: A003 ) elif stream.current.kind == TOKEN_INTERSECTION: stream.next_token() - _path.intersection( + _path = _path.intersection( JSONPath( env=self, selectors=self.parser.parse(stream), diff --git a/jsonpath/path.py b/jsonpath/path.py index 3deb634..08f45ac 100644 --- a/jsonpath/path.py +++ b/jsonpath/path.py @@ -223,10 +223,11 @@ def __init__( *, env: JSONPathEnvironment, path: Union[JSONPath, CompoundJSONPath], + paths: Iterable[Tuple[str, JSONPath]] = (), ) -> None: self.env = env self.path = path - self.paths: List[Tuple[(str, JSONPath)]] = [] + self.paths = tuple(paths) def __str__(self) -> str: buf: List[str] = [str(self.path)] @@ -381,14 +382,20 @@ async def finditer_async( return matches def union(self, path: JSONPath) -> CompoundJSONPath: - """In-place union of this path and another path.""" - self.paths.append((self.env.union_token, path)) - return self + """Union of this path and another path.""" + return self.__class__( + env=self.env, + path=self.path, + paths=self.paths + ((self.env.union_token, path),), + ) def intersection(self, path: JSONPath) -> CompoundJSONPath: - """In-place intersection of this path and another path.""" - self.paths.append((self.env.intersection_token, path)) - return self + """Intersection of this path and another path.""" + return self.__class__( + env=self.env, + path=self.path, + paths=self.paths + ((self.env.intersection_token, path),), + ) T = TypeVar("T")