mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
detect unreferenced keyword arguments in function calls
This commit is contained in:
parent
e9dc824866
commit
3367cecc6b
@ -24,6 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cast.h"
|
#include "cast.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
NAMESPACE_BEGIN(pybind11)
|
NAMESPACE_BEGIN(pybind11)
|
||||||
|
|
||||||
@ -97,16 +98,17 @@ private:
|
|||||||
(void) unused;
|
(void) unused;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T> static void process_extras(const std::tuple<T...> &args,
|
template <typename... T> static int process_extras(const std::tuple<T...> &args,
|
||||||
PyObject *pyArgs, PyObject *kwargs, bool is_method) {
|
PyObject *pyArgs, PyObject *kwargs, bool is_method) {
|
||||||
process_extras(args, pyArgs, kwargs, is_method, typename detail::make_index_sequence<sizeof...(T)>::type());
|
return process_extras(args, pyArgs, kwargs, is_method, typename detail::make_index_sequence<sizeof...(T)>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T, size_t... Index> static void process_extras(const std::tuple<T...> &args,
|
template <typename... T, size_t... Index> static int process_extras(const std::tuple<T...> &args,
|
||||||
PyObject *pyArgs, PyObject *kwargs, bool is_method, detail::index_sequence<Index...>) {
|
PyObject *pyArgs, PyObject *kwargs, bool is_method, detail::index_sequence<Index...>) {
|
||||||
int index = is_method ? 1 : 0;
|
int index = is_method ? 1 : 0, kwarg_refs = 0;
|
||||||
int unused[] = { 0, (process_extra(std::get<Index>(args), index, pyArgs, kwargs), 0)... };
|
int unused[] = { 0, (process_extra(std::get<Index>(args), index, kwarg_refs, pyArgs, kwargs), 0)... };
|
||||||
(void) unused; (void) index;
|
(void) unused; (void) index;
|
||||||
|
return kwarg_refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_extra(const char *doc, function_entry *entry, const char **, const char **) { entry->doc = doc; }
|
static void process_extra(const char *doc, function_entry *entry, const char **, const char **) { entry->doc = doc; }
|
||||||
@ -133,8 +135,8 @@ private:
|
|||||||
static void process_extra(const pybind11::return_value_policy p, function_entry *entry, const char **, const char **) { entry->policy = p; }
|
static void process_extra(const pybind11::return_value_policy p, function_entry *entry, const char **, const char **) { entry->policy = p; }
|
||||||
static void process_extra(pybind11::sibling s, function_entry *entry, const char **, const char **) { entry->sibling = s.value; }
|
static void process_extra(pybind11::sibling s, function_entry *entry, const char **, const char **) { entry->sibling = s.value; }
|
||||||
|
|
||||||
template <typename T> static void process_extra(T, int &, PyObject *, PyObject *) { }
|
template <typename T> static void process_extra(T, int &, int&, PyObject *, PyObject *) { }
|
||||||
static void process_extra(const pybind11::arg &a, int &index, PyObject *args, PyObject *kwargs) {
|
static void process_extra(const pybind11::arg &a, int &index, int &kwarg_refs, PyObject *args, PyObject *kwargs) {
|
||||||
if (kwargs) {
|
if (kwargs) {
|
||||||
if (PyTuple_GET_ITEM(args, index) != nullptr) {
|
if (PyTuple_GET_ITEM(args, index) != nullptr) {
|
||||||
index++;
|
index++;
|
||||||
@ -144,12 +146,13 @@ private:
|
|||||||
if (value) {
|
if (value) {
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
PyTuple_SetItem(args, index, value);
|
PyTuple_SetItem(args, index, value);
|
||||||
|
kwarg_refs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void process_extra(const pybind11::arg_t<T> &a, int &index, PyObject *args, PyObject *kwargs) {
|
static void process_extra(const pybind11::arg_t<T> &a, int &index, int &kwarg_refs, PyObject *args, PyObject *kwargs) {
|
||||||
if (PyTuple_GET_ITEM(args, index) != nullptr) {
|
if (PyTuple_GET_ITEM(args, index) != nullptr) {
|
||||||
index++;
|
index++;
|
||||||
return;
|
return;
|
||||||
@ -158,6 +161,7 @@ private:
|
|||||||
if (kwargs)
|
if (kwargs)
|
||||||
value = PyDict_GetItemString(kwargs, a.name);
|
value = PyDict_GetItemString(kwargs, a.name);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
kwarg_refs++;
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
} else {
|
} else {
|
||||||
value = detail::type_caster<typename detail::decay<T>::type>::cast(
|
value = detail::type_caster<typename detail::decay<T>::type>::cast(
|
||||||
@ -185,9 +189,9 @@ public:
|
|||||||
|
|
||||||
m_entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject * {
|
m_entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject * {
|
||||||
capture *data = (capture *) entry->data;
|
capture *data = (capture *) entry->data;
|
||||||
process_extras(data->extras, pyArgs, kwargs, entry->is_method);
|
int kwarg_refs = process_extras(data->extras, pyArgs, kwargs, entry->is_method);
|
||||||
cast_in args;
|
cast_in args;
|
||||||
if (!args.load(pyArgs, true))
|
if (kwarg_refs != (kwargs ? PyDict_Size(kwargs) : 0) || !args.load(pyArgs, true))
|
||||||
return (PyObject *) 1; /* Special return code: try next overload */
|
return (PyObject *) 1; /* Special return code: try next overload */
|
||||||
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
|
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
|
||||||
};
|
};
|
||||||
@ -248,9 +252,9 @@ private:
|
|||||||
|
|
||||||
m_entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject *{
|
m_entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject *{
|
||||||
capture *data = (capture *) entry->data;
|
capture *data = (capture *) entry->data;
|
||||||
process_extras(data->extras, pyArgs, kwargs, entry->is_method);
|
int kwarg_refs = process_extras(data->extras, pyArgs, kwargs, entry->is_method);
|
||||||
cast_in args;
|
cast_in args;
|
||||||
if (!args.load(pyArgs, true))
|
if (kwarg_refs != (kwargs ? PyDict_Size(kwargs) : 0) || !args.load(pyArgs, true))
|
||||||
return (PyObject *) 1; /* Special return code: try next overload */
|
return (PyObject *) 1; /* Special return code: try next overload */
|
||||||
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
|
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user