For a usage overview, see README.md.
Bindings call the public Rust facade. PyO3 supplies types; the generator handles declared overloads, indexing and NumPy annotations. See the binding contract for implementation rules and examples.
Run all commands from the repository root.
Dev and rc builds are for development testing:
pip install --upgrade --pre cosmolkit--pre allows both dev and rc versions. To test a specific build, use
pip install cosmolkit==<published-version>.
Install development tools and the extractor matching PyO3:
uv sync --group dev
cargo install pyo3-introspection --version 0.30.1 --locked --root target/pyo3-tools.venv/bin/python python/build_stubs.py \
--extractor target/pyo3-tools/bin/pyo3-introspectionThis command compiles the Rust extension, extracts types and generates the Python
package and .pyi. It does not run tests or build a wheel.
The package is written to
python/artifacts/smoke/package/cosmolkit/.
Run runtime samples and static type checks without rebuilding:
.venv/bin/python python/check_stubs.pyThis check uses the development dependencies, including RDKit for its interop
type annotations. Coverage and local pre-commit checks run it; publishing does not.
After changing bindings or generation rules, run build_stubs.py again.
.venv/bin/python python/registry_check.pyCompares the canonical registry with the built package and generated types,
including configuration fields and errors. Writes python/artifacts/registry.json.
After build_stubs.py, package the extension, __init__.py, __init__.pyi and py.typed:
.venv/bin/maturin build --release --manifest-path python/Cargo.toml \
--target-dir target/typed_facade_projection --features extension \
--interpreter .venv/bin/python \
--out python/artifacts/wheels
uv pip install --python .venv/bin/python --reinstall \
python/artifacts/wheels/cosmolkit-*.whl
.venv/bin/python -c 'import cosmolkit as ck; print(ck.mol_from_smiles("CCO").num_atoms)'The final command prints 3. Omit --release only for faster local debug
builds; use optimized wheels for applications and performance measurements.
Distribution name: cosmolkit; import name: cosmolkit.
Release wheels use release-abi3-py39 for Python 3.9 and newer, alongside
release-cpython builds for Python 3.11, 3.12 and 3.13. Type declarations are
generated separately with the current Python/PyO3 environment and packaged
unchanged with those wheels.
Molecules support pickle.dumps(mol) and pickle.loads(data) through the stable
cosmolkit._molecule_from_binary reconstruction function and native binary format.
Explicit 3D coordinate inputs use Rust Vec<[f64; 3]>. Lists and tuples use a
shared input adapter; NumPy arrays use an array view rather than per-element
Python extraction. Shape is checked before numeric conversion, and Rust checks
finite values. The official stub does not encode the fixed row length of 3.
Configurations declare fields only in their Rust owner, using
#[derive(cosmolkit_macros::Configuration)]. Re-export its generated
hidden metadata alongside the native type; the facade also re-exports its
__ck_configuration_TypeName macro. The Python declaration names only that type:
ck::project_configuration!(ck::MaccsFingerprintParams);The shared projection generates typed construction and writable properties over the actual Rust configuration. Getters return tuples, readonly mappings or nested configuration views. Child edits update the parent; containers are replaced through whole-field assignment. Conversion failures leave the Rust field unchanged, including fixed-array length errors. No editable Python container mirror is retained.
p = ck.MorganCallParams(from_atoms=[0])
p.from_atoms = [0, 2] # Assigns the actual Rust field.
assert p.from_atoms == (0, 2)
# p.from_atoms = ["wrong"] # TypeError; the field stays (0, 2).Native annotations specify construction and composition: required keeps
mandatory inputs, none_default accepts None as the native default, flatten
exposes explicitly composed options, and factory forwards the registered
new() method. Every ordinary parameter wrapper retains its native record.
Callbacks, random sources and private execution state use an explicit adapter:
ck::project_configuration!(ck::SubstructMatchParams, using match_parameters);Their native declarations mark state and adapter fields; ordinary fields
still come from native metadata and assign the actual native fields.
Adapters retain actual native ownership, initialization and invocation errors.
Unmarked private fields, generic records and unsupported field types fail
compilation, rather than being inferred or downgraded.
Ordinary new APIs must not require generator, runner or consumer-sample changes.
tests/runtime.py and tests/positive.py contain only a few fixed framework
examples; they do not enumerate business APIs. New projection protocols require
an explicit design decision.