>> I'm using Windows XP, using IDLE (which was mentioned already)

> in the context of editing/displaying code, not executing it. Does the
> problem occur before or after you edit a file with IDLE?

Actually, neither. I'm not editing the code. I open it in IDLE in 2.5
and attempt to run it through the Run menu "Run Module" menu item or
by pressing F5. It immediately fails with a tabnanny error. If I run
it from 2.4's IDLE, it works.

>> and I
>> downloaded the 2.5.1 exe/msi file from python.org to install it.

> What you downloaded doesn't answer the question about how you
> installed it. Do you still have your 2.4 installation?

Yes, I use both 2.4 and 2.5 as I migrate from one to the other. I've
attached a file that causes it consistently. On two systems with both
2.4 and 2.5 installed, it fails on line 206 when run from the IDLE
included with 2.5.

>> I have yet to find a simple one which exhibits the issue to post. It
>> seems to happen to my complex files, not the simple ones.

> So chop up a complex file ...
> Have you inspected the failing files using a text editor that can
> display tabs and spaces (e.g. PythonWin, TextPad)?

I just used Notepad++ to inspect the file and it does indeed have tabs
at line 206 rather than spaces. I take it that Python 2.5 is more
sensitive to that than is 2.4? I program almost exclusively in IDLE as
I'd read that this can happen in some text editors, but it seemed
implied that it didn't if you used IDLE. At least, that's what I got
from various Python books and the website:
http://www.python.org/idle/doc/idlemain.html

Anyway, thanks for the help.

Mike
# scrubber.pyw
#
# Author: Mike Driscoll
#
# Updated: 05/16/2007
#
# Deletes folders and files, ignores errors. The deletion functions
# run in a separate thread.


import wx
import os
import glob
import sys
import shutil
import time
import win32api

from threading import Thread

userid = win32api.GetUserName()

class ProfileScrubber(wx.App):
    def __init__(self, redirect=True, filename=None):
        wx.App.__init__(self, redirect, filename)
        
    def OnInit(self):
        self.frame = wx.Frame(None, -1, title='Profile Scrubber Beta 0.3', 
size=(400,500))
    
        panel = wx.Panel(self.frame, -1)

        # user list up-to-date as of 10/20/2006
        user_list = self.getProfileList()
        
        tempF = r'C:\Documents and Settings\%s\Local Settings\Temp' % userid
        tempIntF = r'C:\Documents and Settings\%s\Local Settings\Temporary 
Internet Files' % userid

        # Create the controls        
        descriptionLbl = wx.StaticText(panel, -1, ' Choose an option below:')
        font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD)
        descriptionLbl.SetFont(font)
        genericPathLbl = wx.StaticText(panel, -1, 'Enter Path:')
        self.path = wx.TextCtrl(panel, -1, '', size=(500,-1))

        optionLbl = wx.StaticText(panel, -1, 'Other Folders to be Deleted:')
        optionLbl.SetFont(font)
        self.tempCkbx = wx.CheckBox(panel, -1, 'Temp', size=wx.DefaultSize)
        self.tempCkbx.SetValue(True)
        self.tempFilesCkbx = wx.CheckBox(panel, -1, 'Temporary Internet Files', 
size=wx.DefaultSize)
        self.tempFilesCkbx.SetValue(True)
        self.tempTxt = wx.TextCtrl(panel, -1, tempF, size=(500,-1))
        self.tempTxt.Disable()
        self.tempFilesTxt = wx.TextCtrl(panel, -1, tempIntF, size=(500,-1))
        self.tempFilesTxt.Disable()        
                
        useridLbl = wx.StaticText(panel, -1, 'Choose the user \n(if 
different):')
        self.user = wx.ComboBox(panel, -1, userid, None, (150, -1), user_list, 
wx.CB_DROPDOWN)
        self.user.Bind(wx.EVT_COMBOBOX, self.comboChoice)
        
        scrubBtn = wx.Button(panel, -1, 'Scrub')
        self.Bind(wx.EVT_BUTTON, self.scrub, scrubBtn)
        closeBtn = wx.Button(panel, -1, 'Close')
        self.Bind(wx.EVT_BUTTON, self.close, closeBtn)

        # create a checklistbox widget to list all the user profiles on the 
