API Reference

Complete reference for the sgraph Python API.

Core Classes

SGraph

The main graph container class that holds the entire model.

from sgraph import SGraph, SElement

# Create a new graph
root_element = SElement(None, 'root')
graph = SGraph(root_element)

Methods

createOrGetElementFromPath(path: str) -> SElement

Creates or retrieves an element at the specified path.

element = graph.createOrGetElementFromPath('/project/src/main.py')
getAllElements() -> List[SElement]

Returns all elements in the graph.

all_elements = graph.getAllElements()
print(f"Total elements: {len(all_elements)}")
getElementsByName(name: str) -> List[SElement]

Finds all elements with the specified name.

main_files = graph.getElementsByName('main.py')
to_xml(fname: str = None) -> str

Exports the graph to sgraph XML format.

# Return as string
xml_content = graph.to_xml()

# Save to file
graph.to_xml('model.xml')
to_deps(fname: str = None) -> str

Exports the graph to Deps format.

# Return as string
deps_content = graph.to_deps()

# Save to file
graph.to_deps('dependencies.txt')

SElement

Represents a single element (node) in the graph.

from sgraph import SElement

# Create an element
parent = SElement(None, 'parent')
child = SElement(parent, 'child')

Properties

  • name: str - The element’s name
  • parent: SElement - Parent element (None for root)
  • id: int - Unique identifier

Methods

getPath() -> str

Returns the full path from root to this element.

path = element.getPath()
# Example: '/project/src/main.py'
getChildElements() -> List[SElement]

Returns direct children of this element.

children = element.getChildElements()
for child in children:
    print(child.name)
addAttribute(key: str, value: str)

Adds a custom attribute.

element.addAttribute('type', 'file')
element.addAttribute('loc', '150')
getAttribute(key: str, default_value: str = None) -> str

Retrieves an attribute value.

file_type = element.getAttribute('type', 'unknown')
lines = int(element.getAttribute('loc', '0'))
getAssociationsFrom() -> List[SElementAssociation]

Returns all outgoing associations.

dependencies = element.getAssociationsFrom()
for dep in dependencies:
    print(f"Depends on: {dep.toElement.getPath()}")
getAssociationsTo() -> List[SElementAssociation]

Returns all incoming associations.

dependents = element.getAssociationsTo()
for dep in dependents:
    print(f"Used by: {dep.fromElement.getPath()}")

SElementAssociation

Represents a relationship between two elements.

from sgraph import SElementAssociation

# Create an association
association = SElementAssociation(from_element, to_element, 'import')
association.initElems()  # Must call this to activate the association

Properties

  • fromElement: SElement - Source element
  • toElement: SElement - Target element
  • type: str - Relationship type

Methods

initElems()

Activates the association by adding it to both elements.

association.initElems()
addAttribute(key: str, value: str)

Adds metadata to the relationship.

association.addAttribute('frequency', 'high')
association.addAttribute('conditional', 'true')
getAttribute(key: str, default_value: str = None) -> str

Retrieves relationship metadata.

frequency = association.getAttribute('frequency', 'unknown')

High-Level APIs

ModelApi

Provides convenient methods for querying and analyzing models.

from sgraph.modelapi import ModelApi

# Load a model
api = ModelApi(filepath='model.xml')

Methods

getAllElements() -> List[SElement]

Returns all elements in the model.

getElementsByName(name: str) -> List[SElement]

Finds elements by name.

getElementsByType(element_type: str) -> List[SElement]

Finds elements by type attribute.

functions = api.getElementsByType('function')
classes = api.getElementsByType('class')
getCalledFunctions(element: SElement) -> List[SElement]

For a function element, returns all functions it calls.

called = api.getCalledFunctions(main_function)
print(f"Calls {len(called)} functions")
getCallingFunctions(element: SElement) -> List[SElement]

For a function element, returns all functions that call it.

callers = api.getCallingFunctions(utility_function)
print(f"Called by {len(callers)} functions")

MetricsApi

Provides methods for calculating architecture metrics.

from sgraph.metricsapi import MetricsApi

metrics = MetricsApi(filepath='model.xml')

Methods

calculateComplexityMetrics() -> Dict

Calculates various complexity metrics.

calculateCouplingMetrics() -> Dict

Calculates coupling and cohesion metrics.

Converters

XML Converters

XmlToDeps

from sgraph.converters.xml_to_deps import XmlToDeps

converter = XmlToDeps()
converter.convert('model.xml', 'dependencies.txt')

XmlToJson

from sgraph.converters.xml_to_json import XmlToJson

