Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cuda_pathfinder/cuda/pathfinder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
find_nvidia_binary_utility as find_nvidia_binary_utility,
)
from cuda.pathfinder._binaries.supported_nvidia_binaries import SUPPORTED_BINARIES as _SUPPORTED_BINARIES
from cuda.pathfinder._dynamic_libs.load_dl_common import (
DynamicLibNotAvailableError as DynamicLibNotAvailableError,
)
from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError as DynamicLibNotFoundError
from cuda.pathfinder._dynamic_libs.load_dl_common import (
DynamicLibUnknownError as DynamicLibUnknownError,
)
from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as LoadedDL
from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib
from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ class DynamicLibNotFoundError(RuntimeError):
pass


class DynamicLibNotAvailableError(DynamicLibNotFoundError):
pass


class DynamicLibUnknownError(DynamicLibNotFoundError):
pass


@dataclass
class LoadedDL:
abs_path: str | None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
_FindNvidiaDynamicLib,
derive_ctk_root,
)
from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError, LoadedDL, load_dependencies
from cuda.pathfinder._dynamic_libs.load_dl_common import (
DynamicLibNotAvailableError,
DynamicLibNotFoundError,
DynamicLibUnknownError,
LoadedDL,
load_dependencies,
)
from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import (
_CTK_ROOT_CANARY_ANCHOR_LIBNAMES,
_CTK_ROOT_CANARY_DISCOVERABLE_LIBNAMES,
Expand Down Expand Up @@ -41,6 +47,8 @@
_ALL_SUPPORTED_LIBNAMES: frozenset[str] = frozenset(
(SUPPORTED_WINDOWS_DLLS if IS_WINDOWS else SUPPORTED_LINUX_SONAMES).keys()
)
_ALL_KNOWN_LIBNAMES: frozenset[str] = frozenset(SUPPORTED_LINUX_SONAMES) | frozenset(SUPPORTED_WINDOWS_DLLS)
_PLATFORM_NAME = "Windows" if IS_WINDOWS else "Linux"

# Driver libraries: shipped with the NVIDIA display driver, always on the
# system linker path. These skip all CTK search steps (site-packages,
Expand Down Expand Up @@ -205,7 +213,9 @@ def load_nvidia_dynamic_lib(libname: str) -> LoadedDL:
https://github.com/NVIDIA/cuda-python/issues/1011

Raises:
ValueError: If ``libname`` is not a recognized library name.
DynamicLibUnknownError: If ``libname`` is not a recognized library name.
DynamicLibNotAvailableError: If ``libname`` is recognized but not
supported on this platform.
DynamicLibNotFoundError: If the library cannot be found or loaded.
RuntimeError: If Python is not 64-bit.

Expand Down Expand Up @@ -278,6 +288,11 @@ def load_nvidia_dynamic_lib(libname: str) -> LoadedDL:
f" Currently running: {pointer_size_bits}-bit Python"
f" {sys.version_info.major}.{sys.version_info.minor}"
)
if libname not in _ALL_KNOWN_LIBNAMES:
raise DynamicLibUnknownError(f"Unknown library name: {libname!r}. Known names: {sorted(_ALL_KNOWN_LIBNAMES)}")
if libname not in _ALL_SUPPORTED_LIBNAMES:
raise ValueError(f"Unsupported library name: {libname!r}. Supported names: {sorted(_ALL_SUPPORTED_LIBNAMES)}")
raise DynamicLibNotAvailableError(
f"Library name {libname!r} is known but not available on {_PLATFORM_NAME}. "
f"Supported names on {_PLATFORM_NAME}: {sorted(_ALL_SUPPORTED_LIBNAMES)}"
)
return _load_lib_no_cache(libname)
4 changes: 4 additions & 0 deletions cuda_pathfinder/docs/nv-versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"version": "latest",
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/latest/"
},
{
"version": "1.4.0",
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.4.0/"
},
{
"version": "1.3.5",
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.3.5/"
Expand Down
2 changes: 2 additions & 0 deletions cuda_pathfinder/docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ locating NVIDIA C/C++ header directories, and finding CUDA binary utilities.
load_nvidia_dynamic_lib
LoadedDL
DynamicLibNotFoundError
DynamicLibUnknownError
DynamicLibNotAvailableError

SUPPORTED_HEADERS_CTK
SUPPORTED_HEADERS_NON_CTK
Expand Down
17 changes: 16 additions & 1 deletion cuda_pathfinder/docs/source/release/1.3.5-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@

Released on Feb 23, 2026

.. warning::

``cuda-pathfinder==1.3.5`` introduced a short-lived backward-incompatible
exception regression in ``load_nvidia_dynamic_lib()`` (unsupported
library names incorrectly raising ``ValueError``).

This bug was corrected in ``cuda-pathfinder>=1.4.0``, restoring backward-compatible
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads awkward to me. Bugs are corrected in specific releases, and by implication that means >=. Combining those two notions just makes this strange to read.

Not blocking though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this should just be 1.4.0, but it's not misleading, I don't want to run the CI again for this, and not use [doc-only] in the PR description because that could be confusing when we look at it later. I'll go ahead and merge this as-is, then make the release.

``DynamicLibNotFoundError`` subclass behavior while preserving more specific
error signaling.

See `Issue #1684 <https://github.com/NVIDIA/cuda-python/issues/1684>`_ and
`PR #1688 <https://github.com/NVIDIA/cuda-python/pull/1688>`_.

Highlights
----------

* Add support for loading NVIDIA driver libraries (``"cuda"``, ``"nvml"``)
via ``load_nvidia_dynamic_lib()``, and reject unsupported library names
with ``ValueError``.
with ``ValueError`` (**EDIT:** this behavior was
`a regression <https://github.com/NVIDIA/cuda-python/issues/1684>`_
and was corrected in ``cuda-pathfinder>=1.4.0``).
(`PR #1602 <https://github.com/NVIDIA/cuda-python/pull/1602>`_)

* Add bitcode library discovery helpers and public API support, including
Expand Down
23 changes: 23 additions & 0 deletions cuda_pathfinder/docs/source/release/1.4.0-notes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.. SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
.. SPDX-License-Identifier: Apache-2.0

.. py:currentmodule:: cuda.pathfinder

``cuda-pathfinder`` 1.4.0 Release notes
=======================================

Released on Feb 25, 2026

Highlights
----------

* Add CTK root canary probing for non-standard-path libraries in
``load_nvidia_dynamic_lib()`` (notably ``nvvm``), including spawned child
process isolation for the canary probe.
(`PR #1595 <https://github.com/NVIDIA/cuda-python/pull/1595>`_)

* Restore backward-compatible exception behavior for
``load_nvidia_dynamic_lib()`` argument validation by replacing the short-lived
``ValueError`` introduced in ``1.3.5`` with ``DynamicLibNotFoundError``
subclasses: ``DynamicLibUnknownError`` and ``DynamicLibNotAvailableError``.
(`PR #1688 <https://github.com/NVIDIA/cuda-python/pull/1688>`_)
19 changes: 16 additions & 3 deletions cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from child_load_nvidia_dynamic_lib_helper import build_child_process_failed_for_libname_message, child_process_func
from local_helpers import have_distribution

from cuda.pathfinder import load_nvidia_dynamic_lib
from cuda.pathfinder import DynamicLibNotAvailableError, DynamicLibUnknownError, load_nvidia_dynamic_lib
from cuda.pathfinder._dynamic_libs import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib_module
from cuda.pathfinder._dynamic_libs import supported_nvidia_libs
from cuda.pathfinder._utils.platform_aware import IS_WINDOWS, quote_for_shell
from cuda.pathfinder._utils.spawned_process_runner import run_in_spawned_child_process
Expand Down Expand Up @@ -69,11 +70,23 @@ def test_runtime_error_on_non_64bit_python(mocker):
load_nvidia_dynamic_lib("cudart")


def test_unsupported_libname_raises_value_error():
with pytest.raises(ValueError, match=r"Unsupported library name: 'not_a_real_lib'.*cudart"):
def test_unknown_libname_raises_dynamic_lib_unknown_error():
with pytest.raises(DynamicLibUnknownError, match=r"Unknown library name: 'not_a_real_lib'.*cudart"):
load_nvidia_dynamic_lib("not_a_real_lib")


def test_known_but_platform_unavailable_libname_raises_dynamic_lib_not_available_error(monkeypatch):
load_nvidia_dynamic_lib.cache_clear()
monkeypatch.setattr(load_nvidia_dynamic_lib_module, "_ALL_KNOWN_LIBNAMES", frozenset(("known_but_unavailable",)))
monkeypatch.setattr(load_nvidia_dynamic_lib_module, "_ALL_SUPPORTED_LIBNAMES", frozenset())
monkeypatch.setattr(load_nvidia_dynamic_lib_module, "_PLATFORM_NAME", "TestOS")
with pytest.raises(
DynamicLibNotAvailableError,
match=r"known_but_unavailable.*not available on TestOS",
):
load_nvidia_dynamic_lib("known_but_unavailable")


IMPORTLIB_METADATA_DISTRIBUTIONS_NAMES = {
"cufftMp": r"^nvidia-cufftmp-.*$",
"mathdx": r"^nvidia-libmathdx-.*$",
Expand Down
Loading