From f45008d58e98710840fb4b03a30720a56b80647e Mon Sep 17 00:00:00 2001 From: Mike Droettboom Date: Wed, 8 Jul 2026 16:33:58 -0400 Subject: [PATCH 1/4] Make pre-commit work on Windows --- .github/workflows/ci.yml | 31 +++++++++ .pre-commit-config.yaml | 6 +- CONTRIBUTING.md | 9 +++ .../pathfinder/_dynamic_libs/load_dl_linux.py | 56 ++++++++++------- .../_dynamic_libs/load_dl_windows.py | 19 ++++-- .../_dynamic_libs/platform_loader.py | 6 +- .../cuda/pathfinder/_utils/driver_info.py | 7 ++- toolshed/run_stubgen_pyx.py | 63 +++++++++++++++++++ 8 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 toolshed/run_stubgen_pyx.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe43b52d01a..5ef808820be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -416,6 +416,35 @@ jobs: with: is-release: ${{ github.ref_type == 'tag' }} + precommit-windows: + name: Pre-commit on Windows + runs-on: windows-latest + if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) }} + needs: + - should-skip + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 1 + + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: '3.13' + + - name: Install pre-commit + shell: bash + run: | + set -euxo pipefail + python -m pip install --upgrade pip pre-commit + + - name: Run pre-commit + shell: bash + run: | + set -euxo pipefail + pre-commit run --all-files + checks: name: Check job status if: always() @@ -429,6 +458,7 @@ jobs: - test-linux-aarch64 - test-windows - doc + - precommit-windows steps: - name: Exit run: | @@ -461,6 +491,7 @@ jobs: check_result "should-skip" "success" "${{ needs.should-skip.result }}" check_result "detect-changes" "success" "${{ needs.detect-changes.result }}" check_result "doc" "success" "${{ needs.doc.result }}" + check_result "precommit-windows" "success" "${{ needs.precommit-windows.result }}" # [doc-only] flips these from 'success' to 'skipped' if [[ "$doc_only" == "true" ]]; then expected="skipped"; else expected="success"; fi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ac6754ae10..00697e1e7f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: - id: stubgen-pyx-cuda-core name: Generate .pyi stubs for cuda_core - entry: stubgen-pyx cuda_core/cuda --continue-on-error --include-private + entry: python ./toolshed/run_stubgen_pyx.py language: python files: ^cuda_core/cuda/.*\.(pyx|pxd)$ pass_filenames: false @@ -68,6 +68,7 @@ repos: hooks: - id: lychee args: + - --cache - --max-concurrency=4 - --max-retries=3 @@ -88,6 +89,7 @@ repos: - id: check-yaml - id: debug-statements - id: end-of-file-fixer + exclude_types: [symlink] exclude: &gen_exclude '^(?:cuda_python/README\.md|cuda_bindings/cuda/bindings/.*\.in?|cuda_bindings/docs/source/module/.*\.rst?|.*\.pyi)$' - id: mixed-line-ending - id: trailing-whitespace @@ -123,7 +125,7 @@ repos: pass_filenames: false args: [--config-file=cuda_core/pyproject.toml, cuda_core/cuda/core] additional_dependencies: - - numpy + - numpy==2.4.2 - repo: https://github.com/rhysd/actionlint rev: "914e7df21a07ef503a81201c76d2b11c789d3fca" # frozen: v1.7.12 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 012126cc842..9b5069772fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,6 +21,7 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of - [Table of Contents](#table-of-contents) - [Type stubs for cuda.core](#type-stubs-for-cudacore) - [Pre-commit](#pre-commit) + - [Pre-commit on Windows](#pre-commit-on-windows) - [Signing Your Work](#signing-your-work) - [Code signing](#code-signing) - [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco) @@ -74,6 +75,14 @@ between commits, leaving stale headers or out-of-date stubs in the history. If the hook isn't installed, `pre-commit run` (and CI) will print a visible warning reminding you to run `pre-commit install`. +### Pre-commit on Windows + +For development on Windows (not WSL), the `lychee` pre-commit task will not work. +You will need to set the following environment variable to make it pass: + +``` +SKIP=lychee +``` ## Signing Your Work diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 4bce75d109c..173e0c58215 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 from __future__ import annotations @@ -7,6 +7,7 @@ import ctypes import ctypes.util import os +import sys from typing import TYPE_CHECKING, cast from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL @@ -14,7 +15,10 @@ if TYPE_CHECKING: from cuda.pathfinder._dynamic_libs.lib_descriptor import LibDescriptor -CDLL_MODE = os.RTLD_NOW | os.RTLD_GLOBAL +if sys.platform == "linux": + CDLL_MODE = os.RTLD_NOW | os.RTLD_GLOBAL +else: + CDLL_MODE = 0 def _load_libdl() -> ctypes.CDLL: @@ -132,27 +136,35 @@ def _candidate_sonames(desc: LibDescriptor) -> list[str]: return candidates -def check_if_already_loaded_from_elsewhere(desc: LibDescriptor, _have_abs_path: bool) -> LoadedDL | None: - for soname in _candidate_sonames(desc): - try: - handle = ctypes.CDLL(soname, mode=os.RTLD_NOLOAD) - except OSError: - continue - else: - return LoadedDL( - abs_path_for_dynamic_library(desc.name, handle), - True, - handle._handle, - "was-already-loaded-from-elsewhere", - ) - return None +if sys.platform == "linux": + + def check_if_already_loaded_from_elsewhere(desc: LibDescriptor, _have_abs_path: bool) -> LoadedDL | None: + for soname in _candidate_sonames(desc): + try: + handle = ctypes.CDLL(soname, mode=os.RTLD_NOLOAD) + except OSError: + continue + else: + return LoadedDL( + abs_path_for_dynamic_library(desc.name, handle), + True, + handle._handle, + "was-already-loaded-from-elsewhere", + ) + return None + + def _load_lib(desc: LibDescriptor, filename: str) -> ctypes.CDLL: + cdll_mode = CDLL_MODE + if desc.requires_rtld_deepbind: + cdll_mode |= os.RTLD_DEEPBIND + return ctypes.CDLL(filename, cdll_mode) +else: + def check_if_already_loaded_from_elsewhere(_desc: LibDescriptor, _have_abs_path: bool) -> LoadedDL | None: + raise RuntimeError(f"check_if_already_loaded_from_elsewhere() is not supported on platform {sys.platform!r}") -def _load_lib(desc: LibDescriptor, filename: str) -> ctypes.CDLL: - cdll_mode = CDLL_MODE - if desc.requires_rtld_deepbind: - cdll_mode |= os.RTLD_DEEPBIND - return ctypes.CDLL(filename, cdll_mode) + def _load_lib(_desc: LibDescriptor, _filename: str) -> ctypes.CDLL: + raise RuntimeError(f"_load_lib() is not supported on platform {sys.platform!r}") def load_with_system_search(desc: LibDescriptor) -> LoadedDL | None: @@ -199,7 +211,7 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: ctypes.CDLL(dep_path, CDLL_MODE) -def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: +def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str = "absolute-path") -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index a296813aa29..1588d4ba997 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 from __future__ import annotations @@ -21,7 +21,10 @@ POINTER_ADDRESS_SPACE = 2 ** (struct.calcsize("P") * 8) # Set up kernel32 functions with proper types -kernel32 = ctypes.windll.kernel32 # type: ignore[attr-defined] +windll = getattr(ctypes, "windll", None) +if windll is None: + raise RuntimeError("ctypes.windll is required on Windows") +kernel32 = windll.kernel32 # GetModuleHandleW kernel32.GetModuleHandleW.argtypes = [ctypes.wintypes.LPCWSTR] @@ -47,6 +50,10 @@ kernel32.AddDllDirectory.argtypes = [ctypes.wintypes.LPCWSTR] kernel32.AddDllDirectory.restype = ctypes.c_void_p # DLL_DIRECTORY_COOKIE +# GetLastError +kernel32.GetLastError.argtypes = [] +kernel32.GetLastError.restype = ctypes.wintypes.DWORD + def ctypes_handle_to_unsigned_int(handle: ctypes.wintypes.HMODULE) -> int: """Convert ctypes HMODULE to unsigned int.""" @@ -87,7 +94,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) length = kernel32.GetModuleFileNameW(handle, buffer, len(buffer)) if length == 0: - error_code = ctypes.GetLastError() # type: ignore[attr-defined] + error_code = kernel32.GetLastError() raise RuntimeError(f"GetModuleFileNameW failed for {libname!r} (error code: {error_code})") # If buffer was too small, try with larger buffer @@ -95,7 +102,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) buffer = ctypes.create_unicode_buffer(32768) # Extended path length length = kernel32.GetModuleFileNameW(handle, buffer, len(buffer)) if length == 0: - error_code = ctypes.GetLastError() # type: ignore[attr-defined] + error_code = kernel32.GetLastError() raise RuntimeError(f"GetModuleFileNameW failed for {libname!r} (error code: {error_code})") return buffer.value @@ -140,7 +147,7 @@ def load_with_system_search(desc: LibDescriptor) -> LoadedDL | None: return None -def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: +def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str = "absolute-path") -> LoadedDL: """Load a dynamic library from the given path. Args: @@ -161,7 +168,7 @@ def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str | No handle = kernel32.LoadLibraryExW(found_path, None, flags) if not handle: - error_code = ctypes.GetLastError() # type: ignore[attr-defined] + error_code = kernel32.GetLastError() raise RuntimeError(f"Failed to load DLL at {found_path}: Windows error {error_code}") return LoadedDL(found_path, False, ctypes_handle_to_unsigned_int(handle), found_via) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py index 9b108a57acc..210d1ca7132 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 """Platform loader seam for OS-specific dynamic linking. @@ -28,7 +28,9 @@ def check_if_already_loaded_from_elsewhere(self, desc: LibDescriptor, have_abs_p def load_with_system_search(self, desc: LibDescriptor) -> LoadedDL | None: ... - def load_with_abs_path(self, desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: ... + def load_with_abs_path( + self, desc: LibDescriptor, found_path: str, found_via: str = "absolute-path" + ) -> LoadedDL: ... if IS_WINDOWS: diff --git a/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py b/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py index a5d4d167d33..8164a9f9adf 100644 --- a/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py +++ b/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py @@ -64,9 +64,10 @@ def _query_driver_cuda_version_int() -> int: """Return the encoded CUDA driver version from ``cuDriverGetVersion()``.""" loaded_cuda = _load_nvidia_dynamic_lib("cuda") if IS_WINDOWS: - # `ctypes.WinDLL` exists on Windows at runtime. The ignore is only for - # Linux mypy runs, where the platform stubs do not define that attribute. - loader_cls: Callable[[str], ctypes.CDLL] = ctypes.WinDLL # type: ignore[attr-defined] + win_dll_loader = getattr(ctypes, "WinDLL", None) + if win_dll_loader is None: + raise RuntimeError("ctypes.WinDLL is not available on this Python runtime.") + loader_cls: Callable[[str], ctypes.CDLL] = win_dll_loader else: loader_cls = ctypes.CDLL driver_lib = loader_cls(loaded_cuda.abs_path) diff --git a/toolshed/run_stubgen_pyx.py b/toolshed/run_stubgen_pyx.py new file mode 100644 index 00000000000..bb6e34066c1 --- /dev/null +++ b/toolshed/run_stubgen_pyx.py @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Run stubgen-pyx for cuda_core and normalize line endings in the generated +stubs across platforms. +""" + +from __future__ import annotations + +import os +import pathlib +import subprocess + + +def _normalize_generated_stubs(root: pathlib.Path) -> None: + for stub in root.rglob("*.pyi"): + data = stub.read_bytes() + if not data: + continue + + # Normalize line endings to LF so Windows runs do not churn tracked files. + normalized_data = data.replace(b"\r\n", b"\n").replace(b"\r", b"\n") + + split_at = normalized_data.find(b"\n") + if split_at == -1: + first_line = normalized_data + remainder = b"" + newline = b"" + else: + first_line = normalized_data[:split_at] + remainder = normalized_data[split_at + 1 :] + newline = b"\n" + + if not first_line.startswith(b"# This file was generated by stubgen-pyx"): + continue + + normalized_header = first_line.replace(b"\\", b"/") + updated_data = normalized_header + newline + remainder + if updated_data != data: + stub.write_bytes(updated_data) + + +def main() -> int: + env = os.environ.copy() + env.setdefault("PYTHONUTF8", "1") + env.setdefault("PYTHONIOENCODING", "utf-8") + + cmd = [ + "stubgen-pyx", + "cuda_core/cuda", + "--continue-on-error", + "--include-private", + ] + result = subprocess.run(cmd, env=env) # noqa: S603 + if result.returncode != 0: + return result.returncode + + _normalize_generated_stubs(pathlib.Path("cuda_core/cuda")) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From 9684d1921fb178d37e103d484a79eaacd1cec1c5 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 9 Jul 2026 10:01:44 -0400 Subject: [PATCH 2/4] Update .pre-commit-config.yaml --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 00697e1e7f0..1e4e412f408 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,7 +68,6 @@ repos: hooks: - id: lychee args: - - --cache - --max-concurrency=4 - --max-retries=3 From a446787f0f8306e518c0218593a583c41c91b6cd Mon Sep 17 00:00:00 2001 From: Mike Droettboom Date: Thu, 9 Jul 2026 11:23:22 -0400 Subject: [PATCH 3/4] Address some of the comments in the PR --- .github/workflows/ci.yml | 5 ++++- .pre-commit-config.yaml | 3 +-- CONTRIBUTING.md | 13 ++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ef808820be..a60d64d1a48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -422,11 +422,14 @@ jobs: if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) }} needs: - should-skip + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 1 + persist-credentials: false - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 @@ -443,7 +446,7 @@ jobs: shell: bash run: | set -euxo pipefail - pre-commit run --all-files + SKIP=lychee pre-commit run --all-files checks: name: Check job status diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e4e412f408..24a6ec2bb14 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -88,8 +88,7 @@ repos: - id: check-yaml - id: debug-statements - id: end-of-file-fixer - exclude_types: [symlink] - exclude: &gen_exclude '^(?:cuda_python/README\.md|cuda_bindings/cuda/bindings/.*\.in?|cuda_bindings/docs/source/module/.*\.rst?|.*\.pyi)$' + exclude: &gen_exclude '^(?:cuda_python/README\.md|(?:^|/)CLAUDE\.md|(?:^|/)\.git_archival\.txt|cuda_bindings/cuda/bindings/.*\.in?|cuda_bindings/docs/source/module/.*\.rst?|.*\.pyi)$' - id: mixed-line-ending - id: trailing-whitespace exclude: | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b5069772fc..cebd399e255 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,12 +77,15 @@ warning reminding you to run `pre-commit install`. ### Pre-commit on Windows -For development on Windows (not WSL), the `lychee` pre-commit task will not work. -You will need to set the following environment variable to make it pass: +For development on Windows (not WSL), the `lychee` pre-commit task will not work +when running `pre-commit run --all-files`. This problem does not occur if you +install the pre-commit hook and run it automatically as part of your `git +commit` workflow. To resolve this, you can either: -``` -SKIP=lychee -``` +1. Run `pre-commit` it in Git Bash, rather directly in PowerShell or cmd + +2. Skip it by setting the environment variable `SKIP` to `lychee`. This would + be `$env:SKIP = "lychee"` in PowerShell or `SKIP=lychee` in cmd. ## Signing Your Work From 25525cd6e4da81e8547b469727488d5324dae864 Mon Sep 17 00:00:00 2001 From: Mike Droettboom Date: Thu, 9 Jul 2026 11:45:01 -0400 Subject: [PATCH 4/4] Simplify type-checking --- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 2 +- .../cuda/pathfinder/_dynamic_libs/load_dl_windows.py | 2 +- .../cuda/pathfinder/_dynamic_libs/platform_loader.py | 8 +++----- cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py | 9 +++------ 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 173e0c58215..9f13e0540f4 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -211,7 +211,7 @@ def _work_around_known_bugs(libname: str, found_path: str) -> None: ctypes.CDLL(dep_path, CDLL_MODE) -def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str = "absolute-path") -> LoadedDL: +def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 1588d4ba997..cf8369482f0 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -147,7 +147,7 @@ def load_with_system_search(desc: LibDescriptor) -> LoadedDL | None: return None -def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str = "absolute-path") -> LoadedDL: +def load_with_abs_path(desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py index 210d1ca7132..64bf55efe3d 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/platform_loader.py @@ -16,11 +16,11 @@ from __future__ import annotations +import sys from typing import Protocol from cuda.pathfinder._dynamic_libs.lib_descriptor import LibDescriptor from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL -from cuda.pathfinder._utils.platform_aware import IS_WINDOWS class PlatformLoader(Protocol): @@ -28,12 +28,10 @@ def check_if_already_loaded_from_elsewhere(self, desc: LibDescriptor, have_abs_p def load_with_system_search(self, desc: LibDescriptor) -> LoadedDL | None: ... - def load_with_abs_path( - self, desc: LibDescriptor, found_path: str, found_via: str = "absolute-path" - ) -> LoadedDL: ... + def load_with_abs_path(self, desc: LibDescriptor, found_path: str, found_via: str | None = None) -> LoadedDL: ... -if IS_WINDOWS: +if sys.platform == "win32": from cuda.pathfinder._dynamic_libs import load_dl_windows as _impl else: from cuda.pathfinder._dynamic_libs import load_dl_linux as _impl diff --git a/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py b/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py index 8164a9f9adf..74a561b4e7c 100644 --- a/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py +++ b/cuda_pathfinder/cuda/pathfinder/_utils/driver_info.py @@ -5,13 +5,13 @@ import ctypes import functools +import sys from collections.abc import Callable from dataclasses import dataclass from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import ( load_nvidia_dynamic_lib as _load_nvidia_dynamic_lib, ) -from cuda.pathfinder._utils.platform_aware import IS_WINDOWS class QueryDriverCudaVersionError(RuntimeError): @@ -63,11 +63,8 @@ def query_driver_cuda_version() -> DriverCudaVersion: def _query_driver_cuda_version_int() -> int: """Return the encoded CUDA driver version from ``cuDriverGetVersion()``.""" loaded_cuda = _load_nvidia_dynamic_lib("cuda") - if IS_WINDOWS: - win_dll_loader = getattr(ctypes, "WinDLL", None) - if win_dll_loader is None: - raise RuntimeError("ctypes.WinDLL is not available on this Python runtime.") - loader_cls: Callable[[str], ctypes.CDLL] = win_dll_loader + if sys.platform == "win32": + loader_cls: Callable[[str], ctypes.CDLL] = ctypes.WinDLL else: loader_cls = ctypes.CDLL driver_lib = loader_cls(loaded_cuda.abs_path)