Housekeeping ahead of the Inc 1-4 coverage work
- inventory.py --methods: report the instance methods the app calls per class, plus chained calls that constrain a return type. --check says which classes to bind; this says what to bind on them, which is what writing ~38 module TUs needs. - Drop StlAPI from the inventory: StlAPI_Writer has no app call site (the only use was a test fixture, now on the app's own STL writer). 138 symbols / 47 modules. - adding-symbols.md: scope the executing-constructor ban to the BRepAlgoAPI booleans, which are the only classes with a deferred Set*/Build form — BRepMesh_IncrementalMesh, GeomAPI_*, BRepCheck_Analyzer and friends compute in their constructor by design and bind as stock. Replace the per-increment app-test guidance: backend/tests/conftest.py imports n3xd.main, so no app test can collect until the last module is bound. Increments gate on stock-recorded fixtures here; the app suite is the Inc 4 gate. - parity_venv.sh: run the ocp suite in the swapped venv (it imports only OCP/n3xd_ocp, so it works throughout). - Fix a stale macro name in occt_handle.h (ocp_new, not OCP_TRANSIENT_NEW) and drop the unused ocp_transient_class helper. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DfriM8XUkn7uYf5Dwe2xo6
This commit is contained in:
@@ -6,15 +6,22 @@ Read [design.md](design.md) first if you are touching the machinery instead.
|
||||
## 1. Find what is missing
|
||||
|
||||
```bash
|
||||
python tools/inventory.py --emit # re-scan the app for OCP usage
|
||||
python tools/inventory.py --check # what the installed wheel lacks, by module
|
||||
python tools/inventory.py --emit # re-scan the app for OCP usage
|
||||
python tools/inventory.py --check # what the wheel lacks, by module
|
||||
python tools/inventory.py --methods --only BRepAdaptor # what to bind on each class
|
||||
```
|
||||
|
||||
`--check` groups gaps by module, which is how increments are scoped. Note it
|
||||
only sees symbols reached through an import (`TopExp.MapShapes_s`), not methods
|
||||
called on instances (`shape.IsSame(...)`) — a green `--check` is necessary, not
|
||||
sufficient. Running the app's own tests in the parity venv is what catches the
|
||||
rest, loudly, as an `AttributeError`.
|
||||
`--check` groups gaps by module, which is how increments are scoped. It only
|
||||
sees symbols reached through an import (`TopExp.MapShapes_s`), so it answers
|
||||
*which* classes to bind but not *what* to bind on them.
|
||||
|
||||
`--methods` answers the second question: it resolves variables assigned
|
||||
straight from a constructor and reports the methods called on them, plus
|
||||
chained calls as `Klass.Outer() -> Inner` (those constrain `Outer`'s **return**
|
||||
type — `adaptor.Cylinder().Radius()` is a requirement on `gp_Cylinder`). It is
|
||||
a heuristic — it does not follow arguments, returns or attributes, and a local
|
||||
reassigned from something else shows up as noise — so read it as a starting
|
||||
surface, not a specification.
|
||||
|
||||
## 2. Write the module
|
||||
|
||||
@@ -50,8 +57,13 @@ only in that a base class must precede its derived classes.
|
||||
`nb::class_` declaration and bind constructors with `ocp_new<T, Args...>()`.
|
||||
Never `nb::init<>` — see design.md.
|
||||
- **Long kernel call** → `OCP_NOGIL`, but only if it cannot re-enter Python.
|
||||
- **Executing constructor** → do not bind it. Bind the default constructor plus
|
||||
the `SetX`/`Build` sequence.
|
||||
- **Executing constructor** → banned only where a deferred `SetX`/`Build` API
|
||||
exists and the constructor duplicates `Build()`: the `BRepAlgoAPI_*` booleans
|
||||
and splitter. Bind their default constructor plus the `SetX`/`Build`
|
||||
sequence. Classes that only compute in their constructor and have no deferred
|
||||
form — `BRepMesh_IncrementalMesh`, `BRepCheck_Analyzer`, `GeomAPI_*`,
|
||||
`BRepClass3d_SolidClassifier`, `BRepExtrema_DistShapeShape`, `GCPnts_*`,
|
||||
`BRepBuilderAPI_Transform` — bind exactly as stock does.
|
||||
- **Enum** → `nb::is_arithmetic()` and `.export_values()`.
|
||||
- **`Message_ProgressRange` parameters** → omit them. The app never passes one
|
||||
(no `OCP.Message` import anywhere), and leaving them out keeps signatures
|
||||
@@ -82,11 +94,18 @@ make publish
|
||||
tools/parity_venv.sh && python tools/inventory.py --check
|
||||
```
|
||||
|
||||
Then run the slice of the app's suite the increment claims — Inc 1 is gated on
|
||||
`backend/tests/test_geom_memo.py`, Inc 2 on the tessellation tests plus
|
||||
`pytest -m perf`, Inc 4 on `test_cad_pool.py` and `test_derive.py`, and the
|
||||
cutover on the full suite plus `backend/tools/rebuild_sweep.py --diff` over the
|
||||
project store.
|
||||
**The app's own tests cannot gate an individual increment.** `backend/tests/
|
||||
conftest.py` imports `n3xd.main`, which pulls in the whole app and therefore the
|
||||
whole OCP surface, so every backend test fails at collection until the last
|
||||
module is bound. Increments are gated here instead: `tools/gen_fixtures.py`
|
||||
records reference values from the *stock* wheel (counts, `Modified`/`Generated`/
|
||||
`IsDeleted` history maps, measured floats) into `tests/data/manifest.json`, and
|
||||
`tests/test_inc<N>_*.py` reproduces the same constructions under our wheel.
|
||||
Counts and history maps must match exactly; floats compare at rel 1e-9.
|
||||
|
||||
The app's full suite is the **Inc 4** gate, run in the parity venv, alongside
|
||||
`pytest -m perf` and `backend/tools/rebuild_sweep.py --diff` over the project
|
||||
store.
|
||||
|
||||
## Adding to `n3xd_ocp` instead
|
||||
|
||||
|
||||
Reference in New Issue
Block a user