Skip to content

Commit 3d01d6a

Browse files
authored
Merge branch 'main' into fix/windows-pixi-task-vars
2 parents 0745279 + 545ead4 commit 3d01d6a

File tree

133 files changed

+7238
-5747
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+7238
-5747
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: "CI: Enforce assignee/label/milestone on PRs"
6+
7+
on:
8+
pull_request_target:
9+
types:
10+
- opened
11+
- edited
12+
- synchronize
13+
- assigned
14+
- unassigned
15+
- labeled
16+
- unlabeled
17+
- reopened
18+
- ready_for_review
19+
20+
jobs:
21+
check-metadata:
22+
name: PR has assignee, labels, and milestone
23+
if: github.repository_owner == 'NVIDIA'
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Check for assignee, labels, and milestone
27+
env:
28+
ASSIGNEES: ${{ toJson(github.event.pull_request.assignees) }}
29+
LABELS: ${{ toJson(github.event.pull_request.labels) }}
30+
MILESTONE: ${{ github.event.pull_request.milestone && github.event.pull_request.milestone.title || '' }}
31+
PR_URL: ${{ github.event.pull_request.html_url }}
32+
IS_BOT: ${{ github.actor == 'dependabot[bot]' || github.actor == 'pre-commit-ci[bot]' || github.actor == 'copy-pr-bot[bot]' }}
33+
IS_DRAFT: ${{ github.event.pull_request.draft }}
34+
run: |
35+
if [ "$IS_BOT" = "true" ] || [ "$IS_DRAFT" = "true" ]; then
36+
echo "Skipping check for bot or draft PR."
37+
exit 0
38+
fi
39+
40+
ERRORS=""
41+
42+
ASSIGNEE_COUNT=$(echo "$ASSIGNEES" | jq 'length')
43+
if [ "$ASSIGNEE_COUNT" -eq 0 ]; then
44+
ERRORS="${ERRORS}- **Missing assignee**: assign at least one person to this PR.\n"
45+
fi
46+
47+
# Module labels identify which package the PR touches.
48+
# Cross-cutting labels exempt PRs from needing a module label.
49+
LABEL_NAMES=$(echo "$LABELS" | jq -r '.[].name')
50+
MODULE_LABELS="cuda.bindings cuda.core cuda.pathfinder"
51+
MODULE_EXEMPT_LABELS="CI/CD"
52+
HAS_MODULE=false
53+
for label in $LABEL_NAMES; do
54+
for mod in $MODULE_LABELS $MODULE_EXEMPT_LABELS; do
55+
if [ "$label" = "$mod" ]; then
56+
HAS_MODULE=true
57+
break 2
58+
fi
59+
done
60+
done
61+
62+
if [ "$HAS_MODULE" = "false" ]; then
63+
ERRORS="${ERRORS}- **Missing module label**: add at least one of: \`cuda.bindings\`, \`cuda.core\`, \`cuda.pathfinder\` (or a cross-cutting label such as \`CI/CD\`).\n"
64+
fi
65+
66+
# Type labels categorize the kind of change.
67+
TYPE_LABELS="bug enhancement feature documentation test example CI/CD packaging dependencies performance experiment RFC support P0 P1 P2"
68+
HAS_TYPE=false
69+
for label in $LABEL_NAMES; do
70+
for typ in $TYPE_LABELS; do
71+
if [ "$label" = "$typ" ]; then
72+
HAS_TYPE=true
73+
break 2
74+
fi
75+
done
76+
done
77+
78+
if [ "$HAS_TYPE" = "false" ]; then
79+
ERRORS="${ERRORS}- **Missing type label**: add at least one of: \`bug\`, \`enhancement\`, \`feature\`, \`documentation\`, \`test\`, \`example\`, \`CI/CD\`, \`packaging\`, \`dependencies\`, \`performance\`, \`experiment\`, \`RFC\`, \`support\`, \`P0\`, \`P1\`, \`P2\`.\n"
80+
fi
81+
82+
if [ -z "$MILESTONE" ]; then
83+
ERRORS="${ERRORS}- **Missing milestone**: assign a milestone to this PR.\n"
84+
fi
85+
86+
# Block PRs with labels that indicate they are not ready to merge.
87+
BLOCKED_PATTERNS="blocked DO NOT MERGE do not merge"
88+
for label in $LABEL_NAMES; do
89+
for pattern in $BLOCKED_PATTERNS; do
90+
if echo "$label" | grep -qi "$pattern"; then
91+
ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n"
92+
break
93+
fi
94+
done
95+
done
96+
97+
if [ -n "$ERRORS" ]; then
98+
echo "::error::This PR is missing required metadata. See the job summary for details."
99+
{
100+
echo "## PR Metadata Check Failed"
101+
echo ""
102+
printf '%b' "$ERRORS"
103+
echo ""
104+
echo "Please update the PR at: $PR_URL"
105+
} >> "$GITHUB_STEP_SUMMARY"
106+
exit 1
107+
fi
108+
109+
ASSIGNEE_LIST=$(echo "$ASSIGNEES" | jq -r '.[].login' | paste -sd ', ' -)
110+
LABEL_LIST=$(echo "$LABEL_NAMES" | paste -sd ', ' -)
111+
{
112+
echo "## PR Metadata Check Passed"
113+
echo ""
114+
echo "- **Assignees**: $ASSIGNEE_LIST"
115+
echo "- **Labels**: $LABEL_LIST"
116+
echo "- **Milestone**: $MILESTONE"
117+
} >> "$GITHUB_STEP_SUMMARY"