converter = XmlToJson()
converter.convert('model.xml', 'model.json')

XmlToGraphMl

from sgraph.converters.xml_to_graphml import XmlToGraphMl

converter = XmlToGraphMl()
converter.convert('model.xml', 'graph.graphml')

XmlToPlantUml

from sgraph.converters.xml_to_plantuml import XmlToPlantUml

converter = XmlToPlantUml()
converter.convert('model.xml', 'diagram.puml')

Format Converters

DepsToXml

from sgraph.converters.deps_to_xml import DepsToXml

converter = DepsToXml()
converter.convert('dependencies.txt', 'model.xml')

GraphMlToXml

from sgraph.converters.graphml_to_xml import GraphMlToXml

converter = GraphMlToXml()
converter.convert('graph.graphml', 'model.xml')

Visualization Converters

SGraphToCytoscape

from sgraph.converters.sgraph_to_cytoscape import SGraphToCytoscape

converter = SGraphToCytoscape()
converter.convert('model.xml', 'cytoscape.html')

XmlTo3DForceGraph

from sgraph.converters.xml_to_3dforcegraph import XmlTo3DForceGraph

converter = XmlTo3DForceGraph()
converter.convert('model.xml', 'force_graph.html')

Algorithms

Graph Analysis

SGraphAnalysis

from sgraph.algorithms.sgraphanalysis import SGraphAnalysis

analysis = SGraphAnalysis(model)
Methods
  • findCycles() -> List[List[SElement]] - Detect circular dependencies
  • calculateDepth(element: SElement) -> int - Calculate element depth
  • findRoots() -> List[SElement] - Find root elements

SGraphMetrics

from sgraph.algorithms.sgraphmetrics import SGraphMetrics

metrics = SGraphMetrics(model)
Methods
  • calculateFanIn(element: SElement) -> int - Count incoming dependencies
  • calculateFanOut(element: SElement) -> int - Count outgoing dependencies
  • calculateInstability(element: SElement) -> float - Calculate instability metric

Filtering

SGraphFiltering

from sgraph.algorithms.sgraphfiltering import SGraphFiltering

filtering = SGraphFiltering(model)
Methods
  • filterByType(element_type: str) -> SGraph - Filter by element type
  • filterByPath(path_pattern: str) -> SGraph - Filter by path pattern
  • removeIsolatedElements() -> SGraph - Remove elements with no relationships

Comparison

ModelCompare

from sgraph.compare.modelcompare import ModelCompare

comparer = ModelCompare()
# Returns a *compare model* (an SGraph), not a plain dict.
compare_model = comparer.compare('old_model.xml', 'new_model.xml')

compare() / compareModels() return a new SGraph (the “compare model”) in which differences are annotated as element/association attributes (compare, _only_in, _changed_dep, _change_count, _attr_diff, …). Use the getCompareInfos() / printCompareInfos() helpers, or the individual extractors below, to turn that compare model into structured results.

Building the compare model

compare(path1: str, path2: str, exclude_attrs: set[str] | None = None) -> SGraph

Loads two models from XML (or zipped XML) file paths and compares them.

compareModels(model1: SGraph, model2: SGraph, rename_detection: bool = False, exclude_attrs: set[str] | None = None) -> SGraph

Compares two already-loaded in-memory models.

exclude_attrs is a set of attribute names to ignore during comparison. The preset SLIDING_WINDOW_ATTRS (from sgraph.compare.compareutils) suppresses time-windowed metric noise (author/commit/bug counts, last_modified, etc.):

from sgraph.compare.compareutils import SLIDING_WINDOW_ATTRS

compare_model = comparer.compare('a.xml', 'b.xml', exclude_attrs=SLIDING_WINDOW_ATTRS)

Reading the results

getCompareInfos(compare_model: SGraph) -> tuple

Returns a 6-tuple: (new_deps, removed_deps, changed_elems, new_elems, removed_elems, attr_changes).

printCompareInfos(compare_model: SGraph) -> tuple

Prints a human-readable summary and returns the same 6-tuple as getCompareInfos().

The tuple elements are:

Field Shape Meaning
new_deps list[(SElementAssociation, int)] Added dependencies with dependency length, longest first
removed_deps list[(SElementAssociation, int)] Removed dependencies with dependency length, longest first
changed_elems list[(SElement, int)] Elements with a change count, highest first
new_elems list[(str, SElement)] Added elements as ("parent/name", element)
removed_elems list[(str, SElement)] Removed elements as ("parent/name", element)
attr_changes list[(SElement, str)] Elements whose attributes changed, with the diff string

