netrun-sim 0.1.1__tar.gz → 0.1.2__tar.gz

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.
Files changed (49) hide show
  1. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/Cargo.lock +2 -1
  2. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/PKG-INFO +1 -1
  3. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/Cargo.toml +6 -1
  4. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/examples/diamond_flow.rs +92 -30
  5. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/examples/linear_flow.rs +52 -19
  6. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/src/graph.rs +143 -378
  7. netrun_sim-0.1.2/core/src/graph_tests.rs +363 -0
  8. netrun_sim-0.1.2/core/src/net.rs +2173 -0
  9. netrun_sim-0.1.2/core/src/net_tests.rs +2027 -0
  10. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/src/test_fixtures.rs +54 -30
  11. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/tests/common/mod.rs +17 -25
  12. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/tests/graph_api.rs +132 -11
  13. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/tests/net_api.rs +64 -58
  14. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/tests/workflow.rs +113 -54
  15. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/pyproject.toml +12 -1
  16. netrun_sim-0.1.2/python/.envrc +3 -0
  17. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/Cargo.toml +1 -1
  18. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/README.md +5 -5
  19. netrun_sim-0.1.2/python/examples/nbs/00_basic_net.ipynb +421 -0
  20. {netrun_sim-0.1.1/python/examples → netrun_sim-0.1.2/python/examples/nbs}/diamond_flow.ipynb +82 -213
  21. {netrun_sim-0.1.1/python/examples → netrun_sim-0.1.2/python/examples/nbs}/linear_flow.ipynb +65 -182
  22. netrun_sim-0.1.2/python/examples/pts/00_basic_net.pct.py +224 -0
  23. netrun_sim-0.1.2/python/examples/pts/diamond_flow.pct.py +337 -0
  24. netrun_sim-0.1.2/python/examples/pts/linear_flow.pct.py +293 -0
  25. netrun_sim-0.1.2/python/nblite.toml +10 -0
  26. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/netrun_sim/__init__.py +7 -2
  27. netrun_sim-0.1.2/python/netrun_sim/__init__.pyi +901 -0
  28. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/python/netrun_sim/__init__.py +7 -2
  29. netrun_sim-0.1.2/python/python/netrun_sim/__init__.pyi +901 -0
  30. netrun_sim-0.1.2/python/src/errors.rs +279 -0
  31. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/src/graph.rs +392 -174
  32. netrun_sim-0.1.2/python/src/net.rs +1251 -0
  33. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/uv.lock +411 -1947
  34. netrun_sim-0.1.1/core/src/net.rs +0 -1612
  35. netrun_sim-0.1.1/python/.envrc +0 -2
  36. netrun_sim-0.1.1/python/examples/diamond_flow.py +0 -218
  37. netrun_sim-0.1.1/python/examples/linear_flow.py +0 -160
  38. netrun_sim-0.1.1/python/netrun_sim/__init__.pyi +0 -475
  39. netrun_sim-0.1.1/python/python/netrun_sim/__init__.pyi +0 -475
  40. netrun_sim-0.1.1/python/src/errors.rs +0 -156
  41. netrun_sim-0.1.1/python/src/net.rs +0 -818
  42. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/Cargo.toml +0 -0
  43. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/src/_utils.rs +0 -0
  44. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/core/src/lib.rs +0 -0
  45. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/CHANGELOG.md +0 -0
  46. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/netrun_sim/py.typed +0 -0
  47. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/publish_new_version.sh +0 -0
  48. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/python/netrun_sim/py.typed +0 -0
  49. {netrun_sim-0.1.1 → netrun_sim-0.1.2}/python/src/lib.rs +0 -0
