Extract package metadata from Lazarus .lpk package files (XML format). .lpk is an XML file listing the package name, required dependencies, and the Pascal units that belong to the package. Produces nodes for: - The package file itself - The package (by name) - Each required
(path: Path)
| 13791 | |
| 13792 | |
| 13793 | def extract_lazarus_package(path: Path) -> dict: |
| 13794 | """Extract package metadata from Lazarus .lpk package files (XML format). |
| 13795 | |
| 13796 | .lpk is an XML file listing the package name, required dependencies, |
| 13797 | and the Pascal units that belong to the package. |
| 13798 | |
| 13799 | Produces nodes for: |
| 13800 | - The package file itself |
| 13801 | - The package (by name) |
| 13802 | - Each required package (dependency) |
| 13803 | - Each listed unit file (resolved to path-based IDs where possible) |
| 13804 | |
| 13805 | Produces edges for: |
| 13806 | - file --contains--> package |
| 13807 | - package --imports--> required dependency (context: "import") |
| 13808 | - package --contains--> listed unit |
| 13809 | """ |
| 13810 | try: |
| 13811 | import xml.etree.ElementTree as ET |
| 13812 | src = path.read_bytes() |
| 13813 | except OSError as e: |
| 13814 | return {"nodes": [], "edges": [], "error": str(e)} |
| 13815 | |
| 13816 | if len(src) > _PROJECT_XML_MAX_BYTES: |
| 13817 | return {"nodes": [], "edges": [], "error": "package file too large"} |
| 13818 | if not _project_xml_is_safe(src): |
| 13819 | return {"nodes": [], "edges": [], |
| 13820 | "error": "refusing XML with DOCTYPE/ENTITY declaration"} |
| 13821 | |
| 13822 | try: |
| 13823 | xml_root = ET.fromstring(src) |
| 13824 | except Exception as e: |
| 13825 | return {"nodes": [], "edges": [], "error": str(e)} |
| 13826 | |
| 13827 | str_path = str(path) |
| 13828 | stem = _file_stem(path) |
| 13829 | nodes: list[dict] = [] |
| 13830 | edges: list[dict] = [] |
| 13831 | seen_ids: set[str] = set() |
| 13832 | |
| 13833 | def add_node(nid: str, label: str) -> None: |
| 13834 | if nid not in seen_ids: |
| 13835 | seen_ids.add(nid) |
| 13836 | nodes.append({ |
| 13837 | "id": nid, "label": label, "file_type": "code", |
| 13838 | "source_file": str_path, "source_location": "L1", |
| 13839 | }) |
| 13840 | |
| 13841 | def add_edge(src: str, tgt: str, relation: str, context: str | None = None) -> None: |
| 13842 | edge: dict[str, Any] = { |
| 13843 | "source": src, "target": tgt, "relation": relation, |
| 13844 | "confidence": "EXTRACTED", "source_file": str_path, |
| 13845 | "source_location": "L1", "weight": 1.0, |
| 13846 | } |
| 13847 | if context: |
| 13848 | edge["context"] = context |
| 13849 | edges.append(edge) |
| 13850 |