diff --git a/cuda_core/build_hooks.py b/cuda_core/build_hooks.py index 4aec4981c53..36a327257e5 100644 --- a/cuda_core/build_hooks.py +++ b/cuda_core/build_hooks.py @@ -46,9 +46,9 @@ def _import_get_cuda_path_or_home(): cuda = None for p in sys.path: - sp_cuda = os.path.join(p, "cuda") - if os.path.isdir(os.path.join(sp_cuda, "pathfinder")): - cuda.__path__ = list(cuda.__path__) + [sp_cuda] + sp_cuda = Path(p, "cuda") + if (sp_cuda / "pathfinder").is_dir(): + cuda.__path__ = list(cuda.__path__) + [str(sp_cuda)] break else: raise ModuleNotFoundError( @@ -93,7 +93,7 @@ def _determine_cuda_major_version() -> str: # Derive from the CUDA headers (the authoritative source for what we compile against). cuda_path = _get_cuda_path() - cuda_h = os.path.join(cuda_path, "include", "cuda.h") + cuda_h = Path(cuda_path, "include", "cuda.h") try: with open(cuda_h, encoding="utf-8") as f: for line in f: @@ -153,10 +153,11 @@ def _build_cuda_core(debug=False): # It seems setuptools' wildcard support has problems for namespace packages, # so we explicitly spell out all Extension instances. def module_names(): - root_path = os.path.sep.join(["cuda", "core", ""]) - for filename in glob.glob(f"{root_path}/**/*.pyx", recursive=True): - mod = filename[len(root_path) : -4] - if sys.platform == "win32" and mod.replace(os.path.sep, "/") in _posix_only_modules: + root_path = Path("cuda", "core") + for filename in glob.glob(str(root_path / "**" / "*.pyx"), recursive=True): + # Module names are always spelled POSIX-style, on every platform. + mod = Path(filename).relative_to(root_path).with_suffix("").as_posix() + if sys.platform == "win32" and mod in _posix_only_modules: continue yield mod @@ -167,12 +168,12 @@ def get_sources(mod_name): # Add module-specific .cpp file from _cpp/ directory if it exists # Example: _resource_handles.pyx finds _cpp/resource_handles.cpp. cpp_file = f"cuda/core/_cpp/{mod_name.lstrip('_')}.cpp" - if os.path.exists(cpp_file): + if Path(cpp_file).exists(): sources.append(cpp_file) return sources - all_include_dirs = [os.path.join(_get_cuda_path(), "include")] + all_include_dirs = [str(Path(_get_cuda_path(), "include"))] extra_compile_args = [] extra_link_args = [] extra_cythonize_kwargs = {} @@ -196,7 +197,7 @@ def get_sources(mod_name): ext_modules = tuple( Extension( - f"cuda.core.{mod.replace(os.path.sep, '.')}", + f"cuda.core.{mod.replace('/', '.')}", sources=get_sources(mod), include_dirs=[ "cuda/core/_include", @@ -230,7 +231,7 @@ def get_sources(mod_name): return -def _add_cython_include_paths_to_pth(wheel_path: str) -> None: +def _add_cython_include_paths_to_pth(wheel_path: Path) -> None: """ Modify the .pth file in an editable install wheel to add Cython include paths. @@ -261,7 +262,7 @@ def _add_cython_include_paths_to_pth(wheel_path: str) -> None: # Create a temporary directory for wheel manipulation with tempfile.TemporaryDirectory() as tmpdir: tmpdir_path = Path(tmpdir) - wheel_file = Path(wheel_path) + wheel_file = wheel_path # Extract the wheel extract_dir = tmpdir_path / "extracted" @@ -316,7 +317,7 @@ def build_editable(wheel_directory, config_settings=None, metadata_directory=Non wheel_name = _build_meta.build_editable(wheel_directory, config_settings, metadata_directory) # Patch the .pth file to add Cython include paths - wheel_path = os.path.join(wheel_directory, wheel_name) + wheel_path = Path(wheel_directory, wheel_name) _add_cython_include_paths_to_pth(wheel_path) return wheel_name diff --git a/cuda_core/examples/thread_block_cluster.py b/cuda_core/examples/thread_block_cluster.py index 078407ac6be..6c8b03c290e 100644 --- a/cuda_core/examples/thread_block_cluster.py +++ b/cuda_core/examples/thread_block_cluster.py @@ -14,8 +14,8 @@ # dependencies = ["cuda_bindings", "cuda_core"] # /// -import os import sys +from pathlib import Path import numpy as np @@ -74,14 +74,15 @@ def main(): if cuda_path is None: print("This example requires CUDA_PATH or CUDA_HOME to point to a CUDA toolkit.", file=sys.stderr) sys.exit(1) - cuda_include = os.path.join(cuda_path, "include") - if not os.path.isdir(cuda_include): + cuda_include = Path(cuda_path, "include") + if not cuda_include.is_dir(): print(f"CUDA include directory not found: {cuda_include}", file=sys.stderr) sys.exit(1) - include_path = [cuda_include] - cccl_include = os.path.join(cuda_include, "cccl") - if os.path.isdir(cccl_include): - include_path.insert(0, cccl_include) + # ProgramOptions.include_path is documented as str, so keep these str. + include_path = [str(cuda_include)] + cccl_include = cuda_include / "cccl" + if cccl_include.is_dir(): + include_path.insert(0, str(cccl_include)) dev = Device() arch = dev.compute_capability diff --git a/cuda_core/examples/tma_tensor_map.py b/cuda_core/examples/tma_tensor_map.py index 8c048d4a15d..4e275d11c9f 100644 --- a/cuda_core/examples/tma_tensor_map.py +++ b/cuda_core/examples/tma_tensor_map.py @@ -26,8 +26,8 @@ # dependencies = ["cuda_bindings", "cuda_core>0.6.0", "cupy-cuda13x"] # /// -import os import sys +from pathlib import Path import cupy as cp import numpy as np @@ -113,15 +113,16 @@ def _get_cccl_include_paths(): print("This example requires CUDA_PATH or CUDA_HOME to point to a CUDA toolkit.", file=sys.stderr) sys.exit(1) - cuda_include = os.path.join(cuda_path, "include") - if not os.path.isdir(cuda_include): + cuda_include = Path(cuda_path, "include") + if not cuda_include.is_dir(): print(f"CUDA include directory not found: {cuda_include}", file=sys.stderr) sys.exit(1) - include_path = [cuda_include] - cccl_include = os.path.join(cuda_include, "cccl") - if os.path.isdir(cccl_include): - include_path.insert(0, cccl_include) + # ProgramOptions.include_path is documented as str, so keep these str. + include_path = [str(cuda_include)] + cccl_include = cuda_include / "cccl" + if cccl_include.is_dir(): + include_path.insert(0, str(cccl_include)) return include_path diff --git a/cuda_core/tests/example_tests/test_basic_examples.py b/cuda_core/tests/example_tests/test_basic_examples.py index bf423758366..3195004ecb4 100644 --- a/cuda_core/tests/example_tests/test_basic_examples.py +++ b/cuda_core/tests/example_tests/test_basic_examples.py @@ -9,6 +9,7 @@ import subprocess import sys import warnings +from pathlib import Path import pytest from cuda_python_test_helpers.pep723 import has_package_requirements_or_skip @@ -91,14 +92,14 @@ def has_recent_memory_pool_support() -> bool: } -samples_path = os.path.join(os.path.dirname(__file__), "..", "..", "examples") -sample_files = [os.path.basename(x) for x in glob.glob(samples_path + "**/*.py", recursive=True)] +samples_path = Path(__file__).parents[2] / "examples" +sample_files = [Path(x).name for x in glob.glob(f"{samples_path}**/*.py", recursive=True)] @pytest.mark.parametrize("example", sample_files) @pytest.mark.parallel_threads_limit(8) def test_example(example): - example_path = os.path.join(samples_path, example) + example_path = samples_path / example has_package_requirements_or_skip(example_path) system_requirement = SYSTEM_REQUIREMENTS.get(example, lambda: True) diff --git a/cuda_core/tests/helpers/__init__.py b/cuda_core/tests/helpers/__init__.py index 5ce5ab7f05b..234182f33e7 100644 --- a/cuda_core/tests/helpers/__init__.py +++ b/cuda_core/tests/helpers/__init__.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import functools -import os +from pathlib import Path from typing import Union from cuda.core._utils.cuda_utils import handle_return @@ -13,13 +13,14 @@ CUDA_INCLUDE_PATH = None CCCL_INCLUDE_PATHS = None if CUDA_PATH is not None: - path = os.path.join(CUDA_PATH, "include") - if os.path.isdir(path): - CUDA_INCLUDE_PATH = path - CCCL_INCLUDE_PATHS = (path,) - path = os.path.join(path, "cccl") - if os.path.isdir(path): - CCCL_INCLUDE_PATHS = (path,) + CCCL_INCLUDE_PATHS + path = Path(CUDA_PATH, "include") + if path.is_dir(): + # ProgramOptions.include_path is documented as str, so keep these str. + CUDA_INCLUDE_PATH = str(path) + CCCL_INCLUDE_PATHS = (str(path),) + path = path / "cccl" + if path.is_dir(): + CCCL_INCLUDE_PATHS = (str(path),) + CCCL_INCLUDE_PATHS @functools.cache