wrap/pybind11/setup.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Setup script for PyPI; use CMakeFile.txt to build extension modules
4 from __future__ import annotations
5 
6 import contextlib
7 import os
8 import re
9 import shutil
10 import string
11 import subprocess
12 import sys
13 from collections.abc import Generator
14 from pathlib import Path
15 from tempfile import TemporaryDirectory
16 
17 import setuptools.command.sdist
18 
19 DIR = Path(__file__).parent.absolute()
20 VERSION_REGEX = re.compile(
21  r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
22 )
23 VERSION_FILE = Path("pybind11/_version.py")
24 COMMON_FILE = Path("include/pybind11/detail/common.h")
25 
26 
27 def build_expected_version_hex(matches: dict[str, str]) -> str:
28  patch_level_serial = matches["PATCH"]
29  serial = None
30  major = int(matches["MAJOR"])
31  minor = int(matches["MINOR"])
32  flds = patch_level_serial.split(".")
33  if flds:
34  patch = int(flds[0])
35  if len(flds) == 1:
36  level = "0"
37  serial = 0
38  elif len(flds) == 2:
39  level_serial = flds[1]
40  for level in ("a", "b", "c", "dev"):
41  if level_serial.startswith(level):
42  serial = int(level_serial[len(level) :])
43  break
44  if serial is None:
45  msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
46  raise RuntimeError(msg)
47  version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
48  return f"0x{version_hex_str.upper()}"
49 
50 
51 # PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
52 # files, and the sys.prefix files (CMake and headers).
53 
54 global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST", False)
55 
56 setup_py = Path(
57  "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
58 )
59 extra_cmd = 'cmdclass["sdist"] = SDist\n'
60 
61 to_src = (
62  (Path("pyproject.toml"), Path("tools/pyproject.toml")),
63  (Path("setup.py"), setup_py),
64 )
65 
66 
67 # Read the listed version
68 loc: dict[str, str] = {}
69 code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
70 exec(code, loc)
71 version = loc["__version__"]
72 
73 # Verify that the version matches the one in C++
74 matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
75 cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
76 if version != cpp_version:
77  msg = f"Python version {version} does not match C++ version {cpp_version}!"
78  raise RuntimeError(msg)
79 
80 version_hex = matches.get("HEX", "MISSING")
81 exp_version_hex = build_expected_version_hex(matches)
82 if version_hex != exp_version_hex:
83  msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
84  raise RuntimeError(msg)
85 
86 
87 # TODO: use literals & overload (typing extensions or Python 3.8)
88 def get_and_replace(filename: Path, binary: bool = False, **opts: str) -> bytes | str:
89  if binary:
90  contents = filename.read_bytes()
91  return string.Template(contents.decode()).substitute(opts).encode()
92 
93  return string.Template(filename.read_text()).substitute(opts)
94 
95 
96 # Use our input files instead when making the SDist (and anything that depends
97 # on it, like a wheel)
98 class SDist(setuptools.command.sdist.sdist):
99  def make_release_tree(self, base_dir: str, files: list[str]) -> None:
100  super().make_release_tree(base_dir, files)
101 
102  for to, src in to_src:
103  txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
104 
105  dest = Path(base_dir) / to
106 
107  # This is normally linked, so unlink before writing!
108  dest.unlink()
109  dest.write_bytes(txt) # type: ignore[arg-type]
110 
111 
112 # Remove the CMake install directory when done
113 @contextlib.contextmanager
114 def remove_output(*sources: str) -> Generator[None, None, None]:
115  try:
116  yield
117  finally:
118  for src in sources:
119  shutil.rmtree(src)
120 
121 
122 with remove_output("pybind11/include", "pybind11/share"):
123  # Generate the files if they are not present.
124  with TemporaryDirectory() as tmpdir:
125  cmd = ["cmake", "-S", ".", "-B", tmpdir] + [
126  "-DCMAKE_INSTALL_PREFIX=pybind11",
127  "-DBUILD_TESTING=OFF",
128  "-DPYBIND11_NOPYTHON=ON",
129  "-Dprefix_for_pc_file=${pcfiledir}/../../",
130  ]
131  if "CMAKE_ARGS" in os.environ:
132  fcommand = [
133  c
134  for c in os.environ["CMAKE_ARGS"].split()
135  if "DCMAKE_INSTALL_PREFIX" not in c
136  ]
137  cmd += fcommand
138  subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
139  subprocess.run(
140  ["cmake", "--install", tmpdir],
141  check=True,
142  cwd=DIR,
143  stdout=sys.stdout,
144  stderr=sys.stderr,
145  )
146 
147  txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
148  code = compile(txt, setup_py, "exec")
149  exec(code, {"SDist": SDist})
gtsam.examples.DogLegOptimizerExample.int
int
Definition: DogLegOptimizerExample.py:111
encode
int encode(Index i, Index j)
Definition: indexed_view.cpp:45
setup.SDist.make_release_tree
None make_release_tree(self, str base_dir, list[str] files)
Definition: wrap/pybind11/setup.py:99
format
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
Definition: openglsupport.cpp:226
dict
Definition: pytypes.h:2107
setup.SDist
Definition: wrap/pybind11/setup.py:98
exec
void exec(const str &expr, object global=globals(), object local=object())
Definition: eval.h:88
setup.build_expected_version_hex
str build_expected_version_hex(dict[str, str] matches)
Definition: wrap/pybind11/setup.py:27
gtsam::split
void split(const G &g, const PredecessorMap< KEY > &tree, G &Ab1, G &Ab2)
Definition: graph-inl.h:245
setup.remove_output
Generator[None, None, None] remove_output(*str sources)
Definition: wrap/pybind11/setup.py:114
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2446
setup.get_and_replace
bytes|str get_and_replace(Path filename, bool binary=False, **str opts)
Definition: wrap/pybind11/setup.py:88


gtsam
Author(s):
autogenerated on Fri Nov 1 2024 03:35:15