Skip to content

Commit eaeca55

Browse files
Move out all version-dependent functions.
1 parent 5f2af62 commit eaeca55

File tree

7 files changed

+74
-42
lines changed

7 files changed

+74
-42
lines changed

include/pybind11/detail/class.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -180,28 +180,12 @@ std::string error_string();
180180

181181
/// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`.
182182
extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
183-
#if PY_VERSION_HEX >= 0x030D0000
184-
PyObject_VisitManagedDict(self, visit, arg);
185-
#else
186-
PyObject *&dict = *non_limited_api::_PyObject_GetDictPtr(self);
187-
Py_VISIT(dict);
188-
#endif
189-
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
190-
#if PY_VERSION_HEX >= 0x03090000
191-
Py_VISIT(Py_TYPE(self));
192-
#endif
193-
return 0;
183+
return non_limited_api::pybind11_traverse(self, visit, arg);
194184
}
195185

196186
/// dynamic_attr: Allow the GC to clear the dictionary.
197187
extern "C" inline int pybind11_clear(PyObject *self) {
198-
#if PY_VERSION_HEX >= 0x030D0000
199-
PyObject_ClearManagedDict(self);
200-
#else
201-
PyObject *&dict = *non_limited_api::_PyObject_GetDictPtr(self);
202-
Py_CLEAR(dict);
203-
#endif
204-
return 0;
188+
return non_limited_api::pybind11_clear(self);
205189
}
206190

