Skip to content

Commit 67561bc

Browse files
committed
Merge branch 'master' into smart_holder
2 parents 59ef530 + da104a9 commit 67561bc

File tree

16 files changed

+171
-38
lines changed

16 files changed

+171
-38
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ jobs:
325325
# Testing NVCC; forces sources to behave like .cu files
326326
cuda:
327327
runs-on: ubuntu-latest
328-
name: "🐍 3.8 • CUDA 11.2 • Ubuntu 20.04"
329-
container: nvidia/cuda:11.2.2-devel-ubuntu20.04
328+
name: "🐍 3.10 • CUDA 11.7 • Ubuntu 22.04"
329+
container: nvidia/cuda:11.7.0-devel-ubuntu22.04
330330

331331
steps:
332332
- uses: actions/checkout@v3
@@ -738,6 +738,9 @@ jobs:
738738
args: -DCMAKE_CXX_STANDARD=20
739739
- python: 3.8
740740
args: -DCMAKE_CXX_STANDARD=17
741+
- python: 3.7
742+
args: -DCMAKE_CXX_STANDARD=14
743+
741744

742745
name: "🐍 ${{ matrix.python }} • MSVC 2019 • x86 ${{ matrix.args }}"
743746
runs-on: windows-2019

.pre-commit-config.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
#
1313
# See https://github.com/pre-commit/pre-commit
1414

15+
16+
ci:
17+
autoupdate_commit_msg: "chore(deps): update pre-commit hooks"
18+
autofix_commit_msg: "style: pre-commit fixes"
19+
autoupdate_schedule: monthly
20+
1521
# third-party content
1622
exclude: ^tools/JoinPaths.cmake$
1723

@@ -36,7 +42,7 @@ repos:
3642

3743
# Upgrade old Python syntax
3844
- repo: https://github.com/asottile/pyupgrade
39-
rev: "v2.37.3"
45+
rev: "v2.38.2"
4046
hooks:
4147
- id: pyupgrade
4248
args: [--py36-plus]
@@ -113,7 +119,7 @@ repos:
113119

114120
# PyLint has native support - not always usable, but works for us
115121
- repo: https://github.com/PyCQA/pylint
116-
rev: "v2.15.2"
122+
rev: "v2.15.3"
117123
hooks:
118124
- id: pylint
119125
files: ^pybind11
@@ -129,7 +135,7 @@ repos:
129135

130136
# Check static types with mypy
131137
- repo: https://github.com/pre-commit/mirrors-mypy
132-
rev: "v0.971"
138+
rev: "v0.981"
133139
hooks:
134140
- id: mypy
135141
args: []

include/pybind11/cast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@ class unpacking_collector {
15861586
throw cast_error_unable_to_convert_call_arg(a.name, a.type);
15871587
#endif
15881588
}
1589-
m_kwargs[a.name] = a.value;
1589+
m_kwargs[a.name] = std::move(a.value);
15901590
}
15911591

15921592
void process(list & /*args_list*/, detail::kwargs_proxy kp) {

include/pybind11/detail/common.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,12 +1045,7 @@ PYBIND11_NAMESPACE_END(detail)
10451045
/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func)
10461046
/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func)
10471047
template <typename... Args>
1048-
# if (defined(_MSC_VER) && _MSC_VER < 1920) /* MSVC 2017 */ \
1049-
|| (defined(__clang__) && __clang_major__ == 5)
1050-
static constexpr detail::overload_cast_impl<Args...> overload_cast = {};
1051-
# else
1052-
static constexpr detail::overload_cast_impl<Args...> overload_cast;
1053-
# endif
1048+
static constexpr detail::overload_cast_impl<Args...> overload_cast{};
10541049
#endif
10551050

10561051
/// Const member function selector for overload_cast

