[pypy-issue] Issue #2774: cpyext: pybind11: 'instancemethod' has no attribute '__name__' (pypy/pypy)

Andrew Stepanov issues-reply at bitbucket.org
Tue Mar 20 13:51:10 EDT 2018


New issue 2774: cpyext: pybind11: 'instancemethod' has no attribute '__name__'
https://bitbucket.org/pypy/pypy/issues/2774/cpyext-pybind11-instancemethod-has-no

Andrew Stepanov:

When I try to use this simple [pybind11](https://github.com/pybind/pybind11) binding code (which by the way compiles just fine under pypy3-v5.10.1):

```
#!cpp

#include <pybind11/pybind11.h>

class A {
 public:
  int field;
};

namespace py = pybind11;

PYBIND11_MODULE(simple, m) {
  py::class_<A>(m, "A")
      .def(py::init<>())
      .def_readwrite("field", &A::field);
}
```
I get
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: AttributeError: 'instancemethod' object has no attribute '__name__'
```

As it turns out, `InstanceMethod` indeed doesn't have `__name__` attribute (along with `__module__` and `__doc__` which pybind11 uses, see [pypy/module/cpyext/classobject.py:34](https://bitbucket.org/pypy/pypy/src/d12c359516b2ee430bd53958b2bc6bf3373b5557/pypy/module/cpyext/classobject.py?at=py3.5&fileviewer=file-view-default#classobject.py-34))

```
InstanceMethod.typedef = TypeDef("instancemethod",
    __new__ = interp2app(InstanceMethod.descr_new),
    __call__ = interp2app(InstanceMethod.descr_call,
                          descrmismatch='__call__'),
    __get__ = interp2app(InstanceMethod.descr_get),
    __repr__ = interp2app(InstanceMethod.descr_repr,
                          descrmismatch='__repr__'),
    __func__= interp_attrproperty_w('w_function', cls=InstanceMethod),
)
```

When I implement them straightforwardly using `self.w_function` attributes

```
class InstanceMethod(W_Root):
    ...

    def fget_name(self, space):
        return space.getattr(self.w_function, space.newtext("__name__"))

    def fget_module(self, space):
        return space.getattr(self.w_function, space.newtext("__module__"))

    def fget_docstring(self, space):
        return space.getattr(self.w_function, space.newtext("__doc__"))

    ...

InstanceMethod.typedef = TypeDef("instancemethod",
    ...
    __name__= GetSetProperty(InstanceMethod.fget_name, cls=InstanceMethod),
    __module__= GetSetProperty(InstanceMethod.fget_module, cls=InstanceMethod),
    __doc__= GetSetProperty(InstanceMethod.fget_docstring, cls=InstanceMethod), 
)
```

everything works fine and example pybind11 module above can be imported with no problems.

In fact, with this modifications all but the 2 tests (`test_multiple_inheritance.py`, `test_eval.py`) in pybind11 test suite pass, which makes the pybind11 library useful in practice (from my own experience: big binding library used in our private project compiles and passes all of our tests)




More information about the pypy-issue mailing list