summaryrefslogtreecommitdiff
path: root/ext/pybind11/include/pybind11/attr.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/include/pybind11/attr.h')
-rw-r--r--ext/pybind11/include/pybind11/attr.h121
1 files changed, 94 insertions, 27 deletions
diff --git a/ext/pybind11/include/pybind11/attr.h b/ext/pybind11/include/pybind11/attr.h
index e38a1a32d..dce875a6b 100644
--- a/ext/pybind11/include/pybind11/attr.h
+++ b/ext/pybind11/include/pybind11/attr.h
@@ -1,5 +1,5 @@
/*
- pybind11/pybind11.h: Infrastructure for processing custom
+ pybind11/attr.h: Infrastructure for processing custom
type and function attributes
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -12,7 +12,7 @@
#include "cast.h"
-NAMESPACE_BEGIN(pybind11)
+NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/// \addtogroup annotations
/// @{
@@ -58,15 +58,56 @@ struct metaclass {
handle value;
PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.")
- metaclass() = default;
+ metaclass() {}
/// Override pybind11's default metaclass
explicit metaclass(handle value) : value(value) { }
};
+/// Annotation that marks a class as local to the module:
+struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } };
+
/// Annotation to mark enums as an arithmetic type
struct arithmetic { };
+/** \rst
+ A call policy which places one or more guard variables (``Ts...``) around the function call.
+
+ For example, this definition:
+
+ .. code-block:: cpp
+
+ m.def("foo", foo, py::call_guard<T>());
+
+ is equivalent to the following pseudocode:
+
+ .. code-block:: cpp
+
+ m.def("foo", [](args...) {
+ T scope_guard;
+ return foo(args...); // forwarded arguments
+ });
+ \endrst */
+template <typename... Ts> struct call_guard;
+
+template <> struct call_guard<> { using type = detail::void_type; };
+
+template <typename T>
+struct call_guard<T> {
+ static_assert(std::is_default_constructible<T>::value,
+ "The guard type must be default constructible");
+
+ using type = T;
+};
+
+template <typename T, typename... Ts>
+struct call_guard<T, Ts...> {
+ struct type {
+ T guard{}; // Compose multiple guard types with left-to-right default-constructor order
+ typename call_guard<Ts...>::type next{};
+ };
+};
+
/// @} annotations
NAMESPACE_BEGIN(detail)
@@ -75,8 +116,6 @@ enum op_id : int;
enum op_type : int;
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(size_t Nurse, size_t Patient, function_call &call, handle ret);
/// Internal data structure which holds metadata about a keyword argument
@@ -85,16 +124,17 @@ struct argument_record {
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
+ bool none : 1; ///< True if None is allowed when loading
- argument_record(const char *name, const char *descr, handle value, bool convert)
- : name(name), descr(descr), value(value), convert(convert) { }
+ argument_record(const char *name, const char *descr, handle value, bool convert, bool none)
+ : name(name), descr(descr), value(value), convert(convert), none(none) { }
};
/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.)
struct function_record {
function_record()
- : is_constructor(false), is_stateless(false), is_operator(false),
- has_args(false), has_kwargs(false), is_method(false) { }
+ : is_constructor(false), is_new_style_constructor(false), is_stateless(false),
+ is_operator(false), has_args(false), has_kwargs(false), is_method(false) { }
/// Function name
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
@@ -123,6 +163,9 @@ struct function_record {
/// True if name == '__init__'
bool is_constructor : 1;
+ /// True if this is a new-style `__init__` defined in `detail/init.h`
+ bool is_new_style_constructor : 1;
+
/// True if this is a stateless function pointer
bool is_stateless : 1;
@@ -157,7 +200,7 @@ struct function_record {
/// Special data structure which (temporarily) holds metadata about a bound class
struct type_record {
PYBIND11_NOINLINE type_record()
- : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false) { }
+ : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false), module_local(false) { }
/// Handle to the parent scope
handle scope;
@@ -171,17 +214,17 @@ struct type_record {
/// How large is the underlying C++ type?
size_t type_size = 0;
- /// How large is pybind11::instance<type>?
- size_t instance_size = 0;
+ /// How large is the type's holder?
+ size_t holder_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;
+ /// Function pointer to class_<..>::init_instance
+ void (*init_instance)(instance *, const void *) = nullptr;
/// Function pointer to class_<..>::dealloc
- void (*dealloc)(PyObject *) = nullptr;
+ void (*dealloc)(detail::value_and_holder &) = nullptr;
/// List of base classes of the newly created type
list bases;
@@ -204,17 +247,20 @@ struct type_record {
/// 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);
+ /// Is the class definition local to the module shared object?
+ bool module_local : 1;
+
+ PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) {
+ auto base_info = detail::get_type_info(base, false);
if (!base_info) {
- std::string tname(base->name());
+ std::string tname(base.name());
detail::clean_type_id(tname);
pybind11_fail("generic_type: type \"" + std::string(name) +
"\" referenced unknown base type \"" + tname + "\"");
}
if (default_holder != base_info->default_holder) {
- std::string tname(base->name());
+ std::string tname(base.name());
detail::clean_type_id(tname);
pybind11_fail("generic_type: type \"" + std::string(name) + "\" " +
(default_holder ? "does not have" : "has") +
@@ -228,7 +274,7 @@ struct type_record {
dynamic_attr = true;
if (caster)
- base_info->implicit_casts.push_back(std::make_pair(type, caster));
+ base_info->implicit_casts.emplace_back(type, caster);
}
};
@@ -238,6 +284,9 @@ inline function_call::function_call(function_record &f, handle p) :
args_convert.reserve(f.nargs);
}
+/// Tag for a new-style `__init__` defined in `detail/init.h`
+struct is_new_style_constructor { };
+
/**
* Partial template specializations to process custom attributes provided to
* cpp_function_ and class_. These are either used to initialize the respective
@@ -296,12 +345,16 @@ template <> struct process_attribute<is_operator> : process_attribute_default<is
static void init(const is_operator &, function_record *r) { r->is_operator = true; }
};
+template <> struct process_attribute<is_new_style_constructor> : process_attribute_default<is_new_style_constructor> {
+ static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
+};
+
/// Process a keyword argument attribute (*without* a default value)
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(), true /*convert*/);
- r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert);
+ r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
+ r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
}
};
@@ -309,7 +362,7 @@ 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 /*descr*/, handle() /*parent*/, true /*convert*/);
+ r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/);
if (!a.value) {
#if !defined(NDEBUG)
@@ -332,7 +385,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
"Compile in debug mode for more information.");
#endif
}
- r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert);
+ r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
}
};
@@ -345,7 +398,7 @@ struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attrib
/// Process a parent class attribute (deprecated, does not support multiple inheritance)
template <typename T>
struct process_attribute<base<T>> : process_attribute_default<base<T>> {
- static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); }
+ static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); }
};
/// Process a multiple inheritance attribute
@@ -369,12 +422,19 @@ struct process_attribute<metaclass> : process_attribute_default<metaclass> {
static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; }
};
+template <>
+struct process_attribute<module_local> : process_attribute_default<module_local> {
+ static void init(const module_local &l, type_record *r) { r->module_local = l.value; }
+};
/// Process an 'arithmetic' attribute for enums (does nothing here)
template <>
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
-/***
+template <typename... Ts>
+struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> { };
+
+/**
* Process a keep_alive call policy -- invokes keep_alive_impl during the
* pre-call handler if both Nurse, Patient != 0 and use the post-call handler
* otherwise
@@ -410,6 +470,13 @@ template <typename... Args> struct process_attributes {
}
};
+template <typename T>
+using is_call_guard = is_instantiation<call_guard, T>;
+
+/// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found)
+template <typename... Extra>
+using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type;
+
/// Check the number of named arguments at compile time
template <typename... Extra,
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),
@@ -419,4 +486,4 @@ constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
}
NAMESPACE_END(detail)
-NAMESPACE_END(pybind11)
+NAMESPACE_END(PYBIND11_NAMESPACE)