12 from pathlib
import Path
13 from tempfile
import TemporaryDirectory
14 from typing
import Dict, Iterator, List, Union
16 import setuptools.command.sdist
18 DIR = Path(__file__).parent.absolute()
19 VERSION_REGEX = re.compile(
20 r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
22 VERSION_FILE = Path(
"pybind11/_version.py")
23 COMMON_FILE = Path(
"include/pybind11/detail/common.h")
27 patch_level_serial = matches[
"PATCH"]
29 major =
int(matches[
"MAJOR"])
30 minor =
int(matches[
"MINOR"])
31 flds = patch_level_serial.split(
".")
38 level_serial = flds[1]
39 for level
in (
"a",
"b",
"c",
"dev"):
40 if level_serial.startswith(level):
41 serial =
int(level_serial[
len(level) :])
44 msg = f
'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"' 45 raise RuntimeError(msg)
46 version_hex_str = f
"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}" 47 return f
"0x{version_hex_str.upper()}" 53 global_sdist = os.environ.get(
"PYBIND11_GLOBAL_SDIST",
False)
56 "tools/setup_global.py.in" if global_sdist
else "tools/setup_main.py.in" 58 extra_cmd =
'cmdclass["sdist"] = SDist\n' 61 (Path(
"pyproject.toml"), Path(
"tools/pyproject.toml")),
62 (Path(
"setup.py"), setup_py),
67 loc: Dict[str, str] = {}
68 code = compile(VERSION_FILE.read_text(encoding=
"utf-8"),
"pybind11/_version.py",
"exec")
70 version = loc[
"__version__"]
73 matches =
dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding=
"utf8")))
74 cpp_version =
"{MAJOR}.{MINOR}.{PATCH}".
format(**matches)
75 if version != cpp_version:
76 msg = f
"Python version {version} does not match C++ version {cpp_version}!" 77 raise RuntimeError(msg)
79 version_hex = matches.get(
"HEX",
"MISSING")
81 if version_hex != exp_version_hex:
82 msg = f
"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!" 83 raise RuntimeError(msg)
88 filename: Path, binary: bool =
False, **opts: str
89 ) -> Union[bytes, str]:
91 contents = filename.read_bytes()
92 return string.Template(contents.decode()).substitute(opts).
encode()
94 return string.Template(filename.read_text()).substitute(opts)
99 class SDist(setuptools.command.sdist.sdist):
103 for to, src
in to_src:
106 dest = Path(base_dir) / to
110 dest.write_bytes(txt)
114 @contextlib.contextmanager
125 with TemporaryDirectory()
as tmpdir:
126 cmd = [
"cmake",
"-S",
".",
"-B", tmpdir] + [
127 "-DCMAKE_INSTALL_PREFIX=pybind11",
128 "-DBUILD_TESTING=OFF",
129 "-DPYBIND11_NOPYTHON=ON",
131 if "CMAKE_ARGS" in os.environ:
134 for c
in os.environ[
"CMAKE_ARGS"].
split()
135 if "DCMAKE_INSTALL_PREFIX" not in c
138 subprocess.run(cmd, check=
True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
140 [
"cmake",
"--install", tmpdir],
148 code = compile(txt, setup_py,
"exec")
149 exec(code, {
"SDist": SDist})
void exec(const str &expr, object global=globals(), object local=object())
void split(const G &g, const PredecessorMap< KEY > &tree, G &Ab1, G &Ab2)
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
def build_expected_version_hex
int encode(Index i, Index j)
size_t len(handle h)
Get the length of a Python object.