include/pybind11/detail/internals.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ PYBIND11_NOINLINE internals &get_internals() {
423423
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
424424
struct gil_scoped_acquire_local {
425425
gil_scoped_acquire_local() : state(PyGILState_Ensure()) {}
426+
gil_scoped_acquire_local(const gil_scoped_acquire_local &) = delete;
427+
gil_scoped_acquire_local &operator=(const gil_scoped_acquire_local &) = delete;
426428
~gil_scoped_acquire_local() { PyGILState_Release(state); }
427429
const PyGILState_STATE state;
428430
} gil;
@@ -523,8 +525,13 @@ struct local_internals {
523525

524526
/// Works like `get_internals`, but for things which are locally registered.
525527
inline local_internals &get_local_internals() {
526-
static local_internals locals;
527-
return locals;
528+
// Current static can be created in the interpreter finalization routine. If the later will be
529+
// destroyed in another static variable destructor, creation of this static there will cause
530+
// static deinitialization fiasco. In order to avoid it we avoid destruction of the
531+
// local_internals static. One can read more about the problem and current solution here:
532+
// https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
533+
static auto *locals = new local_internals();
534+
return *locals;
528535
}
529536

530537
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its

include/pybind11/gil.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ class gil_scoped_acquire {
8080
inc_ref();
8181
}
8282

83+
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
84+
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
85+
8386
void inc_ref() { ++tstate->gilstate_counter; }
8487

8588
PYBIND11_NOINLINE void dec_ref() {
@@ -144,6 +147,9 @@ class gil_scoped_release {
144147
}
145148
}
146149

150+
gil_scoped_release(const gil_scoped_acquire &) = delete;
151+
gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
152+
147153
/// This method will disable the PyThreadState_DeleteCurrent call and the
148154
/// GIL won't be acquired. This method should be used if the interpreter
149155
/// could be shutting down when this is called, as thread deletion is not
@@ -178,6 +184,8 @@ class gil_scoped_acquire {
178184

179185
public:
180186
gil_scoped_acquire() { state = PyGILState_Ensure(); }
187+
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
188+
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
181189
~gil_scoped_acquire() { PyGILState_Release(state); }
182190
void disarm() {}
183191
};
@@ -187,6 +195,8 @@ class gil_scoped_release {
187195

188196
public:
189197
gil_scoped_release() { state = PyEval_SaveThread(); }
198+
gil_scoped_release(const gil_scoped_release &) = delete;
199+
gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
190200
~gil_scoped_release() { PyEval_RestoreThread(state); }
191201
void disarm() {}
192202
};

include/pybind11/operators.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct op_impl {};
8484
/// Operator implementation generator
8585
template <op_id id, op_type ot, typename L, typename R>
8686
struct op_ {
87+
static constexpr bool op_enable_if_hook = true;
8788
template <typename Class, typename... Extra>
8889
void execute(Class &cl, const Extra &...extra) const {
8990
using Base = typename Class::type;

include/pybind11/pybind11.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,14 +1808,14 @@ class class_ : public detail::generic_type {
18081808
return *this;
18091809
}
18101810

1811-
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
1812-
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
1811+
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
1812+
class_ &def(const T &op, const Extra &...extra) {
18131813
op.execute(*this, extra...);
18141814
return *this;
18151815
}
18161816

1817-
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
1818-
class_ &def_cast(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
1817+
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
1818+
class_ &def_cast(const T &op, const Extra &...extra) {
18191819
op.execute_cast(*this, extra...);
18201820
return *this;
18211821
}

include/pybind11/pytypes.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,18 +1829,18 @@ class capsule : public object {
18291829
// guard if destructor called while err indicator is set
18301830
error_scope error_guard;
18311831
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
1832-
if (destructor == nullptr) {
1833-
if (PyErr_Occurred()) {
1834-
throw error_already_set();
1835-
}
1836-
pybind11_fail("Unable to get capsule context");
1832+
if (PyErr_Occurred()) {
1833+
throw error_already_set();
18371834
}
18381835
const char *name = get_name_in_error_scope(o);
18391836
void *ptr = PyCapsule_GetPointer(o, name);
18401837
if (ptr == nullptr) {
18411838
throw error_already_set();
18421839
}
1843-
destructor(ptr);
1840+
1841+
if (destructor != nullptr) {
1842+
destructor(ptr);
1843+
}
18441844
});
18451845

18461846
if (!m_ptr || PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
@@ -2022,14 +2022,20 @@ class list : public object {
20222022
detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; }
20232023
template <typename T>
20242024
void append(T &&val) /* py-non-const */ {
2025-
PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr());
2025+
if (PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()) != 0) {
2026+
throw error_already_set();
2027+
}
20262028
}
20272029
template <typename IdxType,
20282030
typename ValType,
20292031
detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0>
20302032
void insert(const IdxType &index, ValType &&val) /* py-non-const */ {
2031-
PyList_Insert(
2032-
m_ptr, ssize_t_cast(index), detail::object_or_cast(std::forward<ValType>(val)).ptr());
2033+
if (PyList_Insert(m_ptr,
2034+
ssize_t_cast(index),
2035+
detail::object_or_cast(std::forward<ValType>(val)).ptr())
2036+
!= 0) {
2037+
throw error_already_set();
2038+
}
20332039
}
20342040
};
20352041

include/pybind11/stl.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,31 @@ constexpr forwarded_type<T, U> forward_like(U &&u) {
4949
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
5050
}
5151

52+
// Checks if a container has a STL style reserve method.
53+
// This will only return true for a `reserve()` with a `void` return.
54+
template <typename C>
55+
using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
56+
5257
template <typename Type, typename Key>
5358
struct set_caster {
5459
using type = Type;
5560
using key_conv = make_caster<Key>;
5661

62+
private:
63+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
64+
void reserve_maybe(const anyset &s, Type *) {
65+
value.reserve(s.size());
66+
}
67+
void reserve_maybe(const anyset &, void *) {}
68+
69+
public:
5770
bool load(handle src, bool convert) {
5871
if (!isinstance<anyset>(src)) {
5972
return false;
6073
}
6174
auto s = reinterpret_borrow<anyset>(src);
6275
value.clear();
76+
reserve_maybe(s, &value);
6377
for (auto entry : s) {
6478
key_conv conv;
6579
if (!conv.load(entry, convert)) {
@@ -94,12 +108,21 @@ struct map_caster {
94108
using key_conv = make_caster<Key>;
95109
using value_conv = make_caster<Value>;
96110

111+
private:
112+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
113+
void reserve_maybe(const dict &d, Type *) {
114+
value.reserve(d.size());
115+
}
116+
void reserve_maybe(const dict &, void *) {}
117+
118+
public:
97119
bool load(handle src, bool convert) {
98120
if (!isinstance<dict>(src)) {
99121
return false;
100122
}
101123
auto d = reinterpret_borrow<dict>(src);
102124
value.clear();
125+
reserve_maybe(d, &value);
103126
for (auto it : d) {
104127
key_conv kconv;
105128
value_conv vconv;
@@ -160,9 +183,7 @@ struct list_caster {
160183
}
161184

162185
private:
163-
template <
164-
typename T = Type,
165-
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
186+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
166187
void reserve_maybe(const sequence &s, Type *) {
167188
value.reserve(s.size());
168189
}

0 commit comments

Comments
 (0)