Skip to content

fix(bindings): don't abort the build when an integer build knob is set but empty - #2572

Open
LeSingh1 wants to merge 1 commit into
NVIDIA:mainfrom
LeSingh1:bindings-build-knobs
Open

fix(bindings): don't abort the build when an integer build knob is set but empty#2572
LeSingh1 wants to merge 1 commit into
NVIDIA:mainfrom
LeSingh1:bindings-build-knobs

Conversation

@LeSingh1

@LeSingh1 LeSingh1 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Problem

cuda_bindings reads three integer build knobs from the environment, and each one is fed straight to a bare int():

# cuda_bindings/build_hooks.py (and the same block in cuda_bindings/setup.py)
if os.environ.get("PARALLEL_LEVEL") is not None:
    warn("Environment variable PARALLEL_LEVEL is deprecated. ...", DeprecationWarning, stacklevel=2)
    nthreads = int(os.environ.get("PARALLEL_LEVEL", "0"))
else:
    nthreads = int(os.environ.get("CUDA_PYTHON_PARALLEL_LEVEL", "0") or "0")

compile_for_coverage = bool(int(os.environ.get("CUDA_PYTHON_COVERAGE", "0")))

1. An empty value aborts the build. CUDA_PYTHON_COVERAGE= pip install . is how a variable gets neutralised — the same shape as an empty ENV in a Dockerfile or an unset job-spec variable in CI. int("") raises

ValueError: invalid literal for int() with base 10: ''

while the PEP 517 backend module is still being imported, so the build dies before it emits any output and the traceback never names the variable at fault. CUDA_PYTHON_PARALLEL_LEVEL already guards itself with or "0"; CUDA_PYTHON_COVERAGE and PARALLEL_LEVEL do not.

2. PARALLEL_LEVEL selects its branch on is not None. So PARALLEL_LEVEL= takes the deprecated path: it warns about a variable the caller has explicitly neutralised, shadows CUDA_PYTHON_PARALLEL_LEVEL (which may well be the one that is actually set), and then crashes in int("").

3. A genuinely wrong value is not diagnosed. CUDA_PYTHON_COVERAGE=yes raises the same anonymous invalid literal for int() — worth stopping for, but worth naming.

Fix

Add env_int(name, default), which treats unset and empty alike and reports a non-integer value with the variable's name attached, plus parallel_level(), which keeps the deprecation warning for a value that is actually set and otherwise falls through to CUDA_PYTHON_PARALLEL_LEVEL. setup.py now calls the same two helpers rather than keeping a second copy of the parsing, so the two build entry points cannot drift.

Behaviour that does not change: a set, integer value parses exactly as before (including 0 and negatives), and PARALLEL_LEVEL=<n> still warns and still wins over CUDA_PYTHON_PARALLEL_LEVEL.

This mirrors #2547, which makes the same change for the cuda.core copies. The two packages have separate build backends and neither imports the other's, so the fixes are independent files; the wording of the helper is kept identical so a future reader sees one convention.

Tests

New cuda_bindings/tests/test_build_hooks.py, modelled on the existing cuda_core/tests/test_build_hooks.py (same importlib loader so sys.path never gains the cuda_bindings/ source directory, same --noconftest note). 15 cases covering empty/whitespace/unset/integer/non-integer values and all four PARALLEL_LEVEL × CUDA_PYTHON_PARALLEL_LEVEL combinations.

What I ran

Environment: macOS, no CUDA driver and no CUDA toolkit, so cuda.bindings is not built here.

  • Ran: pytest cuda_bindings/tests/test_build_hooks.py --noconftest — 15 passed. These tests need only setuptools; build_hooks.py imports Cython lazily inside _build_cuda_bindings, so the module loads without a toolkit. (--noconftest is required because cuda_bindings/tests/conftest.py imports cuda.bindings.driver; cuda_core/tests/test_build_hooks.py documents the same requirement.)
  • Ran (teeth check): restored build_hooks.py and setup.py from main with the new test file in place — all 15 fail (ValueError: invalid literal for int() with base 10: '' for the empty-value cases, AttributeError: module 'build_hooks' has no attribute 'env_int' for the rest).
  • Ran: ruff check and ruff format --check on the three changed files — clean, no new findings against a main baseline for the same files.
  • Did not run: any actual wheel/editable build, or anything requiring a CUDA toolkit or GPU.

Refs #2547

…t but empty

`CUDA_PYTHON_COVERAGE= pip install .` is how a variable gets neutralised --
the same shape as an empty value in a Dockerfile `ENV` or a CI job spec. Both
build entry points fed those values to a bare `int()`:

    compile_for_coverage = bool(int(os.environ.get("CUDA_PYTHON_COVERAGE", "0")))

so an empty value raised `ValueError: invalid literal for int() with base 10:
''` while the PEP 517 backend module was still being imported, before any build
output, and without naming the variable at fault.

`PARALLEL_LEVEL` had a second problem. The branch was chosen with `is not
None`, so `PARALLEL_LEVEL=` took the deprecated path -- warning about a
variable the caller had explicitly neutralised, then crashing in `int("")` --
instead of falling through to `CUDA_PYTHON_PARALLEL_LEVEL`, which already
guarded itself with `or "0"`.

Route all three knobs through `env_int`, which treats unset and empty alike,
and reports a genuinely non-integer value (`CUDA_PYTHON_COVERAGE=yes`, which
would otherwise silently produce a build with no coverage instrumentation) with
the variable's name attached. `parallel_level()` keeps the deprecation warning
for a value that is actually set.

This mirrors the cuda.core change in NVIDIA#2547 for the cuda-bindings copies; the
two packages have separate build backends and neither imports the other's.

Refs NVIDIA#2547
@copy-pr-bot

copy-pr-bot Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the cuda.bindings Everything related to the cuda.bindings module label Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.bindings Everything related to the cuda.bindings module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant