[wxPython] wxMVCTree - *very* strange behavior

I'm having a very weird problem with wxMVCTree
(python 2.2, wxPython-2.3.2.1, "wxGTK2.3_1-2.3.2-4mdk")

Here's a short program that is supposed to display a
directory tree starting at any chosen directory:

import os
from wxPython.wx import *
from wxPython.lib.mvctree import *

frame = wxFrame(None, -1, "Weird MVCTree Behavior")
tree = wxMVCTree(frame, -1)
tree.SetModel(FSTreeModel(os.getcwd()))

menu = wxMenu()
wxid = wxNewId()
menu.Append(wxid, "&Open Directory\tCtrl-O"," Open another directory")

def OnMenuOpen(e):
    dlg = wxDirDialog(frame, "Choose a directory", os.getcwd())
    dlg.ShowModal()
    tree.SetModel(FSTreeModel(dlg.GetPath()))

EVT_MENU(frame, wxid, OnMenuOpen)
menuBar = wxMenuBar()
menuBar.Append(menu,"&File")
frame.SetMenuBar(menuBar)

app = wxPySimpleApp()
frame.Show(1)
app.MainLoop()

However, it doesn't work: The first diretory shows up fine, but
subsequent directories get *added* to the tree - i.e. both the new
and the old tree gets merged together (the best way to understand it
is to just try out the program).

This behavior can be fixed by modifying wxPython/lib/mvctree.py
slightly:

Line 869 (class wxMVCTree, function SetModel)
  > self.layoutRoot = MVCTreeNode()
  > self.layoutRoot = MVCTreeNode(None, None, [])

This change fixes the problem. But - and here's the weirdest part
of the story - the MVCTreeNode() constructor is defined as follows:

class MVCTreeNode:
    def __init__(self, data=None, parent=None, kids=[], x=0, y=0):
        ...

So, MVCTreeNode() should be equivalent to MVCTreeNode(None, None, [])
since (None, None, []) are exactly the default parameters values in the
constructor. So the change I made shouldn't have any effect at all.

Either I'm missing something very fundamental here, or there's a
bug somewhere in the python interpreter...

Any ideas on what's going on here?

-Paramjit Oberoi

···

_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com

This behavior can be fixed by modifying wxPython/lib/mvctree.py
slightly:

Line 869 (class wxMVCTree, function SetModel)
  > self.layoutRoot = MVCTreeNode()
  > self.layoutRoot = MVCTreeNode(None, None, )

This change fixes the problem. But - and here's the weirdest part
of the story - the MVCTreeNode() constructor is defined as follows:

class MVCTreeNode:
    def __init__(self, data=None, parent=None, kids=, x=0, y=0):
        ...

So, MVCTreeNode() should be equivalent to MVCTreeNode(None, None, )
since (None, None, ) are exactly the default parameters values in the
constructor. So the change I made shouldn't have any effect at all.

Either I'm missing something very fundamental here, or there's a
bug somewhere in the python interpreter...

This is a common Python problem and the following patch will fix it. The
issue is that when setting self.kids to the default parameter and then
appending to it, the default empty list opbject is being modified, and then
later when called with the default again, the modified list is reused. The
patch changes it so it will not use an empty list as the default, but assign
a new empty list when needed.

(this patch will probably get word wrapped, but you should easily get the
jist of it...)

Index: mvctree.py

···

===================================================================
RCS file: /home/wxcvs/wxWindows/wxPython/wxPython/lib/mvctree.py,v
retrieving revision 1.5
diff -u -4 -r1.5 mvctree.py
--- mvctree.py 2 Jul 2002 17:12:13 -0000 1.5
+++ mvctree.py 7 Aug 2002 04:56:13 -0000
@@ -36,15 +36,17 @@
     Used internally by wxMVCTree to manage its data. Contains information
about
     screen placement, the actual data associated with it, and more. These
are
     the nodes passed to all the other helper parts to do their work with.
     """
- def __init__(self, data=None, parent = None, kids = , x = 0, y = 0):
+ def __init__(self, data=None, parent = None, kids = None, x = 0, y =
0):
         self.x = 0
         self.y = 0
         self.projx = 0
         self.projy = 0
         self.parent = parent
         self.kids = kids
+ if self.kids is None:
+ self.kids =
         self.data = data
         self.expanded = false
         self.selected = false
         self.built = false

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!