207191
/** Create a brand new Python type according to the `type_record` specification.

include/pybind11/detail/internals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
/// further ABI-incompatible changes may be made before the ABI is officially
3838
/// changed to the new version.
3939
#ifndef PYBIND11_INTERNALS_VERSION
40-
# if PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
40+
// Hardcoding a same default value for compatibility with all python versions
41+
# if 1 // PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
4142
// Version bump for Python 3.12+, before first 3.12 beta release.
4243
// Version bump for MSVC piggy-backed on PR #4779. See comments there.
4344
# ifdef Py_GIL_DISABLED

include/pybind11/detail/non_limited_api.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class handle;
4242
class memoryview;
4343
struct buffer_info;
4444
struct InitializingFunctionRecordDeleter;
45+
class dict;
4546

4647
PYBIND11_NAMESPACE_BEGIN(detail)
4748
class generic_type;
@@ -183,6 +184,10 @@ PYBIND11_NONLIMITEDAPI_FUNC(bool, PyObjectIsInstanceWithOneOfTpNames, (PyObject
183184
PYBIND11_NONLIMITEDAPI_FUNC(int, PyGen_Check_, (PyObject *obj), (obj))
184185
PYBIND11_NONLIMITEDAPI_FUNC(PyInterpreterState *, PyInterpreterState_Get, (), ())
185186
PYBIND11_NONLIMITEDAPI_FUNC(PyObject *, PyInterpreterState_GetDict, (PyInterpreterState *state), (state))
187+
PYBIND11_NONLIMITEDAPI_FUNC(int, pybind11_traverse, (PyObject *self, visitproc visit, void *arg), (self, visit, arg))
188+
PYBIND11_NONLIMITEDAPI_FUNC(int, pybind11_clear, (PyObject *self), (self))
189+
PYBIND11_NONLIMITEDAPI_FUNC(void, globals, (dict &out), (out))
190+
PYBIND11_NONLIMITEDAPI_FUNC(PyObject *, dict_getitemstringref, (PyObject *v, const char *key), (v, key))
186191

187192
PYBIND11_NAMESPACE_END(non_limited_api)
188193
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

include/pybind11/embed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ inline void precheck_interpreter() {
9696
# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
9797
#endif
9898

99+
// NOTE: Not patching out this use of `PY_VERSION_HEX` because we don't support versions <3.8, and I belive Pybind itself also doesn't anymore.
99100
#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
100101
inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
101102
int argc,
@@ -127,6 +128,7 @@ inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
127128

128129
PYBIND11_NAMESPACE_END(detail)
129130

131+
// NOTE: Not patching out this use of `PY_VERSION_HEX` because we don't support versions <3.8, and I belive Pybind itself also doesn't anymore.
130132
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
131133
inline void initialize_interpreter(PyConfig *config,
132134
int argc = 0,
@@ -245,6 +247,7 @@ class scoped_interpreter {
245247
initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
246248
}
247249

250+
// NOTE: Not patching out this use of `PY_VERSION_HEX` because we don't support versions <3.8, and I belive Pybind itself also doesn't anymore.
248251
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
249252
explicit scoped_interpreter(PyConfig *config,
250253
int argc = 0,

include/pybind11/pybind11.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,14 +1065,9 @@ using module = module_;
10651065
/// Return a dictionary representing the global variables in the current execution frame,
10661066
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).
10671067
inline dict globals() {
1068-
#if PY_VERSION_HEX >= 0x030d0000
1069-
PyObject *p = PyEval_GetFrameGlobals();
1070-
return p ? reinterpret_steal<dict>(p)
1071-
: reinterpret_borrow<dict>(module_::import("__main__").attr("__dict__").ptr());
1072-
#else
1073-
PyObject *p = PyEval_GetGlobals();
1074-
return reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
1075-
#endif
1068+
dict ret;
1069+
non_limited_api::globals(ret);
1070+
return ret;
10761071
}
10771072

10781073
template <typename... Args, typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>>

include/pybind11/pytypes.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,8 @@ struct error_fetch_and_normalize {
511511
"of the original active exception type.");
512512
}
513513
m_lazy_error_string = exc_type_name_orig;
514-
#if PY_VERSION_HEX >= 0x030C0000
514+
// NOTE: Patching out this entirely for compatibility with all python versions.
515+
#if 0 && PY_VERSION_HEX >= 0x030C0000
515516
// The presence of __notes__ is likely due to exception normalization
516517
// errors, although that is not necessarily true, therefore insert a
517518
// hint only:
@@ -844,20 +845,7 @@ inline PyObject *dict_getitem(PyObject *v, PyObject *key) {
844845
}
845846

846847
inline PyObject *dict_getitemstringref(PyObject *v, const char *key) {
847-
#if PY_VERSION_HEX >= 0x030D0000
848-
PyObject *rv;
849-
if (PyDict_GetItemStringRef(v, key, &rv) < 0) {
850-
throw error_already_set();
851-
}
852-
return rv;
853-
#else
854-
PyObject *rv = dict_getitemstring(v, key);
855-
if (rv == nullptr && PyErr_Occurred()) {
856-
throw error_already_set();
857-
}
858-
Py_XINCREF(rv);
859-
return rv;
860-
#endif
848+
return non_limited_api::dict_getitemstringref(v, key);
861849
}
862850

863851
// Helper aliases/functions to support implicit casting of values given to python

source/non_limited_api/non_limited_api.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,3 +1849,59 @@ PyInterpreterState *pybind11::non_limited_api::pybind11NLA_PyInterpreterState_Ge
18491849
return ::PyInterpreterState_Get();
18501850
#endif
18511851
}
1852+
1853+
int pybind11::non_limited_api::pybind11NLA_pybind11_traverse(PyObject *self, visitproc visit, void *arg)
1854+
{
1855+
#if PY_VERSION_HEX >= 0x030D0000
1856+
PyObject_VisitManagedDict(self, visit, arg);
1857+
#else
1858+
PyObject *&dict = *non_limited_api::_PyObject_GetDictPtr(self);
1859+
Py_VISIT(dict);
1860+
#endif
1861+
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
1862+
#if PY_VERSION_HEX >= 0x03090000
1863+
Py_VISIT(Py_TYPE(self));
1864+
#endif
1865+
return 0;
1866+
}
1867+
1868+
int pybind11::non_limited_api::pybind11NLA_pybind11_clear(PyObject *self)
1869+
{
1870+
#if PY_VERSION_HEX >= 0x030D0000
1871+
PyObject_ClearManagedDict(self);
1872+
#else
1873+
PyObject *&dict = *non_limited_api::_PyObject_GetDictPtr(self);
1874+
Py_CLEAR(dict);
1875+
#endif
1876+
return 0;
1877+
}
1878+
1879+
void pybind11::non_limited_api::pybind11NLA_globals(dict &out)
1880+
{
1881+
#if PY_VERSION_HEX >= 0x030d0000
1882+
PyObject *p = PyEval_GetFrameGlobals();
1883+
out = p ? reinterpret_steal<dict>(p)
1884+
: reinterpret_borrow<dict>(module_::import("__main__").attr("__dict__").ptr());
1885+
#else
1886+
PyObject *p = PyEval_GetGlobals();
1887+
out = reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
1888+
#endif
1889+
}
1890+
1891+
PyObject *pybind11::non_limited_api::pybind11NLA_dict_getitemstringref(PyObject *v, const char *key)
1892+
{
1893+
#if PY_VERSION_HEX >= 0x030D0000
1894+
PyObject *rv;
1895+
if (PyDict_GetItemStringRef(v, key, &rv) < 0) {
1896+
throw error_already_set();
1897+
}
1898+
return rv;
1899+
#else
1900+
PyObject *rv = dict_getitemstring(v, key);
1901+
if (rv == nullptr && PyErr_Occurred()) {
1902+
throw error_already_set();
1903+
}
1904+
Py_XINCREF(rv);
1905+
return rv;
1906+
#endif
1907+
}

0 commit comments

Comments
 (0)