Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2001-11-14 08:33:48


----- Original Message -----
From: "Ivan A. Vigasin" <vig_at_[hidden]>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "<stdin>", line 5, in __init__
> TypeError: unbound method __init__() must be called with instance as
first argument
>
> ;((
>
> Maybe result depends on python's or boost's version?

Perhaps. What versions are you using?

The Boost code in question hasn't changed in a year. I was using
Python2.2b1, but it's hard to imagine that Python can get any control over
this! The code in question is at the bottom of the message.

Aha!

OK, I believe that Python2.2 is just being liberal, here. If you look at the
code below, Boost.Python only does that method unwinding when looking at
/base/ class attributes. So, this should work for you:

class Base:
    def __init__(self):
        self.x = 'x'

class BasePrime(Base):
    __init_Base_ = Base.__init__

class Derived(A1,BasePrime):
    def __init__(self):
        A1.__init__(self)
        self.__init_Base_()
        self.y = 'y'

I guess it would be good to have a more explicit mechansim for this, eh?

Oh, please try this one as well:

class BasePrime(Base): pass
class Derived(A1,BasePrime):
    def __init__(self):
        A1.__init__(self)
        BasePrime.__init__(self)

I think that one should work, too, and it's a bit more elegant.

-Dave

---------

      ref local_attribute = m_name_space.get_item(string(name).reference());

      if (local_attribute.get())
          return local_attribute.release();

      // In case there are no bases...
      PyErr_SetString(PyExc_AttributeError, name);

      // Check bases
      for (std::size_t i = 0; i < m_bases.size(); ++i)
      {
          if (PyErr_ExceptionMatches(PyExc_AttributeError))
              PyErr_Clear(); // we're going to try a base class
          else if (PyErr_Occurred())
              break; // Other errors count, though!

          PyObject* base_attribute =
PyObject_GetAttrString(m_bases[i].get(), const_cast<char*>(name));

          if (base_attribute != 0)
          {
              // Unwind the actual underlying function from unbound Python
class
              // methods in case of multiple inheritance from real Python
              // classes. Python stubbornly insists that the first argument
to a
              // method must be a true Python instance object otherwise. Do
not
              // unwrap bound methods; that would interfere with intended
semantics.
              if (PyMethod_Check(base_attribute)
                  &&
reinterpret_cast<PyMethodObject*>(base_attribute)->im_self == 0)
              {
                  PyObject* function
                      =
reinterpret_cast<PyMethodObject*>(base_attribute)->im_func;
                  Py_INCREF(function);
                  Py_DECREF(base_attribute);
                  return function;
              }
              else
              {
                  return base_attribute;
              }
          }
      }


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk