Enhancement: allow method definition with python code by an augmenting meta class
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Issue description
Making it easy to define new methods for pybind11 generated classes, in Python code instead of in C++ code, and without actually creating new subclasses.
Reproducible example code
I come across this enhancement implemented by a meta class:
from . import core
# must derive from pybind11's default meta class
class AugmentCxxClass(core.PerfPack.__class__):
"""
Make it easy to define new methods for pybind11 generated classes, in Python code instead of in C++ code,
and without actually creating new subclasses.
"""
def __new__(cls, name, bases, namespace, **kwds):
assert len(bases) == 1, 'Augment multiple classes at same time ?!'
for k, v in namespace.items():
if k in ('__module__', '__qualname__'):
continue
for tcls in bases:
setattr(tcls, k, v)
return bases[0]
Then for my bound C++ class Freq, I can neatly augment it with python code and re-export it from the outer python module:
class Freq(core.Freq, metaclass=AugmentCxxClass):
# preserve generated docstring by not defining one here
def __repr__(self):
return f'as_freq({self.nomenclature!r})'
def __str__(self):
return self.nomenclature
def __int__(self):
return self.span
def __eq__(self, other):
if isinstance(other, Freq):
return other.nomenclature == self.nomenclature
return str(other) == self.nomenclature
This works well for me and I'd think it may be implemented as an official feature to benefit others. I tried to make this as a PR but failed to find home for such python code in current codebase, the blocker is how to obtain pybind11_builtins.pybind11_type to serve as AugmentCxxClass' base class, or errors will occur. Though it can be obtained from any pybind defined wrapper class, even works crossing extension modules. I currently use a separate dummy extension module defining the dummy PerfPack class.
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 the pybind11_builtins.pybind11_type dependency and the AugmentCxxClass example in the issue; compare how a bound class such as core.Freq is exposed across extension modules. Done means Python-side augmentation is supported officially without requiring a separate dummy extension module.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100