@@ -123,9 +123,10 @@ dependencies = [
123
123
 
124
124
  [[package]]
125
125
  name = "netrun-sim"
126
- version = "0.1.0"
126
+ version = "0.1.2"
127
127
  dependencies = [
128
128
  "indexmap",
129
+ "pyo3",
129
130
  "thiserror",
130
131
  "ulid",
131
132
  "utcnow",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netrun-sim
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Requires-Dist: python-ulid>=1.0
@@ -1,13 +1,18 @@
1
1
  [package]
2
2
  name = "netrun-sim"
3
3
  description = "A flow-based development (FBD) simulation engine."
4
- version = "0.1.0"
4
+ version = "0.1.2"
5
5
  edition = "2024"
6
6
  license-file = "../../LICENSE"
7
7
  repository = "https://github.com/lukastk/netrun/"
8
8
 
9
+ [features]
10
+ default = []
11
+ python = ["pyo3"]
12
+
9
13
  [dependencies]
10
14
  indexmap = "2.12.1"
11
15
  thiserror = "2.0"
12
16
  ulid = "=1.1.0"
13
17
  utcnow = "0.2.7"
18
+ pyo3 = { version = "0.23", features = ["abi3-py38"], optional = true }
@@ -13,11 +13,11 @@
13
13
  //! - Synchronization: D's epoch only triggers when both inputs are present
14
14
 
15
15
  use netrun_sim::graph::{
16
- Edge, Graph, Node, Port, PortRef, PortSlotSpec, PortState, PortType,
16
+ Edge, Graph, MaxSalvos, Node, PacketCount, Port, PortRef, PortSlotSpec, PortState, PortType,
17
17
  SalvoCondition, SalvoConditionTerm,
18
18
  };
19
19
  use netrun_sim::net::{
20
- Net, NetAction, NetActionResponse, NetActionResponseData, PacketLocation,
20
+ NetAction, NetActionResponse, NetActionResponseData, NetSim, PacketLocation,
21
21
  };
22
22
  use std::collections::HashMap;
23
23
 
@@ -27,7 +27,7 @@ fn main() {
27
27
  println!("Created diamond graph: A -> B,C -> D");
28
28
  println!("D requires inputs from BOTH B and C\n");
29
29
 
30
- let mut net = Net::new(graph);
30
+ let mut net = NetSim::new(graph);
31
31
 
32
32
  // Create two packets and place them on edges from A
33
33
  let packet1 = create_packet(&mut net);
@@ -36,19 +36,28 @@ fn main() {
36
36
 
37
37
  // Place packet1 on edge A -> B
38
38
  let edge_a_b = edge_location("A", "out1", "B", "in");
39
- net.do_action(&NetAction::TransportPacketToLocation(packet1.clone(), edge_a_b));
39
+ net.do_action(&NetAction::TransportPacketToLocation(
40
+ packet1.clone(),
41
+ edge_a_b,
42
+ ));
40
43
  println!("Placed packet1 on edge A -> B");
41
44
 
42
45
  // Place packet2 on edge A -> C
43
46
  let edge_a_c = edge_location("A", "out2", "C", "in");
44
- net.do_action(&NetAction::TransportPacketToLocation(packet2.clone(), edge_a_c));
47
+ net.do_action(&NetAction::TransportPacketToLocation(
48
+ packet2.clone(),
49
+ edge_a_c,
50
+ ));
45
51
  println!("Placed packet2 on edge A -> C");
46
52
 
47
53
  // Run network - packets move to B and C, triggering epochs
48
- net.do_action(&NetAction::RunNetUntilBlocked);
54
+ net.run_until_blocked();
49
55
 
50
56
  let startable = net.get_startable_epochs();
51
- println!("\nAfter first run: {} startable epochs (B and C)", startable.len());
57
+ println!(
58
+ "\nAfter first run: {} startable epochs (B and C)",
59
+ startable.len()
60
+ );
52
61
 
53
62
  // Process B and C, sending outputs to D
54
63
  for epoch_id in startable {
@@ -70,8 +79,14 @@ fn main() {
70
79
  let output = create_packet_in_epoch(&mut net, &started.id);
71
80
 
72
81
  // Load into output port and send
73
- net.do_action(&NetAction::LoadPacketIntoOutputPort(output, "out".to_string()));
74
- net.do_action(&NetAction::SendOutputSalvo(started.id.clone(), "default".to_string()));
82
+ net.do_action(&NetAction::LoadPacketIntoOutputPort(
83
+ output,
84
+ "out".to_string(),
85
+ ));
86
+ net.do_action(&NetAction::SendOutputSalvo(
87
+ started.id.clone(),
88
+ "default".to_string(),
89
+ ));
75
90
 
76
91
  // Finish epoch
77
92
  net.do_action(&NetAction::FinishEpoch(started.id));
@@ -79,7 +94,7 @@ fn main() {
79
94
  }
80
95
 
81
96
  // Run network - packets move from B->D and C->D edges to D's input ports
82
- net.do_action(&NetAction::RunNetUntilBlocked);
97
+ net.run_until_blocked();
83
98
 
84
99
  // Check D's input ports
85
100
  let d_in1 = PacketLocation::InputPort("D".to_string(), "in1".to_string());
@@ -94,7 +109,10 @@ fn main() {
94
109
 
95
110
  if let Some(d_epoch_id) = startable_d.first() {
96
111
  let d_epoch = net.get_epoch(d_epoch_id).unwrap();
97
- println!("D's epoch received {} packets from both branches!", d_epoch.in_salvo.packets.len());
112
+ println!(
113
+ "D's epoch received {} packets from both branches!",
114
+ d_epoch.in_salvo.packets.len()
115
+ );
98
116
  }
99
117
 
100
118
  println!("\nDiamond flow example complete!");
@@ -106,9 +124,20 @@ fn create_diamond_graph() -> Graph {
106
124
  name: "A".to_string(),
107
125
  in_ports: HashMap::new(),
108
126
  out_ports: [
109
- ("out1".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
110
- ("out2".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
111
- ].into(),
127
+ (
128
+ "out1".to_string(),
129
+ Port {
130
+ slots_spec: PortSlotSpec::Infinite,
131
+ },
132
+ ),
133
+ (
134
+ "out2".to_string(),
135
+ Port {
136
+ slots_spec: PortSlotSpec::Infinite,
137
+ },
138
+ ),
139
+ ]
140
+ .into(),
112
141
  in_salvo_conditions: HashMap::new(),
113
142
  out_salvo_conditions: HashMap::new(),
114
143
  };
@@ -123,15 +152,31 @@ fn create_diamond_graph() -> Graph {
123
152
  let node_d = Node {
124
153
  name: "D".to_string(),
125
154
  in_ports: [
126
- ("in1".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
127
- ("in2".to_string(), Port { slots_spec: PortSlotSpec::Infinite }),
128
- ].into(),
155
+ (
156
+ "in1".to_string(),
157
+ Port {
158
+ slots_spec: PortSlotSpec::Infinite,
159
+ },
160
+ ),
161
+ (
162
+ "in2".to_string(),
163
+ Port {
164
+ slots_spec: PortSlotSpec::Infinite,
165
+ },
166
+ ),
167
+ ]
168
+ .into(),
129
169
  out_ports: HashMap::new(),
130
170
  in_salvo_conditions: [(
131
171
  "default".to_string(),
132
172
  SalvoCondition {
133
- max_salvos: 1,
134
- ports: vec!["in1".to_string(), "in2".to_string()],
173
+ max_salvos: MaxSalvos::Finite(1),
174
+ ports: [
175
+ ("in1".to_string(), PacketCount::All),
176
+ ("in2".to_string(), PacketCount::All),
177
+ ]
178
+ .into_iter()
179
+ .collect(),
135
180
  // Require BOTH inputs to be non-empty
136
181
  term: SalvoConditionTerm::And(vec![
137
182
  SalvoConditionTerm::Port {
@@ -144,7 +189,8 @@ fn create_diamond_graph() -> Graph {
144
189
  },
145
190
  ]),
146
191
  },
147
- )].into(),
192
+ )]
193
+ .into(),
148
194
  out_salvo_conditions: HashMap::new(),
149
195
  };
150
196
 
@@ -163,30 +209,46 @@ fn create_diamond_graph() -> Graph {
163
209
  fn create_simple_node(name: &str) -> Node {
164
210
  Node {
165
211
  name: name.to_string(),
166
- in_ports: [("in".to_string(), Port { slots_spec: PortSlotSpec::Infinite })].into(),
167
- out_ports: [("out".to_string(), Port { slots_spec: PortSlotSpec::Infinite })].into(),
212
+ in_ports: [(
213
+ "in".to_string(),
214
+ Port {
215
+ slots_spec: PortSlotSpec::Infinite,
216
+ },
217
+ )]
218
+ .into(),
219
+ out_ports: [(
220
+ "out".to_string(),
221
+ Port {
222
+ slots_spec: PortSlotSpec::Infinite,
223
+ },
224
+ )]
225
+ .into(),
168
226
  in_salvo_conditions: [(
169
227
  "default".to_string(),
170
228
  SalvoCondition {
171
- max_salvos: 1,
172
- ports: vec!["in".to_string()],
229
+ max_salvos: MaxSalvos::Finite(1),
230
+ ports: [("in".to_string(), PacketCount::All)].into_iter().collect(),
173
231
  term: SalvoConditionTerm::Port {
174
232
  port_name: "in".to_string(),
175
233
  state: PortState::NonEmpty,
176
234
  },
177
235
  },
178
- )].into(),
236
+ )]
237
+ .into(),
179
238
  out_salvo_conditions: [(
180
239
  "default".to_string(),
181
240
  SalvoCondition {
182
- max_salvos: 0,
183
- ports: vec!["out".to_string()],
241
+ max_salvos: MaxSalvos::Infinite,
242
+ ports: [("out".to_string(), PacketCount::All)]
243
+ .into_iter()
244
+ .collect(),
184
245
  term: SalvoConditionTerm::Port {
185
246
  port_name: "out".to_string(),
186
247
  state: PortState::NonEmpty,
187
248
  },
188
249
  },
189
- )].into(),
250
+ )]
251
+ .into(),
190
252
  }
191
253
  }
192
254
 
@@ -220,14 +282,14 @@ fn edge_location(src_node: &str, src_port: &str, tgt_node: &str, tgt_port: &str)
220
282
  })
221
283
  }
222
284
 
223
- fn create_packet(net: &mut Net) -> ulid::Ulid {
285
+ fn create_packet(net: &mut NetSim) -> ulid::Ulid {
224
286
  match net.do_action(&NetAction::CreatePacket(None)) {
225
287
  NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
226
288
  _ => panic!("Failed to create packet"),
227
289
  }
228
290
  }
229
291
 
230
- fn create_packet_in_epoch(net: &mut Net, epoch_id: &ulid::Ulid) -> ulid::Ulid {
292
+ fn create_packet_in_epoch(net: &mut NetSim, epoch_id: &ulid::Ulid) -> ulid::Ulid {
231
293
  match net.do_action(&NetAction::CreatePacket(Some(epoch_id.clone()))) {
232
294
  NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
233
295
  _ => panic!("Failed to create packet in epoch"),
@@ -8,11 +8,11 @@
8
8
  //! - Sending output salvos to continue flow
9
9
 
10
10
  use netrun_sim::graph::{
11
- Edge, Graph, Node, Port, PortRef, PortSlotSpec, PortState, PortType,
11
+ Edge, Graph, MaxSalvos, Node, PacketCount, Port, PortRef, PortSlotSpec, PortState, PortType,
12
12
  SalvoCondition, SalvoConditionTerm,
13
13
  };
14
14
  use netrun_sim::net::{
15
- Net, NetAction, NetActionResponse, NetActionResponseData, PacketLocation,
15
+ NetAction, NetActionResponse, NetActionResponseData, NetSim, PacketLocation,
16
16
  };
17
17
  use std::collections::HashMap;
18
18
 
@@ -22,7 +22,7 @@ fn main() {
22
22
  println!("Created graph with {} nodes", graph.nodes().len());
23
23
 
24
24
  // Create a network from the graph
25
- let mut net = Net::new(graph);
25
+ let mut net = NetSim::new(graph);
26
26
 
27
27
  // Create a packet outside the network
28
28
  let packet_id = match net.do_action(&NetAction::CreatePacket(None)) {
@@ -46,11 +46,14 @@ fn main() {
46
46
  port_name: "in".to_string(),
47
47
  },
48
48
  });
49
- net.do_action(&NetAction::TransportPacketToLocation(packet_id.clone(), edge_a_b));
49
+ net.do_action(&NetAction::TransportPacketToLocation(
50
+ packet_id.clone(),
51
+ edge_a_b,
52
+ ));
50
53
  println!("Placed packet on edge A -> B");
51
54
 
52
55
  // Run the network - packet moves to B's input port and triggers an epoch
53
- net.do_action(&NetAction::RunNetUntilBlocked);
56
+ net.run_until_blocked();
54
57
  println!("Ran network until blocked");
55
58
 
56
59
  // Check for startable epochs
@@ -71,18 +74,25 @@ fn main() {
71
74
  println!("Consumed input packet");
72
75
 
73
76
  // Create an output packet
74
- let output_packet = match net.do_action(&NetAction::CreatePacket(Some(epoch.id.clone()))) {
75
- NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
76
- _ => panic!("Failed to create output packet"),
77
- };
77
+ let output_packet =
78
+ match net.do_action(&NetAction::CreatePacket(Some(epoch.id.clone()))) {
79
+ NetActionResponse::Success(NetActionResponseData::Packet(id), _) => id,
80
+ _ => panic!("Failed to create output packet"),
81
+ };
78
82
  println!("Created output packet: {}", output_packet);
79
83
 
80
84
  // Load it into the output port
81
- net.do_action(&NetAction::LoadPacketIntoOutputPort(output_packet.clone(), "out".to_string()));
85
+ net.do_action(&NetAction::LoadPacketIntoOutputPort(
86
+ output_packet.clone(),
87
+ "out".to_string(),
88
+ ));
82
89
  println!("Loaded packet into output port");
83
90
 
84
91
  // Send the output salvo
85
- net.do_action(&NetAction::SendOutputSalvo(epoch.id.clone(), "default".to_string()));
92
+ net.do_action(&NetAction::SendOutputSalvo(
93
+ epoch.id.clone(),
94
+ "default".to_string(),
95
+ ));
86
96
  println!("Sent output salvo - packet is now on edge B -> C");
87
97
 
88
98
  // Finish the epoch
@@ -90,12 +100,15 @@ fn main() {
90
100
  println!("Finished epoch");
91
101
 
92
102
  // Run the network again - packet moves to C
93
- net.do_action(&NetAction::RunNetUntilBlocked);
103
+ net.run_until_blocked();
94
104
  println!("Ran network until blocked again");
95
105
 
96
106
  // Check for new startable epochs at C
97
107
  let startable_c = net.get_startable_epochs();
98
- println!("New startable epochs (should be at C): {}", startable_c.len());
108
+ println!(
109
+ "New startable epochs (should be at C): {}",
110
+ startable_c.len()
111
+ );
99
112
  }
100
113
  _ => panic!("Failed to start epoch"),
101
114
  }
@@ -125,12 +138,26 @@ fn create_linear_graph() -> Graph {
125
138
  fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
126
139
  let in_ports_map: HashMap<String, Port> = in_ports
127
140
  .iter()
128
- .map(|p| (p.to_string(), Port { slots_spec: PortSlotSpec::Infinite }))
141
+ .map(|p| {
142
+ (
143
+ p.to_string(),
144
+ Port {
145
+ slots_spec: PortSlotSpec::Infinite,
146
+ },
147
+ )
148
+ })
129
149
  .collect();
130
150
 
131
151
  let out_ports_map: HashMap<String, Port> = out_ports
132
152
  .iter()
133
- .map(|p| (p.to_string(), Port { slots_spec: PortSlotSpec::Infinite }))
153
+ .map(|p| {
154
+ (
155
+ p.to_string(),
156
+ Port {
157
+ slots_spec: PortSlotSpec::Infinite,
158
+ },
159
+ )
160
+ })
134
161
  .collect();
135
162
 
136
163
  // Default input salvo condition: trigger when any input port is non-empty
@@ -139,8 +166,11 @@ fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
139
166
  in_salvo_conditions.insert(
140
167
  "default".to_string(),
141
168
  SalvoCondition {
142
- max_salvos: 1,
143
- ports: in_ports.iter().map(|s| s.to_string()).collect(),
169
+ max_salvos: MaxSalvos::Finite(1),
170
+ ports: in_ports
171
+ .iter()
172
+ .map(|s| (s.to_string(), PacketCount::All))
173
+ .collect(),
144
174
  term: SalvoConditionTerm::Port {
145
175
  port_name: in_ports[0].to_string(),
146
176
  state: PortState::NonEmpty,
@@ -155,8 +185,11 @@ fn create_node(name: &str, in_ports: Vec<&str>, out_ports: Vec<&str>) -> Node {
155
185
  out_salvo_conditions.insert(
156
186
  "default".to_string(),
157
187
  SalvoCondition {
158
- max_salvos: 0, // unlimited
159
- ports: out_ports.iter().map(|s| s.to_string()).collect(),
188
+ max_salvos: MaxSalvos::Infinite,
189
+ ports: out_ports
190
+ .iter()
191
+ .map(|s| (s.to_string(), PacketCount::All))
192
+ .collect(),
160
193
  term: SalvoConditionTerm::Port {
161
194
  port_name: out_ports[0].to_string(),
162
195
  state: PortState::NonEmpty,