mirror of
https://github.com/pybind/pybind11.git
synced 2025-02-16 13:47:53 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
commit
44d158ca50
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
@ -235,8 +235,8 @@ directory inside your pybind11 git clone. Files will be modified in place,
|
||||
so you can use git to monitor the changes.
|
||||
|
||||
```bash
|
||||
docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:13
|
||||
apt-get update && apt-get install -y python3-dev python3-pytest
|
||||
docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:15-bullseye
|
||||
apt-get update && apt-get install -y git python3-dev python3-pytest
|
||||
cmake -S /mounted_pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color" -DDOWNLOAD_EIGEN=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=17
|
||||
cmake --build build -j 2
|
||||
```
|
||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -284,8 +284,6 @@ jobs:
|
||||
include:
|
||||
- clang: 5
|
||||
std: 14
|
||||
- clang: 10
|
||||
std: 20
|
||||
- clang: 10
|
||||
std: 17
|
||||
- clang: 11
|
||||
|
4
.github/workflows/format.yml
vendored
4
.github/workflows/format.yml
vendored
@ -39,12 +39,12 @@ jobs:
|
||||
# in .github/CONTRIBUTING.md and update as needed.
|
||||
name: Clang-Tidy
|
||||
runs-on: ubuntu-latest
|
||||
container: silkeh/clang:13
|
||||
container: silkeh/clang:15-bullseye
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install requirements
|
||||
run: apt-get update && apt-get install -y python3-dev python3-pytest
|
||||
run: apt-get update && apt-get install -y git python3-dev python3-pytest
|
||||
|
||||
- name: Configure
|
||||
run: >
|
||||
|
@ -42,20 +42,20 @@ repos:
|
||||
|
||||
# Upgrade old Python syntax
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: "v3.3.0"
|
||||
rev: "v3.3.1"
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
|
||||
# Nicely sort includes
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: "5.10.1"
|
||||
rev: "5.11.4"
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
# Black, the code formatter, natively supports pre-commit
|
||||
- repo: https://github.com/psf/black
|
||||
rev: "22.10.0" # Keep in sync with blacken-docs
|
||||
rev: "22.12.0" # Keep in sync with blacken-docs
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
@ -119,7 +119,7 @@ repos:
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v2.15.8"
|
||||
rev: "v2.15.9"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
@ -163,7 +163,7 @@ repos:
|
||||
|
||||
# Check for common shell mistakes
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: "v0.8.0.4"
|
||||
rev: "v0.9.0.2"
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
@ -178,7 +178,7 @@ repos:
|
||||
|
||||
# Clang format the codebase automatically
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: "v15.0.4"
|
||||
rev: "v15.0.6"
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c, cuda]
|
||||
|
@ -118,6 +118,34 @@ The ``call_go`` wrapper can also be simplified using the ``call_guard`` policy
|
||||
m.def("call_go", &call_go, py::call_guard<py::gil_scoped_release>());
|
||||
|
||||
|
||||
Common Sources Of Global Interpreter Lock Errors
|
||||
==================================================================
|
||||
|
||||
Failing to properly hold the Global Interpreter Lock (GIL) is one of the
|
||||
more common sources of bugs within code that uses pybind11. If you are
|
||||
running into GIL related errors, we highly recommend you consult the
|
||||
following checklist.
|
||||
|
||||
- Do you have any global variables that are pybind11 objects or invoke
|
||||
pybind11 functions in either their constructor or destructor? You are generally
|
||||
not allowed to invoke any Python function in a global static context. We recommend
|
||||
using lazy initialization and then intentionally leaking at the end of the program.
|
||||
|
||||
- Do you have any pybind11 objects that are members of other C++ structures? One
|
||||
commonly overlooked requirement is that pybind11 objects have to increase their reference count
|
||||
whenever their copy constructor is called. Thus, you need to be holding the GIL to invoke
|
||||
the copy constructor of any C++ class that has a pybind11 member. This can sometimes be very
|
||||
tricky to track for complicated programs Think carefully when you make a pybind11 object
|
||||
a member in another struct.
|
||||
|
||||
- C++ destructors that invoke Python functions can be particularly troublesome as
|
||||
destructors can sometimes get invoked in weird and unexpected circumstances as a result
|
||||
of exceptions.
|
||||
|
||||
- You should try running your code in a debug build. That will enable additional assertions
|
||||
within pybind11 that will throw exceptions on certain GIL handling errors
|
||||
(reference counting operations).
|
||||
|
||||
Binding sequence data types, iterators, the slicing protocol, etc.
|
||||
==================================================================
|
||||
|
||||
|
@ -15,6 +15,39 @@ IN DEVELOPMENT
|
||||
|
||||
Changes will be summarized here periodically.
|
||||
|
||||
Changes:
|
||||
|
||||
* ``PyGILState_Check()``'s in ``pybind11::handle``'s ``inc_ref()`` &
|
||||
``dec_ref()`` are now enabled by default again.
|
||||
`#4246 <https://github.com/pybind/pybind11/pull/4246>`_
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Update clang-tidy to 15 in CI.
|
||||
`#4387 <https://github.com/pybind/pybind11/pull/4387>`_
|
||||
|
||||
|
||||
Version 2.10.3 (Jan 3, 2023)
|
||||
----------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
* Temporarily made our GIL status assertions (added in 2.10.2) disabled by
|
||||
default (re-enable manually by defining
|
||||
``PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF``, will be enabled in 2.11).
|
||||
`#4432 <https://github.com/pybind/pybind11/pull/4432>`_
|
||||
|
||||
* Improved error messages when ``inc_ref``/``dec_ref`` are called with an
|
||||
invalid GIL state.
|
||||
`#4427 <https://github.com/pybind/pybind11/pull/4427>`_
|
||||
`#4436 <https://github.com/pybind/pybind11/pull/4436>`_
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
* Some minor touchups found by static analyzers.
|
||||
`#4440 <https://github.com/pybind/pybind11/pull/4440>`_
|
||||
|
||||
|
||||
Version 2.10.2 (Dec 20, 2022)
|
||||
-----------------------------
|
||||
|
||||
@ -30,7 +63,7 @@ Changes:
|
||||
* ``PyGILState_Check()``'s were integrated to ``pybind11::handle``
|
||||
``inc_ref()`` & ``dec_ref()``. The added GIL checks are guarded by
|
||||
``PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF``, which is the default only if
|
||||
``NDEBUG`` is not defined.
|
||||
``NDEBUG`` is not defined. (Made non-default in 2.10.3, will be active in 2.11)
|
||||
`#4246 <https://github.com/pybind/pybind11/pull/4246>`_
|
||||
|
||||
* Add option for enable/disable enum members in docstring.
|
||||
|
@ -399,7 +399,7 @@ struct process_attribute<doc> : process_attribute_default<doc> {
|
||||
template <>
|
||||
struct process_attribute<const char *> : process_attribute_default<const char *> {
|
||||
static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); }
|
||||
static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); }
|
||||
static void init(const char *d, type_record *r) { r->doc = d; }
|
||||
};
|
||||
template <>
|
||||
struct process_attribute<char *> : process_attribute<const char *> {};
|
||||
|
@ -10,12 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#define PYBIND11_VERSION_MAJOR 2
|
||||
#define PYBIND11_VERSION_MINOR 10
|
||||
#define PYBIND11_VERSION_PATCH 2
|
||||
#define PYBIND11_VERSION_MINOR 11
|
||||
#define PYBIND11_VERSION_PATCH 0.dev1
|
||||
|
||||
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
|
||||
// Additional convention: 0xD = dev
|
||||
#define PYBIND11_VERSION_HEX 0x020A0200
|
||||
#define PYBIND11_VERSION_HEX 0x020B00D1
|
||||
|
||||
// Define some generic pybind11 helper macros for warning management.
|
||||
//
|
||||
@ -436,7 +436,7 @@ PYBIND11_WARNING_POP
|
||||
|
||||
/** \rst
|
||||
This macro creates the entry point that will be invoked when the Python interpreter
|
||||
imports an extension module. The module name is given as the fist argument and it
|
||||
imports an extension module. The module name is given as the first argument and it
|
||||
should not be in quotes. The second macro argument defines a variable of type
|
||||
`py::module_` which can be used to initialize the module.
|
||||
|
||||
|
@ -480,12 +480,14 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
#if defined(WITH_THREAD)
|
||||
|
||||
PyThreadState *tstate = PyThreadState_Get();
|
||||
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) {
|
||||
pybind11_fail("get_internals: could not successfully initialize the tstate TSS key!");
|
||||
}
|
||||
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate);
|
||||
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) {
|
||||
pybind11_fail("get_internals: could not successfully initialize the "
|
||||
"loader_life_support TSS key!");
|
||||
@ -525,6 +527,7 @@ struct local_internals {
|
||||
struct shared_loader_life_support_data {
|
||||
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||
shared_loader_life_support_data() {
|
||||
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||
if (!PYBIND11_TLS_KEY_CREATE(loader_life_support_tls_key)) {
|
||||
pybind11_fail("local_internals: could not successfully initialize the "
|
||||
"loader_life_support TLS key!");
|
||||
|
@ -176,7 +176,7 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!convert && !temp.dtype().is(dtype::of<typename Type::Scalar>())) {
|
||||
if (!temp.dtype().is(dtype::of<typename Type::Scalar>())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -250,9 +250,9 @@ public:
|
||||
#ifdef PYBIND11_HANDLE_REF_DEBUG
|
||||
inc_ref_counter(1);
|
||||
#endif
|
||||
#if defined(PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF)
|
||||
#ifdef PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF
|
||||
if (m_ptr != nullptr && !PyGILState_Check()) {
|
||||
throw std::runtime_error("pybind11::handle::inc_ref() PyGILState_Check() failure.");
|
||||
throw_gilstate_error("pybind11::handle::inc_ref()");
|
||||
}
|
||||
#endif
|
||||
Py_XINCREF(m_ptr);
|
||||
@ -265,9 +265,9 @@ public:
|
||||
this function automatically. Returns a reference to itself.
|
||||
\endrst */
|
||||
const handle &dec_ref() const & {
|
||||
#if defined(PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF)
|
||||
#ifdef PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF
|
||||
if (m_ptr != nullptr && !PyGILState_Check()) {
|
||||
throw std::runtime_error("pybind11::handle::dec_ref() PyGILState_Check() failure.");
|
||||
throw_gilstate_error("pybind11::handle::dec_ref()");
|
||||
}
|
||||
#endif
|
||||
Py_XDECREF(m_ptr);
|
||||
@ -296,8 +296,28 @@ public:
|
||||
protected:
|
||||
PyObject *m_ptr = nullptr;
|
||||
|
||||
#ifdef PYBIND11_HANDLE_REF_DEBUG
|
||||
private:
|
||||
#ifdef PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF
|
||||
void throw_gilstate_error(const std::string &function_name) const {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s is being called while the GIL is either not held or invalid. Please see "
|
||||
"https://pybind11.readthedocs.io/en/stable/advanced/"
|
||||
"misc.html#common-sources-of-global-interpreter-lock-errors for debugging advice.\n",
|
||||
function_name.c_str());
|
||||
fflush(stderr);
|
||||
if (Py_TYPE(m_ptr)->tp_name != nullptr) {
|
||||
fprintf(stderr,
|
||||
"The failing %s call was triggered on a %s object.\n",
|
||||
function_name.c_str(),
|
||||
Py_TYPE(m_ptr)->tp_name);
|
||||
fflush(stderr);
|
||||
}
|
||||
throw std::runtime_error(function_name + " PyGILState_Check() failure.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PYBIND11_HANDLE_REF_DEBUG
|
||||
static std::size_t inc_ref_counter(std::size_t add) {
|
||||
thread_local std::size_t counter = 0;
|
||||
counter += add;
|
||||
@ -443,7 +463,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
// Equivalent to obj.__class__.__name__ (or obj.__name__ if obj is a class).
|
||||
inline const char *obj_class_name(PyObject *obj) {
|
||||
if (Py_TYPE(obj) == &PyType_Type) {
|
||||
if (PyType_Check(obj)) {
|
||||
return reinterpret_cast<PyTypeObject *>(obj)->tp_name;
|
||||
}
|
||||
return Py_TYPE(obj)->tp_name;
|
||||
@ -481,7 +501,7 @@ struct error_fetch_and_normalize {
|
||||
"active exception.");
|
||||
}
|
||||
const char *exc_type_name_norm = detail::obj_class_name(m_type.ptr());
|
||||
if (exc_type_name_orig == nullptr) {
|
||||
if (exc_type_name_norm == nullptr) {
|
||||
pybind11_fail("Internal error: " + std::string(called)
|
||||
+ " failed to obtain the name "
|
||||
"of the normalized active exception type.");
|
||||
|
@ -316,6 +316,7 @@ struct optional_caster {
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
||||
return value_conv::cast(*std::forward<T>(src), policy, parent);
|
||||
}
|
||||
|
||||
|
@ -355,13 +355,17 @@ void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl)
|
||||
using DiffType = typename Vector::difference_type;
|
||||
using ItType = typename Vector::iterator;
|
||||
cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
|
||||
if (i < 0 && (i += v.size()) < 0) {
|
||||
if (i < 0) {
|
||||
i += v.size();
|
||||
if (i < 0) {
|
||||
throw index_error();
|
||||
}
|
||||
}
|
||||
auto i_st = static_cast<SizeType>(i);
|
||||
if (i_st >= v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
if ((SizeType) i >= v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
return v[(SizeType) i];
|
||||
return v[i_st];
|
||||
});
|
||||
|
||||
cl.def(
|
||||
|
@ -8,5 +8,5 @@ def _to_int(s: str) -> Union[int, str]:
|
||||
return s
|
||||
|
||||
|
||||
__version__ = "2.10.2"
|
||||
__version__ = "2.11.0.dev1"
|
||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||
|
@ -74,6 +74,8 @@ PYBIND11_TYPE_CASTER_BASE_HOLDER(MismatchDerived2, std::shared_ptr<MismatchDeriv
|
||||
PYBIND11_TYPE_CASTER_BASE_HOLDER(SamePointer, std::unique_ptr<SamePointer>)
|
||||
|
||||
TEST_SUBMODULE(class_, m) {
|
||||
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
|
||||
|
||||
// test_instance
|
||||
struct NoConstructor {
|
||||
NoConstructor() = default;
|
||||
|
@ -1,10 +1,19 @@
|
||||
import pytest
|
||||
|
||||
import env # noqa: F401
|
||||
import env
|
||||
from pybind11_tests import ConstructorStats, UserType
|
||||
from pybind11_tests import class_ as m
|
||||
|
||||
|
||||
def test_obj_class_name():
|
||||
if env.PYPY:
|
||||
expected_name = "UserType"
|
||||
else:
|
||||
expected_name = "pybind11_tests.UserType"
|
||||
assert m.obj_class_name(UserType(1)) == expected_name
|
||||
assert m.obj_class_name(UserType) == expected_name
|
||||
|
||||
|
||||
def test_repr():
|
||||
assert "pybind11_type" in repr(type(UserType))
|
||||
assert "UserType" in repr(UserType)
|
||||
|
@ -99,6 +99,8 @@ void m_defs(py::module_ &m) {
|
||||
} // namespace handle_from_move_only_type_with_operator_PyObject
|
||||
|
||||
TEST_SUBMODULE(pytypes, m) {
|
||||
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
|
||||
|
||||
handle_from_move_only_type_with_operator_PyObject::m_defs(m);
|
||||
|
||||
// test_bool
|
||||
|
@ -9,6 +9,12 @@ from pybind11_tests import detailed_error_messages_enabled
|
||||
from pybind11_tests import pytypes as m
|
||||
|
||||
|
||||
def test_obj_class_name():
|
||||
assert m.obj_class_name(None) == "NoneType"
|
||||
assert m.obj_class_name(list) == "list"
|
||||
assert m.obj_class_name([]) == "list"
|
||||
|
||||
|
||||
def test_handle_from_move_only_type_with_operator_PyObject(): # noqa: N802
|
||||
assert m.handle_from_move_only_type_with_operator_PyObject_ncnst()
|
||||
assert m.handle_from_move_only_type_with_operator_PyObject_const()
|
||||
|
@ -31,8 +31,10 @@ issues = (issue for page in issues_pages for issue in page)
|
||||
missing = []
|
||||
|
||||
for issue in issues:
|
||||
changelog = ENTRY.findall(issue.body)
|
||||
if changelog:
|
||||
changelog = ENTRY.findall(issue.body or "")
|
||||
if not changelog or not changelog[0]:
|
||||
missing.append(issue)
|
||||
else:
|
||||
(msg,) = changelog
|
||||
if not msg.startswith("* "):
|
||||
msg = "* " + msg
|
||||
@ -44,9 +46,6 @@ for issue in issues:
|
||||
print(Syntax(msg, "rst", theme="ansi_light", word_wrap=True))
|
||||
print()
|
||||
|
||||
else:
|
||||
missing.append(issue)
|
||||
|
||||
if missing:
|
||||
print()
|
||||
print("[blue]" + "-" * 30)
|
||||
|
Loading…
Reference in New Issue
Block a user