Individual extractors are also available: newAndRemovedElems(), newAndRemovedDependenciesLists(), elemsWithChanges(), elemsWithAttrChanges(), uniqueConnectionsCreated(), uniqueConnectionsRemoved(), externalChanges(), and getElementsWithAttrDiff(compare_model, attribute).

CLI Tools

show_model

Display model information.

python -m sgraph.cli.show_model model.xml

Options:

  • --stats - Show statistics
  • --elements - List all elements
  • --relationships - Show relationships

filter

Filter model content.

python -m sgraph.cli.filter model.xml --output filtered.xml --include "*.py"

Options:

  • --include PATTERN - Include elements matching pattern
  • --exclude PATTERN - Exclude elements matching pattern
  • --type TYPE - Filter by element type
  • --output FILE - Output file path

compare

Compare two models and report the differences (added/removed/changed elements and dependencies). MODEL_A is the “before”/old model, MODEL_B the “after”/new model.

# Human-readable summary
python -m sgraph.cli.compare old_model.xml new_model.xml

# Machine-readable, pretty-printed JSON
python -m sgraph.cli.compare old_model.xml new_model.xml -f json

Options:

  • -f, --format {text,json} - Output format (default: text; text reuses ModelCompare.printCompareInfos())
  • -o, --output FILE - Write output to a file instead of stdout
  • --rename-detection - Detect renamed elements (collapses an add+remove into a single changed element annotated with old_name)
  • --exclude-attrs a,b,c - Comma-separated attribute names to ignore during comparison

Exit codes follow git diff conventions:

Code Meaning
0 Models are equivalent (no differences)
1 Differences were found
2 Error (bad path, parse failure, or usage error)

This makes it usable as a change gate in scripts/CI:

if ! python -m sgraph.cli.compare before.xml after.xml -f json -o diff.json; then
    echo "Model changed — see diff.json"
fi

Exceptions

SElementMergedException

Raised when attempting to merge elements incorrectly.

from sgraph.exceptions import SElementMergedException

try:
    # Some operation that might fail
    element.merge(other_element)
except SElementMergedException as e:
    print(f"Merge failed: {e}")

ModelNotFoundException

Raised when a model file cannot be found.

from sgraph.exceptions import ModelNotFoundException

try:
    api = ModelApi(filepath='nonexistent.xml')
except ModelNotFoundException as e:
    print(f"Model not found: {e}")

Utilities

Graph Utilities

from sgraph.algorithms.graphutils import GraphUtils

# Find shortest path
path = GraphUtils.findShortestPath(from_element, to_element)

# Calculate graph diameter
diameter = GraphUtils.calculateDiameter(model)

# Find strongly connected components
components = GraphUtils.findStronglyConnectedComponents(model)

Element Utilities

from sgraph.algorithms.selementutils import SElementUtils

# Get all descendants
descendants = SElementUtils.getAllDescendants(element)

# Check if element is ancestor
is_ancestor = SElementUtils.isAncestor(parent, child)

# Calculate element size (including children)
size = SElementUtils.calculateSubtreeSize(element)

Configuration

Loading Configuration

from sgraph.loader.modelloader import ModelLoader

# Configure loader
loader = ModelLoader()
loader.configure({
    'batch_size': 1000,
    'validate': True,
    'encoding': 'utf-8'
})

# Load with configuration
model = loader.load('large_model.xml')

Best Practices

Performance Optimization

# Use ModelApi for large models
api = ModelApi(filepath='large_model.xml')

# Query specific elements instead of loading all
specific_elements = api.getElementsByName('target_name')

# Use batch operations
elements_to_analyze = api.getElementsByType('function')

Memory Management

# For very large models, process incrementally
def process_large_model(filepath):
    api = ModelApi(filepath=filepath)
    
    # Process in chunks
    all_functions = api.getElementsByType('function')
    chunk_size = 1000
    
    for i in range(0, len(all_functions), chunk_size):
        chunk = all_functions[i:i + chunk_size]
        process_function_chunk(chunk)
        # Optionally clear processed data

Error Handling

from sgraph.exceptions import SElementMergedException, ModelNotFoundException

def safe_model_operation(filepath):
    try:
        api = ModelApi(filepath=filepath)
        # Perform operations
        return api.getAllElements()
        
    except ModelNotFoundException:
        print("Model file not found")
        return []
        
    except SElementMergedException:
        print("Element merge conflict")
        return []
        
    except Exception as e:
        print(f"Unexpected error: {e}")
        return []

This API reference covers the essential classes and methods you’ll need to work with sgraph effectively. For the most up-to-date information, refer to the source code and docstrings.