Skip to content

Commit 5ca79de

Browse files
authored
fix: windows path correction (#346)
The header and filename need to match. --------- Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
1 parent aeb7995 commit 5ca79de

File tree

1 file changed

+28
-15
lines changed

1 file changed

+28
-15
lines changed

src/scikit_build_core/build/_wheelfile.py

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from collections.abc import Mapping, Set
1414
from email.message import Message
1515
from email.policy import EmailPolicy
16-
from pathlib import Path, PurePosixPath
16+
from pathlib import Path
1717
from zipfile import ZipInfo
1818

1919
import packaging.utils
@@ -72,8 +72,8 @@ class WheelWriter:
7272
tags: Set[Tag]
7373
wheel_metadata = WheelMetadata(root_is_purelib=False)
7474
buildver: str = ""
75-
zipfile: zipfile.ZipFile | None = None
7675
license_files: Mapping[Path, bytes] = dataclasses.field(default_factory=dict)
76+
_zipfile: zipfile.ZipFile | None = None
7777

7878
@property
7979
def name_ver(self) -> str:
@@ -155,56 +155,69 @@ def build(self, wheel_dirs: dict[str, Path]) -> None:
155155
if filename.is_file() and not is_in_dist_info and not is_python_cache:
156156
relpath = filename.relative_to(path)
157157
target = Path(data_dir) / key / relpath if key else relpath
158-
# Zipfiles require Posix paths for the arcname
159-
self.write(str(filename), str(PurePosixPath(target)))
158+
self.write(str(filename), str(target))
160159

161160
dist_info_contents = self.dist_info_contents()
162161
for key, data in dist_info_contents.items():
163162
self.writestr(f"{self.dist_info}/{key}", data)
164163

165164
def write(self, filename: str, arcname: str | None = None) -> None:
166-
"""Write a file to the archive."""
165+
"""Write a file to the archive. Paths are normalized to Posix paths."""
167166

168167
with Path(filename).open("rb") as f:
169168
st = os.fstat(f.fileno())
170169
data = f.read()
171-
zinfo = ZipInfo(arcname or str(filename), date_time=self.timestamp(st.st_mtime))
170+
171+
# Zipfiles require Posix paths for the arcname
172+
zinfo = ZipInfo(
173+
(arcname or filename).replace("\\", "/"),
174+
date_time=self.timestamp(st.st_mtime),
175+
)
172176
zinfo.compress_type = zipfile.ZIP_DEFLATED
173177
zinfo.external_attr = (stat.S_IMODE(st.st_mode) | stat.S_IFMT(st.st_mode)) << 16
174178
self.writestr(zinfo, data)
175179

176180
def writestr(self, zinfo_or_arcname: str | ZipInfo, data: bytes) -> None:
177181
"""Write bytes (not strings) to the archive."""
178182
assert isinstance(data, bytes)
179-
assert self.zipfile is not None
183+
assert self._zipfile is not None
180184
if isinstance(zinfo_or_arcname, zipfile.ZipInfo):
181185
zinfo = zinfo_or_arcname
182186
else:
183-
zinfo = zipfile.ZipInfo(zinfo_or_arcname, date_time=self.timestamp())
187+
zinfo = zipfile.ZipInfo(
188+
zinfo_or_arcname.replace("\\", "/"),
189+
date_time=self.timestamp(),
190+
)
184191
zinfo.compress_type = zipfile.ZIP_DEFLATED
185192
zinfo.external_attr = (0o664 | stat.S_IFREG) << 16
186-
self.zipfile.writestr(zinfo, data)
193+
assert (
194+
"\\" not in zinfo.filename
195+
), f"\\ not supported in zip; got {zinfo.filename!r}"
196+
self._zipfile.writestr(zinfo, data)
187197

188198
def __enter__(self) -> Self:
189199
if not self.wheelpath.parent.exists():
190200
self.wheelpath.parent.mkdir(parents=True)
191201

192-
self.zipfile = zipfile.ZipFile(
202+
self._zipfile = zipfile.ZipFile(
193203
self.wheelpath, "w", compression=zipfile.ZIP_DEFLATED
194204
)
195205
return self
196206

197207
def __exit__(self, *args: object) -> None:
198-
assert self.zipfile is not None
208+
assert self._zipfile is not None
199209
record = f"{self.dist_info}/RECORD"
200210
data = io.StringIO()
201211
writer = csv.writer(data, delimiter=",", quotechar='"', lineterminator="\n")
202-
for member in self.zipfile.infolist():
203-
with self.zipfile.open(member) as f:
212+
for member in self._zipfile.infolist():
213+
assert (
214+
"\\" not in member.filename
215+
), f"Invalid zip contents: {member.filename}"
216+
with self._zipfile.open(member) as f:
204217
member_data = f.read()
205218
sha = _b64encode(hashlib.sha256(member_data).digest()).decode("ascii")
206219
writer.writerow((member.filename, f"sha256={sha}", member.file_size))
207220
writer.writerow((record, "", ""))
208221
self.writestr(record, data.getvalue().encode("utf-8"))
209-
self.zipfile.close()
210-
self.zipfile = None
222+
self._zipfile.close()
223+
self._zipfile = None

0 commit comments

Comments
 (0)