Skip to content

Commit cfc0054

Browse files
authored
Merge branch 'main' into oom-early-reservation-workaround
2 parents 51f6ff4 + 16f9c58 commit cfc0054

12 files changed

Lines changed: 70 additions & 33 deletions

File tree

.github/workflows/coverage.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,34 @@ jobs:
235235
cd cuda_bindings
236236
../.venv/Scripts/pip wheel -v --no-deps . -w ../wheels/
237237
238+
# Pin cuda-bindings to the wheel built above; PIP_PRE, which is what makes
239+
# that .devN wheel visible, would otherwise let a PyPI pre-release win.
238240
- name: Build cuda.core wheel
239241
run: |
240242
export PIP_FIND_LINKS="$(pwd)/wheels"
241243
export PIP_PRE=1
244+
bindings_whl="$(ls ./wheels/cuda_bindings-*.whl | head -1)"
245+
bindings_ver="$(basename "$bindings_whl" | cut -d- -f2)"
246+
echo "cuda-bindings==${bindings_ver%%+*}" > "$GITHUB_WORKSPACE/constraints.txt"
247+
cat "$GITHUB_WORKSPACE/constraints.txt"
248+
export PIP_CONSTRAINT="$GITHUB_WORKSPACE/constraints.txt"
242249
cd cuda_core
243250
../.venv/Scripts/pip wheel -v --no-deps . -w ../wheels/
244251
252+
# Vendor the DLLs these wheels were built against, the way cibuildwheel
253+
# does for every other Windows build. --namespace-pkg is needed because
254+
# `cuda` is a namespace package.
255+
- name: Repair the Windows wheels
256+
run: |
257+
.venv/Scripts/pip install delvewheel
258+
mkdir -p wheels-repaired
259+
for whl in ./wheels/cuda_bindings-*.whl ./wheels/cuda_core-*.whl; do
260+
.venv/Scripts/delvewheel repair --namespace-pkg cuda \
261+
--exclude "torch_cpu.dll;torch_python.dll" \
262+
-w ./wheels-repaired "$whl"
263+
done
264+
mv -f ./wheels-repaired/*.whl ./wheels/
265+
245266
- name: List wheel artifacts
246267
run: |
247268
echo "=== Windows wheel artifacts ==="

ci/tools/merge_cuda_core_wheels.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22

3-
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

@@ -27,10 +27,9 @@
2727
import tempfile
2828
import zipfile
2929
from pathlib import Path
30-
from typing import List
3130

3231

33-
def run_command(cmd: List[str], cwd: Path | None = None, env: dict = os.environ) -> subprocess.CompletedProcess:
32+
def run_command(cmd: list[str], cwd: Path | None = None, env: dict = os.environ) -> subprocess.CompletedProcess:
3433
"""Run a command with error handling."""
3534
print(f"Running: {' '.join(cmd)}")
3635
if cwd:
@@ -78,7 +77,7 @@ def print_wheel_directory_structure(wheel_path: Path, filter_prefix: str = "cuda
7877
print(f"Warning: Could not list wheel contents: {e}", file=sys.stderr)
7978

8079

81-
def merge_wheels(wheels: List[Path], output_dir: Path, show_wheel_contents: bool = True) -> Path:
80+
def merge_wheels(wheels: list[Path], output_dir: Path, show_wheel_contents: bool = True) -> Path:
8281
"""Merge multiple wheels into a single wheel with version-specific binaries."""
8382
print("\n=== Merging wheels ===", file=sys.stderr)
8483
print(f"Input wheels: {[w.name for w in wheels]}", file=sys.stderr)

cuda_core/tests/helpers/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import functools
55
import os
6-
from typing import Union
76

87
from cuda.core._utils.cuda_utils import handle_return
98
from cuda.pathfinder import get_cuda_path_or_home
@@ -23,7 +22,7 @@
2322

2423

2524
@functools.cache
26-
def supports_ipc_mempool(device_id: Union[int, object]) -> bool:
25+
def supports_ipc_mempool(device_id: int | object) -> bool:
2726
"""Return True if mempool IPC via POSIX file descriptor is supported.
2827
2928
Uses cuDeviceGetAttribute(CU_DEVICE_ATTRIBUTE_MEMPOOL_SUPPORTED_HANDLE_TYPES)

cuda_pathfinder/tests/test_ctk_root_discovery.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import subprocess
77
import sys
88
import textwrap
9+
from pathlib import Path
910

1011
import pytest
1112

@@ -427,7 +428,7 @@ def test_resolve_ctk_root_via_canary_none_when_probe_fails(mocker):
427428
def test_resolve_ctk_root_via_canary_none_when_unrecognized(mocker):
428429
mocker.patch(
429430
f"{_MODULE}._resolve_system_loaded_abs_path_in_subprocess",
430-
return_value=os.path.join(os.sep, "weird", "path", "libcudart.so.13"),
431+
return_value=str(Path(os.sep, "weird", "path", "libcudart.so.13")),
431432
)
432433
assert resolve_ctk_root_via_canary("cudart") is None
433434

cuda_pathfinder/tests/test_driver_lib_loading.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"""
1010

1111
import os
12+
from pathlib import Path
1213

1314
import pytest
1415
from child_load_nvidia_dynamic_lib_helper import (
@@ -157,7 +158,7 @@ def raise_child_process_failed():
157158
abs_path = payload.abs_path
158159
assert abs_path is not None
159160
info_summary_append(f"abs_path={quote_for_shell(abs_path)}")
160-
assert os.path.isfile(abs_path)
161+
assert Path(abs_path).is_file()
161162

162163

163164
def test_real_query_driver_cuda_version(info_summary_append):

cuda_pathfinder/tests/test_find_bitcode_lib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def _located_bitcode_lib_asserts(located_bitcode_lib):
6666
assert isinstance(located_bitcode_lib.filename, str)
6767
assert isinstance(located_bitcode_lib.found_via, str)
6868
assert located_bitcode_lib.found_via in ("site-packages", "conda", "CUDA_PATH")
69-
assert os.path.isfile(located_bitcode_lib.abs_path)
69+
assert Path(located_bitcode_lib.abs_path).is_file()
7070

7171

7272
@pytest.mark.usefixtures("clear_find_bitcode_lib_cache")
@@ -83,10 +83,10 @@ def test_locate_bitcode_lib(info_summary_append, libname):
8383

8484
info_summary_append(f"{lib_path=!r}")
8585
_located_bitcode_lib_asserts(located_lib)
86-
assert os.path.isfile(lib_path)
86+
assert Path(lib_path).is_file()
8787
assert lib_path == located_lib.abs_path
8888
expected_filename = located_lib.filename
89-
assert os.path.basename(lib_path) == expected_filename
89+
assert Path(lib_path).name == expected_filename
9090

9191

9292
@pytest.mark.usefixtures("clear_find_bitcode_lib_cache")
@@ -156,7 +156,7 @@ def test_find_bitcode_lib_not_found_error_includes_cuda_home_directory_listing(m
156156
find_bitcode_lib("device")
157157

158158
message = str(exc_info.value)
159-
expected_missing_file = os.path.join(str(lib_dir), _bitcode_lib_filename("device"))
159+
expected_missing_file = lib_dir / _bitcode_lib_filename("device")
160160
assert f"No such file: {expected_missing_file}" in message
161161
assert f'listdir("{lib_dir}"):' in message
162162
assert "README.txt" in message

cuda_pathfinder/tests/test_find_nvidia_headers.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ def test_locate_non_ctk_headers(info_summary_append, libname):
138138
info_summary_append(f"{hdr_dir=!r}")
139139
if hdr_dir:
140140
_located_hdr_dir_asserts(located_hdr_dir)
141-
assert os.path.isdir(hdr_dir)
142-
assert os.path.isfile(os.path.join(hdr_dir, SUPPORTED_HEADERS_NON_CTK[libname]))
141+
hdr_dir_path = Path(hdr_dir)
142+
assert hdr_dir_path.is_dir()
143+
assert (hdr_dir_path / SUPPORTED_HEADERS_NON_CTK[libname]).is_file()
143144
if have_distribution_for(libname):
144145
assert hdr_dir is not None
145-
hdr_dir_parts = hdr_dir.split(os.path.sep)
146-
assert "site-packages" in hdr_dir_parts
146+
assert "site-packages" in Path(hdr_dir).parts
147147
elif STRICTNESS == "all_must_work":
148148
assert hdr_dir is not None
149149
if conda_prefix := os.environ.get("CONDA_PREFIX"):
@@ -152,6 +152,8 @@ def test_locate_non_ctk_headers(info_summary_append, libname):
152152
inst_dirs = SUPPORTED_INSTALL_DIRS_NON_CTK.get(libname)
153153
if inst_dirs is not None:
154154
for inst_dir in inst_dirs:
155+
# Absolute glob pattern: Path.glob needs a separate base dir,
156+
# and the wildcard is not pinned to the last component.
155157
globbed = glob.glob(inst_dir)
156158
if hdr_dir in globbed:
157159
break
@@ -172,9 +174,10 @@ def test_locate_ctk_headers(info_summary_append, libname):
172174
info_summary_append(f"{hdr_dir=!r}")
173175
if hdr_dir:
174176
_located_hdr_dir_asserts(located_hdr_dir)
175-
assert os.path.isdir(hdr_dir)
177+
hdr_dir_path = Path(hdr_dir)
178+
assert hdr_dir_path.is_dir()
176179
h_filename = SUPPORTED_HEADERS_CTK[libname]
177-
assert os.path.isfile(os.path.join(hdr_dir, h_filename))
180+
assert (hdr_dir_path / h_filename).is_file()
178181
if STRICTNESS == "all_must_work":
179182
if libname == "cudla":
180183
skip_if_missing_libnvcudla_so(libname, timeout=30)

cuda_pathfinder/tests/test_find_static_lib.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def _located_static_lib_asserts(located_static_lib):
5252
assert isinstance(located_static_lib.filename, str)
5353
assert isinstance(located_static_lib.found_via, str)
5454
assert located_static_lib.found_via in ("site-packages", "conda", "CUDA_PATH")
55-
assert os.path.isfile(located_static_lib.abs_path)
55+
assert Path(located_static_lib.abs_path).is_file()
5656

5757

5858
@pytest.mark.usefixtures("clear_find_static_lib_cache")
@@ -69,10 +69,10 @@ def test_locate_static_lib(info_summary_append, libname):
6969

7070
info_summary_append(f"abs_path={quote_for_shell(lib_path)}")
7171
_located_static_lib_asserts(located_lib)
72-
assert os.path.isfile(lib_path)
72+
assert Path(lib_path).is_file()
7373
assert lib_path == located_lib.abs_path
7474
expected_filename = located_lib.filename
75-
assert os.path.basename(lib_path) == expected_filename
75+
assert Path(lib_path).name == expected_filename
7676

7777

7878
@pytest.mark.usefixtures("clear_find_static_lib_cache")
@@ -81,7 +81,7 @@ def test_locate_static_lib_search_order(monkeypatch, tmp_path):
8181
conda_rel_path = CUDADEVRT_INFO["conda_rel_paths"][0]
8282

8383
site_pkg_rel = CUDADEVRT_INFO["site_packages_dirs"][0]
84-
site_packages_lib_dir = tmp_path / "site-packages" / Path(site_pkg_rel.replace("/", os.sep))
84+
site_packages_lib_dir = tmp_path / "site-packages" / Path(site_pkg_rel)
8585
site_packages_path = _make_static_lib_file(site_packages_lib_dir, filename)
8686

8787
conda_prefix = tmp_path / "conda-prefix"
@@ -202,7 +202,7 @@ def test_find_static_lib_not_found_error_includes_cuda_home_directory_listing(mo
202202
find_static_lib("cudadevrt")
203203

204204
message = str(exc_info.value)
205-
expected_missing_file = os.path.join(str(lib_dir), filename)
205+
expected_missing_file = lib_dir / filename
206206
assert f"No such file: {expected_missing_file}" in message
207207
assert f'listdir("{lib_dir}"):' in message
208208
assert "README.txt" in message

cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import os
55
import platform
6+
from pathlib import Path
67

78
import pytest
89
from child_load_nvidia_dynamic_lib_helper import (
@@ -159,4 +160,4 @@ def raise_child_process_failed():
159160
abs_path = payload.abs_path
160161
assert abs_path is not None
161162
info_summary_append(f"abs_path={quote_for_shell(abs_path)}")
162-
assert os.path.isfile(abs_path) # double-check the abs_path
163+
assert Path(abs_path).is_file() # double-check the abs_path

cuda_pathfinder/tests/test_utils_find_sub_dirs.py

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

4-
import os
4+
from pathlib import Path
55

66
import pytest
77

@@ -77,7 +77,7 @@ def test_empty_parent_paths():
7777
def test_empty_sub_dirs(test_tree):
7878
parent_paths = test_tree["parent_paths"]
7979
result = find_sub_dirs(parent_paths, ())
80-
expected = [p for p in parent_paths if os.path.isdir(p)]
80+
expected = [p for p in parent_paths if Path(p).is_dir()]
8181
assert sorted(result) == sorted(expected)
8282

8383

0 commit comments

Comments
 (0)