Merge branch 'master' into smart_holder

This commit is contained in:
Ralf W. Grosse-Kunstleve 2021-07-15 15:05:40 -07:00
commit 1f04229733
7 changed files with 70 additions and 31 deletions

View File

@ -18,20 +18,6 @@
This is the pybind11 **smart_holder** branch. Please refer to This is the pybind11 **smart_holder** branch. Please refer to
``README_smart_holder.rst`` for branch-specific information. ``README_smart_holder.rst`` for branch-specific information.
.. warning::
Combining older versions of pybind11 (< 2.6.0) with Python 3.9.0 will
trigger undefined behavior that typically manifests as crashes during
interpreter shutdown (but could also destroy your data. **You have been
warned.**)
We recommend that you update to the latest patch release of Python (3.9.1),
which includes a `fix <https://github.com/python/cpython/pull/22670>`_
that resolves this problem. If you do use Python 3.9.0, please update to
the latest version of pybind11 (2.6.0 or newer), which includes a temporary
workaround specifically when Python 3.9.0 is detected at runtime.
**pybind11** is a lightweight header-only library that exposes C++ types **pybind11** is a lightweight header-only library that exposes C++ types
in Python and vice versa, mainly to create Python bindings of existing in Python and vice versa, mainly to create Python bindings of existing
C++ code. Its goals and syntax are similar to the excellent C++ code. Its goals and syntax are similar to the excellent
@ -115,7 +101,7 @@ goodies:
transparently applied to all entries of one or more NumPy array transparently applied to all entries of one or more NumPy array
arguments. arguments.
- Pythons slice-based access and assignment operations can be - Python's slice-based access and assignment operations can be
supported with just a few lines of code. supported with just a few lines of code.
- Everything is contained in just a few header files; there is no need - Everything is contained in just a few header files; there is no need

View File

@ -57,16 +57,16 @@ clean, well written patch would likely be accepted to solve them.
Python 3.9.0 warning Python 3.9.0 warning
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
Combining older versions of pybind11 (< 2.6.0) with Python on 3.9.0 will Combining older versions of pybind11 (< 2.6.0) with Python on exactly 3.9.0
trigger undefined behavior that typically manifests as crashes during will trigger undefined behavior that typically manifests as crashes during
interpreter shutdown (but could also destroy your data. **You have been interpreter shutdown (but could also destroy your data. **You have been
warned**). warned**).
This issue has been This issue was `fixed in Python <https://github.com/python/cpython/pull/22670>`_.
`fixed in Python <https://github.com/python/cpython/pull/22670>`_. As a As a mitigation for this bug, pybind11 2.6.0 or newer includes a workaround
mitigation until 3.9.1 is released and commonly used, pybind11 (2.6.0 or newer) specifically when Python 3.9.0 is detected at runtime, leaking about 50 bytes
includes a temporary workaround specifically when Python 3.9.0 is detected at of memory when a callback function is garbage collected. For reference, the
runtime, leaking about 50 bytes of memory when a callback function is garbage pybind11 test suite has about 2,000 such callbacks, but only 49 are garbage
collected. For reference; the pybind11 test suite has about 2,000 such collected before the end-of-process. Wheels (even if built with Python 3.9.0)
callbacks, but only 49 are garbage collected before the end-of-process. Wheels will correctly avoid the leak when run in Python 3.9.1, and this does not
built with Python 3.9.0 will correctly avoid the leak when run in Python 3.9.1. affect other 3.X versions.

View File

@ -1,4 +1,7 @@
breathe==4.26.1 breathe==4.26.1
# docutils 0.17 breaks HTML tags & RTD theme
# https://github.com/sphinx-doc/sphinx/issues/9001
docutils==0.16
sphinx==3.3.1 sphinx==3.3.1
sphinx_rtd_theme==0.5.0 sphinx_rtd_theme==0.5.0
sphinxcontrib-moderncmakedomain==3.17 sphinxcontrib-moderncmakedomain==3.17

View File

@ -13,6 +13,10 @@
#define PYBIND11_VERSION_MINOR 6 #define PYBIND11_VERSION_MINOR 6
#define PYBIND11_VERSION_PATCH 3.dev1 #define PYBIND11_VERSION_PATCH 3.dev1
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
// Additional convention: 0xD = dev
#define PYBIND11_VERSION_HEX 0x020603D1
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name { #define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
#define PYBIND11_NAMESPACE_END(name) } #define PYBIND11_NAMESPACE_END(name) }

View File

@ -53,14 +53,18 @@ def docs(session: nox.Session) -> None:
session.install("-r", "docs/requirements.txt") session.install("-r", "docs/requirements.txt")
session.chdir("docs") session.chdir("docs")
if "pdf" in session.posargs:
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
return
session.run("sphinx-build", "-M", "html", ".", "_build") session.run("sphinx-build", "-M", "html", ".", "_build")
if session.posargs:
if "serve" in session.posargs: if "serve" in session.posargs:
print("Launching docs at http://localhost:8000/ - use Ctrl-C to quit") session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")
session.run("python", "-m", "http.server", "8000", "-d", "_build/html") session.run("python", "-m", "http.server", "8000", "-d", "_build/html")
else: elif session.posargs:
print("Unsupported argument to docs") session.error("Unsupported argument to docs")
@nox.session(reuse_venv=True) @nox.session(reuse_venv=True)

View File

@ -19,6 +19,36 @@ VERSION_REGEX = re.compile(
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
) )
def build_expected_version_hex(matches):
patch_level_serial = matches["PATCH"]
serial = None
try:
major = int(matches["MAJOR"])
minor = int(matches["MINOR"])
flds = patch_level_serial.split(".")
if flds:
patch = int(flds[0])
level = None
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
except ValueError:
pass
if serial is None:
msg = 'Invalid PYBIND11_VERSION_PATCH: "{}"'.format(patch_level_serial)
raise RuntimeError(msg)
return "0x{:02x}{:02x}{:02x}{}{:x}".format(
major, minor, patch, level[:1].upper(), serial
)
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers # PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
# files, and the sys.prefix files (CMake and headers). # files, and the sys.prefix files (CMake and headers).
@ -49,6 +79,15 @@ if version != cpp_version:
) )
raise RuntimeError(msg) raise RuntimeError(msg)
version_hex = matches.get("HEX", "MISSING")
expected_version_hex = build_expected_version_hex(matches)
if version_hex != expected_version_hex:
msg = "PYBIND11_VERSION_HEX {} does not match expected value {}!".format(
version_hex,
expected_version_hex,
)
raise RuntimeError(msg)
def get_and_replace(filename, binary=False, **opts): def get_and_replace(filename, binary=False, **opts):
with open(filename, "rb" if binary else "r") as f: with open(filename, "rb" if binary else "r") as f:

View File

@ -32,6 +32,9 @@ setup(
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"pybind11-config = pybind11.__main__:main", "pybind11-config = pybind11.__main__:main",
],
"pipx.run": [
"pybind11 = pybind11.__main__:main",
] ]
}, },
cmdclass=cmdclass cmdclass=cmdclass