Ticket #71 (closed bug: fixed)
Initializer breakage in base.py for Python >= v2.6
Reported by: | jason@… | Owned by: | parpg |
---|---|---|---|
Priority: | major | Milestone: | Techdemo 1 |
Component: | scripts | Version: | trunk |
Keywords: | inheritance initializer 2.6 python | Cc: | |
Blocked By: | Blocking: | ||
Department: |
Description
I got this error trying to run PARPG on a brand-new installation:
Traceback (most recent call last):
File "run.py", line 149, in <module>
main()
File "run.py", line 145, in main
app = PARPG()
File "run.py", line 87, in init
self.model.loadMap(str(TDS.readSetting("MapFile?")))
File "/home/jason/FIFE/clients/parpg/scripts/engine.py", line 266, in loadMap
self.loadObjects(map_file[:-4] + "_objects.xml")
File "/home/jason/FIFE/clients/parpg/scripts/engine.py", line 121, in loadObjects
self.createGameObjects(other_handler.local_info)
File "/home/jason/FIFE/clients/parpg/scripts/engine.py", line 137, in createGameObjects
obj = createObject(info, extra)
File "/home/jason/FIFE/clients/parpg/scripts/objects/init.py", line 52, in createObject
return getAllObjects()[obj_type](ID, info)
File "/home/jason/FIFE/clients/parpg/scripts/objects/actors.py", line 275, in init
super(NonPlayerCharacter?, self).init(ID, kwargs)
File "/home/jason/FIFE/clients/parpg/scripts/objects/base.py", line 91, in init
super(GameObject?,self).init (kwargs)
File "/home/jason/FIFE/clients/parpg/scripts/objects/base.py", line 209, in init
super(Living,self).init (kwargs)
File "/home/jason/FIFE/clients/parpg/scripts/objects/base.py", line 222, in init
super(Scriptable,self).init (kwargs)
File "/home/jason/FIFE/clients/parpg/scripts/objects/base.py", line 238, in init
super(CharStats?,self).init (kwargs)
I ran this on Ubuntu 9.04 with the default Python installation, Python 2.6.2.0.
This error cropped up because of the changes made in Python 2.6. Note that this error did not manifest on Windows machines running 2.6. The only reason I can think is that the reporter was running ActiveState? Python, and ActiveState? often applies patches to the vanilla source before packing it for release.
The technique used to initialize base classes that are multiply-inherited is not Python 2.6+ friendly. The current strategy depends on cooperative super() calls in every base class. Because the root of the inheritance tree is the Python class 'object', eventually object.init() is called with two arguments, like this:
super( <blah>, self ).init( self, kwargs )
where 'kwargs' are passed into the caller's init(). Pre-Python 2.6, this worked fine, because object.init() ignored all of its arguments.
I have confirmed that both the vanilla Python 2.6.2.0 distribution as well as the Ubuntu 9.04 distribution both exhibit this behavior.
My suggestion is to replace the cooperative super() calls with simple, explicit calls to base class initializers. This actually simplifies the code, IMHO. For one, it removes the seemingly random 'super()' calls in classes with no base (other than 'object'). For another, it makes it patently obvious what's going on.
I've attached a patch (taken at FIFE/clients/parpg) that contains my changes to base.py and actors.py. Submitted for your approval.