diff --git a/README.rst b/README.rst index 1ad52700c..a05278400 100644 --- a/README.rst +++ b/README.rst @@ -18,20 +18,6 @@ This is the pybind11 **smart_holder** branch. Please refer to ``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 `_ - 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 in Python and vice versa, mainly to create Python bindings of existing 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 arguments. -- Python’s 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. - Everything is contained in just a few header files; there is no need diff --git a/docs/limitations.rst b/docs/limitations.rst index be7300cdb..def5ad659 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -57,16 +57,16 @@ clean, well written patch would likely be accepted to solve them. Python 3.9.0 warning ^^^^^^^^^^^^^^^^^^^^ -Combining older versions of pybind11 (< 2.6.0) with Python on 3.9.0 will -trigger undefined behavior that typically manifests as crashes during +Combining older versions of pybind11 (< 2.6.0) with Python on exactly 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**). -This issue has been -`fixed in Python `_. As a -mitigation until 3.9.1 is released and commonly used, pybind11 (2.6.0 or newer) -includes a temporary workaround specifically when Python 3.9.0 is detected at -runtime, leaking about 50 bytes of memory when a callback function is garbage -collected. For reference; the pybind11 test suite has about 2,000 such -callbacks, but only 49 are garbage collected before the end-of-process. Wheels -built with Python 3.9.0 will correctly avoid the leak when run in Python 3.9.1. +This issue was `fixed in Python `_. +As a mitigation for this bug, pybind11 2.6.0 or newer includes a workaround +specifically when Python 3.9.0 is detected at runtime, leaking about 50 bytes +of memory when a callback function is garbage collected. For reference, the +pybind11 test suite has about 2,000 such callbacks, but only 49 are garbage +collected before the end-of-process. Wheels (even if built with Python 3.9.0) +will correctly avoid the leak when run in Python 3.9.1, and this does not +affect other 3.X versions. diff --git a/docs/requirements.txt b/docs/requirements.txt index 671dc4b3f..8f293b5d3 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,7 @@ 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_rtd_theme==0.5.0 sphinxcontrib-moderncmakedomain==3.17 diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index f804e7c85..f036269af 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -13,6 +13,10 @@ #define PYBIND11_VERSION_MINOR 6 #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_END(name) } diff --git a/noxfile.py b/noxfile.py index 3bc61273f..f0f668015 100644 --- a/noxfile.py +++ b/noxfile.py @@ -53,14 +53,18 @@ def docs(session: nox.Session) -> None: session.install("-r", "docs/requirements.txt") session.chdir("docs") + + if "pdf" in session.posargs: + session.run("sphinx-build", "-M", "latexpdf", ".", "_build") + return + session.run("sphinx-build", "-M", "html", ".", "_build") - if session.posargs: - if "serve" in session.posargs: - print("Launching docs at http://localhost:8000/ - use Ctrl-C to quit") - session.run("python", "-m", "http.server", "8000", "-d", "_build/html") - else: - print("Unsupported argument to docs") + if "serve" in session.posargs: + session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit") + session.run("python", "-m", "http.server", "8000", "-d", "_build/html") + elif session.posargs: + session.error("Unsupported argument to docs") @nox.session(reuse_venv=True) diff --git a/setup.py b/setup.py index 3a0327982..ced3d6958 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,36 @@ VERSION_REGEX = re.compile( 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 # files, and the sys.prefix files (CMake and headers). @@ -49,6 +79,15 @@ if version != cpp_version: ) 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): with open(filename, "rb" if binary else "r") as f: diff --git a/tools/setup_main.py.in b/tools/setup_main.py.in index bcd4ef4ae..533a75ae7 100644 --- a/tools/setup_main.py.in +++ b/tools/setup_main.py.in @@ -32,6 +32,9 @@ setup( entry_points={ "console_scripts": [ "pybind11-config = pybind11.__main__:main", + ], + "pipx.run": [ + "pybind11 = pybind11.__main__:main", ] }, cmdclass=cmdclass