Skip to content

Commit 098e77b

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

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
@@ -9,7 +9,6 @@
99
import argparse
1010
import contextlib
1111
import os
12-
import re
1312
from pathlib import Path
1413
from typing import TYPE_CHECKING
1514

@@ -21,10 +20,6 @@
2120
nox.needs_version = ">=2025.2.9"
2221
nox.options.default_venv_backend = "uv|virtualenv"
2322

24-
MARKER_PATTERN = re.compile(
25-
r"# not-in-global-start.*?# not-in-global-end\n?", re.DOTALL
26-
)
27-
2823

2924
@nox.session(reuse_venv=True)
3025
def lint(session: nox.Session) -> None:
@@ -137,22 +132,17 @@ def build_global(session: nox.Session) -> None:
137132
"""
138133

139134
installer = ["--installer=uv"] if session.venv_backend == "uv" else []
140-
session.install("build")
135+
session.install("build", "tomlkit")
141136
session.log("Building pybind11-global files")
142137
pyproject = Path("pyproject.toml")
143-
with preserve_file(pyproject) as txt:
144-
new_txt = txt.replace('name = "pybind11"', 'name = "pybind11-global"')
145-
assert txt != new_txt
146-
newer_txt = MARKER_PATTERN.sub("", new_txt)
147-
assert new_txt != newer_txt
148-
138+
with preserve_file(pyproject):
139+
newer_txt = session.run("python", "tools/make_global.py", silent=True)
140+
assert isinstance(newer_txt, str)
149141
pyproject.write_text(newer_txt, encoding="utf-8")
150142
session.run(
151143
"python",
152144
"-m",
153145
"build",
154146
*installer,
155-
"-Cskbuild.wheel.install-dir=/data",
156-
"-Cskbuild.experimental=true",
157147
*session.posargs,
158148
)

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
@@ -14,3 +14,4 @@ scipy~=1.5.4; platform_python_implementation=="CPython" and python_version<"3.10
1414
scipy~=1.8.0; platform_python_implementation=="CPython" and python_version=="3.10" and sys_platform!="win32"
1515
scipy~=1.11.1; platform_python_implementation=="CPython" and python_version>="3.11" and python_version<"3.13" and sys_platform!="win32"
1616
scipy~=1.15.2; platform_python_implementation=="CPython" and python_version=="3.13" and sys_platform!="win32"
17+
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)