About
This package provides a fast edit-preview workflow for build123d CAD projects, especially when working in editors like Emacs.
The ocp123d command starts a single long-lived ocp_vscode viewer server, watches your project directory recursively, and re-runs your entry script whenever Python files change.
Key behavior:
- starts the viewer server once and keeps it running
- cleans up a previously recorded viewer process on the same port
- watches the entire project recursively
- reloads when indirectly imported Python modules change
- re-runs the preview when a new browser viewer tab registers
- avoids stale imports by running each reload in a fresh child process
Table of Contents
Installation
Install this tool into the same virtual environment as your CAD project:
pip install build123d-ocp-preview
For local development from this repository:
pip install -e /path/to/build123d-ocp-preview
build123d is not a required dependency of this watcher because your CAD project
environment should normally provide it. For a fresh demo environment, install the
optional extra:
python -m pip install "build123d-ocp-preview[build123d]"
Quick Start
Given a project like:
/Users/me/my-build123-project/
assembly.py
my_cad/
scratch.py
where assembly.py calls ocp_vscode.show(...), run:
cd /Users/me/my-build123-project
source .venv/bin/activate
ocp123d -p . assembly.py
Open the viewer URL printed by ocp123d, usually:
http://127.0.0.1:3939/viewer
By default, ocp123d also opens this viewer page in your browser before the
initial preview run. This gives ocp_vscode time to register the browser client,
so the first model is loaded immediately instead of leaving the splash preview on
screen.
Now saving assembly.py or any project Python module such as
picar_cad/scratch.py triggers a debounced re-run of assembly.py.
If you open the viewer in a new browser tab later, ocp123d detects the new
browser client registration and triggers another debounced preview run. This
works around ocp_vscode initializing fresh browser clients with its built-in
logo scene.
CLI
ocp123d [options] ENTRY [ENTRY ...]
Options:
-p, --project PATH Project directory to watch. Defaults to cwd.
-o, --port PORT ocp_vscode port. Defaults to 3939.
-d, --debounce-ms N Debounce window in milliseconds. Defaults to 250.
-i, --ignore PATH Project-relative Python file path to ignore. Repeatable.
-c, --config PATH TOML config file.
-n, --no-initial-run Start watching without running entries immediately.
-b, --no-open Do not open the browser viewer before the initial run.
-h, --help Show help.
Examples:
ocp123d -p . assembly.py
ocp123d -p . -o 3940 -d 500 assembly.py
ocp123d -p . -i picar_cad/temp.py assembly.py
ocp123d -p . --no-open assembly.py
ocp123d -p . assembly.py second_preview.py
Config File
The optional config file is TOML. Currently it supports exact ignored file paths:
ignore = [
"picar_cad/temp.py",
"picar_cad/generated.py",
]
Use it with:
ocp123d -p . -c ocp123d.toml assembly.py
CLI ignores and config ignores are merged:
ocp123d -p . -c ocp123d.toml -i picar_cad/scratch_experiment.py assembly.py
Ignore paths are resolved relative to the project directory unless absolute. Wildcard and glob matching are not implemented yet.
Entry Scripts
Your entry script should be a normal Python script that sends geometry to
ocp_vscode, for example:
from build123d import Box
from ocp_vscode import show
show(Box(10, 20, 30), names=["box"])
ocp123d sets the viewer port before running the entry script. It also prepends the
project directory to PYTHONPATH, so project-local imports work when the command is
run from elsewhere.
What Gets Watched
The watcher observes .py files under the project directory recursively.
It always ignores common noisy directories:
.git.venvvenv__pycache__.mypy_cache.pytest_cache.ruff_cachenode_modules
How Reloading Works
On each reload, ocp123d launches a fresh child process for each entry file. This
is intentionally simple and reliable:
entry.py imports A
A imports B
B imports C
If C.py changes, the watcher sees the file change and re-runs entry.py in a new
process. Python imports the whole graph from disk again, so stale imported objects
from a previous run do not survive.
The tradeoff is that heavy CAD scripts pay their normal script execution cost on each reload. The viewer server itself stays running.
ocp123d records the ocp_vscode process ID it started in a temporary state
file. On the next launch for the same port, it removes dead PID files and only
terminates a still-running process if the recorded command line is identifiable
as ocp_vscode for that port. It deliberately does not kill arbitrary processes
that happen to use the same port.
Current Limitations
- No persistent IPython/Jupyter console.
- No partial in-process module reload.
- Ignore rules are exact paths only, not globs.
- Only Python source changes trigger reloads.
Development
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
pytest -q
ruff check .
pyright
Metadata
Release files for build123d-ocp-preview 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| build123d_ocp_preview-0.2.1.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| build123d_ocp_preview-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.0 kB
Release files / build123d_ocp_preview-0.2.1.tar.gz
| Download URL | build123d_ocp_preview-0.2.1.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b4849a0244619f0c93fdbc39cd1efc2a3cdc2c2cba454af28d75e32356f8ef14
|
|
BLAKE2b-256 checksum How to use checksums |
9555083ae4ea262c3821fb23d5f4104d0124713d7bb4394f1ca491c09032d5ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / build123d_ocp_preview-0.2.1-py3-none-any.whl
| Download URL | build123d_ocp_preview-0.2.1-py3-none-any.whl |
|---|---|
| Size | 18.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
42546b14fcf76e17565a522dbc38cff9ea65d48ce4d5ecaed5083bd97355ed17
|
|
BLAKE2b-256 checksum How to use checksums |
7e26b3ddfe66a398fd1a7e3553d6b603eae112a3852b3a5fe412773096737baf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|