Skip to content

pydantic_jsonpointer.traversal

pydantic_jsonpointer.traversal

Pointer-traversal API: Ptr cursor, walker, and convenience functions.

Layered above adapters and errors. The Pydantic-specific BaseModelAdapter is registered against pydantic.BaseModel in __init__.py, so this module does not import Pydantic directly.

Ptr dataclass

Ptr(
    pointer: JsonPointer,
    _parent: Any,
    _key: int | str | None,
    _adapter: ContainerAdapter,
    _frozen: bool = False,
)

A live cursor into a (parent, key) slot of a document.

Ptr instances are produced by resolve(doc, pointer). Reads and mutations always re-execute through _adapter; the cursor does not cache the value at (_parent, _key).

add

add(value: Any) -> None

Insert (lists) or set (dicts/models) at this slot.

For dicts/models this creates-or-replaces; for lists this inserts at the resolved index, with the "-" marker appending at the tail. Raises RootRebindError on the root Ptr or ImmutableTargetError if any ancestor binding was frozen.

Source code in src/pydantic_jsonpointer/traversal.py
def add(self, value: Any) -> None:
    """Insert (lists) or set (dicts/models) at this slot.

    For dicts/models this creates-or-replaces; for lists this inserts at
    the resolved index, with the ``"-"`` marker appending at the tail.
    Raises ``RootRebindError`` on the root Ptr or ``ImmutableTargetError``
    if any ancestor binding was frozen.
    """
    self._guard_mutation()
    assert self._key is not None
    self._adapter.add(self._parent, self._key, value)

exists

exists() -> bool

True for the root Ptr, otherwise _adapter.has(_parent, _key).

Source code in src/pydantic_jsonpointer/traversal.py
def exists(self) -> bool:
    """True for the root Ptr, otherwise ``_adapter.has(_parent, _key)``."""
    if self._key is None:
        return True
    return self._adapter.has(self._parent, self._key)

get

get() -> Any

Return the value at this slot.

For the root Ptr returns the document itself. For non-root Ptrs re-fetches through the adapter and raises PointerNotFoundError when the slot does not exist.

Source code in src/pydantic_jsonpointer/traversal.py
def get(self) -> Any:
    """Return the value at this slot.

    For the root Ptr returns the document itself. For non-root Ptrs
    re-fetches through the adapter and raises ``PointerNotFoundError``
    when the slot does not exist.
    """
    if self._key is None:
        return self._parent
    return self._adapter.get(self._parent, self._key)

remove

remove() -> Any

Remove and return the value at this slot.

Raises RootRebindError on the root Ptr, ImmutableTargetError if any ancestor binding was frozen, PointerNotFoundError if the slot does not exist.

Source code in src/pydantic_jsonpointer/traversal.py
def remove(self) -> Any:
    """Remove and return the value at this slot.

    Raises ``RootRebindError`` on the root Ptr, ``ImmutableTargetError``
    if any ancestor binding was frozen, ``PointerNotFoundError`` if the
    slot does not exist.
    """
    self._guard_mutation()
    assert self._key is not None
    return self._adapter.remove(self._parent, self._key)

set

set(value: Any) -> None

Replace the value at this slot. Target must already exist.

Raises RootRebindError on the root Ptr, ImmutableTargetError if any ancestor binding was frozen, PointerNotFoundError if the slot does not exist.

Source code in src/pydantic_jsonpointer/traversal.py
def set(self, value: Any) -> None:
    """Replace the value at this slot. Target must already exist.

    Raises ``RootRebindError`` on the root Ptr, ``ImmutableTargetError``
    if any ancestor binding was frozen, ``PointerNotFoundError`` if the
    slot does not exist.
    """
    self._guard_mutation()
    assert self._key is not None
    self._adapter.set(self._parent, self._key, value)

try_get

try_get(default: Any = ...) -> Any

Return the value at this slot, or default if missing.

With no default (or default=...), behaves like get() — raises PointerNotFoundError on missing. The Ellipsis singleton serves as the "no default supplied" sentinel.

Source code in src/pydantic_jsonpointer/traversal.py
def try_get(self, default: Any = ...) -> Any:
    """Return the value at this slot, or ``default`` if missing.

    With no ``default`` (or ``default=...``), behaves like ``get()`` —
    raises ``PointerNotFoundError`` on missing. The ``Ellipsis`` singleton
    serves as the "no default supplied" sentinel.
    """
    if self.exists():
        return self.get()
    if default is ...:
        raise PointerNotFoundError(str(self.pointer))
    return default

add_value

add_value(
    doc: Any,
    pointer: JsonPointer,
    value: Any,
    *,
    resolver: Any = None,
) -> None

Insert (lists) or set (dicts/models) value at pointer in doc.

Source code in src/pydantic_jsonpointer/traversal.py
def add_value(
    doc: Any, pointer: JsonPointer, value: Any, *, resolver: Any = None
) -> None:
    """Insert (lists) or set (dicts/models) ``value`` at ``pointer`` in ``doc``."""
    resolve(doc, pointer, resolver=resolver).add(value)

get_value

get_value(
    doc: Any, pointer: JsonPointer, *, resolver: Any = None
) -> Any

Return the value at pointer in doc.

Source code in src/pydantic_jsonpointer/traversal.py
def get_value(doc: Any, pointer: JsonPointer, *, resolver: Any = None) -> Any:
    """Return the value at ``pointer`` in ``doc``."""
    return resolve(doc, pointer, resolver=resolver).get()

remove_value

remove_value(
    doc: Any, pointer: JsonPointer, *, resolver: Any = None
) -> Any

Remove and return the value at pointer in doc.

Source code in src/pydantic_jsonpointer/traversal.py
def remove_value(doc: Any, pointer: JsonPointer, *, resolver: Any = None) -> Any:
    """Remove and return the value at ``pointer`` in ``doc``."""
    return resolve(doc, pointer, resolver=resolver).remove()

resolve

resolve(
    doc: Any, pointer: JsonPointer, *, resolver: Any = None
) -> Ptr

Resolve pointer against doc and return a Ptr to the target slot.

The returned Ptr may have exists() == False (for JSON-Patch add on a missing key, or for the array-tail "-" marker). For the empty pointer the root Ptr is returned. The optional resolver kwarg overrides the default BaseModelAdapter field-name policy for this call only (no registry mutation).

Source code in src/pydantic_jsonpointer/traversal.py
def resolve(doc: Any, pointer: JsonPointer, *, resolver: Any = None) -> Ptr:
    """Resolve ``pointer`` against ``doc`` and return a Ptr to the target slot.

    The returned Ptr may have ``exists() == False`` (for JSON-Patch ``add`` on
    a missing key, or for the array-tail ``"-"`` marker). For the empty
    pointer the root Ptr is returned. The optional ``resolver`` kwarg
    overrides the default ``BaseModelAdapter`` field-name policy for this
    call only (no registry mutation).
    """
    last: Ptr | None = None
    for ptr in _iter_resolve(doc, pointer, resolver=resolver):
        last = ptr
    if last is None:
        raise PointerError("internal: _iter_resolve yielded no Ptr")
    return last

set_value

set_value(
    doc: Any,
    pointer: JsonPointer,
    value: Any,
    *,
    resolver: Any = None,
) -> None

Replace the value at pointer in doc. Target must already exist.

Source code in src/pydantic_jsonpointer/traversal.py
def set_value(
    doc: Any, pointer: JsonPointer, value: Any, *, resolver: Any = None
) -> None:
    """Replace the value at ``pointer`` in ``doc``. Target must already exist."""
    resolve(doc, pointer, resolver=resolver).set(value)