diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2017-05-09 19:22:53 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2017-05-22 17:15:09 +0000 |
commit | 6914a229a038206341ae1fea46393965a555ca9a (patch) | |
tree | 4a11cfaed46dabc827c5ee17cd976f42b5f53d49 /ext/pybind11/include/pybind11/attr.h | |
parent | ca1d18d599dcc620bf526fb22042af95b1b60b68 (diff) | |
download | gem5-6914a229a038206341ae1fea46393965a555ca9a.tar.xz |
ext: Upgrade PyBind11 to version 2.1.1
Change-Id: I16870dec402d661295f9d013dc23e362b2b2c169
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/3225
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Diffstat (limited to 'ext/pybind11/include/pybind11/attr.h')
-rw-r--r-- | ext/pybind11/include/pybind11/attr.h | 132 |
1 files changed, 96 insertions, 36 deletions
diff --git a/ext/pybind11/include/pybind11/attr.h b/ext/pybind11/include/pybind11/attr.h index 448612c52..e38a1a32d 100644 --- a/ext/pybind11/include/pybind11/attr.h +++ b/ext/pybind11/include/pybind11/attr.h @@ -14,6 +14,9 @@ NAMESPACE_BEGIN(pybind11) +/// \addtogroup annotations +/// @{ + /// Annotation for methods struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; @@ -39,7 +42,7 @@ template <typename T> struct base { }; /// Keep patient alive while nurse lives -template <int Nurse, int Patient> struct keep_alive { }; +template <size_t Nurse, size_t Patient> struct keep_alive { }; /// Annotation indicating that a class is involved in a multiple inheritance relationship struct multiple_inheritance { }; @@ -47,9 +50,25 @@ struct multiple_inheritance { }; /// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class struct dynamic_attr { }; +/// Annotation which enables the buffer protocol for a type +struct buffer_protocol { }; + +/// Annotation which requests that a special metaclass is created for a type +struct metaclass { + handle value; + + PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.") + metaclass() = default; + + /// Override pybind11's default metaclass + explicit metaclass(handle value) : value(value) { } +}; + /// Annotation to mark enums as an arithmetic type struct arithmetic { }; +/// @} annotations + NAMESPACE_BEGIN(detail) /* Forward declarations */ enum op_id : int; @@ -58,16 +77,17 @@ struct undefined_t; template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_; template <typename... Args> struct init; template <typename... Args> struct init_alias; -inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret); +inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret); /// Internal data structure which holds metadata about a keyword argument struct argument_record { const char *name; ///< Argument name const char *descr; ///< Human-readable version of the argument value handle value; ///< Associated Python object + bool convert : 1; ///< True if the argument is allowed to convert when loading - argument_record(const char *name, const char *descr, handle value) - : name(name), descr(descr), value(value) { } + argument_record(const char *name, const char *descr, handle value, bool convert) + : name(name), descr(descr), value(value), convert(convert) { } }; /// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) @@ -89,7 +109,7 @@ struct function_record { std::vector<argument_record> args; /// Pointer to lambda function which converts arguments and performs the actual call - handle (*impl) (function_record *, handle, handle, handle) = nullptr; + handle (*impl) (function_call &) = nullptr; /// Storage for the wrapped function pointer and captured data, if any void *data[3] = { }; @@ -118,8 +138,8 @@ struct function_record { /// True if this is a method bool is_method : 1; - /// Number of arguments - uint16_t nargs; + /// Number of arguments (including py::args and/or py::kwargs, if present) + std::uint16_t nargs; /// Python method object PyMethodDef *def = nullptr; @@ -136,7 +156,8 @@ struct function_record { /// Special data structure which (temporarily) holds metadata about a bound class struct type_record { - PYBIND11_NOINLINE type_record() { } + PYBIND11_NOINLINE type_record() + : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false) { } /// Handle to the parent scope handle scope; @@ -153,6 +174,9 @@ struct type_record { /// How large is pybind11::instance<type>? size_t instance_size = 0; + /// The global operator new can be overridden with a class-specific variant + void *(*operator_new)(size_t) = ::operator new; + /// Function pointer to class_<..>::init_holder void (*init_holder)(PyObject *, const void *) = nullptr; @@ -165,11 +189,20 @@ struct type_record { /// Optional docstring const char *doc = nullptr; + /// Custom metaclass (optional) + handle metaclass; + /// Multiple inheritance marker - bool multiple_inheritance = false; + bool multiple_inheritance : 1; /// Does the class manage a __dict__? - bool dynamic_attr = false; + bool dynamic_attr : 1; + + /// Does the class implement the buffer protocol? + bool buffer_protocol : 1; + + /// Is the default (unique_ptr) holder type used? + bool default_holder : 1; PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) { auto base_info = detail::get_type_info(*base, false); @@ -180,6 +213,15 @@ struct type_record { "\" referenced unknown base type \"" + tname + "\""); } + if (default_holder != base_info->default_holder) { + std::string tname(base->name()); + detail::clean_type_id(tname); + pybind11_fail("generic_type: type \"" + std::string(name) + "\" " + + (default_holder ? "does not have" : "has") + + " a non-default holder type while its base \"" + tname + "\" " + + (base_info->default_holder ? "does not" : "does")); + } + bases.append((PyObject *) base_info->type); if (base_info->type->tp_dictoffset != 0) @@ -190,6 +232,12 @@ struct type_record { } }; +inline function_call::function_call(function_record &f, handle p) : + func(f), parent(p) { + args.reserve(f.nargs); + args_convert.reserve(f.nargs); +} + /** * Partial template specializations to process custom attributes provided to * cpp_function_ and class_. These are either used to initialize the respective @@ -202,8 +250,8 @@ template <typename T> struct process_attribute_default { /// Default implementation: do nothing static void init(const T &, function_record *) { } static void init(const T &, type_record *) { } - static void precall(handle) { } - static void postcall(handle, handle) { } + static void precall(function_call &) { } + static void postcall(function_call &, handle) { } }; /// Process an attribute specifying the function's name @@ -252,8 +300,8 @@ template <> struct process_attribute<is_operator> : process_attribute_default<is template <> struct process_attribute<arg> : process_attribute_default<arg> { static void init(const arg &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr, handle()); - r->args.emplace_back(a.name, nullptr, handle()); + r->args.emplace_back("self", nullptr, handle(), true /*convert*/); + r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert); } }; @@ -261,32 +309,34 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> { template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { static void init(const arg_v &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr, handle()); + r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/); if (!a.value) { #if !defined(NDEBUG) - auto descr = "'" + std::string(a.name) + ": " + a.type + "'"; + std::string descr("'"); + if (a.name) descr += std::string(a.name) + ": "; + descr += a.type + "'"; if (r->is_method) { if (r->name) descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'"; else descr += " in method of '" + (std::string) str(r->scope) + "'"; } else if (r->name) { - descr += " in function named '" + (std::string) r->name + "'"; + descr += " in function '" + (std::string) r->name + "'"; } - pybind11_fail("arg(): could not convert default keyword argument " + pybind11_fail("arg(): could not convert default argument " + descr + " into a Python object (type not registered yet?)"); #else - pybind11_fail("arg(): could not convert default keyword argument " + pybind11_fail("arg(): could not convert default argument " "into a Python object (type not registered yet?). " "Compile in debug mode for more information."); #endif } - r->args.emplace_back(a.name, a.descr, a.value.inc_ref()); + r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert); } }; -/// Process a parent class attribute +/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees that) template <typename T> struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> { static void init(const handle &h, type_record *r) { r->bases.append(h); } @@ -309,6 +359,16 @@ struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } }; +template <> +struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> { + static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; } +}; + +template <> +struct process_attribute<metaclass> : process_attribute_default<metaclass> { + static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; } +}; + /// Process an 'arithmetic' attribute for enums (does nothing here) template <> @@ -319,15 +379,15 @@ struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; * pre-call handler if both Nurse, Patient != 0 and use the post-call handler * otherwise */ -template <int Nurse, int Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> { - template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> - static void precall(handle args) { keep_alive_impl(Nurse, Patient, args, handle()); } - template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> - static void postcall(handle, handle) { } - template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> - static void precall(handle) { } - template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> - static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); } +template <size_t Nurse, size_t Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> { + template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> + static void precall(function_call &call) { keep_alive_impl(Nurse, Patient, call, handle()); } + template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> + static void postcall(function_call &, handle) { } + template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> + static void precall(function_call &) { } + template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> + static void postcall(function_call &call, handle ret) { keep_alive_impl(Nurse, Patient, call, ret); } }; /// Recursively iterate over variadic template arguments @@ -340,12 +400,12 @@ template <typename... Args> struct process_attributes { int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; ignore_unused(unused); } - static void precall(handle fn_args) { - int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(fn_args), 0) ... }; + static void precall(function_call &call) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(call), 0) ... }; ignore_unused(unused); } - static void postcall(handle fn_args, handle fn_ret) { - int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(fn_args, fn_ret), 0) ... }; + static void postcall(function_call &call, handle fn_ret) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0) ... }; ignore_unused(unused); } }; @@ -354,8 +414,8 @@ template <typename... Args> struct process_attributes { template <typename... Extra, size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)> -constexpr bool expected_num_args(size_t nargs) { - return named == 0 || (self + named) == nargs; +constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) { + return named == 0 || (self + named + has_args + has_kwargs) == nargs; } NAMESPACE_END(detail) |