Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3c06704
build: allow a pure-Python wheel, and drop pkg_resources
sspickle Aug 10, 2026
b64d142
feat: a wasm/Web-Worker transport — the host supplies the pipe
sspickle Aug 10, 2026
ae16fc7
feat: host-agnostic browser front-end ported from glowcomm.js
sspickle Aug 10, 2026
58c22ff
fix: don't clobber glow's __context, and drop (not forward) synthesiz…
sspickle Aug 10, 2026
379672f
feat(worker): eager boot + async rate/sleep + loud deferrals for wasm…
sspickle Aug 10, 2026
3772014
fix(worker): render cap, rate(0) parity, fixture isolation, stale com…
sspickle Aug 10, 2026
502d6f8
feat(worker): port glowcomm's event capture — mouse, keys, camera
sspickle Aug 10, 2026
0a6ddbe
fix(worker): tell the front-end when the clock stops; poll the canvas…
sspickle Aug 10, 2026
393c1d6
feat(worker): poll() — a pacing tick that stays quiet while rate() dr…
sspickle Aug 10, 2026
47875af
fix(worker): the loud-deferral list was five constructs short, and sl…
sspickle Aug 10, 2026
ec6d59d
fix(worker): rate(N) slept a full period ON TOP of the student's loop…
sspickle Aug 10, 2026
68eff8c
fix(worker): the await is right, the reason given for it was wrong
sspickle Aug 10, 2026
2504893
docs(worker): the mechanism was corrected everywhere EXCEPT the code …
sspickle Aug 10, 2026
c8fd10a
ci: build the pure-Python (py3-none-any) wheel as a pinned-artifact f…
sspickle Aug 15, 2026
77521bb
ci: never publish pre-releases to PyPI
sspickle Aug 15, 2026
6c357e6
ci: fix invalid if under on.release — the guard belongs on jobs only
sspickle Aug 15, 2026
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
58 changes: 58 additions & 0 deletions .github/workflows/pure-wheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Pure-Python wheel (wasm/Pyodide)

# Builds the VPYTHON_PURE_PYTHON=1 wheel (py3-none-any) that Pyodide/micropip
# and other wasm targets can install — they cannot use platform wheels.
# Consumers (e.g. trinket) pin the artifact by URL + sha256; a GitHub release
# gets the wheel attached automatically so pins survive artifact expiry.

on:
workflow_dispatch:
push:
branches: [master, pyodide-packaging]
release:
types: [published]

jobs:
pure-wheel:
runs-on: ubuntu-latest
permissions:
contents: write # needed only for the release-asset upload step
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # setuptools_scm-style dev versions need history

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Build pure wheel
run: |
pip install build
VPYTHON_PURE_PYTHON=1 python -m build --wheel --outdir dist
ls -l dist

- name: Verify wheel is py3-none-any and imports
run: |
python - <<'EOF'
import glob, sys
w = glob.glob('dist/*.whl')
assert w and w[0].endswith('py3-none-any.whl'), f"not a pure wheel: {w}"
print("pure wheel:", w[0])
EOF
pip install dist/*.whl
python -c "import vpython; print('import ok', vpython.__version__)"

- name: Checksum
run: shasum -a 256 dist/*.whl | tee dist/SHA256SUMS

- uses: actions/upload-artifact@v4
with:
name: vpython-pure-wheel
path: dist/

- name: Attach wheel to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "${{ github.event.release.tag_name }}" dist/*.whl dist/SHA256SUMS --clobber
9 changes: 9 additions & 0 deletions .github/workflows/upload_pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ on:
release:
types: [created]

# Pre-releases exist to host pinned artifacts (see pure-wheel.yml) — they must
# NEVER publish to PyPI. Guarded per-job because uploads happen per-job: on
# 2026-08-15 a pre-release tag partially published 7.6.6.dev0 (sdist + mac/win
# wheels) before the linux legs failed.

jobs:
wheels:
if: ${{ !github.event.release.prerelease }}

strategy:
max-parallel: 4
Expand Down Expand Up @@ -40,6 +46,7 @@ jobs:
twine upload dist/*.whl

linux_wheels:
if: ${{ !github.event.release.prerelease }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
Expand Down Expand Up @@ -71,6 +78,7 @@ jobs:
twine upload dist/vpython-*-manylinux*.whl

linux_aarch64_wheels:
if: ${{ !github.event.release.prerelease }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
Expand Down Expand Up @@ -100,6 +108,7 @@ jobs:
twine upload dist/vpython-*-manylinux*.whl

sdist:
if: ${{ !github.event.release.prerelease }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ docs/_build/

# PyBuilder
target/

# local virtualenvs
.venv/
venv/
36 changes: 28 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import os

from setuptools import setup

from distutils.extension import Extension

try:
from Cython.Build import cythonize
USE_CYTHON = True
extensions = cythonize('vpython/cyvector.pyx')
except ImportError:
extensions = [Extension('vpython.cyvector', ['vpython/cyvector.c'])]
# Set VPYTHON_PURE_PYTHON=1 to build with no C extension at all. The result is a
# `py3-none-any` wheel, which is what Pyodide/micropip and other wasm targets
# require — they cannot install a platform wheel, and declaring `ext_modules` is
# what makes every wheel a platform wheel.
#
# Nothing is lost but speed: `_vector_import_helper` already falls back to the
# pure-Python `vector` implementation when `cyvector` cannot be imported, so the
# same source runs either way. Ordinary builds are unchanged — this is opt-in.
PURE_PYTHON = os.environ.get('VPYTHON_PURE_PYTHON', '').strip() not in ('', '0', 'false', 'False')

if PURE_PYTHON:
extensions = []
else:
try:
from Cython.Build import cythonize
USE_CYTHON = True
extensions = cythonize('vpython/cyvector.pyx')
except ImportError:
extensions = [Extension('vpython.cyvector', ['vpython/cyvector.c'])]


install_requires = ['jupyter', 'jupyter-server-proxy', 'jupyterlab-vpython>=3.1.8', 'notebook>=7.0.0', 'numpy', 'ipykernel',
Expand Down Expand Up @@ -35,14 +50,19 @@
'Topic :: Multimedia :: Graphics :: 3D Rendering',
'Topic :: Scientific/Engineering :: Visualization',
],
ext_modules=extensions,
install_requires=install_requires,
python_requires=">=3.8",
python_requires=">=3.8", # importlib.metadata, used in vpython/__init__.py
package_data={'vpython': ['vpython_data/*',
'vpython_libraries/*',
'vpython_libraries/images/*']},
)

# `ext_modules` is added only for a normal build. Omitting the key entirely (as
# opposed to passing an empty list) is what makes setuptools tag the wheel
# `py3-none-any` rather than a platform wheel.
if not PURE_PYTHON:
setup_args['ext_modules'] = extensions

try:
setup(**setup_args)
except SystemExit as e:
Expand Down
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Make the in-tree ``vpython`` package importable regardless of cwd.

The repo root is prepended (not appended) so these tests always exercise the
working tree rather than any copy of vpython installed in site-packages.
"""

import os
import sys

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
Loading
Loading