MCPcopy Create free account
hub / github.com/ParzivalHack/PySpector / _build_ast_json_and_chunks

Function _build_ast_json_and_chunks

src/pyspector/ast_cache.py:129–180  ·  view source on GitHub ↗

Serialise *tree* to AST JSON, reusing encoded subtrees from *old_chunks* for any chunk whose content hash AND start_line are both unchanged. Skips encode_node() for every unchanged top-level function/class — typically 80-100 % of body nodes when only a few lines change. Return

(
    tree: ast.Module,
    source: str,
    old_chunks: Dict[str, AstChunk],
)

Source from the content-addressed store, hash-verified

127
128
129def _build_ast_json_and_chunks(
130 tree: ast.Module,
131 source: str,
132 old_chunks: Dict[str, AstChunk],
133) -> Tuple[str, Dict[str, AstChunk]]:
134 """
135 Serialise *tree* to AST JSON, reusing encoded subtrees from *old_chunks*
136 for any chunk whose content hash AND start_line are both unchanged.
137
138 Skips encode_node() for every unchanged top-level function/class
139 typically 80-100 % of body nodes when only a few lines change.
140
141 Returns (full_ast_json, new_chunks_dict).
142 """
143 lines = source.splitlines(keepends=True)
144 seen: Dict[str, int] = {}
145 new_chunks: Dict[str, AstChunk] = {}
146 body_parts: List[str] = []
147
148 for node in tree.body:
149 cid = _make_chunk_id(node, seen)
150 src = _source_slice(lines, node)
151 end = getattr(node, "end_lineno", node.lineno)
152 new_hash = hashlib.sha256(src.encode()).hexdigest()
153
154 old = old_chunks.get(cid)
155 reuse = (
156 old is not None
157 and old.content_hash == new_hash
158 and old.start_line == node.lineno
159 )
160
161 if reuse:
162 assert old is not None # type narrowing
163 node_json = zlib.decompress(old.ast_json_z).decode()
164 chunk_z = old.ast_json_z
165 else:
166 node_json = encode_node(node)
167 chunk_z = zlib.compress(node_json.encode(), _ZLIB_LEVEL)
168
169 new_chunks[cid] = AstChunk(
170 chunk_id=cid,
171 start_line=node.lineno,
172 end_line=end,
173 content_hash=new_hash,
174 ast_json_z=chunk_z,
175 )
176 body_parts.append(node_json)
177
178 type_ignore_parts = [encode_node(ti) for ti in tree.type_ignores]
179 full_json = _assemble_module_json(body_parts, type_ignore_parts)
180 return full_json, new_chunks
181
182
183# ── Disk serialization — JSON + base64, no executable deserialization ─────────

Callers 5

_buildMethod · 0.90
_make_entryMethod · 0.90
_buildMethod · 0.85

Calls 5

_make_chunk_idFunction · 0.85
_source_sliceFunction · 0.85
encode_nodeFunction · 0.85
AstChunkClass · 0.85
_assemble_module_jsonFunction · 0.85

Tested by 4

_buildMethod · 0.72
_make_entryMethod · 0.72