Skip to content

feat(sdk): node navigation helpers get_node, get_node_parent, get_node_path, get_node_map - #542

Merged
rejojer merged 4 commits into
mainfrom
feat/node-helpers
Oct 1, 2026
Merged

rejojer merged 4 commits into
mainfrom
feat/node-helpers

Conversation

@rejojer

@rejojer rejojer commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Adds four functions for navigating a document tree, in pageindex.utils (also reachable as pageindex.get_node etc.):

tree = client.get_document_structure(doc_id)

get_node(tree, "0007")         # the node, or None
get_node_parent(tree, "0007")  # its parent; None for a top-level or absent node
get_node_path(tree, "0007")    # [top-level ancestor, ..., node]; [] if absent
get_node_map(tree)             # {node_id: node}
  • They take the tree, not a doc_id: fetch it once and navigate locally, instead of one request per step.
  • The first three share one depth-first walk, O(n) per call; trees run tens to a few hundred nodes.
  • They return the tree's own nodes rather than copies (unlike get_nodes / get_leaf_nodes), so node["nodes"] keeps working.
  • Wrong input raises TypeError naming the right one, so it never reads as "not found": the whole get_tree() response (pass its ['result']), a None tree, or a non-string id.
  • get_node_map is create_node_mapping, plus that input check, under a name in the same family. create_node_mapping stays as the 0.2.8 surface.
  • create_node_mapping (so get_node_map too) walks past a node whose nodes is None instead of raising TypeError, as get_node already did.

Tests: test_node_navigation and test_node_navigation_rejects_wrong_input in tests/test_package_surface.py.

…e_path, get_node_map

They take the tree, not a doc_id: fetch it once (get_document_structure)
and navigate locally, instead of one request per step.

get_node / get_node_parent / get_node_path share one depth-first walk,
O(n) per call; trees run tens to a few hundred nodes. They return the
tree's own nodes rather than copies (unlike get_nodes / get_leaf_nodes),
so node["nodes"] keeps working.

get_node_map is create_node_mapping under a name in the same family.
It leaves out include_page_ranges, which reads page_index and raises
KeyError on local trees. create_node_mapping stays as the 0.2.8 surface.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-10-01T11:42:38.969508Z d03ef98 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

…ranges

get_node, get_node_parent, get_node_path and get_node_map returned
None / [] / {} when handed the whole get_tree() response or a None tree,
and get_node matched nothing for an int id. Callers (AI-written ones
especially) read that as "node absent". They now raise TypeError naming
get_document_structure(doc_id) / get_tree(doc_id)['result'].

create_node_mapping(include_page_ranges=True) read node["page_index"],
so a raw tree from page_index_main (start_index/end_index) raised
KeyError although it already carries its ranges. A node's own
start_index/end_index now win; page_index trees map as before.
#541 makes the same change (a node's own start_index/end_index win) with
its own test, and the two versions conflict on merge. The node helpers
here don't depend on it.
create_node_mapping walked children with tree.get('nodes', []), so a
node carrying nodes: None raised TypeError while get_node and
get_node_path, which use `or []`, handled the same tree. Use `or []`
in the shared walker so every create_node_mapping caller is covered.
#541 does not touch this line; a trial merge with its head 79d88e8 is
clean.
@rejojer
rejojer merged commit 60c8ff8 into main Oct 1, 2026
14 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant