Graphinate 0.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
graphinate/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ from . import builders, renderers
2
+ from .builders import build
3
+ from .enums import GraphType
4
+ from .modeling import GraphModel, Multiplicity, model
5
+ from .renderers import graphql, matplotlib, mermaid
6
+
7
+ __all__ = (
8
+ 'GraphModel',
9
+ 'GraphType',
10
+ 'Multiplicity',
11
+ 'build',
12
+ 'builders',
13
+ 'graphql',
14
+ 'matplotlib',
15
+ 'mermaid',
16
+ 'model',
17
+ 'renderers'
18
+ )
graphinate/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .cli import cli # pragma: no cover
2
+
3
+ if __name__ == '__main__': # pragma: no cover
4
+ cli()
@@ -0,0 +1,55 @@
1
+ """Builder Classes: Abstraction Layer to Generate Graph Data Structures
2
+
3
+ This module defines builder base classes and implementations that construct graph
4
+ data structures from a `GraphModel`. It supports generating various graph formats,
5
+ including NetworkX, D3, Mermaid, and GraphQL schema representations.
6
+
7
+ Attributes:
8
+ - **GraphRepresentation:** Types of representations the builder can produce.
9
+ - **GraphType:** Enumeration for different graph types (directed, undirected, etc.).
10
+
11
+ Main Classes:
12
+ - `GraphType` : Enum defining networkx-compatible graph types.
13
+ - `Builder` : Abstract base class for custom graph builders.
14
+ - `NetworkxBuilder` : A builder class for constructing Graph representations using NetworkX.
15
+ - `D3Builder` : Builder class transforming graphs into D3-compatible structures.
16
+ - `MermaidBuilder`: Supports MermaidJS diagram generation.
17
+ - `GraphQLBuilder`: Constructs GraphQL schema representations of graphs.
18
+ """
19
+
20
+ __all__ = ['Builder', 'D3Builder', 'GraphQLBuilder', 'MermaidBuilder', 'NetworkxBuilder', 'build']
21
+
22
+ from collections.abc import Mapping
23
+ from typing import Any
24
+
25
+ from ..enums import GraphType
26
+ from ..modeling import GraphModel
27
+ from ._builder import Builder
28
+ from ._d3 import D3Builder
29
+ from ._graphql import GraphQLBuilder
30
+ from ._mermaid import MermaidBuilder
31
+ from ._networkx import NetworkxBuilder
32
+
33
+
34
+ def build(builder_cls: type[Builder],
35
+ graph_model: GraphModel,
36
+ graph_type: GraphType = GraphType.Graph,
37
+ default_node_attributes: Mapping | None = None,
38
+ **kwargs: Any) -> Any:
39
+ """
40
+ Build a graph from a graph model
41
+
42
+ Args:
43
+ builder_cls: builder class type
44
+ graph_model: a GraphModel instance
45
+ graph_type: type of the generated graph
46
+ default_node_attributes: default node attributes
47
+ **kwargs: node id values
48
+
49
+ Returns:
50
+ Graph data structure
51
+ """
52
+
53
+ builder = builder_cls(graph_model, graph_type)
54
+ materialized_graph = builder.build(default_node_attributes=default_node_attributes, **kwargs)
55
+ return materialized_graph
@@ -0,0 +1,58 @@
1
+ from abc import ABC, abstractmethod
2
+ from collections.abc import Mapping
3
+ from types import MappingProxyType
4
+ from typing import Any
5
+
6
+ from ..converters import edge_label_converter, node_label_converter
7
+ from ..enums import GraphType
8
+ from ..modeling import GraphModel
9
+ from ..typing import GraphRepresentation
10
+
11
+
12
+ class Builder(ABC):
13
+ """Abstract Base Class for Graph Builders.
14
+
15
+ This class acts as a blueprint for all concrete builders that generate graph-like
16
+ data structures from a given `GraphModel`.
17
+
18
+ Attributes:
19
+ default_node_attributes (Mapping): Default attributes for all nodes.
20
+ default_edge_attributes (Mapping): Default attributes for all edges.
21
+ """
22
+
23
+ default_node_attributes: Mapping = MappingProxyType({
24
+ 'type': 'node',
25
+ 'label': node_label_converter,
26
+ 'value': [],
27
+ 'lineage': None
28
+ })
29
+
30
+ default_edge_attributes: Mapping = MappingProxyType({
31
+ 'type': 'edge',
32
+ 'label': edge_label_converter,
33
+ 'value': [],
34
+ 'weight': 1.0
35
+ })
36
+
37
+ def __init__(self, model: GraphModel, graph_type: GraphType = GraphType.Graph):
38
+ """Initialize a Builder instance with a specific graph model and type.
39
+
40
+ Args:
41
+ model (GraphModel): The model defining the graph's structure and data.
42
+ graph_type (GraphType): Enum specifying the type of the graph.
43
+ """
44
+
45
+ self._cached_build_kwargs: dict[str, Any] = {}
46
+ self.model = model
47
+ self.graph_type = graph_type
48
+
49
+ @abstractmethod
50
+ def build(self, **kwargs: Any) -> GraphRepresentation:
51
+ """Build the graph representation.
52
+
53
+ Subclasses must override this method to implement specific build logic.
54
+
55
+ Args:
56
+ **kwargs: Any additional parameters for the build process.
57
+ """
58
+ self._cached_build_kwargs = MappingProxyType(kwargs)
@@ -0,0 +1,61 @@
1
+ import json
2
+ from collections.abc import Iterable, Mapping
3
+ from datetime import datetime, timedelta
4
+ from typing import Any, Literal
5
+
6
+ import mappingtools
7
+ import networkx as nx
8
+
9
+ from .. import color
10
+ from ..enums import GraphType
11
+ from ..modeling import GraphModel
12
+ from ._networkx import NetworkxBuilder
13
+
14
+
15
+ def _convert(obj: Any) -> Any:
16
+ """if obj is a not python scalar (e.g. it's some sort of container)
17
+ then return it as is otherwise convert it to a JSON string"""
18
+ match obj:
19
+ case bytes():
20
+ return obj.decode()
21
+ case datetime():
22
+ return obj.isoformat()
23
+ case timedelta():
24
+ return f"{obj.total_seconds()} s"
25
+ case Mapping() | Iterable() | str():
26
+ return obj
27
+ case _:
28
+ return json.dumps(obj, default=str)
29
+
30
+
31
+ class D3Builder(NetworkxBuilder):
32
+ """Build a D3 Graph"""
33
+
34
+ def __init__(self, model: GraphModel, graph_type: GraphType = GraphType.Graph):
35
+ super().__init__(model, graph_type)
36
+
37
+ def build(self, values_format: Literal['json', 'python'] = 'python', **kwargs: Any) -> dict:
38
+ """
39
+ Args:
40
+ values_format: Literal['python', 'json'] - The format of the values
41
+ **kwargs:
42
+
43
+ Returns:
44
+ D3 Graph
45
+ """
46
+ super().build(**kwargs)
47
+ color.convert_colors_to_hex(self._graph)
48
+ d3graph: dict = self.from_networkx(self._graph)
49
+
50
+ match values_format:
51
+ case 'json':
52
+ return mappingtools.transformers.strictify(d3graph, value_converter=_convert)
53
+ case 'python':
54
+ return d3graph
55
+ case _:
56
+ raise ValueError(f"Invalid values format: {values_format}")
57
+
58
+ @staticmethod
59
+ def from_networkx(nx_graph: nx.Graph) -> dict:
60
+ d3_graph: dict = nx.node_link_data(nx_graph, nodes='nodes', edges='links')
61
+ return d3_graph