Skip to content

Commit 09d53c6

Browse files
zenshanda-ai
andcommitted
fix(py): harden cognitive nexus bindings
Update the Python binding package for the Cognitive Nexus 0.8 release. - bump anda_cognitive_nexus_py to 0.3.0 and depend on 0.8 Rust crates - add an idempotent async close API for flushing file-backed stores - convert Python KIP parameters directly into JSON-compatible values - return ValueError for unsupported parameters instead of panicking - add PyO3 extension-module link args and a release-py wheel profile - point maturin at the binding crate manifest and refresh README examples - cover invalid parameters, nested parameters, and close idempotency - document the Python binding changes in the 0.8.0 changelog Co-Authored-By: Anda Bot <noreply@anda.bot>
1 parent d03dcba commit 09d53c6

8 files changed

Lines changed: 246 additions & 67 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ All notable changes to this workspace are documented in this file.
1010
- **KIP recall and portability commands** — Extended `SEARCH` with retrieval modes (`keyword`, `semantic`, `hybrid`) and score thresholds, and added `EXPORT` for serializing matched knowledge into idempotent UPSERT capsules.
1111
- **Commitment capsule** — Added the `Commitment.kip` capsule and updated built-in capsule metadata so agents can model durable commitments alongside events and people.
1212
- **Cognitive Nexus KIP execution coverage** — Implemented KML/KQL/META support for the expanded KIP surface, including update execution, merge handling, search scoring, export generation, and version-conflict reporting.
13-
- **Regression coverage for KIP and Cognitive Nexus behavior** — Added parser and executor tests for optimistic concurrency, update expressions, merge semantics, search modes, export capsules, and the split database implementation.
13+
- **Python binding close API** — Added an idempotent async `PyAndaDB.close()` method so Python clients can explicitly flush and close file-backed Cognitive Nexus stores.
14+
- **Regression coverage for KIP, Cognitive Nexus, and Python binding behavior** — Added parser, executor, and Python tests for optimistic concurrency, update expressions, merge semantics, search modes, export capsules, split database behavior, parameter conversion failures, nested parameters, and close idempotency.
1415

1516
### Changed
1617

1718
- **Workspace crates moved to the 0.8 line** — Bumped `anda_db`, `anda_kip`, and `anda_cognitive_nexus` to `0.8.0`, and updated dependent workspace crates to require the matching `0.8` APIs.
19+
- **Python binding moved to the 0.3 line** — Bumped `anda_cognitive_nexus_py` to `0.3.0`, updated it to depend on the `0.8` Rust crates, and switched the Python package metadata to derive its version from the binding crate manifest.
20+
- **Python wheel build profile clarified** — Added a `release-py` profile for PyO3 extension wheels and pointed maturin at the binding crate manifest.
1821
- **Cognitive Nexus database implementation split by responsibility** — Replaced the monolithic `db.rs` with focused modules for KML execution, KQL execution, proposition matching, META commands, shared database setup, and tests.
1922
- **KIP specification and tool schemas refreshed** — Updated the specification, syntax guide, self/system instructions, and function definition JSON files to describe the RC KIP semantics and the new read/write command set.
2023
- **System metadata semantics clarified** — Documented reserved engine-maintained `_` metadata fields, versioning behavior, and protected-scope constraints for write operations.
@@ -23,3 +26,5 @@ All notable changes to this workspace are documented in this file.
2326

2427
- **Safer endpoint matching syntax** — Tightened embedded endpoint clause handling so nested concept/proposition endpoints remain unnamed, with explicit guidance for binding endpoints through separate clauses.
2528
- **More robust query and mutation behavior** — Hardened Cognitive Nexus helper/type paths around KIP execution, protected scopes, cache invalidation, and proposition matching while preserving concurrent read and exclusive write semantics.
29+
- **Safer Python parameter handling** — Replaced panic-prone JSON string round-tripping with direct JSON-compatible Python value conversion and clear `ValueError` failures for unsupported values, non-finite floats, non-string keys, and excessive nesting.
30+
- **Python extension import/build robustness** — Made logger initialization non-fatal when a host process already installed a logger, added PyO3 macOS extension link arguments, and documented the correct module import path in the Python README.

Cargo.toml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ members = [
1616
"rs/anda_db_shard_proxy",
1717
# "py/anda_cognitive_nexus_py",
1818
]
19-
# Python binding package (anda_cognitive_nexus_py) is excluded from workspace testing
20-
# because it requires Python library linking. Test it separately with:
19+
# The Python binding (anda_cognitive_nexus_py) is excluded from default workspace
20+
# builds because it links against a Python interpreter. To build or test it,
21+
# temporarily uncomment the member above, then:
2122
# cargo test -p anda_cognitive_nexus_py --lib
2223

