Docs ยท Python

glia-py, the engine in process.

pip install glia-py, import glia_py. Build a graph once, keep it loaded, ask it questions. An answer is a native dict or list; only a *_json method returns JSON text. Every record's line is 1-based. A PyGraph holds its own ranking cache for its lifetime and reads the history and calibration snapshots under its repo roots.

A session

import glia_py

g = glia_py.generate(".")                       # build (or load_from_gmap(".") for a cached layout)
g.service_map()                                 # glia arch
g.find("Order")                                 # ranked, located nodes
g.blast_radius("api::internal::models::order::Order", depth=4, top_files=10)
g.cross_stack_trace("POST /api/orders @api")
g.contract_fields()                             # the http_model / graphql_selection drift rows
g.query('unhandled(R) :- node(R, "ROUTE"), not edge(R, _, "HANDLED_BY").')

glia_py.review_vs_rev(".", "main", format="markdown")   # the PR report
glia_py.history_sync(".")                                # once per repo, for the ranked answers

w = glia_py.WatchSession(".")                   # keep the build open
w.poll()                                        # None, or what the last change did to the graph
w.snapshot().blast_radius("Order")

Surface

Every signature below is read from py/api_surface/, the committed pyo3 surface a test regenerates in the commit that changes it.

  • method PyGraph.coverage() -> PyResult<Py<PyAny>>
  • method PyGraph.project_roots() -> PyResult<Py<PyAny>>
  • method PyGraph.service_map(collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.blast_radius(qnames: &Bound<'_, PyAny>, direction: &str = "both", depth: usize = 4, top_k: Option<usize> = None, live_only: bool = false, scope: Option<&str> = None, collapse: bool = true, ranking: Option<&str> = None, cochange: bool = true, top_files: usize = 10) -> PyResult<Py<PyAny>>
  • method PyGraph.node_cell_bytes(node_id: u64, cell_type: &str) -> PyResult<Option<Py<PyBytes>>>
  • method PyGraph.remove_cell(qname: &str, cell_type: &str, entry_id: &str, source: &str = "api") -> PyResult<bool>
  • method PyGraph.set_cell(qname: &str, cell_type: &str, payload: &Bound<'_, PyAny>, kind: Option<String> = None, model: Option<String> = None, dims: Option<u32> = None, hint: Option<String> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.check(strict: bool = false) -> PyResult<Py<PyAny>>
  • method PyGraph.cochange(files: Vec<String>, min_confidence: f64 = 0.3, min_support: u32 = 3, top: usize = 20, unlinked_only: bool = false) -> PyResult<Py<PyAny>>
  • method PyGraph.communities(scope: Option<String> = None, seed: u64 = 42, resolution: f64 = 1.0, top: usize = 30, members: usize = 10, method: Option<String> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.contract_fields() -> PyResult<Py<PyAny>>
  • method PyGraph.contracts() -> PyResult<Py<PyAny>>
  • method PyGraph.cycles(kind: &str = "all", scope: Option<&str> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.diff_impact(diff_text: &str, direction: &str = "both", depth: usize = 4, top_k: Option<usize> = None, live_only: bool = false, scope: Option<&str> = None, ranking: Option<&str> = None, cochange: bool = true, top_files: usize = 10) -> PyResult<Py<PyAny>>
  • method PyGraph.governing_docs(qname: &str, scope: Option<&str> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.duplicate_flows(scope: Option<String> = None, depth: usize = 6, threshold: f64 = 0.8, min_size: usize = 3, include_tests: bool = false, keep_hubs: bool = false) -> PyResult<Py<PyAny>>
  • method PyGraph.effects(qnames: Vec<String>, depth: usize = 8, classes: Option<Vec<String>> = None, writes_only: bool = false, cross_service: bool = false, scope: Option<String> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.feature_flows(group_by: &str = "feature", depth: usize = 6, feature: Option<&str> = None, scope: Option<&str> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.write_feature_flows(out_dir: Option<&str> = None, group_by: &str = "feature", depth: usize = 6) -> PyResult<Py<PyAny>>
  • method PyGraph.find(query: &str, top_k: usize = 20, kinds: Option<Vec<String>> = None, scope: Option<String> = None, collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.find_files(query: &str, top_k: usize = 20) -> PyResult<Py<PyAny>>
  • method PyGraph.resolve(text: &str, kind: &str = "auto", top_k: Option<usize> = None, scope: Option<&str> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.flags(quiet_days: u32 = 90, scope: Option<String> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.gaps(top_k: Option<usize> = None, category: Option<&str> = None) -> PyResult<Py<PyAny>>
  • class PyGraph
  • method PyGraph.cross_edge_count() -> usize
  • method PyGraph.edge_count() -> usize
  • method PyGraph.node_cells(node_id: u64) -> Vec<(u32, String)>
  • method PyGraph.node_count() -> usize
  • method PyGraph.save_to(dir: &str, repo_path: Option<&str> = None) -> PyResult<()>
  • method PyGraph.save_to_default(repo_path: &str) -> PyResult<()>
  • method PyGraph.hotspots(level: &str = "both", top: usize = 20, min_churn: u32 = 2, include_tests: bool = false, scope: Option<String> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.hubs(scope: Option<String> = None, top: usize = 20, category: Option<String> = None, min_degree: u32 = 5, include_tests: bool = false) -> PyResult<Py<PyAny>>
  • method PyGraph.identity_classes(tier: Option<String> = None, rule: Option<String> = None, diverged_only: bool = false, limit: Option<usize> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.implementors(qname: &str, direction: &str = "down", transitive: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.pack(query: &str, budget: usize = 8000, bytes_per_token: f64 = 3.7, seeds: usize = 5, candidates: usize = 200, preset: Option<String> = None, scope: Option<String> = None, ranking: Option<&str> = None, cochange: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.pack_ids(node_ids: Vec<u64>, budget: usize = 8000, bytes_per_token: f64 = 3.7, candidates: usize = 200, preset: Option<String> = None, scope: Option<String> = None, ranking: Option<&str> = None, cochange: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.page_flow() -> PyResult<Py<PyAny>>
  • method PyGraph.patterns(min_support: usize = 5, min_share: usize = 75, scope: Option<&str> = None, group_by: &str = "service") -> PyResult<Py<PyAny>>
  • method PyGraph.query(program: &str, outputs: Option<Vec<String>> = None, limit: Option<usize> = None, explain: bool = false, max_rows: Option<usize> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.query_gql(query: &str, limit: Option<usize> = None, explain: bool = false, max_rows: Option<usize> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.edges_json() -> PyResult<String>
  • method PyGraph.nodes_json() -> PyResult<String>
  • method PyGraph.serves(channel: &str, mechanism: &str = "auto", collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.spec_status(feature: Option<&str> = None) -> PyResult<Py<PyAny>>
  • method PyGraph.splits(scope: Option<String> = None, parts: usize = 2, quotient: &str = "module", source: Option<String> = None, sink: Option<String> = None, min_share: f64 = 0.1, seed: u64 = 42) -> PyResult<Py<PyAny>>
  • method PyGraph.tests_for(qnames: Vec<String>, depth: usize = 6, scope: Option<&str> = None, module_level: bool = true, limit: Option<usize> = None, signals: bool = true, collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.tests_for_diff(diff_text: &str, depth: usize = 6, scope: Option<&str> = None, module_level: bool = true, limit: Option<usize> = None, signals: bool = true, collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.activate(seed_ids: Vec<u64>, top_k: Option<usize> = None, profile: Option<String> = None) -> Vec<(u64, f64)>
  • method PyGraph.dense_text() -> String
  • method PyGraph.dense_text_full() -> String
  • method PyGraph.dense_text_subset(node_ids: Vec<u64>, full: bool = false) -> String
  • method PyGraph.prose(node_ids: Vec<u64>) -> String
  • method PyGraph.cross_stack_trace(feature: &str, depth: usize = 6, to: Option<&str> = None, max_paths: usize = 10, collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.entry_flows(depth: usize = 6, collapse: bool = true) -> PyResult<Py<PyAny>>
  • method PyGraph.bfs(node_id: u64, direction: &str = "out", categories: Option<Vec<CategoryArg>> = None, depth: usize = 3) -> PyResult<Vec<(u64, usize, u32, u64)>>
  • method PyGraph.neighbours(node_id: u64, direction: &str = "out", categories: Option<Vec<CategoryArg>> = None) -> PyResult<Vec<(u64, u32, &'static str)>>
  • method PyGraph.predecessors(node_id: u64, categories: Option<Vec<CategoryArg>> = None, depth: usize = 3) -> PyResult<Vec<u64>>
  • method PyGraph.reachable_by(sink_id: u64, source_ids: Vec<u64>, categories: Option<Vec<CategoryArg>> = None, depth: usize = 6) -> PyResult<Vec<u64>>
  • method PyGraph.shortest_path(from_id: u64, to_id: u64, direction: &str = "both", categories: Option<Vec<CategoryArg>> = None, depth: usize = 12) -> PyResult<Option<Vec<PathStep>>>
  • class WatchSession (name = "WatchSession")
  • method WatchSession.apply(paths: Vec<PathBuf>) -> PyResult<Py<PyAny>>
  • method WatchSession.persist() -> PyResult<()>
  • method WatchSession.poll() -> PyResult<Option<Py<PyAny>>>
  • method WatchSession.snapshot() -> PyGraph
  • method PyGraph.why(from_qname: &str, to_qname: &str, category: Option<&str> = None) -> PyResult<Py<PyAny>>