Skip to content

fix(transpiler): @when result assignment silently dropped in exported module #80

fix(transpiler): @when result assignment silently dropped in exported module

fix(transpiler): @when result assignment silently dropped in exported module #80

Workflow file for this run

name: PR Gate
on:
pull_request:
branches: ["main"]
workflow_dispatch:
# Default least-privilege token scope for every job. Override at job
# scope only when a job legitimately needs more (none currently do —
# all jobs read source and upload artifacts via the workflow-scoped
# implicit ``actions`` token, which is independent of ``contents``).
permissions:
contents: read
# Build the private `bocpy._internal_test` C extension across all CI test
# jobs. It is gated off by default in setup.py so it never ships in
# distributed wheels; CI opts in here so the corresponding pytest modules
# (test_internal_*, test_compat_atomics) actually run instead of being
# skipped.
env:
BOCPY_BUILD_INTERNAL_TESTS: "1"
jobs:
linting:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.14
- name: Install pinned linting dependencies
# Two-step install pattern: pip refuses ``--require-hashes``
# for editable installs, so resolve the locked dependency
# graph first, then install bocpy itself with ``--no-deps``.
run: pip install -r ci/constraints-linting.txt --require-hashes
- name: Install bocpy (editable, no deps)
run: pip install -e . --no-deps
- name: Run flake8
# ``--filename`` opts the walker into .pyi stubs, which flake8
# otherwise skips silently (default is ``*.py`` only).
run: flake8 --filename='*.py,*.pyi' src/bocpy test examples scripts
docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.14
- name: Install pinned docs dependencies
run: pip install -r ci/constraints-docs.txt --require-hashes
- name: Install bocpy (editable, no deps)
run: pip install -e . --no-deps
- name: Build Sphinx docs (warnings as errors)
run: sphinx-build -W -b html sphinx/source sphinx/build/html
audit:
# Vulnerability scan of the hashed CI constraint files. Each
# ``ci/constraints-*.txt`` is checked against the PyPI advisory
# database via ``pip-audit``. ``--strict`` exits non-zero if any
# advisory cannot be matched against the resolver's view of the
# dependency graph (e.g. yanked release, network failure) so we
# never silently skip a leg.
#
# bocpy itself has zero third-party runtime Python deps, so this
# job covers the entire transitive dependency surface that ships
# to a developer's machine via ``pip install bocpy[X]``.
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.14
- name: Install pinned pip-audit
run: pip install -r ci/constraints-audit.txt --require-hashes
- name: Audit test constraints
run: pip-audit --strict --requirement ci/constraints-test.txt
- name: Audit linting constraints
run: pip-audit --strict --requirement ci/constraints-linting.txt
- name: Audit docs constraints
run: pip-audit --strict --requirement ci/constraints-docs.txt
- name: Audit audit constraints (self-check)
run: pip-audit --strict --requirement ci/constraints-audit.txt
c-abi-consumer:
# Build a standalone downstream extension against the bocpy public
# C ABI (templates/c_abi_consumer/) and run its pytest suite. This
# exercises ``bocpy.get_include()`` / ``bocpy.get_sources()`` and
# the ``<bocpy/bocpy.h>`` umbrella from a fresh process that does
# not share build flags with bocpy itself. The Windows leg also
# compiles ``bocpy_msvc.c`` (returned by ``get_sources()`` on
# win32) end-to-end.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
# c-abi-consumer never invokes the private internal-test
# extension, so building it is pure overhead.
install-internal-tests: "false"
- name: Build downstream consumer extension
run: pip install --no-build-isolation ./templates/c_abi_consumer
- name: Run consumer tests
run: pytest -vv templates/c_abi_consumer/test
sdist:
runs-on: ubuntu-latest
# The new sdist must build cleanly without the internal-test
# opt-in; setuptools excludes those sources from the tarball, so
# leaving the workflow-level env in scope would attempt to build
# missing files via PEP 517.
env:
BOCPY_BUILD_INTERNAL_TESTS: ""
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.14
- name: Install build tool
run: pip install build
- name: Build sdist
run: python -m build --sdist
- name: Install from sdist
run: pip install dist/*.tar.gz --verbose
- name: Smoke-test import
run: python -c "import bocpy; print(bocpy.__name__)"
- name: Smoke-test example with data file
run: |
python -c "import importlib, importlib.resources as r; \
m = importlib.import_module('bocpy.examples'); \
assert (r.files(m) / 'cheese.txt').is_file(), 'cheese.txt missing'; \
assert (r.files(m) / 'menu.txt').is_file(), 'menu.txt missing'"
- name: Wheel allow-list (no internal C/H ships)
env:
BOCPY_TEST_WHEEL: "1"
run: |
pip install -r ci/constraints-test.txt --require-hashes
pytest -vv test/test_public_c_abi.py
cpp-format:
runs-on: ubuntu-latest
strategy:
matrix:
path:
- check: src/bocpy
- check: templates/c_abi_consumer/src
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run clang-format style check
uses: jidicula/clang-format-action@654a770daa28443dd111d133e4083e21c1075674 # v4.18.0
with:
clang-format-version: '18'
check-path: ${{matrix.path['check']}}
exclude-regex: ${{matrix.path['exclude']}}
linux:
runs-on: ubuntu-latest
strategy:
matrix:
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
- name: Python test
run: pytest -vv -s
windows:
runs-on: windows-latest
strategy:
matrix:
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
- name: Python test
run: pytest -vv -s
windows-x86:
runs-on: windows-latest
strategy:
matrix:
python_version: ["3.12"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
architecture: x86
- name: Python test
run: pytest -vv -s
macos-arm64:
runs-on: macos-latest
strategy:
matrix:
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
- name: Python test
run: pytest -vv -s
macos-x86_64:
runs-on: macos-15-intel
strategy:
matrix:
python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
- name: Python test
run: pytest -vv -s
free-threaded:
runs-on: ubuntu-latest
strategy:
matrix:
python_version: ["3.13t", "3.14t"]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup bocpy for testing
uses: ./.github/actions/setup-bocpy-test
with:
python-version: ${{ matrix.python_version }}
- name: Verify GIL is disabled
run: python -c "import sys; assert not sys._is_gil_enabled(), 'GIL should be disabled'"
- name: Verify import does not re-enable GIL
run: python -c "import bocpy; import sys; assert not sys._is_gil_enabled(), 'GIL re-enabled on import'"
- name: Python test
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
max_attempts: 3
timeout_minutes: 10
command: pytest -vv -s
asan:
runs-on: ubuntu-latest
env:
CPYTHON_VERSION: v3.14.2
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang llvm build-essential pkg-config \
libbz2-dev libffi-dev libgdbm-dev libgdbm-compat-dev liblzma-dev \
libncurses5-dev libreadline6-dev libsqlite3-dev libssl-dev \
lzma lzma-dev tk-dev uuid-dev zlib1g-dev libzstd-dev
- name: Download CPython ${{ env.CPYTHON_VERSION }}
run: |
git clone --depth 1 --branch ${{ env.CPYTHON_VERSION }} \
https://github.com/python/cpython.git "$RUNNER_TEMP/cpython-src"
- name: Build CPython with ASAN and UBSAN
working-directory: ${{ runner.temp }}/cpython-src
run: |
CC=clang ./configure \
--with-address-sanitizer \
--without-pymalloc \
--with-undefined-behavior-sanitizer \
--without-system-libmpdec
make -j"$(nproc)"
- name: Create virtual environment
run: |
"$RUNNER_TEMP/cpython-src/python" -m venv "$RUNNER_TEMP/asan-venv"
- name: Build bocpy
run: |
source "$RUNNER_TEMP/asan-venv/bin/activate"
python -m pip install --upgrade pip
pip install -r ci/constraints-test.txt --require-hashes
CC="clang -fsanitize=address,undefined -fno-sanitize=vptr" \
pip install -e . --no-deps --verbose
- name: Run tests
env:
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
run: |
source "$RUNNER_TEMP/asan-venv/bin/activate"
pytest -vv -s