12from pathlib
import Path
13from tempfile
import TemporaryDirectory
14from typing
import Dict, Iterator, List, Union
18DIR = Path(__file__).parent.absolute()
19VERSION_REGEX = re.compile(
20 r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
22VERSION_FILE = Path(
"pybind11/_version.py")
23COMMON_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()}"
53global_sdist = os.environ.get(
"PYBIND11_GLOBAL_SDIST",
False)
56 "tools/setup_global.py.in" if global_sdist
else "tools/setup_main.py.in"
58extra_cmd =
'cmdclass["sdist"] = SDist\n'
61 (Path(
"pyproject.toml"), Path(
"tools/pyproject.toml")),
62 (Path(
"setup.py"), setup_py),
67loc: Dict[str, str] = {}
68code = compile(VERSION_FILE.read_text(encoding=
"utf-8"),
"pybind11/_version.py",
"exec")
70version = loc[
"__version__"]
73matches =
dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding=
"utf8")))
74cpp_version =
"{MAJOR}.{MINOR}.{PATCH}".format(**matches)
75if version != cpp_version:
76 msg = f
"Python version {version} does not match C++ version {cpp_version}!"
77 raise RuntimeError(msg)
79version_hex = matches.get(
"HEX",
"MISSING")
81if 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)
99class 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",
130 "-Dprefix_for_pc_file=${pcfiledir}/../../",
132 if "CMAKE_ARGS" in os.environ:
135 for c
in os.environ[
"CMAKE_ARGS"].split()
136 if "DCMAKE_INSTALL_PREFIX" not in c
139 subprocess.run(cmd, check=
True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
141 [
"cmake",
"--install", tmpdir],
149 code = compile(txt, setup_py,
"exec")
150 exec(code, {
"SDist": SDist})
def make_release_tree(self, base_dir, files)
size_t len(handle h)
Get the length of a Python object.
def remove_output(*sources)
def get_and_replace(filename, binary=False, **opts)
def build_expected_version_hex(matches)
void exec(const str &expr, object global=globals(), object local=object())