.github/workflows/test-wheel-windows.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ jobs:
208208
with:
209209
python-version: ${{ matrix.PY_VER }}
210210

211+
- name: Verify LongPathsEnabled
212+
run: |
213+
$val = (Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled').LongPathsEnabled
214+
echo "LongPathsEnabled = $val"
215+
if ($val -ne 1) {
216+
echo "::error::LongPathsEnabled is not set to 1 (see issue #1820)"
217+
exit 1
218+
}
219+
211220
- name: Set up mini CTK
212221
if: ${{ matrix.LOCAL_CTK == '1' }}
213222
uses: ./.github/actions/fetch_ctk

AGENTS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ guide for package-specific conventions and workflows.
1212
- `cuda_core/`: High-level Pythonic CUDA APIs built on top of bindings.
1313
- `cuda_python/`: Metapackage and docs aggregation.
1414

15+
# Pull requests
16+
17+
When creating pull requests with `gh pr create`, always assign at least one
18+
label and a milestone. CI enforces this via the `pr-metadata-check` workflow
19+
and will block PRs that are missing labels or a milestone. Use `--label` and
20+
`--milestone` flags, for example:
21+
22+
```
23+
gh pr create --title "..." --body "..." --label "bug" --milestone "v1.0"
24+
```
25+
26+
If you are unsure which label or milestone to use, check the existing labels
27+
and milestones on the repository with `gh label list` and `gh api
28+
repos/{owner}/{repo}/milestones --jq '.[].title'`, and pick the best match.
29+
30+
1531
# General
1632

1733
- When searching for text or files, prefer using `rg` or `rg --files`

conftest.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,31 @@
1-
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4+
45
import os
56

67
import pytest
78

9+
from cuda.pathfinder import get_cuda_path_or_home
10+
11+
12+
# Please keep in sync with the copy in cuda_core/tests/conftest.py.
13+
def _cuda_headers_available() -> bool:
14+
"""Return True if CUDA headers are available, False if no CUDA path is set.
15+
16+
Raises AssertionError if a CUDA path is set but has no include/ subdirectory.
17+
"""
18+
cuda_path = get_cuda_path_or_home()
19+
if cuda_path is None:
20+
return False
21+
assert os.path.isdir(os.path.join(cuda_path, "include")), (
22+
f"CUDA path {cuda_path} does not contain an 'include' subdirectory"
23+
)
24+
return True
25+
826

927
def pytest_collection_modifyitems(config, items): # noqa: ARG001
10-
cuda_home = os.environ.get("CUDA_HOME")
28+
have_headers = _cuda_headers_available()
1129
for item in items:
1230
nodeid = item.nodeid.replace("\\", "/")
1331

@@ -31,6 +49,10 @@ def pytest_collection_modifyitems(config, items): # noqa: ARG001
3149
):
3250
item.add_marker(pytest.mark.cython)
3351

34-
# Gate core cython tests on CUDA_HOME
35-
if "core" in item.keywords and not cuda_home:
36-
item.add_marker(pytest.mark.skip(reason="CUDA_HOME not set; skipping core cython tests"))
52+
# Gate core cython tests on CUDA_PATH
53+
if "core" in item.keywords and not have_headers:
54+
item.add_marker(
55+
pytest.mark.skip(
56+
reason="Environment variable CUDA_PATH or CUDA_HOME is not set: skipping core cython tests"
57+
)
58+
)

cuda_bindings/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ To run these tests:
3333

