pygraph-sp 2026.1__cp312-cp312-macosx_11_0_arm64.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.
graph_sp/__init__.py
ADDED
|
Binary file
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pygraph-sp
|
|
3
|
+
Version: 2026.1
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Rust
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
17
|
+
Summary: High-performance DAG execution engine with true parallel execution, built in Rust with Python bindings
|
|
18
|
+
Keywords: dag,graph,parallel,execution,workflow,pipeline
|
|
19
|
+
Author: briday1
|
|
20
|
+
License: MIT
|
|
21
|
+
Requires-Python: >=3.7
|
|
22
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
23
|
+
Project-URL: Documentation, https://github.com/briday1/graph-sp#readme
|
|
24
|
+
Project-URL: Homepage, https://github.com/briday1/graph-sp
|
|
25
|
+
Project-URL: Issues, https://github.com/briday1/graph-sp/issues
|
|
26
|
+
Project-URL: Repository, https://github.com/briday1/graph-sp
|
|
27
|
+
|
|
28
|
+
# graph-sp Python Bindings
|
|
29
|
+
|
|
30
|
+
Python bindings for the graph-sp DAG execution engine.
|
|
31
|
+
|
|
32
|
+
For complete documentation and installation instructions, visit the [PyPI package page](https://pypi.org/project/graph-sp/) or the [main repository](https://github.com/briday1/graph-sp).
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install graph-sp
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import graph_sp
|
|
44
|
+
|
|
45
|
+
# Create a graph
|
|
46
|
+
graph = graph_sp.Graph()
|
|
47
|
+
|
|
48
|
+
# Add nodes
|
|
49
|
+
graph.add(
|
|
50
|
+
"source", "Data Source",
|
|
51
|
+
[], # no inputs
|
|
52
|
+
[graph_sp.Port("output", "Numbers")],
|
|
53
|
+
lambda inputs: {"output": [1, 2, 3, 4, 5]}
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
graph.add(
|
|
57
|
+
"doubler", "Multiply by 2",
|
|
58
|
+
[graph_sp.Port("input", "Input")],
|
|
59
|
+
[graph_sp.Port("output", "Output")],
|
|
60
|
+
lambda inputs: {"output": [x * 2 for x in inputs["input"]]}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Connect and execute
|
|
64
|
+
graph.add_edge("source", "output", "doubler", "input")
|
|
65
|
+
executor = graph_sp.Executor()
|
|
66
|
+
result = executor.execute(graph)
|
|
67
|
+
|
|
68
|
+
print(result.get_output("doubler", "output")) # [2, 4, 6, 8, 10]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Examples
|
|
72
|
+
|
|
73
|
+
This directory contains complete Python examples:
|
|
74
|
+
|
|
75
|
+
- **simple_pipeline.py**: Basic 3-node pipeline with graph analysis and Mermaid diagrams
|
|
76
|
+
- **complex_objects.py**: Demonstrates nested objects, JSON, and lists
|
|
77
|
+
- **parallel_execution.py**: Shows parallel execution with 3 independent branches
|
|
78
|
+
- **implicit_edges.py**: Demonstrates auto_connect() with parallel branches and multi-line labels
|
|
79
|
+
|
|
80
|
+
### Running Examples
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Simple pipeline
|
|
84
|
+
python simple_pipeline.py
|
|
85
|
+
|
|
86
|
+
# Complex data structures
|
|
87
|
+
python complex_objects.py
|
|
88
|
+
|
|
89
|
+
# Parallel execution (shows 44% speedup)
|
|
90
|
+
python parallel_execution.py
|
|
91
|
+
|
|
92
|
+
# Implicit edge mapping
|
|
93
|
+
python implicit_edges.py
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Features
|
|
97
|
+
|
|
98
|
+
- ⚡ **True Parallel Execution**: Independent nodes run concurrently (44% faster)
|
|
99
|
+
- 🔌 **Port-based Architecture**: Type-safe data flow between nodes
|
|
100
|
+
- 🔗 **Implicit Edge Mapping**: Auto-connect nodes by matching port names
|
|
101
|
+
- 📊 **Rich Data Types**: Primitives, lists, nested dicts, JSON, binary data
|
|
102
|
+
- 🔍 **Graph Analysis**: Depth, width, sources, sinks, and optimization suggestions
|
|
103
|
+
- 🎨 **Rich Mermaid Diagrams**: Color-coded nodes, parallel group detection, multi-line labels
|
|
104
|
+
- ✅ **Cycle Detection**: Built-in DAG validation
|
|
105
|
+
|
|
106
|
+
## API Overview
|
|
107
|
+
|
|
108
|
+
### Creating Graphs
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import graph_sp
|
|
112
|
+
|
|
113
|
+
# Create a new graph
|
|
114
|
+
graph = graph_sp.Graph()
|
|
115
|
+
|
|
116
|
+
# Add a node with a Python function
|
|
117
|
+
graph.add(
|
|
118
|
+
"node_id", # Unique identifier
|
|
119
|
+
"Node Name", # Display name
|
|
120
|
+
[ # Input ports
|
|
121
|
+
graph_sp.Port("input1", "First Input"),
|
|
122
|
+
graph_sp.Port("input2", "Second Input")
|
|
123
|
+
],
|
|
124
|
+
[ # Output ports
|
|
125
|
+
graph_sp.Port("output", "Result")
|
|
126
|
+
],
|
|
127
|
+
lambda inputs: { # Node function
|
|
128
|
+
"output": inputs["input1"] + inputs["input2"]
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Connect nodes
|
|
133
|
+
graph.add_edge("source_node", "output_port", "target_node", "input_port")
|
|
134
|
+
|
|
135
|
+
# OR use implicit edge mapping (auto-connect by port names)
|
|
136
|
+
edges_created = graph.auto_connect() # No explicit add_edge() needed!
|
|
137
|
+
|
|
138
|
+
# Validate graph (checks for cycles)
|
|
139
|
+
graph.validate()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Implicit Edge Mapping (No add_edge() Needed!)
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Build graphs by matching port names automatically
|
|
146
|
+
graph = graph_sp.Graph()
|
|
147
|
+
|
|
148
|
+
# Add nodes with matching port names
|
|
149
|
+
graph.add("source", "Data Source", [],
|
|
150
|
+
[graph_sp.Port("data", "Data")], source_fn)
|
|
151
|
+
|
|
152
|
+
graph.add("processor", "Processor",
|
|
153
|
+
[graph_sp.Port("data", "Input")], # Matches "data" output!
|
|
154
|
+
[graph_sp.Port("result", "Result")], processor_fn)
|
|
155
|
+
|
|
156
|
+
graph.add("sink", "Sink",
|
|
157
|
+
[graph_sp.Port("result", "Input")], # Matches "result" output!
|
|
158
|
+
[], sink_fn)
|
|
159
|
+
|
|
160
|
+
# Auto-connect based on port name matching
|
|
161
|
+
edges_created = graph.auto_connect()
|
|
162
|
+
print(f"✓ Created {edges_created} edges automatically!")
|
|
163
|
+
|
|
164
|
+
# Generated Mermaid diagram shows all connections:
|
|
165
|
+
# source -->|"data→data"| processor
|
|
166
|
+
# processor -->|"result→result"| sink
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Executing Graphs
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
# Create executor
|
|
173
|
+
executor = graph_sp.Executor()
|
|
174
|
+
|
|
175
|
+
# Execute graph (automatically parallelizes independent nodes)
|
|
176
|
+
result = executor.execute(graph)
|
|
177
|
+
|
|
178
|
+
# Get outputs
|
|
179
|
+
value = result.get_output("node_id", "port_name")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Graph Analysis
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
# Analyze structure
|
|
186
|
+
analysis = graph.analyze()
|
|
187
|
+
print(f"Nodes: {analysis.node_count}")
|
|
188
|
+
print(f"Edges: {analysis.edge_count}")
|
|
189
|
+
print(f"Depth: {analysis.depth}")
|
|
190
|
+
print(f"Width: {analysis.width}") # Parallelization potential
|
|
191
|
+
print(f"Sources: {analysis.source_count}")
|
|
192
|
+
print(f"Sinks: {analysis.sink_count}")
|
|
193
|
+
|
|
194
|
+
# Get text visualization
|
|
195
|
+
structure = graph.visualize()
|
|
196
|
+
print(structure)
|
|
197
|
+
|
|
198
|
+
# Generate Mermaid diagram
|
|
199
|
+
mermaid = graph.to_mermaid()
|
|
200
|
+
print(mermaid)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Mermaid Visualization with Parallel Groups
|
|
204
|
+
|
|
205
|
+
Multi-line labels and parallel execution groups are automatically detected:
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
# Example with parallel branches and multi-line labels
|
|
209
|
+
graph = graph_sp.Graph()
|
|
210
|
+
|
|
211
|
+
graph.add_node("source", "Value Source", [],
|
|
212
|
+
[graph_sp.Port("value", "Value")], source_fn)
|
|
213
|
+
|
|
214
|
+
# Multi-line labels using \n
|
|
215
|
+
graph.add_node("branch_a", "Branch A\\n(×2)",
|
|
216
|
+
[graph_sp.Port("value", "Input")],
|
|
217
|
+
[graph_sp.Port("out_a", "Output")], branch_a_fn)
|
|
218
|
+
|
|
219
|
+
graph.add_node("branch_b", "Branch B\\n(+50)",
|
|
220
|
+
[graph_sp.Port("value", "Input")],
|
|
221
|
+
[graph_sp.Port("out_b", "Output")], branch_b_fn)
|
|
222
|
+
|
|
223
|
+
graph.add_node("merger", "Merger",
|
|
224
|
+
[graph_sp.Port("out_a", "A"), graph_sp.Port("out_b", "B")],
|
|
225
|
+
[], merger_fn)
|
|
226
|
+
|
|
227
|
+
graph.auto_connect()
|
|
228
|
+
mermaid = graph.to_mermaid()
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Generated output:**
|
|
232
|
+
|
|
233
|
+
```mermaid
|
|
234
|
+
graph TD
|
|
235
|
+
source["Value Source"]
|
|
236
|
+
style source fill:#e1f5ff,stroke:#01579b,stroke-width:2px
|
|
237
|
+
branch_a["Branch A<br/>(×2)"]
|
|
238
|
+
style branch_a fill:#fff3e0,stroke:#e65100,stroke-width:2px
|
|
239
|
+
branch_b["Branch B<br/>(+50)"]
|
|
240
|
+
style branch_b fill:#fff3e0,stroke:#e65100,stroke-width:2px
|
|
241
|
+
merger["Merger"]
|
|
242
|
+
style merger fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
|
|
243
|
+
|
|
244
|
+
%% Parallel Execution Groups Detected
|
|
245
|
+
%% Group 1: 2 nodes executing in parallel
|
|
246
|
+
|
|
247
|
+
subgraph parallel_group_1["⚡ Parallel Execution Group 1"]
|
|
248
|
+
direction LR
|
|
249
|
+
branch_b
|
|
250
|
+
branch_a
|
|
251
|
+
end
|
|
252
|
+
style parallel_group_1 fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,stroke-dasharray: 5 5
|
|
253
|
+
|
|
254
|
+
source -->|"value→value"| branch_a
|
|
255
|
+
source -->|"value→value"| branch_b
|
|
256
|
+
branch_a -->|"out_a→out_a"| merger
|
|
257
|
+
branch_b -->|"out_b→out_b"| merger
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Notice:
|
|
261
|
+
- `\n` in node names becomes `<br/>` for proper line breaks
|
|
262
|
+
- Parallel branches are grouped in a dashed green subgraph
|
|
263
|
+
- Color-coded nodes: Blue (source), Orange (processing), Purple (sink)
|
|
264
|
+
- All edges are properly connected (no disconnected nodes)
|
|
265
|
+
|
|
266
|
+
## Data Types
|
|
267
|
+
|
|
268
|
+
All Python types are automatically converted:
|
|
269
|
+
|
|
270
|
+
| Python Type | graph-sp Type |
|
|
271
|
+
|------------|---------------|
|
|
272
|
+
| `int` | `Int` |
|
|
273
|
+
| `float` | `Float` |
|
|
274
|
+
| `str` | `String` |
|
|
275
|
+
| `bool` | `Bool` |
|
|
276
|
+
| `None` | `None` |
|
|
277
|
+
| `list` | `List` |
|
|
278
|
+
| `dict` | `Map` |
|
|
279
|
+
| JSON-serializable | `Json` |
|
|
280
|
+
| `bytes` | `Bytes` |
|
|
281
|
+
|
|
282
|
+
### Complex Data Structures
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
# Nested objects work seamlessly
|
|
286
|
+
user = {
|
|
287
|
+
"name": "Alice",
|
|
288
|
+
"age": 30,
|
|
289
|
+
"address": {
|
|
290
|
+
"city": "NYC",
|
|
291
|
+
"zip": "10001"
|
|
292
|
+
},
|
|
293
|
+
"hobbies": ["reading", "coding", "hiking"]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# Lists of any type
|
|
297
|
+
numbers = [1, 2, 3, 4, 5]
|
|
298
|
+
mixed = [1, "hello", 3.14, True, None]
|
|
299
|
+
|
|
300
|
+
# JSON structures
|
|
301
|
+
product = {
|
|
302
|
+
"id": "laptop-001",
|
|
303
|
+
"specs": {
|
|
304
|
+
"cpu": "Intel i7",
|
|
305
|
+
"ram": "16GB"
|
|
306
|
+
},
|
|
307
|
+
"available": True,
|
|
308
|
+
"price": 999.99
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Parallel Execution
|
|
313
|
+
|
|
314
|
+
The executor automatically identifies and parallelizes independent branches:
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
# Fan-out pattern: 3 branches run in parallel
|
|
318
|
+
#
|
|
319
|
+
# source
|
|
320
|
+
# / | \
|
|
321
|
+
# slow fast medium <- Execute concurrently!
|
|
322
|
+
# \ | /
|
|
323
|
+
# merger
|
|
324
|
+
#
|
|
325
|
+
# Sequential time: 900ms (500 + 100 + 300)
|
|
326
|
+
# Parallel time: 500ms (max branch time)
|
|
327
|
+
# Speedup: 44% faster!
|
|
328
|
+
|
|
329
|
+
graph = graph_sp.Graph()
|
|
330
|
+
|
|
331
|
+
graph.add_node("source", "Source", [],
|
|
332
|
+
[graph_sp.Port("value", "Value")],
|
|
333
|
+
lambda _: {"value": 100})
|
|
334
|
+
|
|
335
|
+
# These 3 nodes will execute in parallel
|
|
336
|
+
graph.add_node("slow", "Slow Branch",
|
|
337
|
+
[graph_sp.Port("input", "Input")],
|
|
338
|
+
[graph_sp.Port("output", "Output")],
|
|
339
|
+
lambda inputs: slow_operation(inputs["input"]))
|
|
340
|
+
|
|
341
|
+
graph.add_node("fast", "Fast Branch",
|
|
342
|
+
[graph_sp.Port("input", "Input")],
|
|
343
|
+
[graph_sp.Port("output", "Output")],
|
|
344
|
+
lambda inputs: fast_operation(inputs["input"]))
|
|
345
|
+
|
|
346
|
+
graph.add_node("medium", "Medium Branch",
|
|
347
|
+
[graph_sp.Port("input", "Input")],
|
|
348
|
+
[graph_sp.Port("output", "Output")],
|
|
349
|
+
lambda inputs: medium_operation(inputs["input"]))
|
|
350
|
+
|
|
351
|
+
# Connect all branches to source and merger
|
|
352
|
+
for branch in ["slow", "fast", "medium"]:
|
|
353
|
+
graph.add_edge("source", "value", branch, "input")
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Building from Source
|
|
357
|
+
|
|
358
|
+
If you want to build from source instead of using PyPI:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# Clone repository
|
|
362
|
+
git clone https://github.com/briday1/graph-sp.git
|
|
363
|
+
cd graph-sp
|
|
364
|
+
|
|
365
|
+
# Install maturin
|
|
366
|
+
pip install maturin
|
|
367
|
+
|
|
368
|
+
# Build and install
|
|
369
|
+
maturin develop --release --features python
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Documentation
|
|
373
|
+
|
|
374
|
+
- **Full Documentation**: https://github.com/briday1/graph-sp
|
|
375
|
+
- **Port Data Types**: See `docs/PORT_DATA_TYPES.md` in the repository
|
|
376
|
+
- **Expected Output**: See `EXPECTED_OUTPUT.md` in this directory
|
|
377
|
+
|
|
378
|
+
## Performance
|
|
379
|
+
|
|
380
|
+
Measured with the `parallel_execution.py` example:
|
|
381
|
+
|
|
382
|
+
- **Sequential execution**: ~900ms
|
|
383
|
+
- **Parallel execution**: ~502ms
|
|
384
|
+
- **Speedup**: 44% faster
|
|
385
|
+
|
|
386
|
+
The executor uses Rust's tokio runtime for true concurrent execution while properly managing Python's GIL.
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT License
|
|
391
|
+
|
|
392
|
+
## Links
|
|
393
|
+
|
|
394
|
+
- **GitHub**: https://github.com/briday1/graph-sp
|
|
395
|
+
- **PyPI**: https://pypi.org/project/graph-sp/
|
|
396
|
+
- **Crates.io**: https://crates.io/crates/graph-sp
|
|
397
|
+
- **Issues**: https://github.com/briday1/graph-sp/issues
|
|
398
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
graph_sp/__init__.py,sha256=xhKDfKdv8a2aPIlaskNZS4LNy00Uy4EuwE31glx0wYA,115
|
|
2
|
+
graph_sp/graph_sp.cpython-312-darwin.so,sha256=pNM1iQbJSZqQ3zJh3n2lopqnZlSai0gcTSXaeyC0Qpw,1256928
|
|
3
|
+
pygraph_sp-2026.1.dist-info/METADATA,sha256=24UvQaxJUR2UJwAklkLWyUn_L0rbKWZa3rP_hhfonLE,10952
|
|
4
|
+
pygraph_sp-2026.1.dist-info/WHEEL,sha256=qr8B0oB3ZR0cwIaW0mxUADH9b4sNRMHcgJlpYNTDAPw,105
|
|
5
|
+
pygraph_sp-2026.1.dist-info/RECORD,,
|