Issue1264260

classification
Title: Multiple inheritance fails with built-in types
Type: Severity: normal
Components: Core Versions:
Milestone:
process
Status: closed Resolution:
Dependencies: Superseder:
Assigned To: fwierzbicki Nosy List: astoddar, fwierzbicki, pedronis
Priority: normal Keywords:

Created on 2005-08-19.18:56:48 by astoddar, last changed 2005-09-05.23:00:32 by fwierzbicki.

Files
File name Uploaded Description Edit Remove
patch_lost_attribute pedronis, 2005-08-19.21:51:45 patch for lost attribute when multi inheriting from new-style and old-style
patch_cast_problem pedronis, 2005-08-19.21:52:25
Messages
msg1023 (view) Author: Alex Stoddard (astoddar) Date: 2005-08-19.18:56:48
A class created with multiple inheritance from a built-in type and a 
non built-in type has faulty method look-up. 

For example:

>>>  class myClass:
...    def foo(self):
...      print "myClass foo called."

>>> class myMulti(dict, myClass):
...    pass
...

>>> t = myMulti()
>>> type(t)
<class '__main__.myMulti'>

>>> t.foo()
Traceback (innermost last):
  File "<console>", line 1, in ?
AttributeError: 'dict' object has no attribute 'foo'


If the order or the inheritance is changed a java ClassCastException 
is thrown at class creation.

>>> class myMulti2(myClass, dict):
...    pass
... 
Traceback (innermost last):
  File "<console>", line 1, in ?
java.lang.ClassCastException
        at org.python.core.PyClass.init(Unknown Source)
        at org.python.core.PyClass.<init>(Unknown Source)
        at org.python.core.Py.makeClass(Unknown Source)
        at org.python.core.Py.makeClass(Unknown Source)
        at org.python.pycode._pyx2.f$0(<console>:1)
        at org.python.pycode._pyx2.call_function(<console>)
        at org.python.core.PyTableCode.call(Unknown Source)
        at org.python.core.PyCode.call(Unknown Source)
        at org.python.core.Py.runCode(Unknown Source)
        at org.python.core.Py.exec(Unknown Source)
        at org.python.util.PythonInterpreter.exec(Unknown Source)
        at org.python.util.InteractiveInterpreter.runcode(Unknown 
Source)
        at org.python.util.InteractiveInterpreter.runsource(Unknown 
Source)
        at org.python.util.InteractiveInterpreter.runsource(Unknown 
Source)
        at org.python.util.InteractiveConsole.push(Unknown Source)
        at org.python.util.InteractiveConsole.interact(Unknown Source)
        at org.python.util.jython.main(Unknown Source)

java.lang.ClassCastException: java.lang.ClassCastException

msg1024 (view) Author: Samuele Pedroni (pedronis) Date: 2005-08-19.21:51:44
Logged In: YES 
user_id=61408

oversights on my part.

the first problem doesn't happen if X is new-style, the
issue is that PyClass doesn't define fastGetDict, see
patch_lost_attr

the second problem is more subtle, old-style classes should
have logic such that if one of the bases is not old-style
its type should be used as metaclass. This cannot be put in
the constructor of PyClass logic because a constructor
cannot return some new instances to substute.

patch_cast_problem puts such logic in Py.makeClass, it
should be the right place but better check whether other
places instatiating PyClass may need a change too (in that
case we need an helper or they should use makeClass instead).

I'm attaching patches and not checking in myself directly
because tonight I have no time to run all the tests and
check all places where PyClass is instantiated. Tomorrow I'm
leaving for a week in Germany for a PyPy sprint.
msg1025 (view) Author: Alex Stoddard (astoddar) Date: 2005-08-20.21:46:58
Logged In: YES 
user_id=1331777

patch_lost_attr  works for the example case but not in a nested situation.
Thus:

>>> class myClass:
... def foo(self):
... print "myClass foo called."

>>> class myNested(myClass):
... pass

>>> class myMulitNested(unicode, myNested):
... pass

>>> t = myMultiNested()
>>> t.foo()Traceback (innermost last):
  File "<console>", line 1, in ?
AttributeError: 'unicode' object has no attribute 'foo'

msg1026 (view) Author: Samuele Pedroni (pedronis) Date: 2005-09-04.17:56:36
Logged In: YES 
user_id=61408

oops, it seems that classic_mro in PyType is incomplete, of
course it should be

    private static PyObject[] classic_mro(PyClass classic_cl) {
        ArrayList acc = new ArrayList();
        fill_classic_mro(acc, classic_cl);
        return (PyObject[])acc.toArray(new PyObject[0]);
    }

the other patches are still very much necessary.
msg1027 (view) Author: Frank Wierzbicki (fwierzbicki) Date: 2005-09-05.23:00:32
Logged In: YES 
user_id=193969

Applied the changes, plus added some test cases in
test_subclasses
History
Date User Action Args
2005-08-19 18:56:48astoddarcreate