diff --git a/.github/RELEASE-core.md b/.github/RELEASE-core.md index a93b3ed8d61..a4431a481cf 100644 --- a/.github/RELEASE-core.md +++ b/.github/RELEASE-core.md @@ -87,6 +87,13 @@ This must happen *before* the release tag is cut. Removals are breaking changes, so they are only permitted at a major-version boundary per the [support policy](https://nvidia.github.io/cuda-python/cuda-core/latest/support.html). +There may also be deprecations in `cuda-bindings` tied to a particular `cuda-core` release. +Find those this way: + +```console +$ grep -rn 'deprecated:: cuda-core' cuda_bindings/cuda +``` + --- ## Finalize the doc update, including release notes diff --git a/cuda_bindings/cuda/bindings/_test_helpers/__init__.py b/cuda_bindings/cuda/bindings/_test_helpers/__init__.py new file mode 100644 index 00000000000..106a19ddb89 --- /dev/null +++ b/cuda_bindings/cuda/bindings/_test_helpers/__init__.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Deprecated shim package. + +These helpers moved to ``cuda_python_test_helpers`` in #2384 (2026-08-04). +This package is kept for one cuda-core release cycle so that already-released +cuda-core test trees (<=1.1.x), which still import from here, keep working +against newer cuda-bindings wheels. See #2725. + +The idea here is to import the current cuda_python_test_helpers that cuda_bindings +expects, even if the real cuda_python_test_helpers name is already claimed by an older, +incompatible copy. + +.. deprecated:: cuda-core-1.2 + Remove this entire subpackage once cuda-core >= 1.2 is the oldest supported + release. +""" + +import importlib +import importlib.util +import pathlib +import sys + +# Private alias under which a modern (post-#2384) cuda_python_test_helpers +# source checkout is loaded, when the real `cuda_python_test_helpers` name is +# already claimed by an older, incompatible copy. See _import_current below. +_CURRENT_ALIAS = "_cuda_bindings_test_helpers_current" + + +def _find_current_test_helpers_package(): + """Locate and load cuda_python_test_helpers source checkout under a private + alias name, bypassing sys.modules entirely. + """ + if _CURRENT_ALIAS in sys.modules: + return sys.modules[_CURRENT_ALIAS] + + candidates = [*pathlib.Path(__file__).parents, pathlib.Path.cwd(), *pathlib.Path.cwd().parents] + seen: set[pathlib.Path] = set() + for candidate in candidates: + if candidate in seen: + continue + seen.add(candidate) + pkg_dir = candidate / "cuda_python_test_helpers" / "cuda_python_test_helpers" + init_file = pkg_dir / "__init__.py" + if init_file.is_file() and (pkg_dir / "arch_check.py").is_file(): + spec = importlib.util.spec_from_file_location( + _CURRENT_ALIAS, init_file, submodule_search_locations=[str(pkg_dir)] + ) + if spec is None or spec.loader is None: + continue + module = importlib.util.module_from_spec(spec) + sys.modules[_CURRENT_ALIAS] = module + spec.loader.exec_module(module) + return module + + return None + + +def _import_current(submodule_name: str): + """Import cuda_python_test_helpers.. + + Prefers whatever is already importable under the real + ``cuda_python_test_helpers`` name. Falls back to a modern copy loaded under + a private alias if the real name resolves to an older, incompatible copy -- + e.g. released cuda-core <= 1.1.1 (tagged 2026-07-29, six days before #2384 + landed) ships its own ``tests/conftest.py`` that puts a pre-#2384 + ``cuda_python_test_helpers`` (predating arch_check.py / mempool.py / + pep723.py living there at all) on sys.path and caches it in sys.modules + under the real name before this shim ever runs. + """ + try: + return importlib.import_module(f"cuda_python_test_helpers.{submodule_name}") + except ImportError: + pass + + module = _find_current_test_helpers_package() + if module is None: + raise ModuleNotFoundError( + f"cuda_python_test_helpers.{submodule_name} is required by cuda.bindings._test_helpers " + "but is not installed, and no source checkout containing it was found near this file " + "or the current working directory." + ) + return importlib.import_module(f"{module.__name__}.{submodule_name}") diff --git a/cuda_bindings/cuda/bindings/_test_helpers/arch_check.py b/cuda_bindings/cuda/bindings/_test_helpers/arch_check.py new file mode 100644 index 00000000000..c7450cf1e4b --- /dev/null +++ b/cuda_bindings/cuda/bindings/_test_helpers/arch_check.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Deprecated shim. Moved to cuda_python_test_helpers.arch_check in #2384 (2026-08-04). +Kept for one release cycle so released cuda-core test trees keep importing. +Remove after cuda-core >= 1.2 is the oldest supported release. +""" + +from cuda.bindings._test_helpers import _import_current + +_arch_check = _import_current("arch_check") +hardware_supports_nvml = _arch_check.hardware_supports_nvml +unsupported_before = _arch_check.unsupported_before + +__all__ = ["hardware_supports_nvml", "unsupported_before"] diff --git a/cuda_bindings/cuda/bindings/_test_helpers/mempool.py b/cuda_bindings/cuda/bindings/_test_helpers/mempool.py new file mode 100644 index 00000000000..02e2f7248d3 --- /dev/null +++ b/cuda_bindings/cuda/bindings/_test_helpers/mempool.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Deprecated shim. Moved to cuda_python_test_helpers.mempool in #2384 (2026-08-04). +Kept for one release cycle so released cuda-core test trees keep importing. +Remove after cuda-core >= 1.2 is the oldest supported release. +""" + +from cuda.bindings._test_helpers import _import_current + +_mempool = _import_current("mempool") +is_windows_mcdm_device = _mempool.is_windows_mcdm_device +xfail_if_mempool_oom = _mempool.xfail_if_mempool_oom + +__all__ = ["is_windows_mcdm_device", "xfail_if_mempool_oom"] diff --git a/cuda_bindings/cuda/bindings/_test_helpers/pep723.py b/cuda_bindings/cuda/bindings/_test_helpers/pep723.py new file mode 100644 index 00000000000..a1fb7dc4dfe --- /dev/null +++ b/cuda_bindings/cuda/bindings/_test_helpers/pep723.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Deprecated shim. Moved to cuda_python_test_helpers.pep723 in #2384 (2026-08-04). +Kept for one release cycle so released cuda-core test trees keep importing. +Remove after cuda-core >= 1.2 is the oldest supported release. +""" + +from cuda.bindings._test_helpers import _import_current + +_pep723 = _import_current("pep723") +has_package_requirements_or_skip = _pep723.has_package_requirements_or_skip + +__all__ = ["has_package_requirements_or_skip"] diff --git a/cuda_core/tests/conftest.py b/cuda_core/tests/conftest.py index ff4cddcb28f..6bf318c24bc 100644 --- a/cuda_core/tests/conftest.py +++ b/cuda_core/tests/conftest.py @@ -29,6 +29,30 @@ pytest_plugins = ["cuda_python_test_helpers._pytest_plugin"] + +class _BanBindingsTestHelpersShimFinder: + """Hard-fails any import of the deprecated ``cuda.bindings._test_helpers`` + shim (added by #2731). + + That shim exists solely so already-released cuda-core <=1.1.1 test trees + keep working against newer cuda-bindings wheels (see #2725); it is + scheduled for removal once cuda-core >= 1.2 is the oldest supported + release. This (current, in-repo) cuda-core test suite must always use + cuda_python_test_helpers directly and should never exercise that shim. + """ + + def find_spec(self, fullname, path, target=None): + if fullname == "cuda.bindings._test_helpers" or fullname.startswith("cuda.bindings._test_helpers."): + raise ImportError( + f"Refusing to import {fullname!r}: this is a deprecated compatibility shim " + "(see #2731/#2725) meant only for already-released cuda-core <=1.1.1 test " + "trees. This test suite must import from cuda_python_test_helpers directly." + ) + return None + + +sys.meta_path.insert(0, _BanBindingsTestHelpersShimFinder()) + from helpers.constants import POOL_SIZE from helpers.memory import skip_if_pinned_memory_unsupported @@ -184,6 +208,21 @@ def session_setup(): multiprocessing.set_start_method("spawn", force=True) +@pytest.fixture(scope="session", autouse=True) +def _forbid_bindings_test_helpers_shim(): + # Belt-and-suspenders alongside _BanBindingsTestHelpersShimFinder above: + # independently re-check at session end that nothing slipped the + # deprecated cuda.bindings._test_helpers shim into sys.modules, in case + # the meta path finder is ever bypassed, disabled, or removed by mistake. + yield + banned = [ + name + for name in sys.modules + if name == "cuda.bindings._test_helpers" or name.startswith("cuda.bindings._test_helpers.") + ] + assert not banned, f"deprecated cuda.bindings._test_helpers shim was imported (see #2731): {banned}" + + @pytest.fixture def init_cuda(): with _init_cuda_context() as device: