Skip to content

Commit 3a16f45

Browse files
authored
tests: use zipfile (#785)
A better fit in general, and doesn't require Python 3.8. Signed-off-by: Henry Schreiner <[email protected]>
1 parent b914469 commit 3a16f45

16 files changed

+269
-281
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
3939
checks:
4040
name:
41-
Check 🐍 ${{ matrix.python-version }} • CMake ${{ matrix.cmake-version }}
41+
🐍 ${{ matrix.python-version }} • CMake ${{ matrix.cmake-version }}
4242
on ${{ matrix.runs-on }}
4343
runs-on: ${{ matrix.runs-on }}
4444
timeout-minutes: 40

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ repos:
1919
- id: mixed-line-ending
2020
- id: name-tests-test
2121
args: ["--pytest-test-first"]
22-
exclude: "^tests/packages/"
22+
exclude: "^tests/packages/|^tests/utils"
2323
- id: requirements-txt-fixer
2424
- id: trailing-whitespace
2525
exclude: "^tests"

docs/getting_started.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,8 @@ your `pyproject.toml`. You should specify exactly what language you use to keep
381381
CMake from searching for both `C` and `CXX` compilers (the default).
382382
383383
You'll need to handle the generation of files by NumPy directly at the moment.
384-
A helper (similar to scikti-build classic) might be added in the future. On
385-
macOS, you may need to set the Fortran compiler and C compiler to different
386-
toolchains with `CC=clang FC=gfortran`.
384+
A helper (similar to scikti-build classic) might be added in the future. You'll
385+
need gfortran on macOS.
387386
388387
````
389388

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ build.hooks.vcs.version-file = "src/scikit_build_core/_version.py"
125125

126126
[tool.pytest.ini_options]
127127
minversion = "7.0"
128-
addopts = ["-ra", "--strict-markers", "--strict-config"]
128+
addopts = ["-rfEsX", "--strict-markers", "--strict-config"]
129129
xfail_strict = true
130130
filterwarnings = [
131131
"error",
@@ -137,6 +137,7 @@ filterwarnings = [
137137
"default:check_home argument is deprecated and ignored.:DeprecationWarning", # Caused by setuptools sometimes
138138
]
139139
log_cli_level = "info"
140+
pythonpath = ["tests/utils"]
140141
testpaths = ["tests"]
141142
markers = [
142143
"broken_on_urct: Broken for now due to lib not found",
@@ -154,7 +155,7 @@ norecursedirs = ["tests/packages/**"]
154155

155156
[tool.mypy]
156157
files = ["src", "tests", "noxfile.py"]
157-
mypy_path = ["$MYPY_CONFIG_FILE_DIR/src"]
158+
mypy_path = ["$MYPY_CONFIG_FILE_DIR/src", "$MYPY_CONFIG_FILE_DIR/tests/utils"]
158159
python_version = "3.8"
159160
warn_unused_configs = true
160161
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
@@ -264,6 +265,9 @@ ignore = [
264265
]
265266
typing-modules = ["scikit_build_core._compat.typing"]
266267

268+
[tool.ruff.lint.isort]
269+
known-local-folder = ["pathutils"]
270+
267271
[tool.ruff.lint.flake8-tidy-imports.banned-api]
268272
"typing.Callable".msg = "Use collections.abc.Callable instead."
269273
"typing.Iterator".msg = "Use collections.abc.Iterator instead."

tests/test_dynamic_metadata.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from scikit_build_core.metadata import regex
2121
from scikit_build_core.settings.skbuild_read_settings import SettingsReader
2222

23+
from pathutils import contained
24+
2325

2426
# these are mock plugins returning known results
2527
# it turns out to be easier to create EntryPoint objects pointing to real
@@ -242,18 +244,15 @@ def test_pep517_wheel(virtualenv):
242244
)
243245
assert license == "MIT License"
244246

245-
with wheel.open("rb") as f:
246-
p = zipfile.Path(f)
247-
file_names = {x.name for x in p.iterdir()}
248-
dynamic_pkg = {x.name for x in p.joinpath("dynamic").iterdir()}
247+
with zipfile.ZipFile(wheel) as zf:
248+
file_paths = {Path(n) for n in zf.namelist()}
249249

250-
filtered_pkg = {x for x in dynamic_pkg if not x.startswith("_module")}
250+
dynamic_pkg = {x.name for x in contained(file_paths, "dynamic")}
251+
filtered_pkg = {x for x in dynamic_pkg if not x.startswith("_module")}
251252

252-
assert len(filtered_pkg) == len(dynamic_pkg) - 1
253-
assert {"dynamic-0.0.2.dist-info", "dynamic"} == file_names
254-
assert {
255-
"__init__.py",
256-
} == filtered_pkg
253+
assert len(filtered_pkg) == len(dynamic_pkg) - 1
254+
assert {"dynamic-0.0.2.dist-info", "dynamic"} == {p.parts[0] for p in file_paths}
255+
assert {"__init__.py"} == filtered_pkg
257256

258257
version = virtualenv.execute("from dynamic import square; print(square(2))")
259258
assert version == "4.0"

tests/test_fortran.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import shutil
2-
import sys
32
import sysconfig
43
import zipfile
54
from pathlib import Path
@@ -48,20 +47,17 @@ def test_pep517_wheel(tmp_path, monkeypatch, virtualenv):
4847
out = build_wheel(str(dist))
4948
(wheel,) = dist.glob("fibby-0.0.1-*.whl")
5049
assert wheel == dist / out
51-
print(wheel)
5250

53-
if sys.version_info >= (3, 8):
54-
with wheel.open("rb") as f:
55-
p = zipfile.Path(f)
56-
file_names = [p.name for p in p.iterdir()]
51+
with zipfile.ZipFile(wheel) as zf:
52+
file_names = {Path(n).parts[0] for n in zf.namelist()}
5753

58-
assert len(file_names) == 2
59-
assert "fibby-0.0.1.dist-info" in file_names
60-
file_names.remove("fibby-0.0.1.dist-info")
61-
(so_file,) = file_names
54+
assert len(file_names) == 2
55+
assert "fibby-0.0.1.dist-info" in file_names
56+
file_names.remove("fibby-0.0.1.dist-info")
57+
(so_file,) = file_names
6258

63-
assert so_file.startswith("fibby")
64-
print("SOFILE:", so_file)
59+
assert so_file.startswith("fibby")
60+
print("SOFILE:", so_file)
6561

6662
virtualenv.install(wheel)
6763

tests/test_pyproject_abi3.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,30 +40,28 @@ def test_abi3_wheel(tmp_path, monkeypatch, virtualenv):
4040
else:
4141
assert "-cp37-abi3-" not in out
4242

43-
if sys.version_info >= (3, 8):
44-
with wheel.open("rb") as f:
45-
p = zipfile.Path(f)
46-
file_names = [p.name for p in p.iterdir()]
43+
with zipfile.ZipFile(wheel) as zf:
44+
file_names = {Path(n).parts[0] for n in zf.namelist()}
4745

48-
assert len(file_names) == 2
49-
assert "abi3_example-0.0.1.dist-info" in file_names
50-
file_names.remove("abi3_example-0.0.1.dist-info")
51-
(so_file,) = file_names
46+
assert len(file_names) == 2
47+
assert "abi3_example-0.0.1.dist-info" in file_names
48+
file_names.remove("abi3_example-0.0.1.dist-info")
49+
(so_file,) = file_names
5250

53-
if sysconfig.get_platform().startswith("win"):
54-
if sys.implementation.name == "cpython":
55-
assert so_file == "abi3_example.pyd"
56-
else:
57-
assert so_file.endswith(".pyd")
58-
elif sys.platform.startswith("cygwin"):
59-
if abi3:
60-
assert so_file == "abi3_example.abi3.dll"
61-
else:
62-
assert so_file != "abi3_example.abi3.dll"
63-
elif abi3:
64-
assert so_file == "abi3_example.abi3.so"
51+
if sysconfig.get_platform().startswith("win"):
52+
if sys.implementation.name == "cpython":
53+
assert so_file == "abi3_example.pyd"
6554
else:
66-
assert so_file != "abi3_example.abi3.so"
55+
assert so_file.endswith(".pyd")
56+
elif sys.platform.startswith("cygwin"):
57+
if abi3:
58+
assert so_file == "abi3_example.abi3.dll"
59+
else:
60+
assert so_file != "abi3_example.abi3.dll"
61+
elif abi3:
62+
assert so_file == "abi3_example.abi3.so"
63+
else:
64+
assert so_file != "abi3_example.abi3.so"
6765

6866
virtualenv.install(wheel)
6967

tests/test_pyproject_extra_dirs.py

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import sys
21
import zipfile
32
from pathlib import Path
43

@@ -7,13 +6,11 @@
76
from scikit_build_core.build import build_wheel
87
from scikit_build_core.errors import CMakeConfigError
98

9+
from pathutils import contained
10+
1011

1112
@pytest.mark.compile()
1213
@pytest.mark.configure()
13-
@pytest.mark.skipif(
14-
sys.version_info < (3, 8),
15-
reason="Python 3.7 doesn't have a nice Path zipfile interface",
16-
)
1714
@pytest.mark.usefixtures("package_filepath_pure")
1815
def test_pep517_wheel_extra_dirs(monkeypatch):
1916
monkeypatch.setenv("SKBUILD_CMAKE_DEFINE", "SOME_DEFINE3=baz;SOME_DEFINE4=baz")
@@ -27,33 +24,30 @@ def test_pep517_wheel_extra_dirs(monkeypatch):
2724
(wheel,) = dist.glob("cmake_dirs-0.0.1-*.whl")
2825
assert wheel == dist / out
2926

30-
if sys.version_info >= (3, 8):
31-
with wheel.open("rb") as f:
32-
p = zipfile.Path(f)
33-
file_names = {p.name for p in p.iterdir()}
34-
data_dir = {p.name for p in p.joinpath("cmake_dirs-0.0.1.data").iterdir()}
35-
package = {p.name for p in p.joinpath("cmake_dirs").iterdir()}
36-
data = {p.name for p in p.joinpath("cmake_dirs-0.0.1.data/data").iterdir()}
37-
headers = {
38-
p.name for p in p.joinpath("cmake_dirs-0.0.1.data/headers").iterdir()
39-
}
40-
scripts = {
41-
p.name for p in p.joinpath("cmake_dirs-0.0.1.data/scripts").iterdir()
42-
}
27+
with zipfile.ZipFile(wheel) as zf:
28+
file_paths = {Path(n) for n in zf.namelist()}
29+
data_paths = set(contained(file_paths, "cmake_dirs-0.0.1.data"))
30+
31+
file_names = {p.parts[0] for p in file_paths}
32+
data_dir = {p.parts[0] for p in data_paths}
33+
package = {p.name for p in contained(file_paths, "cmake_dirs")}
34+
data = {p.name for p in contained(data_paths, "data")}
35+
headers = {p.name for p in contained(data_paths, "headers")}
36+
scripts = {p.name for p in contained(data_paths, "scripts")}
4337

44-
assert {
45-
"cmake_dirs-0.0.1.dist-info",
46-
"cmake_dirs-0.0.1.data",
47-
"cmake_dirs",
48-
"random_file.py",
49-
} == file_names
38+
assert {
39+
"cmake_dirs-0.0.1.dist-info",
40+
"cmake_dirs-0.0.1.data",
41+
"cmake_dirs",
42+
"random_file.py",
43+
} == file_names
5044

51-
assert data_dir == {"data", "headers", "scripts"}
45+
assert data_dir == {"data", "headers", "scripts"}
5246

53-
assert package == {"main.py"}
54-
assert data == {"in_data.txt"}
55-
assert headers == {"in_headers.h"}
56-
assert scripts == {"in_scripts.py"}
47+
assert package == {"main.py"}
48+
assert data == {"in_data.txt"}
49+
assert headers == {"in_headers.h"}
50+
assert scripts == {"in_scripts.py"}
5751

5852

5953
@pytest.mark.usefixtures("package_filepath_pure")

tests/test_pyproject_pep517.py

Lines changed: 62 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -198,31 +198,33 @@ def test_pep517_wheel(virtualenv):
198198
(wheel,) = dist.glob("cmake_example-0.0.1-*.whl")
199199
assert wheel == dist / out
200200

201-
if sys.version_info >= (3, 8):
202-
with wheel.open("rb") as f:
203-
p = zipfile.Path(f)
204-
file_names = [p.name for p in p.iterdir()]
205-
metadata = p.joinpath("cmake_example-0.0.1.dist-info/METADATA").read_text()
206-
entry_points = p.joinpath(
207-
"cmake_example-0.0.1.dist-info/entry_points.txt"
208-
).read_text()
209-
assert p.joinpath("cmake_example-0.0.1.dist-info/licenses/LICENSE").exists()
210-
211-
assert len(file_names) == 2
212-
assert "cmake_example-0.0.1.dist-info" in file_names
213-
file_names.remove("cmake_example-0.0.1.dist-info")
214-
(so_file,) = file_names
215-
216-
assert so_file.startswith("cmake_example")
217-
print("SOFILE:", so_file)
218-
219-
print(entry_points == ENTRYPOINTS)
220-
assert 'Requires-Dist: pytest>=6.0; extra == "test"' in metadata
221-
assert "Metadata-Version: 2.1" in metadata
222-
assert "Name: CMake.Example" in metadata
223-
assert "Version: 0.0.1" in metadata
224-
assert "Requires-Python: >=3.7" in metadata
225-
assert "Provides-Extra: test" in metadata
201+
with zipfile.ZipFile(wheel) as zf:
202+
file_paths = {Path(p) for p in zf.namelist()}
203+
file_names = {p.parts[0] for p in file_paths}
204+
205+
with zf.open("cmake_example-0.0.1.dist-info/METADATA") as f:
206+
metadata = f.read().decode("utf-8")
207+
208+
with zf.open("cmake_example-0.0.1.dist-info/entry_points.txt") as f:
209+
entry_points = f.read().decode("utf-8")
210+
211+
assert Path("cmake_example-0.0.1.dist-info/licenses/LICENSE") in file_paths
212+
213+
assert len(file_names) == 2
214+
assert "cmake_example-0.0.1.dist-info" in file_names
215+
file_names.remove("cmake_example-0.0.1.dist-info")
216+
(so_file,) = file_names
217+
218+
assert so_file.startswith("cmake_example")
219+
print("SOFILE:", so_file)
220+
221+
print(entry_points == ENTRYPOINTS)
222+
assert 'Requires-Dist: pytest>=6.0; extra == "test"' in metadata
223+
assert "Metadata-Version: 2.1" in metadata
224+
assert "Name: CMake.Example" in metadata
225+
assert "Version: 0.0.1" in metadata
226+
assert "Requires-Python: >=3.7" in metadata
227+
assert "Provides-Extra: test" in metadata
226228

227229
virtualenv.install(wheel)
228230

@@ -246,39 +248,41 @@ def test_pep517_wheel_source_dir(virtualenv):
246248
(wheel,) = dist.glob("cmake_example-0.0.1-*.whl")
247249
assert wheel == dist / out
248250

249-
if sys.version_info >= (3, 8):
250-
with wheel.open("rb") as f:
251-
p = zipfile.Path(f)
252-
file_names = [p.name for p in p.iterdir()]
253-
metadata = p.joinpath("cmake_example-0.0.1.dist-info/METADATA").read_text()
254-
wheel_metadata = p.joinpath(
255-
"cmake_example-0.0.1.dist-info/WHEEL"
256-
).read_text()
257-
entry_points = p.joinpath(
258-
"cmake_example-0.0.1.dist-info/entry_points.txt"
259-
).read_text()
260-
assert p.joinpath("cmake_example-0.0.1.dist-info/licenses/LICENSE").exists()
261-
262-
assert len(file_names) == 2
263-
assert "cmake_example-0.0.1.dist-info" in file_names
264-
file_names.remove("cmake_example-0.0.1.dist-info")
265-
(so_file,) = file_names
266-
267-
assert so_file.startswith("cmake_example")
268-
print("SOFILE:", so_file)
269-
270-
print(entry_points == ENTRYPOINTS)
271-
assert 'Requires-Dist: pytest>=6.0; extra == "test"' in metadata
272-
assert "Metadata-Version: 2.1" in metadata
273-
assert "Name: CMake.Example" in metadata
274-
assert "Version: 0.0.1" in metadata
275-
assert "Requires-Python: >=3.7" in metadata
276-
assert "Provides-Extra: test" in metadata
277-
278-
assert "Build: 1foo" in wheel_metadata
279-
assert "Wheel-Version: 1.0" in wheel_metadata
280-
assert "Generator: scikit-build" in wheel_metadata
281-
assert "Root-Is-Purelib: false" in wheel_metadata
251+
with zipfile.ZipFile(wheel) as zf:
252+
file_paths = {Path(p) for p in zf.namelist()}
253+
file_names = {p.parts[0] for p in file_paths}
254+
255+
with zf.open("cmake_example-0.0.1.dist-info/METADATA") as f:
256+
metadata = f.read().decode("utf-8")
257+
258+
with zf.open("cmake_example-0.0.1.dist-info/WHEEL") as f:
259+
wheel_metadata = f.read().decode("utf-8")
260+
261+
with zf.open("cmake_example-0.0.1.dist-info/entry_points.txt") as f:
262+
entry_points = f.read().decode("utf-8")
263+
264+
assert Path("cmake_example-0.0.1.dist-info/licenses/LICENSE") in file_paths
265+
266+
assert len(file_names) == 2
267+
assert "cmake_example-0.0.1.dist-info" in file_names
268+
file_names.remove("cmake_example-0.0.1.dist-info")
269+
(so_file,) = file_names
270+
271+
assert so_file.startswith("cmake_example")
272+
print("SOFILE:", so_file)
273+
274+
print(entry_points == ENTRYPOINTS)
275+
assert 'Requires-Dist: pytest>=6.0; extra == "test"' in metadata
276+
assert "Metadata-Version: 2.1" in metadata
277+
assert "Name: CMake.Example" in metadata
278+
assert "Version: 0.0.1" in metadata
279+
assert "Requires-Python: >=3.7" in metadata
280+
assert "Provides-Extra: test" in metadata
281+
282+
assert "Build: 1foo" in wheel_metadata
283+
assert "Wheel-Version: 1.0" in wheel_metadata
284+
assert "Generator: scikit-build" in wheel_metadata
285+
assert "Root-Is-Purelib: false" in wheel_metadata
282286

283287
virtualenv.install(wheel)
284288

0 commit comments

Comments
 (0)