3434
Cython tests are located in `tests/cython` and need to be built. These builds have the same CUDA Toolkit header requirements as [Installing from Source](https://nvidia.github.io/cuda-python/cuda-bindings/latest/install.html#requirements) where the major.minor version must match `cuda.bindings`. To build them:
3535

36-
1. Setup environment variable `CUDA_HOME` with the path to the CUDA Toolkit installation.
36+
1. Setup environment variable `CUDA_PATH` (or `CUDA_HOME`) with the path to the CUDA Toolkit installation. Note: If both are set, `CUDA_PATH` takes precedence.
3737
2. Run `build_tests` script located in `test/cython` appropriate to your platform. This will both cythonize the tests and build them.
3838

3939
To run these tests:

cuda_bindings/build_hooks.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,16 @@
3434

3535

3636
@functools.cache
37-
def _get_cuda_paths() -> list[str]:
38-
CUDA_HOME = os.environ.get("CUDA_HOME", os.environ.get("CUDA_PATH", None))
39-
if not CUDA_HOME:
40-
raise RuntimeError("Environment variable CUDA_HOME or CUDA_PATH is not set")
41-
CUDA_HOME = CUDA_HOME.split(os.pathsep)
42-
print("CUDA paths:", CUDA_HOME)
43-
return CUDA_HOME
37+
def _get_cuda_path() -> str:
38+
# Not using cuda.pathfinder.get_cuda_path_or_home() here because this
39+
# build backend runs in an isolated venv where the cuda namespace package
40+
# from backend-path shadows the installed cuda-pathfinder. See #1803 for
41+
# a workaround to apply after cuda-pathfinder >= 1.5 is released.
42+
cuda_path = os.environ.get("CUDA_PATH", os.environ.get("CUDA_HOME"))
43+
if not cuda_path:
44+
raise RuntimeError("Environment variable CUDA_PATH or CUDA_HOME is not set")
45+
print("CUDA path:", cuda_path)
46+
return cuda_path
4447

4548

4649
# -----------------------------------------------------------------------
@@ -133,8 +136,8 @@ def _fetch_header_paths(required_headers, include_path_list):
133136
if missing_headers:
134137
error_message = "Couldn't find required headers: "
135138
error_message += ", ".join(missing_headers)
136-
cuda_paths = _get_cuda_paths()
137-
raise RuntimeError(f'{error_message}\nIs CUDA_HOME setup correctly? (CUDA_HOME="{cuda_paths}")')
139+
cuda_path = _get_cuda_path()
140+
raise RuntimeError(f'{error_message}\nIs CUDA_PATH setup correctly? (CUDA_PATH="{cuda_path}")')
138141

139142
return header_dict
140143

@@ -291,7 +294,7 @@ def _build_cuda_bindings(strip=False):
291294

292295
global _extensions
293296

294-
cuda_paths = _get_cuda_paths()
297+
cuda_path = _get_cuda_path()
295298

296299
if os.environ.get("PARALLEL_LEVEL") is not None:
297300
warn(
@@ -307,7 +310,7 @@ def _build_cuda_bindings(strip=False):
307310
compile_for_coverage = bool(int(os.environ.get("CUDA_PYTHON_COVERAGE", "0")))
308311

309312
# Parse CUDA headers
310-
include_path_list = [os.path.join(path, "include") for path in cuda_paths]
313+
include_path_list = [os.path.join(cuda_path, "include")]
311314
header_dict = _fetch_header_paths(_REQUIRED_HEADERS, include_path_list)
312315
found_types, found_functions, found_values, found_struct, struct_list = _parse_headers(
313316
header_dict, include_path_list, parser_caching
@@ -347,7 +350,7 @@ def _build_cuda_bindings(strip=False):
347350
] + include_path_list
348351
library_dirs = [sysconfig.get_path("platlib"), os.path.join(os.sys.prefix, "lib")]
349352
cudalib_subdirs = [r"lib\x64"] if sys.platform == "win32" else ["lib64", "lib"]
350-
library_dirs.extend(os.path.join(prefix, subdir) for prefix in cuda_paths for subdir in cudalib_subdirs)
353+
library_dirs.extend(os.path.join(cuda_path, subdir) for subdir in cudalib_subdirs)
351354

352355
extra_compile_args = []
353356
extra_link_args = []

cuda_bindings/cuda/bindings/_bindings/cydriver.pxd.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
33

4-
# This code was automatically generated with version 13.2.0, generator version 8797618. Do not modify it directly.
4+
# This code was automatically generated with version 13.2.0, generator version 0.3.1.dev1422+gf4812259e.d20260318. Do not modify it directly.
55
from cuda.bindings.cydriver cimport *
66

77
{{if 'cuGetErrorString' in found_functions}}

cuda_bindings/cuda/bindings/_bindings/cydriver.pyx.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
33

4-
# This code was automatically generated with version 13.2.0, generator version 8797618. Do not modify it directly.
4+
# This code was automatically generated with version 13.2.0, generator version 0.3.1.dev1422+gf4812259e.d20260318. Do not modify it directly.
55
{{if 'Windows' == platform.system()}}
66
import os
77
cimport cuda.bindings._lib.windll as windll

cuda_bindings/cuda/bindings/_bindings/cynvrtc.pxd.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
33

4-
# This code was automatically generated with version 13.2.0, generator version 8797618. Do not modify it directly.
4+
# This code was automatically generated with version 13.2.0, generator version 0.3.1.dev1422+gf4812259e.d20260318. Do not modify it directly.
55
from cuda.bindings.cynvrtc cimport *
66

77
{{if 'nvrtcGetErrorString' in found_functions}}

cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2021-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
33

4-
# This code was automatically generated with version 13.2.0, generator version 8797618. Do not modify it directly.
4+
# This code was automatically generated with version 13.2.0, generator version 0.3.1.dev1422+gf4812259e.d20260318. Do not modify it directly.
55
{{if 'Windows' == platform.system()}}
66
import os
77
cimport cuda.bindings._lib.windll as windll

0 commit comments

Comments
 (0)