refactor: replace .get_type with type::handle_of (#2492)

* refactor: replace .get_type with type::handle_of

* refactor: use impl for handle_of

* fix: deprecate h.get_type()
This commit is contained in:
Henry Schreiner 2020-09-16 11:32:17 -04:00 committed by GitHub
parent a4cee36b6f
commit 41aa92601e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 20 deletions

View File

@ -17,10 +17,16 @@ See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
This reduces binary size quite substantially (~25%).
`#2463 <https://github.com/pybind/pybind11/pull/2463>`_
* Keyword-only argument supported in Python 2 or 3 with ``py::kw_only()``.
* Keyword-only arguments supported in Python 2 or 3 with ``py::kw_only()``.
`#2100 <https://github.com/pybind/pybind11/pull/2100>`_
* Positional-only argument supported in Python 2 or 3 with ``py::pos_only()``.
* Positional-only arguments supported in Python 2 or 3 with ``py::pos_only()``.
`#2459 <https://github.com/pybind/pybind11/pull/2459>`_
* Access to the type object now provided with ``py::type::of<T>()`` and
``py::type::of(h)``.
`#2364 <https://github.com/pybind/pybind11/pull/2364>`_
* Perfect forwarding support for methods.
`#2048 <https://github.com/pybind/pybind11/pull/2048>`_

View File

@ -17,6 +17,9 @@ An error is now thrown when ``__init__`` is forgotten on subclasses. This was
incorrect before, but was not checked. Add a call to ``__init__`` if it is
missing.
The undocumented ``h.get_type()`` method has been deprecated and replaced by
``py::type::of(h)``.
If ``__eq__`` defined but not ``__hash__``, ``__hash__`` is now set to
``None``, as in normal CPython. You should add ``__hash__`` if you intended the
class to be hashable, possibly using the new ``py::hash`` shortcut.

View File

@ -636,7 +636,7 @@ public:
/// native typeinfo, or when the native one wasn't able to produce a value.
PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) {
constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID;
const auto pytype = src.get_type();
const auto pytype = type::handle_of(src);
if (!hasattr(pytype, local_key))
return false;
@ -1130,7 +1130,7 @@ public:
}
/* Check if this is a C++ type */
auto &bases = all_type_info((PyTypeObject *) h.get_type().ptr());
auto &bases = all_type_info((PyTypeObject *) type::handle_of(h).ptr());
if (bases.size() == 1) { // Only allowing loading from a single-value type
value = values_and_holders(reinterpret_cast<instance *>(h.ptr())).begin()->value_ptr();
return true;
@ -1708,7 +1708,7 @@ template <typename T, typename SFINAE> type_caster<T, SFINAE> &load_type(type_ca
throw cast_error("Unable to cast Python instance to C++ type (compile in debug mode for details)");
#else
throw cast_error("Unable to cast Python instance of type " +
(std::string) str(handle.get_type()) + " to C++ type '" + type_id<T>() + "'");
(std::string) str(type::handle_of(handle)) + " to C++ type '" + type_id<T>() + "'");
#endif
}
return conv;
@ -1759,7 +1759,7 @@ detail::enable_if_t<!detail::move_never<T>::value, T> move(object &&obj) {
throw cast_error("Unable to cast Python instance to C++ rvalue: instance has multiple references"
" (compile in debug mode for details)");
#else
throw cast_error("Unable to move from Python " + (std::string) str(obj.get_type()) +
throw cast_error("Unable to move from Python " + (std::string) str(type::handle_of(obj)) +
" instance to C++ " + type_id<T>() + " instance: instance has multiple references");
#endif
@ -2206,13 +2206,13 @@ PYBIND11_NAMESPACE_END(detail)
template<typename T>
type type::of() {
handle type::handle_of() {
static_assert(
std::is_base_of<detail::type_caster_generic, detail::make_caster<T>>::value,
"py::type::of<T> only supports the case where T is a registered C++ types."
);
return type((PyObject*) detail::get_type_handle(typeid(T), true).ptr(), borrowed_t());
return detail::get_type_handle(typeid(T), true);
}

View File

@ -553,7 +553,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
object matrix_type = sparse_module.attr(
rowMajor ? "csr_matrix" : "csc_matrix");
if (!obj.get_type().is(matrix_type)) {
if (!type::handle_of(obj).is(matrix_type)) {
try {
obj = matrix_type(obj);
} catch (const error_already_set &) {

View File

@ -1489,7 +1489,7 @@ struct enum_base {
m_base.attr("__repr__") = cpp_function(
[](handle arg) -> str {
handle type = arg.get_type();
handle type = type::handle_of(arg);
object type_name = type.attr("__name__");
dict entries = type.attr("__entries");
for (const auto &kv : entries) {
@ -1503,7 +1503,7 @@ struct enum_base {
m_base.attr("name") = property(cpp_function(
[](handle arg) -> str {
dict entries = arg.get_type().attr("__entries");
dict entries = type::handle_of(arg).attr("__entries");
for (const auto &kv : entries) {
if (handle(kv.second[int_(0)]).equal(arg))
return pybind11::str(kv.first);
@ -1542,7 +1542,7 @@ struct enum_base {
#define PYBIND11_ENUM_OP_STRICT(op, expr, strict_behavior) \
m_base.attr(op) = cpp_function( \
[](object a, object b) { \
if (!a.get_type().is(b.get_type())) \
if (!type::handle_of(a).is(type::handle_of(b))) \
strict_behavior; \
return expr; \
}, \
@ -2115,7 +2115,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty
handle self = get_object_handle(this_ptr, this_type);
if (!self)
return function();
handle type = self.get_type();
handle type = type::handle_of(self);
auto key = std::make_pair(type.ptr(), name);
/* Cache functions that aren't overridden in Python to avoid

View File

@ -152,7 +152,8 @@ public:
/// Return the object's current reference count
int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); }
/// Return a handle to the Python type object underlying the instance
PYBIND11_DEPRECATED("Call py::type::handle_of(h) or py::type::of(h) instead of h.get_type()")
handle get_type() const;
private:
@ -897,13 +898,24 @@ class type : public object {
public:
PYBIND11_OBJECT(type, object, PyType_Check)
static type of(handle h) { return type((PyObject*) Py_TYPE(h.ptr()), borrowed_t{}); }
/// Return a type handle from a handle or an object
static handle handle_of(handle h) { return handle((PyObject*) Py_TYPE(h.ptr())); }
/// Convert C++ type to py::type if previously registered. Does not convert
// standard types, like int, float. etc. yet.
// See https://github.com/pybind/pybind11/issues/2486
/// Return a type object from a handle or an object
static type of(handle h) { return type(type::handle_of(h), borrowed_t{}); }
// Defined in pybind11/cast.h
/// Convert C++ type to handle if previously registered. Does not convert
/// standard types, like int, float. etc. yet.
/// See https://github.com/pybind/pybind11/issues/2486
template<typename T>
static type of();
static handle handle_of();
/// Convert C++ type to type if previously registered. Does not convert
/// standard types, like int, float. etc. yet.
/// See https://github.com/pybind/pybind11/issues/2486
template<typename T>
static type of() {return type(type::handle_of<T>(), borrowed_t{}); }
};
class iterable : public object {
@ -1568,7 +1580,8 @@ template <typename D>
str_attr_accessor object_api<D>::doc() const { return attr("__doc__"); }
template <typename D>
handle object_api<D>::get_type() const { return (PyObject *) Py_TYPE(derived().ptr()); }
PYBIND11_DEPRECATED("Use py::type::of(h) instead of h.get_type()")
handle object_api<D>::get_type() const { return type::handle_of(*this); }
template <typename D>
bool object_api<D>::rich_compare(object_api const &other, int value) const {