aboutsummaryrefslogtreecommitdiff
path: root/libs/plugin_python/src/pybind11-utils/functional.cpp
blob: 4cc7b6c8cda56a3f7c5bc399ce5e0f56cee6a807 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "pybind11_utils/functional.h"

namespace py = pybind11;

namespace mo2::python::detail {

    bool has_compatible_arity(py::function fn, std::size_t arity)
    {
        auto inspect    = py::module_::import("inspect");
        auto arg_spec   = inspect.attr("getfullargspec")(fn);
        py::object args = arg_spec.attr("args"), varargs = arg_spec.attr("varargs"),
                   defaults = arg_spec.attr("defaults");

        auto args_count     = args.is(py::none()) ? 0 : py::len(args);
        auto defaults_count = defaults.is(py::none()) ? 0 : py::len(defaults);

        if (inspect.attr("ismethod")(fn).cast<bool>() && py::hasattr(fn, "__self__")) {
            --args_count;
        }

        auto required_count = args_count - defaults_count;

        return required_count <= arity  // cannot require more parameters than given,
               && (args_count >= arity ||
                   !varargs.is_none());  // must accept enough parameters.
    }

}  // namespace mo2::python::detail