machine
        profLbl = wx.StaticText(panel, -1, 'Please choose what profiles to 
remove:')
        profLbl.SetFont(font)
        self.profile_list = self.getProfileList()
        self.profile_cblb = wx.CheckListBox(panel, -1, size=(100, -1), 
choices=self.profile_list)

        # delete button
        deleteBtn = wx.Button(panel, -1, 'Delete Profiles')
        self.Bind(wx.EVT_BUTTON, self.deleteProfile, deleteBtn)
        
        # Main sizer to hold all the lesser sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(descriptionLbl)
        mainSizer.Add((10,10))
        
        # pathSizer holds the top set of widgets
        pathSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
        pathSizer.AddGrowableCol(1)
        pathSizer.Add(genericPathLbl, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
        pathSizer.Add(self.path, 0, wx.EXPAND)
        pathSizer.Add(useridLbl, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
        pathSizer.Add(self.user, 1)
        pathSizer.Add((10,10))
        pathSizer.Add((10,10))
        pathSizer.Add((10,10))
        pathSizer.Add((10,10))
        pathSizer.Add(optionLbl,0)
        pathSizer.Add((10,10))
        pathSizer.Add(self.tempCkbx,0)
        pathSizer.Add(self.tempTxt,1)
        pathSizer.Add(self.tempFilesCkbx,0)
        pathSizer.Add(self.tempFilesTxt,1)
                        
        # btnSizer (holds the scrub & close buttons)       
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(scrubBtn)
        btnSizer.Add((20,20), 1)
        btnSizer.Add(closeBtn)
        pathSizer.Add((10,10))
        pathSizer.Add(btnSizer, 1, wx.ALIGN_CENTER)

        # Profile Sizer (holds the check box / combobox and its delete button)
        profSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
        profSizer.Add(profLbl, 0)
        profSizer.Add((10,10))
        profSizer.Add(self.profile_cblb, 0)
        profSizer.Add((10,10))
        profSizer.Add(deleteBtn, 0)

        # Add the pathSizer to mainSizer        
        mainSizer.Add(pathSizer, 0, wx.EXPAND|wx.ALL, 10)
        mainSizer.Add(profSizer, 0, wx.EXPAND|wx.ALL, 10)
        panel.SetSizer(mainSizer)
        mainSizer.Fit(self.frame)
        mainSizer.SetSizeHints(self.frame)

        # initialize the thread
        self.iniThread()

        # ---- Make the app visible / OnInit requires a boolean "return" 
        self.frame.Show(True)
        return True

    def comboChoice(self, event):
        ''' On choice, change the two "Temp" directory paths to match the user 
choice. '''
        self.tempTxt.SetValue('')
        self.tempFilesTxt.SetValue('')
        new_user = event.GetString()
        self.tempTxt.AppendText(r'C:\Documents and Settings\%s\Local 
Settings\Temp' % new_user)
        self.tempFilesTxt.AppendText(r'C:\Documents and Settings\%s\Local 
Settings\Temporary Internet Files' % new_user)
            
    def scrub(self, event):
        ''' Delete the folders that the user has chosen. '''
        folders = []
        x = 0   #  Used to control what gets popped
        tempck = self.tempCkbx.GetValue()
        tempFiles_ck = self.tempFilesCkbx.GetValue()
        user_path = self.path.GetValue()
        paths = [self.path, self.tempTxt, self.tempFilesTxt]

        if tempck == False:
            paths.pop(1)
            x = 1
            
        if tempFiles_ck == False:
            if x:       # if true, then there's only 2 values, so pop the 2nd
                paths.pop(1)
            else:       # if false, there's 3 values, so pop the 3rd
                paths.pop(2)
        
        # Create a list of paths to be deleted
        for path in paths:
            if path.GetValue() != '':
                folders.append(path.GetValue())

        # If the user doesn't enter a path and unchecks both boxes, let the 
user know!
        if tempck == False and tempFiles_ck == False and user_path == '':
            dlg = wx.MessageDialog(None, 'You need to enter a path or check a 
checkbox to delete.',
                                   'Information', wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
        
        # Get response code
        resCode = self.warningMessage(folders)
            
        # Delete the folder(s) if user chose "Yes"     
        if (resCode == wx.ID_YES):            
            t = time.ctime()
            print '**************************************************'
            print '\nNew Scrub Job accepted %s\n' % t
            print '**************************************************'
            FDeleteThread(self, folders)
       
    
    def warningMessage(self, folders):
        ''' Create a custom warning message for the user based on his choices. 
'''
        if len(folders) == 3:
            response = wx.MessageDialog(None, 'This will attempt to delete 
these folder\'s subfolders:\n\n%s\n%s\n%s\n\nIs this OK?' % 
(folders[0],folders[1],folders[2]),
                                            'WARNING', wx.YES_NO | 
wx.ICON_QUESTION)
            resCode = response.ShowModal()
            response.Destroy()
        elif len(folders) == 2:
            response = wx.MessageDialog(None, 'This will attempt to delete 
these folder\'s subfolders:\n\n%s\n%s\n\nIs this OK?' % (folders[0],folders[1]),
                                            'WARNING', wx.YES_NO | 
wx.ICON_QUESTION)
            resCode = response.ShowModal()
            response.Destroy()
        elif len(folders) == 1:
            response = wx.MessageDialog(None,'This will attempt to delete this 
folder\'s subfolders:\n\n%s\n\nIs this OK?' % (folders[0]),
                                            'WARNING', wx.YES_NO | 
wx.ICON_QUESTION)
            resCode = response.ShowModal()
            response.Destroy()
        else:
            pass            
        return resCode
    
    def getProfileList(self):
        ''' Search "Documents and Settings" folder and create a list of user 
profiles. '''
        userPaths = glob.glob(r'c:\documents and settings\\*')
        user_list = []
        for i in userPaths:
            if len(i[26:]) > 6:
                pass
            elif i[26:].upper() == userid:
                pass
            else:
                user_list.append(i[26:])
        return user_list

    def deleteProfile(self, event):
        ''' Delete the profile(s). '''        

        prof_list = []
        count = 0
        resCode = ''
        prof_dir = r'C:\Documents and Settings'

        # Check if any profiles are checked and create a list of them.
        for i in self.profile_list:
            if self.profile_cblb.IsChecked(count):
                print '%s is checked' % i
                prof_list.append(i)
            else:
                print '%s is NOT checked' % i
            count += 1
            
        # Warn user about deleting profiles
        if len(prof_list) > 0:
            response = wx.MessageDialog(None, 'Do you really want to delete 
these profile(s)?',
                                                'WARNING', wx.YES_NO | 
wx.ICON_QUESTION)
            resCode = response.ShowModal()
            response.Destroy()

        # If "Yes" is chosen, delete the checked profiles    
        if resCode == wx.ID_YES:
            for x in prof_list:
                print prof_dir + '\\%s' % x
                #shutil.rmtree(prof_dir + '\\%s' % x, ignore_errors=True)
                #os.system(r'RD /S /Q "%s"' % (prof_dir + '\\%s' % x))
                subprocess.Popen(r'RD /S /Q "%s"' % (prof_dir + '\\%s' % x), 
shell=True)
            print 'Finished deleting selected profiles.'

        # Clear the combo-listbox
        self.profile_cblb.Clear()
        print 'cleared'
        self.profile_cblb.AppendItems(self.getProfileList())

    def iniThread(self):
        ''' Initialize thread object. '''
        
        ##### beginning of threading code setup #####
        # Set up event handler for any worker thread results
        EVT_RESULT(self,self.onResult)

        # And indicate we don't have a worker thread yet
        self.worker = None
        ###### end of threading code #######

    def onResult(self, event):
        ''' Reset the worker thread to None. '''       
        print 'Thread has finished!'
        self.worker = None
        
    def close(self, event):
        ''' Close the window '''
        self.frame.Close(True)


#####################################################################################
EVT_RESULT_ID = wx.NewId()

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)
    
class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_RESULT_ID)
        self.data = data
    
class FDeleteThread(Thread):
    """Printer Child Thread Class."""
        
    def __init__(self, notify_window, fList):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self._notify_window = notify_window
        self._want_abort = 0        
        self.folders = fList
        self.start()    # start the thread

    def run(self):
        """Run Worker Thread."""
        for folder in self.folders:
                dirs = glob.glob(folder + '\\*')
                files = glob.glob(folder + '\\*.*')
                for d in dirs:
                    if os.path.isdir(d):                        
                        self.delete2(d)
                    # END IF
                # END INNER FOR LOOP
                for f in files:
                    try:
                        os.remove(f)
                    except:
                        print 'ERROR - Could not remove: %s' % f
        print 'Scrubbing finished!'
        wx.PostEvent(self._notify_window, ResultEvent(10))

    def delete2(self, item):                
        
        if os.path.isdir(item):
            try:
                print '\nDeleting %s' % item
                shutil.rmtree(item)
            except:
                #os.system(r'RD /S /Q "%s"' % item)
                subprocess.Popen(r'RD /S /Q "%s"' % item, shell=True)
        else:
            try:
                os.remove(item)
            except:
                #os.system('DEL /F /S /Q "%s"' % item)
                subprocess.Popen(r'DEL /F /S /Q  "%s"' % item, shell=True)

if __name__ == '__main__':
    app = ProfileScrubber()
    app.MainLoop()
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to