Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2.13] Bump to 2.13.6 #5373

Merged
merged 8 commits into from
Sep 13, 2024
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ jobs:
- uses: actions/checkout@v4

- name: Setup Python ${{ matrix.python-version }} (deadsnakes)
uses: deadsnakes/action@v3.1.0
uses: deadsnakes/action@v3.2.0
with:
python-version: ${{ matrix.python-version }}
debug: ${{ matrix.python-debug }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
- uses: actions/download-artifact@v4

- name: Generate artifact attestation for sdist and wheel
uses: actions/attest-build-provenance@310b0a4a3b0b78ef57ecda988ee04b132db73ef8 # v1.4.1
uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
with:
subject-path: "*/pybind11*"

Expand Down
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ repos:

# Ruff, the Python auto-correcting linter/formatter written in Rust
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.6
rev: v0.6.3
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]
- id: ruff-format

# Check static types with mypy
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.11.1"
rev: "v1.11.2"
hooks:
- id: mypy
args: []
Expand Down Expand Up @@ -93,7 +93,7 @@ repos:

# Avoid directional quotes
- repo: https://github.com/sirosen/texthooks
rev: "0.6.6"
rev: "0.6.7"
hooks:
- id: fix-ligatures
- id: fix-smartquotes
Expand Down Expand Up @@ -142,14 +142,14 @@ repos:

# PyLint has native support - not always usable, but works for us
- repo: https://github.com/PyCQA/pylint
rev: "v3.2.6"
rev: "v3.2.7"
hooks:
- id: pylint
files: ^pybind11

# Check schemas on some of our YAML files
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.29.1
rev: 0.29.2
hooks:
- id: check-readthedocs
- id: check-github-workflows
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,14 @@ endif()
set(PYBIND11_HEADERS
include/pybind11/detail/class.h
include/pybind11/detail/common.h
include/pybind11/detail/cpp_conduit.h
include/pybind11/detail/descr.h
include/pybind11/detail/init.h
include/pybind11/detail/internals.h
include/pybind11/detail/type_caster_base.h
include/pybind11/detail/typeid.h
include/pybind11/detail/value_and_holder.h
include/pybind11/detail/exception_translation.h
include/pybind11/attr.h
include/pybind11/buffer_info.h
include/pybind11/cast.h
Expand Down
55 changes: 55 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ New Features:
* The ``array_caster`` in pybind11/stl.h was enhanced to support value types that are not default-constructible.
`#5305 <https://github.com/pybind/pybind11/pull/5305>`_

* Added ``py::warnings`` namespace with ``py::warnings::warn`` and ``py::warnings::new_warning_type`` that provides the interface for Python warnings.
`#5291 <https://github.com/pybind/pybind11/pull/5291>`_

Version 2.13.6 (September 13, 2024)
-----------------------------------

New Features:

* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
``py::class_``-wrapped types, to enable type-safe interoperability between
different independent Python/C++ bindings systems, including pybind11
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
pybind11 2.11.2, 2.12.1, and 2.13.6+.
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_


Bug fixes:

* Using ``__cpp_nontype_template_args`` instead of ``__cpp_nontype_template_parameter_class``.
`#5330 <https://github.com/pybind/pybind11/pull/5330>`_

* Properly translate C++ exception to Python exception when creating Python buffer from wrapped object.
`#5324 <https://github.com/pybind/pybind11/pull/5324>`_


Documentation:

* Adds an answer (FAQ) for "What is a highly conclusive and simple way to find memory leaks?".
`#5340 <https://github.com/pybind/pybind11/pull/5340>`_


Version 2.13.5 (August 22, 2024)
--------------------------------

Expand Down Expand Up @@ -238,6 +269,18 @@ Other:
* Update docs and noxfile.
`#5071 <https://github.com/pybind/pybind11/pull/5071>`_

Version 2.12.1 (September 13, 2024)
-----------------------------------

New Features:

* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
``py::class_``-wrapped types, to enable type-safe interoperability between
different independent Python/C++ bindings systems, including pybind11
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
pybind11 2.11.2, 2.12.1, and 2.13.6+.
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_


Version 2.12.0 (March 27, 2024)
-------------------------------
Expand Down Expand Up @@ -413,6 +456,18 @@ Other:
* An ``assert()`` was added to help Coverty avoid generating a false positive.
`#4817 <https://github.com/pybind/pybind11/pull/4817>`_

Version 2.11.2 (September 13, 2024)
-----------------------------------

New Features:

* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
``py::class_``-wrapped types, to enable type-safe interoperability between
different independent Python/C++ bindings systems, including pybind11
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
pybind11 2.11.2, 2.12.1, and 2.13.6+.
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_


Version 2.11.1 (July 17, 2023)
------------------------------
Expand Down
44 changes: 44 additions & 0 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,50 @@ been received, you must either explicitly interrupt execution by throwing
});
}

What is a highly conclusive and simple way to find memory leaks (e.g. in pybind11 bindings)?
============================================================================================

Use ``while True`` & ``top`` (Linux, macOS).

For example, locally change tests/test_type_caster_pyobject_ptr.py like this:

.. code-block:: diff

def test_return_list_pyobject_ptr_reference():
+ while True:
vec_obj = m.return_list_pyobject_ptr_reference(ValueHolder)
assert [e.value for e in vec_obj] == [93, 186]
# Commenting out the next `assert` will leak the Python references.
# An easy way to see evidence of the leaks:
# Insert `while True:` as the first line of this function and monitor the
# process RES (Resident Memory Size) with the Unix top command.
- assert m.dec_ref_each_pyobject_ptr(vec_obj) == 2
+ # assert m.dec_ref_each_pyobject_ptr(vec_obj) == 2

