Skip to main content

A graph-based data structure designed for querying CSV files in Joern format in Python

Project description

cpg2py

Python graph query engine for Code Property Graphs from Joern CSV exports. Directed multi-graph with generic ABCs for custom node/edge/graph types.

Features: Load from nodes.csv + rels.csv; query/update nodes and edges (get_property, set_property, set_properties); traverse succ/prev/children/parent/flow_to/flow_from; JSON persistence (save_json, load_json, storage_from_json). Concrete types: CpgGraph, CpgNode, CpgEdge.


Installation

pip install cpg2py

From source (e.g. with uv):

git clone https://github.com/samhsu-dev/cpg2py.git && cd cpg2py
uv sync --dev
uv run pytest tests/

Input format

  • nodes.csv: tab-delimited; must include node id (e.g. id:int or id). Other columns become node properties.
  • rels.csv: tab-delimited; columns start, end, type (or start:str, end:str, type:str).

Usage

Load from CSV

from pathlib import Path
from cpg2py import cpg_graph, CpgGraph, CpgNode, CpgEdge

graph: CpgGraph = cpg_graph(Path("nodes.csv"), Path("rels.csv"))

Nodes and edges (edge identified by (from_id, to_id, edge_type); edge_type is string)

node: CpgNode = graph.node("2")
node.name
node.set_property("name", "x")
node.set_properties({"k": "v"})

edge: CpgEdge = graph.edge("2", "3", "ENTRY")
edge.from_nid, edge.to_nid, edge.type
edge.set_property("weight", 0.5)

Traversal

graph.succ(node)   # successors
graph.prev(node)   # predecessors
graph.children(node)
graph.parent(node)
graph.flow_to(node)
graph.flow_from(node)
graph.topfile_node("5")   # top-level file node for given node ID

Filtered iteration (optional predicate)

graph.nodes(lambda n: n.type == "Function")
graph.edges(lambda e: e.edge_type == "FLOWS_TO")
graph.succ(node, who_satisifies=lambda e: e.edge_type == "PARENT_OF")
graph.descendants(node, condition=...)
graph.ancestors(node, condition=...)

JSON persistence

graph.storage.save_json("graph.json")

storage = Storage()
storage.load_json("graph.json")
graph2 = CpgGraph(storage)

# or
storage = storage_from_json(Path("graph.json"))

JSON schema: {"nodes": { "<id>": { "<key>": <value>, ... }, ... }, "edges": [ {"from": str, "to": str, "type": str, "props": {...} }, ... ]}. See design.md.


Extending (ABCs)

Implement AbcGraphQuerier[MyNode, MyEdge], AbcNodeQuerier, AbcEdgeQuerier; inject Storage. Full interface and contracts: docs/design.md.

Minimal custom graph:

from cpg2py import AbcGraphQuerier, AbcNodeQuerier, AbcEdgeQuerier, Storage
from typing import Optional

class MyNode(AbcNodeQuerier): pass
class MyEdge(AbcEdgeQuerier): pass

class MyGraph(AbcGraphQuerier[MyNode, MyEdge]):
    def node(self, whose_id_is: str) -> Optional[MyNode]:
        return MyNode(self.storage, whose_id_is)
    def edge(self, fid: str, tid: str, eid: str) -> Optional[MyEdge]:
        return MyEdge(self.storage, fid, tid, eid)

g = MyGraph(Storage())

Interface specifications (classes, methods, signatures, validation): docs/design.md.


License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cpg2py-1.2.1.tar.gz (25.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cpg2py-1.2.1-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file cpg2py-1.2.1.tar.gz.

File metadata

  • Download URL: cpg2py-1.2.1.tar.gz
  • Upload date:
  • Size: 25.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for cpg2py-1.2.1.tar.gz
Algorithm Hash digest
SHA256 1333d46bb1a9d19588a6f711838cf34356948b1901a49416f41059b43bb7febb
MD5 653c5ac5a8bf35bf3eb2a4f41f6d3d23
BLAKE2b-256 36a950863126c306abf2561fe41d0863beade42ba3a176c75752f8aa8a60f655

See more details on using hashes here.

File details

Details for the file cpg2py-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: cpg2py-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 16.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.20

File hashes

Hashes for cpg2py-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fa844089cb5826c51bfc853043717804d7c451b9015684c1476e9cbce35f53d2
MD5 677e27760189c0d23710de6017dccc00
BLAKE2b-256 3120a1d038594f8743f829b71de0ce3de7d2a8bd706114a05ee0c0933d58f217

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page