visiter-native 0.1.0__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.
- visiter_native-0.1.0/Cargo.lock +180 -0
- visiter_native-0.1.0/Cargo.toml +21 -0
- visiter_native-0.1.0/PKG-INFO +36 -0
- visiter_native-0.1.0/README.md +19 -0
- visiter_native-0.1.0/pyproject.toml +26 -0
- visiter_native-0.1.0/src/lib.rs +149 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "cfg-if"
|
|
13
|
+
version = "1.0.4"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "heck"
|
|
19
|
+
version = "0.5.0"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "indoc"
|
|
25
|
+
version = "2.0.7"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"rustversion",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "libc"
|
|
34
|
+
version = "0.2.186"
|
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
37
|
+
|
|
38
|
+
[[package]]
|
|
39
|
+
name = "memoffset"
|
|
40
|
+
version = "0.9.1"
|
|
41
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
43
|
+
dependencies = [
|
|
44
|
+
"autocfg",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "once_cell"
|
|
49
|
+
version = "1.21.4"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "portable-atomic"
|
|
55
|
+
version = "1.13.1"
|
|
56
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "proc-macro2"
|
|
61
|
+
version = "1.0.106"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
64
|
+
dependencies = [
|
|
65
|
+
"unicode-ident",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[[package]]
|
|
69
|
+
name = "pyo3"
|
|
70
|
+
version = "0.23.5"
|
|
71
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
72
|
+
checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872"
|
|
73
|
+
dependencies = [
|
|
74
|
+
"cfg-if",
|
|
75
|
+
"indoc",
|
|
76
|
+
"libc",
|
|
77
|
+
"memoffset",
|
|
78
|
+
"once_cell",
|
|
79
|
+
"portable-atomic",
|
|
80
|
+
"pyo3-build-config",
|
|
81
|
+
"pyo3-ffi",
|
|
82
|
+
"pyo3-macros",
|
|
83
|
+
"unindent",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
[[package]]
|
|
87
|
+
name = "pyo3-build-config"
|
|
88
|
+
version = "0.23.5"
|
|
89
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
90
|
+
checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb"
|
|
91
|
+
dependencies = [
|
|
92
|
+
"once_cell",
|
|
93
|
+
"target-lexicon",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "pyo3-ffi"
|
|
98
|
+
version = "0.23.5"
|
|
99
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
100
|
+
checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d"
|
|
101
|
+
dependencies = [
|
|
102
|
+
"libc",
|
|
103
|
+
"pyo3-build-config",
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[[package]]
|
|
107
|
+
name = "pyo3-macros"
|
|
108
|
+
version = "0.23.5"
|
|
109
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
110
|
+
checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da"
|
|
111
|
+
dependencies = [
|
|
112
|
+
"proc-macro2",
|
|
113
|
+
"pyo3-macros-backend",
|
|
114
|
+
"quote",
|
|
115
|
+
"syn",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
[[package]]
|
|
119
|
+
name = "pyo3-macros-backend"
|
|
120
|
+
version = "0.23.5"
|
|
121
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
122
|
+
checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028"
|
|
123
|
+
dependencies = [
|
|
124
|
+
"heck",
|
|
125
|
+
"proc-macro2",
|
|
126
|
+
"pyo3-build-config",
|
|
127
|
+
"quote",
|
|
128
|
+
"syn",
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
[[package]]
|
|
132
|
+
name = "quote"
|
|
133
|
+
version = "1.0.45"
|
|
134
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
135
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
136
|
+
dependencies = [
|
|
137
|
+
"proc-macro2",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
[[package]]
|
|
141
|
+
name = "rustversion"
|
|
142
|
+
version = "1.0.22"
|
|
143
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
144
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
145
|
+
|
|
146
|
+
[[package]]
|
|
147
|
+
name = "syn"
|
|
148
|
+
version = "2.0.117"
|
|
149
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
150
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
151
|
+
dependencies = [
|
|
152
|
+
"proc-macro2",
|
|
153
|
+
"quote",
|
|
154
|
+
"unicode-ident",
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
[[package]]
|
|
158
|
+
name = "target-lexicon"
|
|
159
|
+
version = "0.12.16"
|
|
160
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
161
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
162
|
+
|
|
163
|
+
[[package]]
|
|
164
|
+
name = "unicode-ident"
|
|
165
|
+
version = "1.0.24"
|
|
166
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
167
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
168
|
+
|
|
169
|
+
[[package]]
|
|
170
|
+
name = "unindent"
|
|
171
|
+
version = "0.2.4"
|
|
172
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
173
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
174
|
+
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "visiter_native"
|
|
177
|
+
version = "0.1.0"
|
|
178
|
+
dependencies = [
|
|
179
|
+
"pyo3",
|
|
180
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "visiter_native"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
description = "Optional native BFS engine for visiter (Path A: Python callbacks via PyO3)."
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
name = "visiter_native"
|
|
11
|
+
crate-type = ["cdylib"]
|
|
12
|
+
|
|
13
|
+
[dependencies]
|
|
14
|
+
# abi3-py311: one stable-ABI wheel per platform works on CPython 3.11+,
|
|
15
|
+
# so distribution doesn't need a wheel per Python version.
|
|
16
|
+
pyo3 = { version = "0.23", features = ["abi3-py311"] }
|
|
17
|
+
|
|
18
|
+
[profile.release]
|
|
19
|
+
opt-level = 3
|
|
20
|
+
lto = "fat"
|
|
21
|
+
codegen-units = 1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: visiter_native
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
5
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
|
+
Classifier: Programming Language :: Rust
|
|
7
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
8
|
+
Summary: Optional native BFS engine for visiter (engine='native').
|
|
9
|
+
Keywords: visiter,graph,bfs,native,pyo3
|
|
10
|
+
Author-email: Jakob Stemberger <jakob.stemberger@gmail.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
14
|
+
Project-URL: Homepage, https://github.com/yaccob/visiter
|
|
15
|
+
Project-URL: Issues, https://github.com/yaccob/visiter/issues
|
|
16
|
+
|
|
17
|
+
# visiter_native
|
|
18
|
+
|
|
19
|
+
The optional native BFS engine for [visiter](https://pypi.org/project/visiter/)
|
|
20
|
+
(Path A): a PyO3 extension that runs visiter's graph build natively while keeping
|
|
21
|
+
your Python callbacks.
|
|
22
|
+
|
|
23
|
+
You normally don't install this directly — use the extra:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install "visiter[native]"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Once `visiter_native` is importable, `viter(...).build()` uses it automatically
|
|
30
|
+
for unbounded builds (`engine="auto"`, the default) and produces a graph
|
|
31
|
+
byte-identical to the pure-Python build. visiter works without it — pure Python
|
|
32
|
+
is the always-available baseline.
|
|
33
|
+
|
|
34
|
+
Distributed as `abi3` wheels (one per platform, CPython 3.11+). MIT licensed.
|
|
35
|
+
See the [visiter manual](https://github.com/yaccob/visiter/blob/main/docs/manual.md#8-optional-native-acceleration-and-columnar-storage).
|
|
36
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# visiter_native
|
|
2
|
+
|
|
3
|
+
The optional native BFS engine for [visiter](https://pypi.org/project/visiter/)
|
|
4
|
+
(Path A): a PyO3 extension that runs visiter's graph build natively while keeping
|
|
5
|
+
your Python callbacks.
|
|
6
|
+
|
|
7
|
+
You normally don't install this directly — use the extra:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install "visiter[native]"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Once `visiter_native` is importable, `viter(...).build()` uses it automatically
|
|
14
|
+
for unbounded builds (`engine="auto"`, the default) and produces a graph
|
|
15
|
+
byte-identical to the pure-Python build. visiter works without it — pure Python
|
|
16
|
+
is the always-available baseline.
|
|
17
|
+
|
|
18
|
+
Distributed as `abi3` wheels (one per platform, CPython 3.11+). MIT licensed.
|
|
19
|
+
See the [visiter manual](https://github.com/yaccob/visiter/blob/main/docs/manual.md#8-optional-native-acceleration-and-columnar-storage).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.0,<2.0"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "visiter_native"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Optional native BFS engine for visiter (engine='native')."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Jakob Stemberger", email = "jakob.stemberger@gmail.com" }]
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
keywords = ["visiter", "graph", "bfs", "native", "pyo3"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Programming Language :: Rust",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://github.com/yaccob/visiter"
|
|
23
|
+
Issues = "https://github.com/yaccob/visiter/issues"
|
|
24
|
+
|
|
25
|
+
[tool.maturin]
|
|
26
|
+
features = ["pyo3/extension-module"]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
//! Optional native BFS engine for visiter (Path A / ①).
|
|
2
|
+
//!
|
|
3
|
+
//! `build_raw` mirrors the pure-Python `visiter.iteration.build` BFS for the
|
|
4
|
+
//! **unbounded** subset (no max_depth / max_nodes / time_limit / bound). It
|
|
5
|
+
//! calls the Python condition/op callables per node, so the callbacks stay
|
|
6
|
+
//! Python — only the BFS expansion, deduplication and interning run natively.
|
|
7
|
+
//!
|
|
8
|
+
//! It returns the raw discovered structure (node objects in BFS order, their
|
|
9
|
+
//! depths, and deduplicated edges as `(from_idx, to_idx, op_idx, label?)`).
|
|
10
|
+
//! The Python shim assembles the final Graph dict (string keys, key_type,
|
|
11
|
+
//! tags, op labels) from this, so the output is byte-identical to the
|
|
12
|
+
//! pure-Python build for the supported subset.
|
|
13
|
+
//!
|
|
14
|
+
//! Node order, edge order, depth assignment and dedup semantics are kept
|
|
15
|
+
//! faithful to the Python loop so a Graph-level parity test passes exactly.
|
|
16
|
+
|
|
17
|
+
use pyo3::prelude::*;
|
|
18
|
+
use std::collections::{HashMap, HashSet};
|
|
19
|
+
|
|
20
|
+
/// A Python object used as a node key: hashed by the value's Python `hash()`
|
|
21
|
+
/// (computed once), equality resolved by Python `==` only on hash collision.
|
|
22
|
+
struct Key {
|
|
23
|
+
obj: Py<PyAny>,
|
|
24
|
+
hash: isize,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl std::hash::Hash for Key {
|
|
28
|
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
29
|
+
state.write_isize(self.hash);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
impl PartialEq for Key {
|
|
34
|
+
fn eq(&self, other: &Self) -> bool {
|
|
35
|
+
if self.hash != other.hash {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
Python::with_gil(|py| {
|
|
39
|
+
self.obj.bind(py).eq(other.obj.bind(py)).unwrap_or(false)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
impl Eq for Key {}
|
|
44
|
+
|
|
45
|
+
type Edge = (u32, u32, usize, Option<String>);
|
|
46
|
+
|
|
47
|
+
/// Run the unbounded BFS natively. `op_result_type` is the Python `OpResult`
|
|
48
|
+
/// class, used to detect per-call label overrides.
|
|
49
|
+
#[pyfunction]
|
|
50
|
+
#[pyo3(signature = (starts, conditions, ops, exclusive, default_op, op_result_type))]
|
|
51
|
+
fn build_raw(
|
|
52
|
+
py: Python<'_>,
|
|
53
|
+
starts: Vec<Py<PyAny>>,
|
|
54
|
+
conditions: Vec<Py<PyAny>>,
|
|
55
|
+
ops: Vec<Py<PyAny>>,
|
|
56
|
+
exclusive: Vec<bool>,
|
|
57
|
+
default_op: Option<Py<PyAny>>,
|
|
58
|
+
op_result_type: Py<PyAny>,
|
|
59
|
+
) -> PyResult<(Vec<Py<PyAny>>, Vec<u32>, Vec<Edge>)> {
|
|
60
|
+
let n_rules = conditions.len();
|
|
61
|
+
let default_idx = n_rules; // op index reserved for the default op
|
|
62
|
+
let ort = op_result_type.bind(py);
|
|
63
|
+
|
|
64
|
+
let mut id_of: HashMap<Key, u32> = HashMap::new();
|
|
65
|
+
let mut values: Vec<Py<PyAny>> = Vec::new();
|
|
66
|
+
let mut depths: Vec<u32> = Vec::new();
|
|
67
|
+
let mut edges: Vec<Edge> = Vec::new();
|
|
68
|
+
let mut seen_edges: HashSet<(u32, u32)> = HashSet::new();
|
|
69
|
+
|
|
70
|
+
// `fire` is a macro (not a fn) so it can mutate the locals in place without
|
|
71
|
+
// fighting the borrow checker over a dozen &mut parameters.
|
|
72
|
+
macro_rules! fire {
|
|
73
|
+
($xid:expr, $xb:expr, $op_idx:expr, $op_func:expr, $next:expr) => {{
|
|
74
|
+
let result = $op_func.bind(py).call1(($xb,))?;
|
|
75
|
+
let (nv, label): (Py<PyAny>, Option<String>) =
|
|
76
|
+
if result.is_instance(ort)? {
|
|
77
|
+
let v = result.getattr("value")?.unbind();
|
|
78
|
+
let l: Option<String> = result.getattr("label")?.extract()?;
|
|
79
|
+
(v, l)
|
|
80
|
+
} else {
|
|
81
|
+
(result.unbind(), None)
|
|
82
|
+
};
|
|
83
|
+
let h = nv.bind(py).hash()?;
|
|
84
|
+
let key = Key { obj: nv.clone_ref(py), hash: h };
|
|
85
|
+
let (nid, is_new) = match id_of.get(&key) {
|
|
86
|
+
Some(&i) => (i, false),
|
|
87
|
+
None => {
|
|
88
|
+
let i = values.len() as u32;
|
|
89
|
+
values.push(nv);
|
|
90
|
+
depths.push(depths[$xid as usize] + 1);
|
|
91
|
+
id_of.insert(key, i);
|
|
92
|
+
(i, true)
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
if seen_edges.insert(($xid, nid)) {
|
|
96
|
+
edges.push(($xid, nid, $op_idx, label));
|
|
97
|
+
}
|
|
98
|
+
if is_new {
|
|
99
|
+
$next.push(nid);
|
|
100
|
+
}
|
|
101
|
+
}};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let mut frontier: Vec<u32> = Vec::new();
|
|
105
|
+
for s in starts {
|
|
106
|
+
let h = s.bind(py).hash()?;
|
|
107
|
+
let key = Key { obj: s.clone_ref(py), hash: h };
|
|
108
|
+
if !id_of.contains_key(&key) {
|
|
109
|
+
let id = values.len() as u32;
|
|
110
|
+
values.push(s);
|
|
111
|
+
depths.push(0);
|
|
112
|
+
id_of.insert(key, id);
|
|
113
|
+
frontier.push(id);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
while !frontier.is_empty() {
|
|
118
|
+
let mut next: Vec<u32> = Vec::new();
|
|
119
|
+
for &xid in &frontier {
|
|
120
|
+
let x = values[xid as usize].clone_ref(py);
|
|
121
|
+
let xb = x.bind(py);
|
|
122
|
+
let mut any_matched = false;
|
|
123
|
+
for ri in 0..n_rules {
|
|
124
|
+
if conditions[ri].bind(py).call1((xb,))?.is_truthy()? {
|
|
125
|
+
any_matched = true;
|
|
126
|
+
fire!(xid, xb, ri, ops[ri], next);
|
|
127
|
+
if exclusive[ri] {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if !any_matched {
|
|
133
|
+
if let Some(ref dop) = default_op {
|
|
134
|
+
fire!(xid, xb, default_idx, dop, next);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
frontier = next;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Ok((values, depths, edges))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
#[pymodule]
|
|
145
|
+
fn visiter_native(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
146
|
+
m.add_function(wrap_pyfunction!(build_raw, m)?)?;
|
|
147
|
+
m.add("__version__", "0.0.0")?;
|
|
148
|
+
Ok(())
|
|
149
|
+
}
|