Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bindings/pycvc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ if(CVC_BUILD_PYCVC_CORE)
pycvc_exec:test_pycvc_exec.py
pycvc_exec_async:test_pycvc_exec_async.py
pycvc_exec_coro:test_pycvc_exec_coro.py
pycvc_state_exec:test_pycvc_state_exec.py
pycvc_world_clock:test_pycvc_world_clock.py
pycvc_world_units:test_pycvc_world_units.py
pycvc_dataprep:test_pycvc_dataprep.py
Expand Down
49 changes: 35 additions & 14 deletions bindings/pycvc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,24 @@ Python package that imports `pycvc`.

## Status

- **v0 (this): `Geometry`** — build meshes/polylines incrementally or in
bulk, set per-vertex colors, compute normals, and read/write files
(`.off`, CVC-raw, …) via libcvc's `geometry_file_io`.
- Planned: `Volume` (cvc::volume + SDF), `State` (cvc::state tree), and
numpy fast-paths; then a `vr3` module (exposed by VolumeRover3's embedded
interpreter) that turns a `pycvc.Geometry` into a live scene node.
pycvc covers geometry and volumes (with numpy views), the state tree (`State`),
images, models, world units and clocks, LOD, state_exec (below), and, in the
`pycvc_gl` module, cvcGL scenes, Ariadne and Dear ImGui HUDs. Each area has a
contract test (`test_pycvc_*.py`).

## Design

`pycvc_geometry.h` is a SWIG-safe facade: it *forward-declares*
`cvc::geometry` behind a `shared_ptr`, so SWIG only ever parses
`std::string`/`std::vector`/primitive signatures — never libcvc's heavy
headers. Only the `.cpp` includes libcvc. C++ host apps reach the wrapped
`cvc::geometry` via `native()` (which is `%ignore`d on the Python side).
pycvc wraps the **real** libcvc types under their C++ names; there is no
parallel facade layer (`pycvc.i`). `pycvc.volume` is a `cvc::volume`, `pycvc.State`
is a `cvc::state`, `pycvc.parse` is `cvc::state_exec::parse`. The libcvc headers
are `%include`d and curated with `%ignore` for members that can't cross. A thin
`%extend` layer adds Python conveniences such as numpy views.

Every constructor or operation that needs an app takes it explicitly
(`pycvc.volume(app)`, `pycvc.State.instance(app)`). There is no module-global
"current app". Where C++ takes a `cvc::state&`, Python passes a `pycvc.State`.
The goal is for the Python API to match the C++ API. For state_exec the audit
and plan are in `docs/PYCVC_STATE_EXEC_PARITY.md`.

## Build

Expand Down Expand Up @@ -213,6 +217,23 @@ pycvc.data_options_from_state(root, "", ex.data_defaults()) # what Exec

`Exec` starts from the same defaults as the app's exec scheduler (Ariadne), and
the same `state_exec.defaults.parser.*` and `state_exec.defaults.data.*` keys
override both. A syntax error
raises a `RuntimeError` with the parse error's message. Contract test:
`test_pycvc_exec.py`.
override both. A syntax error raises `pycvc.parse_error`, a `RuntimeError` with
`.line` and `.col`.

The rest of state_exec is the C++ API under the C++ names
(`docs/PYCVC_STATE_EXEC_PARITY.md` lists what is wrapped and what comes next):

```python
from pycvc import symbol
pycvc.parse("(f 'x \"s\")") # [symbol('f'), [symbol('quote'), symbol('x')], 's']
pycvc.parse_all("1 2") # [1, 2]
pycvc.to_string([symbol("a"), 1]) # '(a 1)'
pycvc.encode_value(root.child("snap"), {"k": [1, 2]})
pycvc.decode_value(root.child("snap")) # {'k': [1, 2]}
```

Values convert to native Python types, with `pycvc.symbol` for symbols and
`pycvc.value` as an opaque handle for closures and other non-data values. Such
a handle converts back to the same value when passed into the DSL. Conversion
is strict: non-`str` dict keys, ints outside 64 bits and unsupported types
raise. Contract tests: `test_pycvc_exec.py`, `test_pycvc_state_exec.py`.
Loading
Loading