Skip to content

Commit 3cd31be

Browse files
LeSingh1mdboom
andauthored
Use pathlib in cuda.pathfinder._static_libs (part 2 of #2410) (#2493)
* Migrate _static_libs finders from os.path to pathlib Part 2 of the series proposed in #2410, following the same conversion style as part 1 (#2489). Path construction, joining, and filesystem predicates in find_static_lib.py and find_bitcode_lib.py now go through pathlib.Path instead of os.path string manipulation. Both modules keep importing os solely for os.environ.get("CONDA_PREFIX"). Compatibility is preserved: every entry point still accepts str, and every function that documents or returns str still returns str. Path is used strictly as the internal representation and converted back with str() at each return, so LocatedStaticLib.abs_path, LocatedBitcodeLib .abs_path, find_static_lib() and find_bitcode_lib() are unchanged in both type and value. No signature changes. Signed-off-by: LeSingh1 <sshaurya914@gmail.com> * Return Path from the _static_libs internals Follow-up to the review feedback on #2489: the str-compatibility constraint applies only to the public API. The try_* methods and _no_such_file_in_dir now work in Path throughout. str() is applied once, where abs_path is stored on the public LocatedStaticLib and LocatedBitcodeLib. The relative-path constants go from os.path.join(...) to forward-slash literals, matching how site_packages_dirs is already written in the same dicts; Path normalizes the separator on Windows. One behavior change: a CUDA_PATH or CONDA_PREFIX containing redundant separators ("//", "/.") now produces a normalized abs_path, because Path collapses them. Differential fuzzing against the pre-revision code (16k lookups over randomized trees, comparing located paths and full error text) shows no other difference, and none at all when those variables are free of redundant separators. Signed-off-by: LeSingh1 <sshaurya914@gmail.com> --------- Signed-off-by: LeSingh1 <sshaurya914@gmail.com> Co-authored-by: Michael Droettboom <mdboom@gmail.com>
1 parent b5fbaa6 commit 3cd31be

2 files changed

Lines changed: 47 additions & 43 deletions

File tree

cuda_pathfinder/cuda/pathfinder/_static_libs/find_bitcode_lib.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import functools
55
import os
66
from dataclasses import dataclass
7+
from pathlib import Path
78
from typing import NoReturn, TypedDict
89

910
from cuda.pathfinder._utils.env_vars import get_cuda_path_or_home
@@ -35,7 +36,7 @@ class _BitcodeLibInfo(TypedDict):
3536
_SUPPORTED_BITCODE_LIBS_INFO: dict[str, _BitcodeLibInfo] = {
3637
"device": {
3738
"filename": "libdevice.10.bc",
38-
"rel_path": os.path.join("nvvm", "libdevice"),
39+
"rel_path": "nvvm/libdevice",
3940
"site_packages_dirs": (
4041
"nvidia/cu13/nvvm/libdevice",
4142
"nvidia/cuda_nvcc/nvvm/libdevice",
@@ -64,14 +65,14 @@ class _BitcodeLibInfo(TypedDict):
6465
)
6566

6667

67-
def _no_such_file_in_dir(dir_path: str, filename: str, error_messages: list[str], attachments: list[str]) -> None:
68-
error_messages.append(f"No such file: {os.path.join(dir_path, filename)}")
69-
if os.path.isdir(dir_path):
70-
attachments.append(f' listdir("{dir_path}"):')
71-
for node in sorted(os.listdir(dir_path)):
68+
def _no_such_file_in_dir(directory: Path, filename: str, error_messages: list[str], attachments: list[str]) -> None:
69+
error_messages.append(f"No such file: {directory / filename}")
70+
if directory.is_dir():
71+
attachments.append(f' listdir("{directory}"):')
72+
for node in sorted(node_path.name for node_path in directory.iterdir()):
7273
attachments.append(f" {node}")
7374
else:
74-
attachments.append(f' Directory does not exist: "{dir_path}"')
75+
attachments.append(f' Directory does not exist: "{directory}"')
7576

7677

7778
class _FindBitcodeLib:
@@ -86,38 +87,39 @@ def __init__(self, name: str) -> None:
8687
self.error_messages: list[str] = []
8788
self.attachments: list[str] = []
8889

89-
def try_site_packages(self) -> str | None:
90+
def try_site_packages(self) -> Path | None:
9091
for rel_dir in self.site_packages_dirs:
9192
sub_dir = tuple(rel_dir.split("/"))
9293
for abs_dir in find_sub_dirs_all_sitepackages(sub_dir):
93-
file_path = os.path.join(abs_dir, self.filename)
94-
if os.path.isfile(file_path):
94+
file_path = Path(abs_dir, self.filename)
95+
if file_path.is_file():
9596
return file_path
9697
return None
9798

98-
def try_with_conda_prefix(self) -> str | None:
99+
def try_with_conda_prefix(self) -> Path | None:
99100
conda_prefix = os.environ.get("CONDA_PREFIX")
100101
if not conda_prefix:
101102
return None
102103

103-
anchor = os.path.join(conda_prefix, "Library") if IS_WINDOWS else conda_prefix
104-
file_path = os.path.join(anchor, self.rel_path, self.filename)
105-
if os.path.isfile(file_path):
104+
anchor = Path(conda_prefix, "Library") if IS_WINDOWS else Path(conda_prefix)
105+
file_path = anchor / self.rel_path / self.filename
106+
if file_path.is_file():
106107
return file_path
107108
return None
108109

109-
def try_with_cuda_home(self) -> str | None:
110+
def try_with_cuda_home(self) -> Path | None:
110111
cuda_home = get_cuda_path_or_home()
111112
if cuda_home is None:
112113
self.error_messages.append("CUDA_HOME/CUDA_PATH not set")
113114
return None
114115

115-
file_path = os.path.join(cuda_home, self.rel_path, self.filename)
116-
if os.path.isfile(file_path):
116+
anchor = Path(cuda_home)
117+
file_path = anchor / self.rel_path / self.filename
118+
if file_path.is_file():
117119
return file_path
118120

119121
_no_such_file_in_dir(
120-
os.path.join(cuda_home, self.rel_path),
122+
anchor / self.rel_path,
121123
self.filename,
122124
self.error_messages,
123125
self.attachments,
@@ -143,7 +145,7 @@ def locate_bitcode_lib(name: str) -> LocatedBitcodeLib:
143145
if abs_path is not None:
144146
return LocatedBitcodeLib(
145147
name=name,
146-
abs_path=abs_path,
148+
abs_path=str(abs_path),
147149
filename=finder.filename,
148150
found_via="site-packages",
149151
)
@@ -152,7 +154,7 @@ def locate_bitcode_lib(name: str) -> LocatedBitcodeLib:
152154
if abs_path is not None:
153155
return LocatedBitcodeLib(
154156
name=name,
155-
abs_path=abs_path,
157+
abs_path=str(abs_path),
156158
filename=finder.filename,
157159
found_via="conda",
158160
)
@@ -161,7 +163,7 @@ def locate_bitcode_lib(name: str) -> LocatedBitcodeLib:
161163
if abs_path is not None:
162164
return LocatedBitcodeLib(
163165
name=name,
164-
abs_path=abs_path,
166+
abs_path=str(abs_path),
165167
filename=finder.filename,
166168
found_via="CUDA_PATH",
167169
)

cuda_pathfinder/cuda/pathfinder/_static_libs/find_static_lib.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import functools
55
import os
66
from dataclasses import dataclass
7+
from pathlib import Path
78
from typing import NoReturn, TypedDict
89

910
from cuda.pathfinder._utils.env_vars import get_cuda_path_or_home
@@ -47,8 +48,8 @@ def _cudadevrt_info() -> _StaticLibInfo:
4748
conda_fallback_dirs = ("lib",) if arch_dir == "x64" else ()
4849
return {
4950
"filename": "cudadevrt.lib",
50-
"ctk_rel_paths": (os.path.join("lib", arch_dir),),
51-
"conda_rel_paths": (os.path.join("lib", arch_dir), *conda_fallback_dirs),
51+
"ctk_rel_paths": (str(Path("lib", arch_dir)),),
52+
"conda_rel_paths": (str(Path("lib", arch_dir)), *conda_fallback_dirs),
5253
"site_packages_dirs": (f"nvidia/cu13/lib/{arch_dir}", *component_wheel_dirs),
5354
}
5455

@@ -60,14 +61,14 @@ def _cudadevrt_info() -> _StaticLibInfo:
6061
SUPPORTED_STATIC_LIBS: tuple[str, ...] = tuple(sorted(_SUPPORTED_STATIC_LIBS_INFO.keys()))
6162

6263

63-
def _no_such_file_in_dir(dir_path: str, filename: str, error_messages: list[str], attachments: list[str]) -> None:
64-
error_messages.append(f"No such file: {os.path.join(dir_path, filename)}")
65-
if os.path.isdir(dir_path):
66-
attachments.append(f' listdir("{dir_path}"):')
67-
for node in sorted(os.listdir(dir_path)):
64+
def _no_such_file_in_dir(directory: Path, filename: str, error_messages: list[str], attachments: list[str]) -> None:
65+
error_messages.append(f"No such file: {directory / filename}")
66+
if directory.is_dir():
67+
attachments.append(f' listdir("{directory}"):')
68+
for node in sorted(node_path.name for node_path in directory.iterdir()):
6869
attachments.append(f" {node}")
6970
else:
70-
attachments.append(f' Directory does not exist: "{dir_path}"')
71+
attachments.append(f' Directory does not exist: "{directory}"')
7172

7273

7374
class _FindStaticLib:
@@ -83,40 +84,41 @@ def __init__(self, name: str) -> None:
8384
self.error_messages: list[str] = []
8485
self.attachments: list[str] = []
8586

86-
def try_site_packages(self) -> str | None:
87+
def try_site_packages(self) -> Path | None:
8788
for rel_dir in self.site_packages_dirs:
8889
sub_dir = tuple(rel_dir.split("/"))
8990
for abs_dir in find_sub_dirs_all_sitepackages(sub_dir):
90-
file_path = os.path.join(abs_dir, self.filename)
91-
if os.path.isfile(file_path):
91+
file_path = Path(abs_dir, self.filename)
92+
if file_path.is_file():
9293
return file_path
9394
return None
9495

95-
def try_with_conda_prefix(self) -> str | None:
96+
def try_with_conda_prefix(self) -> Path | None:
9697
conda_prefix = os.environ.get("CONDA_PREFIX")
9798
if not conda_prefix:
9899
return None
99100

100-
anchor = os.path.join(conda_prefix, "Library") if IS_WINDOWS else conda_prefix
101+
anchor = Path(conda_prefix, "Library") if IS_WINDOWS else Path(conda_prefix)
101102
for rel_path in self.conda_rel_paths:
102-
file_path = os.path.join(anchor, rel_path, self.filename)
103-
if os.path.isfile(file_path):
103+
file_path = anchor / rel_path / self.filename
104+
if file_path.is_file():
104105
return file_path
105106
return None
106107

107-
def try_with_cuda_home(self) -> str | None:
108+
def try_with_cuda_home(self) -> Path | None:
108109
cuda_home = get_cuda_path_or_home()
109110
if cuda_home is None:
110111
self.error_messages.append("CUDA_HOME/CUDA_PATH not set")
111112
return None
112113

114+
anchor = Path(cuda_home)
113115
for rel_path in self.ctk_rel_paths:
114-
file_path = os.path.join(cuda_home, rel_path, self.filename)
115-
if os.path.isfile(file_path):
116+
file_path = anchor / rel_path / self.filename
117+
if file_path.is_file():
116118
return file_path
117119

118120
_no_such_file_in_dir(
119-
os.path.join(cuda_home, self.ctk_rel_paths[0]),
121+
anchor / self.ctk_rel_paths[0],
120122
self.filename,
121123
self.error_messages,
122124
self.attachments,
@@ -142,7 +144,7 @@ def locate_static_lib(name: str) -> LocatedStaticLib:
142144
if abs_path is not None:
143145
return LocatedStaticLib(
144146
name=name,
145-
abs_path=abs_path,
147+
abs_path=str(abs_path),
146148
filename=finder.filename,
147149
found_via="site-packages",
148150
)
@@ -151,7 +153,7 @@ def locate_static_lib(name: str) -> LocatedStaticLib:
151153
if abs_path is not None:
152154
return LocatedStaticLib(
153155
name=name,
154-
abs_path=abs_path,
156+
abs_path=str(abs_path),
155157
filename=finder.filename,
156158
found_via="conda",
157159
)
@@ -160,7 +162,7 @@ def locate_static_lib(name: str) -> LocatedStaticLib:
160162
if abs_path is not None:
161163
return LocatedStaticLib(
162164
name=name,
163-
abs_path=abs_path,
165+
abs_path=str(abs_path),
164166
filename=finder.filename,
165167
found_via="CUDA_PATH",
166168
)

0 commit comments

Comments
 (0)