Then run the test as you would normally do, which will go into the infinite loop.

**In another shell, but on the same machine** run:

.. code-block:: bash

top

This will show:

.. code-block::

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1266095 rwgk 20 0 5207496 611372 45696 R 100.0 0.3 0:08.01 test_type_caste

Look for the number under ``RES`` there. You'll see it going up very quickly.

**Don't forget to Ctrl-C the test command** before your machine becomes
unresponsive due to swapping.

This method only takes a couple minutes of effort and is very conclusive.
What you want to see is that the ``RES`` number is stable after a couple
seconds.

CMake doesn't detect the right Python version
=============================================

Expand Down
15 changes: 14 additions & 1 deletion include/pybind11/detail/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <pybind11/attr.h>
#include <pybind11/options.h>

#include "exception_translation.h"

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail)

Expand Down Expand Up @@ -591,7 +593,18 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
return -1;
}
std::memset(view, 0, sizeof(Py_buffer));
buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
buffer_info *info = nullptr;
try {
info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
} catch (...) {
try_translate_exceptions();
raise_from(PyExc_BufferError, "Error getting buffer");
return -1;
}
if (info == nullptr) {
pybind11_fail("FATAL UNEXPECTED SITUATION: tinfo->get_buffer() returned nullptr.");
}

if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
delete info;
// view->obj = nullptr; // Was just memset to 0, so not necessary
Expand Down
77 changes: 77 additions & 0 deletions include/pybind11/detail/cpp_conduit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2024 The pybind Community.

#pragma once

#include <pybind11/pytypes.h>

#include "common.h"
#include "internals.h"

#include <typeinfo>

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail)

// Forward declaration needed here: Refactoring opportunity.
extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *);

inline bool type_is_managed_by_our_internals(PyTypeObject *type_obj) {
#if defined(PYPY_VERSION)
auto &internals = get_internals();
return bool(internals.registered_types_py.find(type_obj)
!= internals.registered_types_py.end());
#else
return bool(type_obj->tp_new == pybind11_object_new);
#endif
}

inline bool is_instance_method_of_type(PyTypeObject *type_obj, PyObject *attr_name) {
PyObject *descr = _PyType_Lookup(type_obj, attr_name);
return bool((descr != nullptr) && PyInstanceMethod_Check(descr));
}

inline object try_get_cpp_conduit_method(PyObject *obj) {
if (PyType_Check(obj)) {
return object();
}
PyTypeObject *type_obj = Py_TYPE(obj);
str attr_name("_pybind11_conduit_v1_");
bool assumed_to_be_callable = false;
if (type_is_managed_by_our_internals(type_obj)) {
if (!is_instance_method_of_type(type_obj, attr_name.ptr())) {
return object();
}
assumed_to_be_callable = true;
}
PyObject *method = PyObject_GetAttr(obj, attr_name.ptr());
if (method == nullptr) {
PyErr_Clear();
return object();
}
if (!assumed_to_be_callable && PyCallable_Check(method) == 0) {
Py_DECREF(method);
return object();
}
return reinterpret_steal<object>(method);
}

inline void *try_raw_pointer_ephemeral_from_cpp_conduit(handle src,
const std::type_info *cpp_type_info) {
object method = try_get_cpp_conduit_method(src.ptr());
if (method) {
capsule cpp_type_info_capsule(const_cast<void *>(static_cast<const void *>(cpp_type_info)),
typeid(std::type_info).name());
object cpp_conduit = method(bytes(PYBIND11_PLATFORM_ABI_ID),
cpp_type_info_capsule,
bytes("raw_pointer_ephemeral"));
if (isinstance<capsule>(cpp_conduit)) {
return reinterpret_borrow<capsule>(cpp_conduit).get_pointer();
}
}
return nullptr;
}

#define PYBIND11_HAS_CPP_CONDUIT 1

PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
71 changes: 71 additions & 0 deletions include/pybind11/detail/exception_translation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
pybind11/detail/exception_translation.h: means to translate C++ exceptions to Python exceptions

Copyright (c) 2024 The Pybind Development Team.

All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/

#pragma once

#include "common.h"
#include "internals.h"

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail)

// Apply all the extensions translators from a list
// Return true if one of the translators completed without raising an exception
// itself. Return of false indicates that if there are other translators
// available, they should be tried.
inline bool apply_exception_translators(std::forward_list<ExceptionTranslator> &translators) {
auto last_exception = std::current_exception();

for (auto &translator : translators) {
try {
translator(last_exception);
return true;
} catch (...) {
last_exception = std::current_exception();
}
}
return false;
}

inline void try_translate_exceptions() {
/* When an exception is caught, give each registered exception
translator a chance to translate it to a Python exception. First
all module-local translators will be tried in reverse order of
registration. If none of the module-locale translators handle
the exception (or there are no module-locale translators) then
the global translators will be tried, also in reverse order of
registration.

A translator may choose to do one of the following:

- catch the exception and call py::set_error()
to set a standard (or custom) Python exception, or
- do nothing and let the exception fall through to the next translator, or
- delegate translation to the next translator by throwing a new type of exception.
*/

bool handled = with_internals([&](internals &internals) {
auto &local_exception_translators = get_local_internals().registered_exception_translators;
if (detail::apply_exception_translators(local_exception_translators)) {
return true;
}
auto &exception_translators = internals.registered_exception_translators;
if (detail::apply_exception_translators(exception_translators)) {
return true;
}
return false;
});

if (!handled) {
set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
}
}

PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
Loading
Loading