aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/pybind11/setup.py
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/pybind11/setup.py')
-rw-r--r--3rdparty/pybind11/setup.py121
1 files changed, 78 insertions, 43 deletions
diff --git a/3rdparty/pybind11/setup.py b/3rdparty/pybind11/setup.py
index 3a032798..68573519 100644
--- a/3rdparty/pybind11/setup.py
+++ b/3rdparty/pybind11/setup.py
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python3
# Setup script for PyPI; use CMakeFile.txt to build extension modules
@@ -10,87 +9,110 @@ import shutil
import string
import subprocess
import sys
-import tempfile
+from pathlib import Path
+from tempfile import TemporaryDirectory
+from typing import Dict, Iterator, List, Union
import setuptools.command.sdist
-DIR = os.path.abspath(os.path.dirname(__file__))
+DIR = Path(__file__).parent.absolute()
VERSION_REGEX = re.compile(
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
)
+VERSION_FILE = Path("pybind11/_version.py")
+COMMON_FILE = Path("include/pybind11/detail/common.h")
+
+
+def build_expected_version_hex(matches: Dict[str, str]) -> str:
+ patch_level_serial = matches["PATCH"]
+ serial = None
+ major = int(matches["MAJOR"])
+ minor = int(matches["MINOR"])
+ flds = patch_level_serial.split(".")
+ if flds:
+ patch = int(flds[0])
+ if len(flds) == 1:
+ level = "0"
+ serial = 0
+ elif len(flds) == 2:
+ level_serial = flds[1]
+ for level in ("a", "b", "c", "dev"):
+ if level_serial.startswith(level):
+ serial = int(level_serial[len(level) :])
+ break
+ if serial is None:
+ msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
+ raise RuntimeError(msg)
+ version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
+ return f"0x{version_hex_str.upper()}"
+
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
# files, and the sys.prefix files (CMake and headers).
global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST", False)
-setup_py = "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
+setup_py = Path(
+ "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
+)
extra_cmd = 'cmdclass["sdist"] = SDist\n'
to_src = (
- ("pyproject.toml", "tools/pyproject.toml"),
- ("setup.py", setup_py),
+ (Path("pyproject.toml"), Path("tools/pyproject.toml")),
+ (Path("setup.py"), setup_py),
)
+
# Read the listed version
-with open("pybind11/_version.py") as f:
- code = compile(f.read(), "pybind11/_version.py", "exec")
-loc = {}
+loc: Dict[str, str] = {}
+code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
exec(code, loc)
version = loc["__version__"]
# Verify that the version matches the one in C++
-with open("include/pybind11/detail/common.h") as f:
- matches = dict(VERSION_REGEX.findall(f.read()))
+matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
if version != cpp_version:
- msg = "Python version {} does not match C++ version {}!".format(
- version, cpp_version
- )
+ msg = f"Python version {version} does not match C++ version {cpp_version}!"
+ raise RuntimeError(msg)
+
+version_hex = matches.get("HEX", "MISSING")
+exp_version_hex = build_expected_version_hex(matches)
+if version_hex != exp_version_hex:
+ msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
raise RuntimeError(msg)
-def get_and_replace(filename, binary=False, **opts):
- with open(filename, "rb" if binary else "r") as f:
- contents = f.read()
- # Replacement has to be done on text in Python 3 (both work in Python 2)
+# TODO: use literals & overload (typing extensions or Python 3.8)
+def get_and_replace(
+ filename: Path, binary: bool = False, **opts: str
+) -> Union[bytes, str]:
if binary:
+ contents = filename.read_bytes()
return string.Template(contents.decode()).substitute(opts).encode()
- else:
- return string.Template(contents).substitute(opts)
+
+ return string.Template(filename.read_text()).substitute(opts)
# Use our input files instead when making the SDist (and anything that depends
# on it, like a wheel)
-class SDist(setuptools.command.sdist.sdist):
- def make_release_tree(self, base_dir, files):
- setuptools.command.sdist.sdist.make_release_tree(self, base_dir, files)
+class SDist(setuptools.command.sdist.sdist): # type: ignore[misc]
+ def make_release_tree(self, base_dir: str, files: List[str]) -> None:
+ super().make_release_tree(base_dir, files)
for to, src in to_src:
txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
- dest = os.path.join(base_dir, to)
+ dest = Path(base_dir) / to
# This is normally linked, so unlink before writing!
- os.unlink(dest)
- with open(dest, "wb") as f:
- f.write(txt)
-
-
-# Backport from Python 3
-@contextlib.contextmanager
-def TemporaryDirectory(): # noqa: N802
- "Prepare a temporary directory, cleanup when done"
- try:
- tmpdir = tempfile.mkdtemp()
- yield tmpdir
- finally:
- shutil.rmtree(tmpdir)
+ dest.unlink()
+ dest.write_bytes(txt) # type: ignore[arg-type]
# Remove the CMake install directory when done
@contextlib.contextmanager
-def remove_output(*sources):
+def remove_output(*sources: str) -> Iterator[None]:
try:
yield
finally:
@@ -105,10 +127,23 @@ with remove_output("pybind11/include", "pybind11/share"):
"-DCMAKE_INSTALL_PREFIX=pybind11",
"-DBUILD_TESTING=OFF",
"-DPYBIND11_NOPYTHON=ON",
+ "-Dprefix_for_pc_file=${pcfiledir}/../../",
]
- cmake_opts = dict(cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
- subprocess.check_call(cmd, **cmake_opts)
- subprocess.check_call(["cmake", "--install", tmpdir], **cmake_opts)
+ if "CMAKE_ARGS" in os.environ:
+ fcommand = [
+ c
+ for c in os.environ["CMAKE_ARGS"].split()
+ if "DCMAKE_INSTALL_PREFIX" not in c
+ ]
+ cmd += fcommand
+ subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
+ subprocess.run(
+ ["cmake", "--install", tmpdir],
+ check=True,
+ cwd=DIR,
+ stdout=sys.stdout,
+ stderr=sys.stderr,
+ )
txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
code = compile(txt, setup_py, "exec")