Skip to content

Commit d8188d9

Browse files
committed
refactor: use tomlkit instead of manual parsing
Signed-off-by: Henry Schreiner <[email protected]>
1 parent 6683437 commit d8188d9

File tree

6 files changed

+71
-63
lines changed

6 files changed

+71
-63
lines changed

CMakeLists.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,10 @@ if(PYBIND11_INSTALL)
330330
if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11")
331331
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/empty")
332332
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py")
333-
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/")
334-
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
333+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
334+
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/")
335+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
336+
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
335337
endif()
336338

337339
# Uninstall target

noxfile.py

+4-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import argparse
44
import contextlib
55
import os
6-
import re
76
from pathlib import Path
87
from typing import TYPE_CHECKING
98

@@ -16,10 +15,6 @@
1615
nox.options.sessions = ["lint", "tests", "tests_packaging"]
1716
nox.options.default_venv_backend = "uv|virtualenv"
1817

19-
MARKER_PATTERN = re.compile(
20-
r"# not-in-global-start.*?# not-in-global-end\n?", re.DOTALL
21-
)
22-
2318

2419
@nox.session(reuse_venv=True)
2520
def lint(session: nox.Session) -> None:
@@ -133,22 +128,17 @@ def build_global(session: nox.Session) -> None:
133128
"""
134129

135130
installer = ["--installer=uv"] if session.venv_backend == "uv" else []
136-
session.install("build")
131+
session.install("build", "tomlkit")
137132
session.log("Building pybind11-global files")
138133
pyproject = Path("pyproject.toml")
139-
with preserve_file(pyproject) as txt:
140-
new_txt = txt.replace('name = "pybind11"', 'name = "pybind11-global"')
141-
assert txt != new_txt
142-
newer_txt = MARKER_PATTERN.sub("", new_txt)
143-
assert new_txt != newer_txt
144-
134+
with preserve_file(pyproject):
135+
newer_txt = session.run("python", "tools/make_global.py", silent=True)
136+
assert isinstance(newer_txt, str)
145137
pyproject.write_text(newer_txt, encoding="utf-8")
146138
session.run(
147139
"python",
148140
"-m",
149141
"build",
150142
*installer,
151-
"-Cskbuild.wheel.install-dir=/data",
152-
"-Cskbuild.experimental=true",
153143
*session.posargs,
154144
)

pyproject.toml

+20-25
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ Discussions = "https://github.com/pybind/pybind11/discussions"
4242
Changelog = "https://pybind11.readthedocs.io/en/latest/changelog.html"
4343
Chat = "https://gitter.im/pybind/Lobby"
4444

45-
# not-in-global-start
4645
[project.optional-dependencies]
4746
global = ["pybind11-global"] # TODO: pin
47+
4848
[project.scripts]
4949
pybind11-config = "pybind11.__main__:main"
5050

@@ -54,24 +54,6 @@ pybind11 = "pybind11.__main__:main"
5454
[project.entry-points.pkg_config]
5555
pybind11 = "pybind11.share.pkgconfig"
5656

57-
[[tool.scikit-build.generate]]
58-
path = "pybind11/_version.py"
59-
template = '''
60-
from __future__ import annotations
61-
62-
63-
def _to_int(s: str) -> int | str:
64-
try:
65-
return int(s)
66-
except ValueError:
67-
return s
68-
69-
70-
__version__ = "$version"
71-
version_info = tuple(_to_int(s) for s in __version__.split("."))
72-
'''
73-
# not-in-global-end
74-
7557

7658
[tool.scikit-build]
7759
minimum-version = "build-system.requires"
@@ -81,11 +63,6 @@ sdist.exclude = [
8163
]
8264
wheel.install-dir = "pybind11"
8365
wheel.platlib = false
84-
wheel.packages = [
85-
# not-in-global-start
86-
"pybind11",
87-
# not-in-global-end
88-
]
8966

9067
[tool.scikit-build.cmake.define]
9168
BUILD_TESTING = false
@@ -103,6 +80,24 @@ regex = '''(?sx)
10380
result = "{major}.{minor}.{patch}"
10481

10582

83+
[[tool.scikit-build.generate]]
84+
path = "pybind11/_version.py"
85+
template = '''
86+
from __future__ import annotations
87+
88+
89+
def _to_int(s: str) -> int | str:
90+
try:
91+
return int(s)
92+
except ValueError:
93+
return s
94+
95+
96+
__version__ = "$version"
97+
version_info = tuple(_to_int(s) for s in __version__.split("."))
98+
'''
99+
100+
106101
[tool.mypy]
107102
files = ["pybind11"]
108103
python_version = "3.8"
@@ -111,7 +106,7 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
111106
warn_unreachable = true
112107

113108
[[tool.mypy.overrides]]
114-
module = ["ghapi.*"]
109+
module = ["ghapi.*", "tomlkit"] # tomlkit has types, but not very helpful
115110
ignore_missing_imports = true
116111

117112

tests/extra_python_package/test_files.py

+9-22
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22

33
import contextlib
44
import os
5-
import re
65
import subprocess
76
import sys
87
import tarfile
98
import zipfile
109
from pathlib import Path
1110
from typing import Generator
12-
from pprint import pprint
1311

1412
# These tests must be run explicitly
1513

1614
DIR = Path(__file__).parent.resolve()
1715
MAIN_DIR = DIR.parent.parent
1816

19-
MARKER_PATTERN = re.compile(
20-
r"# not-in-global-start.*?# not-in-global-end\n?", re.DOTALL
21-
)
17+
18+
# Newer pytest has global path setting, but keeping old pytest for now
19+
sys.path.append(str(MAIN_DIR / "tools"))
20+
21+
from make_global import get_global # noqa: E402
2222

2323
PKGCONFIG = """\
2424
prefix=${{pcfiledir}}/../../
@@ -151,12 +151,8 @@ def build_global() -> Generator[None, None, None]:
151151
"""
152152

153153
pyproject = MAIN_DIR / "pyproject.toml"
154-
with preserve_file(pyproject) as txt:
155-
new_txt = txt.replace('name = "pybind11"', 'name = "pybind11-global"')
156-
assert txt != new_txt
157-
newer_txt = MARKER_PATTERN.sub("", new_txt)
158-
assert new_txt != newer_txt
159-
154+
with preserve_file(pyproject):
155+
newer_txt = get_global()
160156
pyproject.write_text(newer_txt, encoding="utf-8")
161157
yield
162158

@@ -183,16 +179,13 @@ def test_build_sdist(monkeypatch, tmpdir):
183179
(sdist,) = tmpdir.visit("*.tar.gz")
184180

185181
with tarfile.open(str(sdist), "r:gz") as tar:
186-
start = tar.getnames()[0] + "/"
187-
version = start[9:-1]
188182
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
189183

190184
pyproject_toml = read_tz_file(tar, "pyproject.toml")
191185

192186
files = headers | sdist_files
193187
assert files <= simpler
194188

195-
simple_version = ".".join(version.split(".")[:3])
196189
assert b'name = "pybind11"' in pyproject_toml
197190

198191

@@ -207,8 +200,6 @@ def test_build_global_dist(monkeypatch, tmpdir):
207200
(sdist,) = tmpdir.visit("*.tar.gz")
208201

209202
with tarfile.open(str(sdist), "r:gz") as tar:
210-
start = tar.getnames()[0] + "/"
211-
version = start[16:-1]
212203
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
213204

214205
pyproject_toml = read_tz_file(tar, "pyproject.toml")
@@ -249,11 +240,8 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
249240
monkeypatch.chdir(MAIN_DIR)
250241
with build_global():
251242
subprocess.run(
252-
[sys.executable, "-m", "pip", "wheel", ".",
253-
"-Cskbuild.wheel.install-dir=/data",
254-
"-Cskbuild.experimental=true",
255-
"-w",
256-
str(tmpdir)], check=True
243+
[sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)],
244+
check=True,
257245
)
258246

259247
(wheel,) = tmpdir.visit("*.whl")
@@ -272,7 +260,6 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
272260
names = z.namelist()
273261

274262
beginning = names[0].split("/", 1)[0].rsplit(".", 1)[0]
275-
pprint(names)
276263
trimmed = {n[len(beginning) + 1 :] for n in names}
277264

278265
assert files == trimmed

tests/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pytest-timeout
1111
scipy~=1.5.4; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version<"3.10"
1212
scipy~=1.8.0; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version=="3.10" and sys_platform!='win32'
1313
scipy~=1.11.1; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32'
14+
tomlkit

tools/make_global.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env -S uv run -q
2+
3+
# /// script
4+
# dependencies = ["tomlkit"]
5+
# ///
6+
from __future__ import annotations
7+
8+
from pathlib import Path
9+
10+
import tomlkit
11+
12+
DIR = Path(__file__).parent.resolve()
13+
PYPROJECT = DIR.parent / "pyproject.toml"
14+
15+
16+
def get_global() -> str:
17+
pyproject = tomlkit.parse(PYPROJECT.read_text())
18+
del pyproject["tool"]["scikit-build"]["generate"]
19+
del pyproject["project"]["optional-dependencies"]
20+
del pyproject["project"]["entry-points"]
21+
del pyproject["project"]["scripts"]
22+
pyproject["project"]["name"] = "pybind11-global"
23+
pyproject["tool"]["scikit-build"]["experimental"] = True
24+
pyproject["tool"]["scikit-build"]["wheel"]["install-dir"] = "/data"
25+
pyproject["tool"]["scikit-build"]["wheel"]["packages"] = []
26+
27+
result = tomlkit.dumps(pyproject)
28+
assert isinstance(result, str)
29+
return result
30+
31+
32+
if __name__ == "__main__":
33+
print(get_global())

0 commit comments

Comments
 (0)