Uh oh!
There was an error while loading. Please reload this page.
feat: py::type::of<T>() and py::type::of(h) - #2364
Conversation
There was a problem hiding this comment.
Damn, @henryiii, you beat me to it, again ;-)
+1 for adding this!
When considering this PR over the last year, I realized this only works for class_-registered types. So, given that we'll undoubtedly get lots of questions/issues about "why doesn't py::type<int>() not return the int type object?":
- Should we extend this? Yes, your documentation says it's for exposed types, so it's not strictly necessary. But I do wonder how many "bug" reports we're going to get. Plus, it would be a nice way of getting hold of the
inttype object? - Is there an easy way to do so? One possibility I can see would be to add this to
type_casterasstatic py::object type()(orstatic py::handle type()) and add the current implementation totype_caster_base? Not sure if this is a great idea, but it would a) be extensible, and b) be backwards compatible (since you'll get a compile error if thetype_casterdoesn't have a statictypefunction).
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Thanks!!! I've had some code that, uh, dipped into the internals for a while now 😅
EDIT: Thinking on it more, given that I already intercept I am totes fine with this only dealing with registered types. Perhaps, then renaming it to something slightly more obtuse, like |
Uh oh!
There was an error while loading. Please reload this page.
I like the |
EricCousineau-TRI
commented
Aug 10, 2020
Yeah, I think a fail fast is achievable. Perhaps with something like this in the function body? |
YannickJadoul
commented
Aug 10, 2020
Except that we don't have that, I believe? So it'll be something like checking that a subclass of the default |
henryiii
commented
Aug 10, 2020
If we have it fail for now with non-user registered types, it could always be added later - changing a failure to a success is always allowed. :) |
YannickJadoul
commented
Aug 10, 2020
Exactly! As long as we do it safely (at compile time), this would be perfect! |
681c849 to
fd8f6fcCompareUh oh!
There was an error while loading. Please reload this page.
wjakob
commented
Aug 17, 2020
This looks great, but would you mind adding an explicit discussion in the documentation (the auto-extracted docstrings IIRC do end up in the documentation as well, but rather hidden..) |
henryiii
commented
Aug 17, 2020
Waiting pending discussion on #2388 |
2174918 to
8a9238dCompareUh oh!
There was an error while loading. Please reload this page.
henryiii
commented
Sep 9, 2020
By the way, I'm open to ideas on how to get something like |
EricCousineau-TRI
commented
Sep 14, 2020
Filed #2486 ;) |
YannickJadoul
commented
Sep 14, 2020
Right, but then for
That's an interesting suggestion, though, but I'm not sure. It's not really a type, right? Can you create an object using this?
But these do get mapped to the same Python type? I don't see the problem, here? There's a mismatch between C++ and Python, but you can still say "If you pass a C++ type
Agreed! Let's get the easy stuff in, just making sure it doesn't stop us from achieving the more complicated stuff :-) |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Without verifying it could be done, I think you could have
Unless it was extremely easy, was not planning to add to this PR :) |
| PYBIND11_OBJECT_COMMON(type, object, PyType_Check) | ||
| explicit type(handle h): type((PyObject*) Py_TYPE(h.ptr()), borrowed_t{}) {} | ||
| explicit type(object ob): type((PyObject*) Py_TYPE(ob.ptr()), borrowed_t{}) {} |
There was a problem hiding this comment.
This isn't necessary, I think? object should be a subclass of handle, and there's no extra refcounting going on?
There was a problem hiding this comment.
Oh, yes, some slicing, since it's not by reference. But there are precedents for that, I think?
There was a problem hiding this comment.
If you/we choose to keep the object overload, better to make it a const object &, then. It avoids an unnecessary refcount.
There was a problem hiding this comment.
Ah, no, PYBIND11_OBJECT already adds that overload.
pybind11/include/pybind11/pytypes.h
Lines 813 to 817 in cc982ac
How do we fix this such that it works in the intended way? When do we want py::type(...) to "cast" a py::object to a subclass, and when do we want it to actually call type(...)? Does this mean that @henryiii's original py::type::of is necessary, and that we can't have the py::type(obj) interface I've been dreaming of? :-(
There was a problem hiding this comment.
We use PYBIND11_OBJECT_COMMON instead of PYBIND11_OBJECT.
There was a problem hiding this comment.
(I'll try dropping this overload soon)
There was a problem hiding this comment.
Can this be a const handle &?
There was a problem hiding this comment.
We use
PYBIND11_OBJECT_COMMONinstead ofPYBIND11_OBJECT.
🤦 How did I miss that?
Can this be a
const handle &?
Probably, but I don't think it's necessary. handle really is a fancy and more beautiful way of writing PyObject *.
YannickJadoul
commented
Sep 14, 2020
Sorry to open that discussion again (after first telling @henryiii to change it), but, I'm now realizing the following: If |
I think I preferred |
It looks like |
YannickJadoul
commented
Sep 14, 2020
I worked on that here in #2349, but it got stalled behind the |
henryiii
commented
Sep 14, 2020
Good, then leave as is, then we can take advantage of that if it gets merged? |
YannickJadoul
commented
Sep 14, 2020
I really liked |
YannickJadoul
commented
Sep 14, 2020
Good for me. I'll try to pick that up again, soon'ish... |
Uh oh!
There was an error while loading. Please reload this page.
wjakob
commented
Sep 15, 2020
Thanks everyone! |
Pybind11 2.6 introduces `pybind11::type::of<T>()` and `pybind11::type`, see pybind/pybind11#2364. We can use neither: `of<T>()` throws and `type` cannot represent `None`.
Pybind11 2.6 introduces `pybind11::type::of<T>()` and `pybind11::type`, see pybind/pybind11#2364. We can use neither: `of<T>()` throws and `type` cannot represent `None`.
This adds
py::type::of<T>(), which provides a way to get the Python type associated with a C++ type. Currently there are two possible ways to do this (pointed out by @YannickJadoul and @bstaletic on Gitter about a year ago, IIRC), but they require usage of internal structures or the detail namespace. This provides a natural, pythonic way to get the type object without reverting to internal details.This is very useful in templated code; for example, in boost-histogram, it is needed to get the templated storage from a templated histogram.
EDIT (@YannickJadoul):
Closes#1692