faqts : Computers : Programming : Languages : Python : Snippets

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

5 of 7 people (71%) answered Yes
Recently 4 of 6 people (67%) answered Yes

Entry

DirectoryList class

Jul 5th, 2000 10:00
Nathan Wallace, Hans Nowak, Snippet 153, Neelakantan Krishnaswami


"""
Packages: operating_systems.generic;oop
"""
"""
One thing I find myself frequently (okay, twice) doing is trying to
walk a directory tree and do stuff in each directory. It was an annoying
enough chore that I wrote a small class to kill it once and for all, 
and now I'm sharing. :)
So now you can write things like
l = DirectoryList('c:/Program Files/NTemacs')
for dir in l:
    for filename in glob.glob(dir + '/*.el'):
        replace_elisp_with_python(filename)
and replace_elisp_with_python() will get called on every .el file 
in c:\program files\ntemacs and its subdirectories. 
"""
# Name:     DirectoryList.py
# Purpose:  DirectoryList is a sequence class written to make walking
#           through a directory tree very easy. Given a base class, it
#           will generate a sequence of all the subdirectories.
# License:  Released into the public domain by Neel Krishnaswami 15-Mar-1999
# Version:  0.1.0
# Warranty: None whatsoever, use at your own risk. :)
import os
_version = (0,1,0)
class DirectoryList:
    """DirectoryList -- a sequence class that represents the list of
    subdirectories under a base directory. It's intended to make
    stepping through a directory tree extremely easy.
    Object creation:
    foo = DirectoryList(base):
        base is the path that is the root of the directory tree.
    Ex: foo = DirectoryList('c:/Program Files/NTEmacs')
    Methods:
    A DirectoryList supports most of the standard sequence operations,
    including slices. It is guaranteed that the elements will be in
    ascii-betical order; this makes it easier to do things like pick
    a range containing a set of subdirectories.
    >>> for i in range(len(foo)):
    ...     print foo[i]
    ... 
    c:\program files\ntemacs\lisp
    c:\program files\ntemacs\lisp\calendar
    c:\program files\ntemacs\lisp\emacs-lisp
    c:\program files\ntemacs\lisp\emulation
    c:\program files\ntemacs\lisp\gnus
    c:\program files\ntemacs\lisp\international
    c:\program files\ntemacs\lisp\language
    c:\program files\ntemacs\lisp\mail
    c:\program files\ntemacs\lisp\play
    c:\program files\ntemacs\lisp\progmodes
    c:\program files\ntemacs\lisp\term
    c:\program files\ntemacs\lisp\textmodes
    >>> for directory in foo[3:6]: 
    ...     print directory
    ... 
    c:\program files\ntemacs\lisp\emulation
    c:\program files\ntemacs\lisp\gnus
    c:\program files\ntemacs\lisp\international
    The other methods of DirectoryList are:
    o DirectoryList.index(path) -- returns the index of the first
      element that matches the argument. It raises a ValueError if
      no element of the directory list matches the path. 
    >>> foo.index('C:/Program Files/NTEmacs/lisp/gnus')
    4
    >>> foo.index('C:/Python')
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
      File "c:/windows/TEMP/python--3949155iIT", line 30, in index
    ValueError: DirectoryList.index(path): path not in list
    o DirectoryList.renew_subdirs() -- this recreates the directory list,
      in case you have made changes to the directory hierarchy.
      The DirectoryList class creates its list of subdirectories at
      object creation, and keeps that. If you've made alterations to
      the directory tree, you may want to invoke the renew_subdirs()
      method to resync the object's internal list and the file system.
    """
    def __init__(self, base):
        self.base = os.path.normcase(os.path.normpath(base))
        self.renew_subdirs()
    def renew_subdirs(self):
        """DirectoryList.renew_subdirs() -- this recreates the directory
        list, in case you have made changes to the directory hierarchy.
        The DirectoryList class creates its list of subdirectories at
        object creation, and keeps that. If you've made alterations to
        the directory tree, you may want to invoke the renew_subdirs()
        method to resync the object's internal list and the file system."""
        self.subdirs = []
        #
        # I'd like to find a faster way of getting the directories
        # than os.path.walk(), as long as I don't have to do any 
        # work. :)
        os.path.walk(self.base,
                     lambda arg, dirname,
                            names, l=self.subdirs: l.append(dirname),
                     None
                     )
        self.subdirs.sort()
    def index(self, rawdir):
        """DirectoryList.index(path) -- returns the index of the first
        element that matches the argument. It raises a ValueError if
        no element of the directory list matches the path."""
        dir = os.path.normcase(os.path.normpath(rawdir))
        try:
            i = self.subdirs.index(dir)
        except:
            raise ValueError, "DirectoryList.index(path): path not in list"
        return i
    def __cmp__(self, other):
        if type(other) == type(self.subdirs):
            return cmp(self.subdirs, other)
        else:
            return cmp(self.subdirs, other.subdirs)
    def __getitem__(self, i):
        return self.subdirs[i]
    def __getslice__(self, i, j):
        return self.subdirs[i:j]
    def __len__(self):
        return len(self.subdirs)
    def __str__(self):
        return 'DirectoryList:\n' + str(self.subdirs)
    def __repr__(self):
        return "DirectoryList(%s)" % repr(self.base)