[QUESTION] Defining and using metaclasses with pybind11
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
I am aware of the pybind11::metaclass option that can be passed to pybind11::class_, but I can't find any documentation on how it is supposed to be used. There is a single test case here:
but it isn't clear what that case is showing, and I haven't been able to find a single other example of code that uses pybind11::metaclass.
What I'd like to accomplish is to make __class_getitem__ work on Python < 3.7, equivalent to the following pure python code:
class Parent(type):
def __getitem__(self, key):
return self.__class_getitem__(key)
class Child(metaclass=Parent):
@classmethod
def __class_getitem__(cls, key):
return 'got key: %r' % (key,)
assert Child[1] == 'got key: 1'
Note that in Python >= 3.7, this example also works if we eliminate Parent and just use type as the metaclass of Child.
I'd like to accomplish this same thing, where both Parent and Child are defined using pybind11 rather than pure Python.
My initial attempt was:
struct Parent {};
struct Child {};
py::class_<Parent> cls_parent(
m, "Parent",
py::handle(reinterpret_cast<PyObject*>(
pybind11::detail::get_internals().default_metaclass));
cls_parent.def("__getitem__", [](Parent& self, py::object key) {
return py::cast(&self).attr("__class_getitem__")(key);
});
py::class_<Child> cls_child(m, "Child", py::metaclass(cls_parent));
cls_child.def_static("__class_getitem__",
[](std::string key) { return "got key: " + key; });
but that crashes while creating cls_parent: due to the t_size >= b_size condition in the extra_ivars function in typeobject.c.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with tests/test_methods_and_attributes.cpp around line 282 to understand the existing metaclass coverage, then inspect the reported failure in Python's typeobject.c at the extra_ivars t_size >= b_size condition. Reproduce the metaclass construction and determine whether the supported usage or the Python <3.7 class_getitem behavior should be documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100