Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`_
Expand Down
3 changes: 3 additions & 0 deletions docs/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 6 additions & 6 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ class type_caster_generic {
/// 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;

Expand Down Expand Up @@ -1130,7 +1130,7 @@ template <> class type_caster<void> : public type_caster<void_type> {
}

/* 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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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);
}


Expand Down
2 changes: 1 addition & 1 deletion include/pybind11/eigen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 &) {
Expand Down
8 changes: 4 additions & 4 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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; \
}, \
Expand Down Expand Up @@ -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
Expand Down
27 changes: 20 additions & 7 deletions include/pybind11/pytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ class object_api : public pyobject_tag {

/// 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:
Expand Down Expand Up @@ -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())); }

/// 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 handle handle_of();

/// 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
/// 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();
static type of() {return type(type::handle_of<T>(), borrowed_t{}); }
};

class iterable : public object {
Expand Down Expand Up @@ -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 {
Expand Down