2324
[workspace.package]
@@ -105,6 +106,7 @@ regex = { version = "1.11", default-features = false }
105106
rustc-hash = { version = "2", default-features = false, features = ["std"] }
106107
pyo3 = { version = "0.20", default-features = false }
107108
pyo3-asyncio = { version = "0.20", default-features = false }
109+
pyo3-build-config = { version = "0.20" }
108110
serde-pyobject = { version = "0.2", default-features = false }
109111
mimalloc = { version = "0.1", features = ["v3"] }
110112

@@ -118,3 +120,10 @@ strip = true
118120
opt-level = 'z'
119121
codegen-units = 1
120122
panic = "abort"
123+
124+
# Python extension wheels must unwind on panic so PyO3 can turn panics into
125+
# Python exceptions instead of aborting the host interpreter.
126+
# Build with: maturin build --profile release-py
127+
[profile.release-py]
128+
inherits = "release"
129+
panic = "unwind"
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "anda_cognitive_nexus_py"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
edition = "2021"
55

66
[lib]
@@ -10,23 +10,21 @@ crate-type = ["cdylib", "rlib"]
1010
[dependencies]
1111
# Python Bindings
1212
pyo3 = { workspace = true, features = ["extension-module", "serde"] }
13-
pyo3-asyncio = { workspace = true, features = [
14-
"attributes",
15-
"async-std-runtime",
16-
"tokio-runtime",
17-
] }
18-
tokio = { workspace = true }
13+
pyo3-asyncio = { workspace = true, features = ["tokio-runtime"] }
14+
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
1915
serde-pyobject = { workspace = true }
2016

2117
# Anda
22-
anda_cognitive_nexus = { version = "0.7", path = "../../rs/anda_cognitive_nexus" }
23-
anda_kip = { version = "0.7", path = "../../rs/anda_kip" }
24-
anda_db = { version = "0.7", path = "../../rs/anda_db", features = ["full"] }
18+
anda_cognitive_nexus = { version = "0.8", path = "../../rs/anda_cognitive_nexus" }
19+
anda_kip = { version = "0.8", path = "../../rs/anda_kip" }
20+
anda_db = { version = "0.8", path = "../../rs/anda_db", features = ["full"] }
2521
anda_object_store = { version = "0.3", path = "../../rs/anda_object_store" }
2622

2723
# Other Crates
28-
serde_json = { workspace = true }
2924
serde = { workspace = true }
3025
object_store = { workspace = true }
3126
log = { workspace = true }
3227
structured-logger = { workspace = true }
28+
29+
[build-dependencies]
30+
pyo3-build-config = { workspace = true }

py/anda_cognitive_nexus_py/README.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ uv pip install -r tests_py/requirements.txt
5656
maturin develop
5757
```
5858

59-
After this step, the `anda` module is available to be imported in any Python script run from this activated environment.
59+
After this step, the `anda_cognitive_nexus_py` module is available to be imported in any Python script run from this activated environment.
60+
61+
To build a release wheel, use the `release-py` profile so panics unwind into
62+
Python exceptions instead of aborting the interpreter:
63+
64+
```bash
65+
maturin build --profile release-py
66+
```
6067

6168
## Running Tests
6269

@@ -85,7 +92,7 @@ To quickly verify your setup, you can run the following Python script:
8592

8693
```python
8794
# main.py
88-
import anda
95+
import anda_cognitive_nexus_py as anda
8996

9097
# This is the "hello world" function currently implemented
9198
result = anda.sum_as_string(10, 20)
@@ -111,7 +118,7 @@ python main.py
111118
The API now exposes configuration and enums as Python classes, not dicts or strings. Construct configs using `AndaDbConfig` and `StoreLocationType` directly:
112119

113120
```python
114-
import anda
121+
import anda_cognitive_nexus_py as anda
115122

116123
# Construct the config using Python classes (not dicts)
117124
config = anda.AndaDbConfig(
@@ -126,9 +133,16 @@ config = anda.AndaDbConfig(
126133
import asyncio
127134
async def main():
128135
db = await anda.PyAndaDB.create(config)
129-
# Execute a KIP command (async)
130-
result = await db.execute_kip("KIP_COMMAND_STRING")
131-
print(result) # result is a Python dict, not a JSON string
136+
try:
137+
# Execute a KIP command (async), optionally with :name parameters
138+
result = await db.execute_kip(
139+
"FIND(?t.name) WHERE { ?t {type: :t} } LIMIT 10",
140+
parameters={"t": "$ConceptType"},
141+
)
142+
print(result) # result is a Python dict, not a JSON string
143+
finally:
144+
# Flush pending data to storage; required for file-backed stores.
145+
await db.close()
132146

133147
asyncio.run(main())
134148
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
// With pyo3's `extension-module` feature, libpython is not linked; on macOS the
3+
// cdylib needs `-undefined dynamic_lookup` so `cargo build/run` works outside maturin.
4+
pyo3_build_config::add_extension_module_link_args();
5+
}

0 commit comments

Comments
 (0)