It is not possible to create a recursive function over a pyGTK treeStore

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Fri Jun 29 14:53:08 CEST 2007


sebastien.abeille at gmail.com a écrit :
> Hello,
> 
> I would like to create a minimalist file browser using pyGTK.
> 
> Having read lot of tutorials, it seems to me that that in my case, the
> best solution is
> to have a gtk.TreeStore containing all the files and folders so that
> it would map the
> file system hierarchy.
> 
> I wrote a recursive function that would go through the file system
> tree.
> 
> My problem is that a sub-node of a gtk.TreeStore is not a
> gtk.TreeStore, but
> a gtk.TreeIter. And gtk.treeter has almost no functions I would be
> able to use (like "append")
> Therefore I can not explore the whole file system.
> 
> Do you have another way so that I would be able to put all the file
> system hierarchy
> into a gtk.TreeStore?

Sorry, no anwser to that - I don't do much GUI programming. But asking 
on GTK mailing-list may be a good idea.

> I was quite happy with my recursive solution ...

A couple of comments on the code:

> #!/usr/bin/env python
> import pygtk
> pygtk.require('2.0')
> import gtk, gobject, os
> 
> 
> prefdir="/tmp/a"
> 
> class InfoModele:

Do yourself (and the world) a favour: use new-styles classes. And while 
we're at it, be consistant wrt/ naming:

   class InfoModel(object):

> 	def matchPathTreetoModelTree(self, path, treeStoreNode):

<side-note>
You're of course free to use mixedCase, but unless this is a 
project-specific (or workplace-specific) convention, it might be better 
to stick to pep08 (all_lower_with_underscores). But if you choose 
mixedCase, at least be consistant
(ie : self.tree_store => self.treeStore)
</side-note>

> 		files = [f for f in os.listdir(path) if f[0] <> '.']

could also use str.startswith here:

  		files = [f for f in os.listdir(path) \
                          if not f.startswith('.')]

But I don't see the point of this listcomp when you could filter out 
special names in the for loop.

> 		for i in range(len(files)):

Coming from a C-like language ?-)

The for loop in Python is much smarter than this. You don't have to use 
an explicit indexing, you can just iterate over the sequence, ie, 
instead of:

   for i in range(len(files)):
      the_file = files[i]
      do_something_with(the_file)

You can do:

   for the_file in files:
      do_something_with(the_file)

NB : if you need the index for any other reason, you can use enumerate(seq):

   for i, the_file in enumerate(files):
      print >> sys.stderr, "file #%s" % i
      do_something_with(the_file)


> 			if os.path.isfile(path+'/'+files[i]):
> 				print path+'/'+files[i]+" is a file"
> 				treeStoreNode.append( None, (path+'/'+files[i], None) )

My...

1/: use os.path.join()
2/: avoid recomputing the same value thrice or more, especially if 
within a loop
3/ (optional, but good to know): within loops, make the often used 
methods locals - this will save *a lot* of lookup time (since Python is 
highly dynamic, the compiler cannot optimize much here).
4/ stdout is for normal program outputs. Error messages, debug 
informations et al should go to stderr

> 			if os.path.isdir(path+'/'+files[i]): 

Note that you should'nt do this test if the previous succeeded, since 
both are exclusive. IOW, use a elif.

 >	print path+'/'+files[i]+" is a directory"
 >	mother = self.tree_store.append(None, (path+'/'+files[i], None))

You certainly have an error here. If you're already in a subdirectory, 
you don't want to create the node on the root but on the parent's 
directory node - IOW, dont use self.tree_store, but treeStoreNode. Which 
allow to further simplify the code (cf below)

 >	self.matchPathTreetoModelTree(path+'/'+files[i], mother)
> 
> 	def __init__(self):
> 		self.tree_store = gtk.TreeStore( gobject.TYPE_STRING,
> gobject.TYPE_STRING)
> 		path=prefdir

This should be an argument of the initializer

> 		self.matchPathTreetoModelTree(prefdir, self.tree_store)
(snip)

Suggestion:

class InfoModel(object):
   def __init__(self, path):
     self.basepath = path
     self.treeStore = gtk.TreeStore(
                          gobject.TYPE_STRING,
                          gobject.TYPE_STRING
                          )
     self.matchPathTreetoModelTree(path, self.treeStore)

   def matchPathTreetoModelTree(self, path, treeStoreNode):
     isdir = os.path.isdir
     join = os.path.join
     append= treeStoreNode.append
     recurse = self.matchPathTreetoModelTree

     filenames = os.listdir(path)
     for filename in filenames:
       if filename.startswith('.'):
         continue

       filepath = join(path, filename)
       # tracing for debug - assuming this will disappear
       # before going to prod, it's ok to repeat the call
       # to isdir() here
       print >> sys.stderr,  "%s is a %s" \
           % (filepath, ('file', 'dir')[isdir(filepath)])

       # nb: you may want to filter out non-regular files
       # like devices, sockects etc here
       newnode = append(None, (filepath, None))
       if isdir(filepath):
         recurse(filepath, newnode)


HTH



More information about the Python-list mailing list