Post-pass: extract docstrings and rationale comments from Python source. Mutates result in-place by appending to result['nodes'] and result['edges'].
(path: Path, result: dict)
| 5745 | |
| 5746 | |
| 5747 | def _extract_python_rationale(path: Path, result: dict) -> None: |
| 5748 | """Post-pass: extract docstrings and rationale comments from Python source. |
| 5749 | Mutates result in-place by appending to result['nodes'] and result['edges']. |
| 5750 | """ |
| 5751 | try: |
| 5752 | import tree_sitter_python as tspython |
| 5753 | from tree_sitter import Language, Parser |
| 5754 | language = Language(tspython.language()) |
| 5755 | parser = Parser(language) |
| 5756 | source = path.read_bytes() |
| 5757 | tree = parser.parse(source) |
| 5758 | root = tree.root_node |
| 5759 | except Exception: |
| 5760 | return |
| 5761 | |
| 5762 | stem = _file_stem(path) |
| 5763 | str_path = str(path) |
| 5764 | nodes = result["nodes"] |
| 5765 | edges = result["edges"] |
| 5766 | seen_ids = {n["id"] for n in nodes} |
| 5767 | file_nid = _make_id(str(path)) |
| 5768 | |
| 5769 | def _get_docstring(body_node) -> tuple[str, int] | None: |
| 5770 | if not body_node: |
| 5771 | return None |
| 5772 | for child in body_node.children: |
| 5773 | if child.type == "expression_statement": |
| 5774 | for sub in child.children: |
| 5775 | if sub.type in ("string", "concatenated_string"): |
| 5776 | text = source[sub.start_byte:sub.end_byte].decode("utf-8", errors="replace") |
| 5777 | text = text.strip("\"'").strip('"""').strip("'''").strip() |
| 5778 | if len(text) > 20: |
| 5779 | return text, child.start_point[0] + 1 |
| 5780 | break |
| 5781 | return None |
| 5782 | |
| 5783 | def _add_rationale(text: str, line: int, parent_nid: str) -> None: |
| 5784 | label = text[:80].replace("\r\n", " ").replace("\r", " ").replace("\n", " ").strip() |
| 5785 | rid = _make_id(stem, "rationale", str(line)) |
| 5786 | if rid not in seen_ids: |
| 5787 | seen_ids.add(rid) |
| 5788 | nodes.append({ |
| 5789 | "id": rid, |
| 5790 | "label": label, |
| 5791 | "file_type": "rationale", |
| 5792 | "source_file": str_path, |
| 5793 | "source_location": f"L{line}", |
| 5794 | }) |
| 5795 | edges.append({ |
| 5796 | "source": rid, |
| 5797 | "target": parent_nid, |
| 5798 | "relation": "rationale_for", |
| 5799 | "confidence": "EXTRACTED", |
| 5800 | "source_file": str_path, |
| 5801 | "source_location": f"L{line}", |
| 5802 | "weight": 1.0, |
| 5803 | }) |
| 5804 |
no test coverage detected