You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@gump.apache.org by aj...@apache.org on 2004/02/17 22:54:22 UTC

cvs commit: jakarta-gump/python/gump/test/resources/circular1 workspace.xml

ajack       2004/02/17 13:54:22

  Modified:    python/gump/model workspace.py project.py object.py stats.py
                        loader.py rawmodel.py state.py
               python/gump/utils launcher.py xmlutils.py work.py
               python/gump/output nag.py
               python/gump/test/resources/broken1 broken_workspace.xml
               python/gump/test model.py maven.py nagging.py xdoc_tests.py
                        stats.py pyunit.py utils.py gumpset_tests.py
               python/gump/test/resources/simple1 standalone_workspace.xml
               python/gump/syndication syndicator.py
               python/gump/document documenter.py forrest.py text.py
               python/gump/test/resources/full1 profile.xml workspace.xml
               python/gump/test/resources/simple2 workspace.xml
               python/gump/test/resources/circular1 workspace.xml
  Added:       python/gump/results model.py __init__.py loader.py
                        resulter.py rawmodel.py .cvsignore
               python/gump/test resulting.py
               python/gump/test/resources/full1 tracker1.xml
  Log:
  1) Tweaks due to running pychecker
  2) 'results' -- a work in progress, that ain't progressing fast...
  	[i.e. downloading results.xml from other servers...]
  
  Revision  Changes    Path
  1.29      +13 -6     jakarta-gump/python/gump/model/workspace.py
  
  Index: workspace.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/workspace.py,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- workspace.py	15 Feb 2004 17:32:05 -0000	1.28
  +++ workspace.py	17 Feb 2004 21:54:20 -0000	1.29
  @@ -76,7 +76,7 @@
   from gump.model.module import Module, createUnnamedModule
   from gump.model.project import Project, ProjectSummary
   from gump.model.profile import Profile
  -from gump.model.object import ModelObject
  +from gump.model.object import NamedModelObject
   from gump.model.property import PropertyContainer
   from gump.model.stats import Statable, Statistics
   from gump.utils.note import transferAnnotations, Annotatable
  @@ -91,10 +91,17 @@
   BAD_ENVIRONMENT=3
   
   
  -class Workspace(ModelObject,PropertyContainer, Statable):
  +class Workspace(NamedModelObject, PropertyContainer, Statable):
       """Gump Workspace"""
       def __init__(self,xmlworkspace):
  -    	ModelObject.__init__(self,xmlworkspace)    	
  +    
  +        # Workspaces
  +        name='Unnamed'
  +        if xmlworkspace:
  +            if xmlworkspace.getName():
  +                name=xmlworkspace.getName()
  +            
  +    	NamedModelObject.__init__(self,name,xmlworkspace)    	
       	PropertyContainer.__init__(self)
       	
       	#
  
  
  
  1.51      +7 -5      jakarta-gump/python/gump/model/project.py
  
  Index: project.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/project.py,v
  retrieving revision 1.50
  retrieving revision 1.51
  diff -u -r1.50 -r1.51
  --- project.py	13 Feb 2004 22:12:38 -0000	1.50
  +++ project.py	17 Feb 2004 21:54:20 -0000	1.51
  @@ -1004,14 +1004,16 @@
               properties.addPrefixedNamedParameter('-D',property.name,property.value,'=')
           return properties
   
  -    def generateMavenProperties(self):
  +    # The propertiesFile parameter is primarily for testing.
  +    def generateMavenProperties(self,propertiesFile=None):
           """Set properties/overrides for a Maven project"""
           
           #
           # Where to put this:
           #
           basedir = self.maven.getBaseDirectory() or self.getBaseDirectory()
  -        propertiesFile=os.path.abspath(os.path.join(\
  +        if not propertiesFile: 
  +            propertiesFile=os.path.abspath(os.path.join(	\
                       basedir,'build.properties'))
           
           if os.path.exists(propertiesFile):
  
  
  
  1.17      +5 -5      jakarta-gump/python/gump/model/object.py
  
  Index: object.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/object.py,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- object.py	10 Feb 2004 22:48:52 -0000	1.16
  +++ object.py	17 Feb 2004 21:54:20 -0000	1.17
  @@ -112,9 +112,9 @@
                   # Describe the problem
                   #
                   if not message:
  -                    message = lower(stateName(state))
  +                    message = lower(stateDescription(state))
                       if not REASON_UNSET == reason:
  -                        message += " with reason " + lower(reasonString(reason))            
  +                        message += " with reason " + lower(reasonDescription(reason))            
                   self.addError(capitalize(message))
           
                   # Send on the changes...
  
  
  
  1.10      +4 -3      jakarta-gump/python/gump/model/stats.py
  
  Index: stats.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/stats.py,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- stats.py	21 Jan 2004 18:52:30 -0000	1.9
  +++ stats.py	17 Feb 2004 21:54:20 -0000	1.10
  @@ -91,6 +91,7 @@
           self.previousState=STATE_UNSET
           self.startOfState=-1        
           self.sequenceInState=0
  +        self.lastUpdated=0
                   
       def getFOGFactor(self):
           return round((float(self.successes) / (float(self.failures) + float(self.prereqs))), 2)
  
  
  
  1.7       +5 -3      jakarta-gump/python/gump/model/loader.py
  
  Index: loader.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/loader.py,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- loader.py	15 Feb 2004 17:32:05 -0000	1.6
  +++ loader.py	17 Feb 2004 21:54:20 -0000	1.7
  @@ -92,6 +92,7 @@
         #
         # Clear out the maps
         #
  +      XMLWorkspace.map={}
         XMLProfile.map={}
         XMLRepository.map={}
         XMLModule.map={}
  @@ -125,6 +126,7 @@
         #
         # Clear out the maps [so don't continue to use them]
         #
  +      XMLWorkspace.map={}
         XMLModule.map={}
         XMLProject.map={}
         XMLProfile.map={}
  
  
  
  1.15      +12 -10    jakarta-gump/python/gump/model/rawmodel.py
  
  Index: rawmodel.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/rawmodel.py,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- rawmodel.py	15 Feb 2004 17:32:05 -0000	1.14
  +++ rawmodel.py	17 Feb 2004 21:54:20 -0000	1.15
  @@ -108,9 +108,11 @@
         if not name == '@basedir' and not name == 'annotations':
             self.__dict__[name]=value.replace('@@DATE@@',gump.default.date)
         
  -class XMLWorkspace(GumpXMLModelObject):
  +class XMLWorkspace(Named,GumpXMLModelObject):
     """Represents a <workspace/> element."""
   
  +  map={}
  +  
     def init(self):
       self.property=Multiple(XMLProperty)
       self.project=Multiple(XMLProject)
  @@ -124,7 +126,7 @@
       
   # represents a <profile/> element
   class XMLProfile(Named,GumpXMLModelObject):
  -  list={}
  +  map={}
     def init(self):
       self.project=Multiple(XMLProject)
       self.module=Multiple(XMLModule)
  @@ -134,7 +136,7 @@
   
   # represents a <module/> element
   class XMLModule(Named):
  -  list={}
  +  map={}
     def init(self):
       self.cvs=Single(GumpXMLModelObject)
       self.svn=Single(GumpXMLModelObject)
  @@ -147,7 +149,7 @@
   
   # represents a <server/> element
   class XMLServer(Named):
  -  list={}
  +  map={}
     def init(self):
       self.attribution=Single(GumpXMLModelObject)
       self.title=Single(GumpXMLModelObject)
  @@ -156,7 +158,7 @@
       
   # represents a <tracker/> element
   class XMLTracker(Named):
  -  list={}
  +  map={}
     def init(self):
       self.attribution=Single(GumpXMLModelObject)
       self.title=Single(GumpXMLModelObject)
  @@ -165,7 +167,7 @@
   
   # represents a <repository/> element
   class XMLRepository(Named):
  -  list={}
  +  map={}
     def init(self):
       self['home-page']=Single(GumpXMLModelObject)
       self.title=Single(GumpXMLModelObject)
  @@ -186,7 +188,7 @@
   
   # represents a <project/> element
   class XMLProject(Named):
  -  list={}
  +  map={}
     def init(self):
       self.ant=Single(XMLAnt)
       self.maven=Single(XMLAnt)
  
  
  
  1.11      +56 -9     jakarta-gump/python/gump/model/state.py
  
  Index: state.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/state.py,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- state.py	28 Jan 2004 00:13:39 -0000	1.10
  +++ state.py	17 Feb 2004 21:54:20 -0000	1.11
  @@ -73,6 +73,13 @@
   STATE_PREREQ_FAILED=4
   STATE_COMPLETE=5
   
  +stateNames = { STATE_UNSET : "Unset",
  +           STATE_NONE : "NoWork",
  +           STATE_SUCCESS : "Success",
  +           STATE_FAILED : "Failed",
  +           STATE_PREREQ_FAILED : "PrereqFailed",
  +           STATE_COMPLETE : "Complete" }
  +
   stateDescriptions = { STATE_UNSET : "Unset",
              STATE_NONE : "No Work Performed",
              STATE_SUCCESS : "Success",
  @@ -81,9 +88,18 @@
              STATE_COMPLETE : "Complete" }
   
   def stateName(state):
  -    return stateDescriptions.get(state,'Unknown State:' + str(state))
  -    
  +    return stateNames.get(state,'Unknown:' + str(state)) 
  +       
  +def stateDescription(state):
  +    return stateDescriptions.get(state,'Unknown State:' + str(state))    
   
  +namedState = { "Unset" : STATE_UNSET,
  +           "NoWork" : STATE_NONE,
  +            "Success" : STATE_SUCCESS,
  +            "Failed" : STATE_FAILED,
  +            "PrereqFailed" : STATE_PREREQ_FAILED,
  +            "Complete"  : STATE_COMPLETE}
  +            
   describedState = { "Unset" : STATE_UNSET,
              "No Work Performed" : STATE_NONE,
               "Success" : STATE_SUCCESS,
  @@ -92,6 +108,9 @@
               "Complete"  : STATE_COMPLETE}
              
   def stateForName(name):
  +    return namedState.get(name,STATE_UNSET)
  +    
  +def stateForDescription(name):
       return describedState.get(name,STATE_UNSET)
   
   stateMap = {   CMD_STATE_NOT_YET_RUN : STATE_UNSET,
  @@ -116,6 +135,19 @@
   REASON_BUILD_TIMEDOUT=10
   REASON_MISSING_OUTPUTS=11
   
  +reasonCodeNames = { 	REASON_UNSET : "NotSet",
  +                    REASON_PACKAGE : "CompletePackageInstall",
  +                    REASON_PACKAGE_BAD : "BadPackageInstallation",
  +                    REASON_CIRCULAR : "CircularDependency",
  +                    REASON_CONFIG_FAILED : "ConfigurationFailed",
  +                    REASON_UPDATE_FAILED : "UpdateFailed",
  +                    REASON_SYNC_FAILED : "SynchronizeFailed",
  +                    REASON_PREBUILD_FAILED : "Pre-BuildFailed",
  +                    REASON_BUILD_FAILED : "BuildFailed",
  +                    REASON_POSTBUILD_FAILED : "Post-BuildFailed",
  +                    REASON_BUILD_TIMEDOUT : "BuildTimedOut",
  +                    REASON_MISSING_OUTPUTS : "MissingBuildOutputs" }    
  +                    
   reasonCodeDescriptions = { 	REASON_UNSET : "Not Set",
                       REASON_PACKAGE : "Complete Package Install",
                       REASON_PACKAGE_BAD : "Bad Package Installation",
  @@ -129,7 +161,10 @@
                       REASON_BUILD_TIMEDOUT : "Build Timed Out",
                       REASON_MISSING_OUTPUTS : "Missing Build Outputs" }    
       
  -def reasonString(reasonCode):
  +def reasonName(reasonCode):
  +    return reasonCodeNames.get(reasonCode,'Unknown:' + str(reasonCode))
  +    
  +def reasonDescription(reasonCode):
       return reasonCodeDescriptions.get(reasonCode,'Unknown Reason:' + str(reasonCode))
             
   class StatePair:
  @@ -142,9 +177,9 @@
           return str(self)
           
       def __str__(self):
  -        result=stateName(self.state)
  +        result=stateDescription(self.state)
           if not self.reason == REASON_UNSET:
  -            result += ":" + reasonString(self.reason)
  +            result += ":" + reasonDescription(self.reason)
           return result
           
       def __eq__(self,other):
  @@ -162,14 +197,20 @@
           return self.state
           
       def getStateDescription(self):
  +        return stateDescription(self.getState())
  +        
  +    def getStateName(self):
           return stateName(self.getState())
           
       def getReason(self):
           return self.reason
           
  +    def getReasonName(self):
  +        return reasonName(self.getReason())
  +        
       def getReasonDescription(self):
           if self.isReasonUnset(): return ''
  -        return reasonString(self.getReason())
  +        return reasonDescription(self.getReason())
           
       #
       #
  @@ -215,6 +256,9 @@
       def getState(self):
           return self.statePair.state
           
  +    def getStateName(self):
  +        return self.statePair.getStateName()
  +        
       def getStateDescription(self):
           return self.statePair.getStateDescription()
           
  @@ -227,6 +271,9 @@
           
       def getReasonDescription(self):
           return self.statePair.getReasonDescription()
  +        
  +    def getReasonName(self):
  +        return self.statePair.getReasonName()
           
       def isSuccess(self):
           return self.statePair.isSuccess()
  
  
  
  1.11      +4 -4      jakarta-gump/python/gump/utils/launcher.py
  
  Index: launcher.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/utils/launcher.py,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- launcher.py	29 Jan 2004 18:11:56 -0000	1.10
  +++ launcher.py	17 Feb 2004 21:54:21 -0000	1.11
  @@ -283,7 +283,7 @@
           self.end_time=None
           
       def overview(self,indent):
  -        overview + indent+"State: " + states[self.state]
  +        overview = indent+"State: " + states[self.state]
           overview += self.cmd.overview(indent)
           if self.output:
             overview += indent+"Output: " + self.output
  
  
  
  1.9       +0 -0      jakarta-gump/python/gump/utils/xmlutils.py
  
  Index: xmlutils.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/utils/xmlutils.py,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  
  
  
  1.9       +4 -4      jakarta-gump/python/gump/utils/work.py
  
  Index: work.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/utils/work.py,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- work.py	29 Jan 2004 18:11:56 -0000	1.8
  +++ work.py	17 Feb 2004 21:54:21 -0000	1.9
  @@ -103,7 +103,7 @@
               
       def overview(self):
           overview='Work Name: ' + self.name +' (Type: ' + workTypeName(self.type)+')\n'
  -        overview+='State: ' + stateName(self.state)+'\n'
  +        overview+='State: ' + stateDescription(self.state)+'\n'
           if self.message:
               overview+=message+'\n'
           return overview
  
  
  
  1.13      +30 -19    jakarta-gump/python/gump/output/nag.py
  
  Index: nag.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/output/nag.py,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- nag.py	15 Feb 2004 17:32:05 -0000	1.12
  +++ nag.py	17 Feb 2004 21:54:21 -0000	1.13
  @@ -151,7 +151,7 @@
                   
                   
           # Belt and braces (nag to us if not nag to them)
  -        if self.unwanted:
  +        if self.hasUnwanted():
               log.info('Got some unwanted\'s to send to list...')
               self.sendEmail(self.workspace.mailinglist,self.workspace.email,	\
                           'All dressed up, with nowhere to go...',self.unwanted)
  @@ -160,10 +160,10 @@
               # destroyed,
               self.unwanted=''      
           else:
  -            log.debug('No unwanted nags.')
  +            log.info('No unwanted nags.')
                   
           # Belt and braces (nag to us if not nag to them)
  -        if self.unsent:
  +        if self.hasUnsent():
               log.info('Got some unsented\'s to send to list...')    
               self.sendEmail(self.workspace.mailinglist,self.workspace.email,	\
                           'Unable to send...',self.unsent)
  @@ -172,21 +172,32 @@
               # destroyed,
               self.unsent=''
           else:
  -            log.debug('No unsent nags.')
  +            log.info('No unsent nags.')
                   
       def addUnwanted(self,subject,content):
  -        self.addStuff(self.unwanted,subject,content)
  +        if self.unwanted:
  +            self.unwanted += '-------------------------------------------------------------\n'
  +        self.unwanted += subject
  +        self.unwanted += '\n'
  +        self.unwanted += content
  +        self.unwanted += '\n'
       
       def addUnsent(self,subject,content):
  -        self.addStuff(self.unsent,subject,content)
  +        if self.unsent:
  +            self.unsent += '-------------------------------------------------------------\n'
  +        self.unsent += subject
  +        self.unsent += '\n'
  +        self.unsent += content
  +        self.unsent += '\n'
  +                    
  +    def hasUnwanted(self):
  +        if self.unwanted: return 1
  +        return 0
  +    
  +    def hasUnsent(self):
  +        if self.unsent: return 1
  +        return 0
       
  -    def addStuff(self,store,subject,content):
  -        if store:
  -            store += '-------------------------------------------------------------\n'
  -        store += subject
  -        store += "\n"
  -        store += content
  -        store += "\n"
       
       def nagWorkspace(self):
           """ Nag for the workspace """
  @@ -209,7 +220,7 @@
           #
           subject=self.workspace.prefix+	\
                   ': '+module.getName()+' '+	\
  -                lower(stateName(module.getState()))
  +                lower(stateDescription(module.getState()))
                       
           self.sendEmails(self.getAddressPairs(module),subject,content)
               
  @@ -228,7 +239,7 @@
           #
           subject=self.workspace.prefix+': '	\
               +module.getName()+'/'+project.getName()	\
  -            +' '+lower(stateName(project.getState()))
  +            +' '+lower(stateDescription(project.getState()))
                       
           # Send those e-mails
           self.sendEmails(self.getAddressPairs(project),subject,content)
  @@ -387,7 +398,7 @@
               atomurl=self.run.getOptions().getResolver().getUrl(object,feedPrefix,'.atom')
               
               content += "RSS: " + rssurl + " | "
  -            content += "Atom: " + atomurl + "\n"         
  +            content += "Atom: " + atomurl + '\n'         
       
           return content
       
  
  
  
  1.1                  jakarta-gump/python/gump/results/model.py
  
  Index: model.py
  ===================================================================
  #!/usr/bin/env python
  
  # $Header: /home/cvs/jakarta-gump/python/gump/model/object.py,v 1.16 2004/02/10 22:48:52 ajack Exp $
  # $Revision: 1.16 $
  # $Date: 2004/02/10 22:48:52 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  """
      This module contains information on
  """
  
  from time import localtime, strftime, tzname
  from string import lower, capitalize
  
  from gump.utils.note import *
  from gump.utils.work import *
  from gump.utils.owner import *
  from gump.model.state import *
  from gump.results.rawmodel import *
  
  from gump.utils.xmlutils import xmlize
  
  class ResultModelObject(Annotatable,Ownable,Stateful):
      """Base model object for a single entity"""
      def __init__(self,name,xml=None,owner=None):
                  
          # Can scribble on this thing...
      	Annotatable.__init__(self)
  
          # Can be owned
          Ownable.__init__(self,owner)
  
          # Holds a state
          Stateful.__init__(self)
      	
      	# Named
      	self.name=name
      	
          # The XML model
          if xml:
          	self.xml=xml    
   
          # Internals...
      	self.completionPerformed=0
      	
      def isComplete(self):
          return self.completionPerformed
          
      def setComplete(self,complete):
         self.completionPerformed=complete
           
      #
      # Same if same type, and same name
      # i.e project context X is not equals to module context X
      def __eq__(self,other):
          return self.__class__ == other.__class__ and self.name == other.name
          
      def __cmp__(self,other):
          return cmp(self.name,other.name)
          
      def __hash__(self):
          return hash(self.name)
          
      def __repr__(self):
          return str(self.__class__)+':'+self.name
          
      def __str__(self):
          return str(self.__class__)+':'+self.name
  
      def getName(self):
          return self.name
          
      def dump(self, indent=0, output=sys.stdout):
          """ Display the contents of this object """
          output.write(getIndent(indent)+'Name: ' + self.name + '\n')
          Annotatable.dump(self,indent,output)
      
      def hasXML(self):
          if hasattr(self,'xml') and self.xml: return 1
          return 0
          
      def getXML(self):
          return self.xml
      
      def hasXMLData(self):
          if hasattr(self,'xmldata') and self.xmldata: return 1
          return 0
          
      def getXMLData(self):
          if not self.hasXMLData():
              stream=StringIO.StringIO() 
              
              # Create on demand (push object attributes
              # into XML form)
              if not self.hasXML():
                  self.createXML()
                  
              xmlize(self.xml.getTagName(),self.xml,stream)
              stream.seek(0)
              self.xmldata=stream.read()
              stream.close()
      
          return self.xmldata
          
      def writeXMLToFile(self, outputFile):
          """ Serialize to a file """
          try:            
              f=open(outputFile, 'w')
              f.write(self.getXMLData())
          finally:
              # Since we may exit via an exception, close explicitly.
              if f: f.close()            
  
  # represents a <workspaceResult/> element
  class WorkspaceResult(ResultModelObject):
      def __init__(self,name,xml=None,owner=None):
      	ResultModelObject.__init__(self,name,xml,owner)    
      	
      	#
      	# Results per module
      	#
      	self.moduleResults 	=	{}
      	self.projectResults 	=	{}
  
      def hasModuleResults(self):
          if self.moduleResults.values(): return 1
          return 0
          
      def getModuleResults(self):
          return self.moduleResults.values()
          
      def hasProjectResults(self):
          if self.projectResults.values(): return 1
          return 0    
          
      def getProjectResults(self):
          return self.projectResults.values()
      
      def hasProjectResult(self,name):
          if name in self.projectResults: return 1
          return 0
          
      def getProjectResult(self,name):
          return self.projectResults[name]
          
      def setModuleResult(self,moduleResult):
          self.moduleResults[moduleResult.getName()] = moduleResult
                  
          for projectResult in self.getProjectResults():
              self.setProjectResult(projectResult)
          
      def setProjectResult(self,projectResult):
          self.projectResults[projectResult.getName()] = projectResult
          
      def createXML(self):
          if self.hasXML(): return
          
          """ Convert object attribitues into serializable XML """
          self.xml=XMLWorkspaceResult(	\
              {	\
                  'name':self.getName(),	\
                  'state':self.getStateName(),	\
                  'reason':self.getReasonName()	\
              })
              
          for moduleResult in self.moduleResults.values():
              moduleResult.createXML(self.xml)        
                      
      def complete(self, xmlprofileresults, xmlmoduleresults,	\
                      xmlprojectresults): 
          if self.isComplete(): return
          
          #
          # Import all modules
          #  
          for xmlmoduleresult in xmlmoduleresults.values(): 
              moduleResult=ModuleResult(xmlmoduleresult.name,xmlmoduleresult,self)
              self.setModuleResult(moduleResult)
                  
          #
          # Import all projects
          #  
          for xmlprojectresult in xmlprojectresults.values():             
              projectResult=ProjectResult(xmlprojectresult.name,xmlprojectresult,self)
              self.setProjectResult(projectResult)
  
          # Complete the modules
          for moduleResult in self.getModuleResults():
              moduleResult.complete(self)
                          
          # Complete the projects  
          for projectResult in self.getProjectResults():
              # Complete the project
              projectResult.complete(self)           
          
          self.setComplete(1)
          
      def dump(self, indent=0, output=sys.stdout):
          """ Display the contents of this object """
          ResultModelObject.dump(self,indent,output)
          
          for moduleResult in self.moduleResults.values():
              moduleResult.dump(indent+1, output)
          
  # represents a <moduleResult/> element
  class ModuleResult(ResultModelObject):
      def __init__(self,name,xml=None,owner=None):
      	ResultModelObject.__init__(self,name,xml,owner)    
      	
      	# 
      	# Results per project
      	#
      	self.projectResults 	=	{}    
      	
      def setProjectResult(self,projectResult):
          self.projectResults[projectResult.getName()] = projectResult
          # Attach oneself as owner...
          projectResult.setModuleResult(self)
                  
      def hasProjectResults(self):
          if self.projectResults.values(): return 1
          return 0    
          
      def getProjectResults(self):
          return self.projectResults.values()
          
      def createXML(self, workspaceResultXML):
          if self.hasXML(): return
          
          # This call constructs a new one...
          self.xml=workspaceResultXML.moduleResult(	\
              {	\
                  'name':self.getName(),	\
                  'state':self.getStateName(),	\
                  'reason':self.getReasonName()	\
              })
              
          for projectResult in self.getProjectResults():
              print "CREATE XML FOR :" + `projectResult`
              projectResult.createXML(self.xml)
              
      def complete(self, workspaceResult): 
          if self.isComplete(): return
          
          for xmlprojectresult in self.xml.projectResult:
              if workspaceResult.hasProjectResult(xmlprojectresult.name):
                  
                  #
                  # The project pretty much better be in the
                  # workspace, but avoid crashing...
                  #
                  projectResult=workspaceResult.getProjectResult(xmlprojectresult.name)
                  
                  #
                  # Claim ownership
                  #
                  self.setProjectResult(projectResult)
                  
          self.setComplete(1)
          
      def dump(self, indent=0, output=sys.stdout):
          """ Display the contents of this object """
          ResultModelObject.dump(self,indent,output)
          
          for projectResult in self.projectResults.values():
              projectResult.dump(indent+1, output)
              
  # represents a <projectResult/> element
  class ProjectResult(ResultModelObject):
      def __init__(self,name,xml=None,owner=None):
      	ResultModelObject.__init__(self,name,xml,owner)
      	
      	self.moduleResult = None
  
      def createXML(self, moduleResultXML):
          if self.hasXML(): return
          
          self.xml=moduleResultXML.projectResult(	\
              {	\
                  'name':self.getName(),	\
                  'state':self.getStateName(),	\
                  'reason':self.getReasonName()	\
              })
                  
      def setModuleResult(self,moduleResult):
          self.moduleResult=moduleResult
          
      def complete(self,workspaceResult): 
          if self.isComplete(): return
          
          self.setComplete(1)
          
  
  
  
  1.1                  jakarta-gump/python/gump/results/__init__.py
  
  Index: __init__.py
  ===================================================================
  #!/usr/bin/env python
  
  # $Header: /home/cvspublic/jakarta-gump/python/gump/conf.py,v 1.7 2003/05/10 18:20:36 nicolaken Exp $
  # $Revision: 1.7 $
  # $Date: 2003/05/10 18:20:36 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  
  # tell Python what modules make up the gump.output package
  __all__ = ["resulter","module","rawmodel","loader"]
  
  
  
  1.1                  jakarta-gump/python/gump/results/loader.py
  
  Index: loader.py
  ===================================================================
  #!/usr/bin/env python
  
  # $Header: /home/cvs/jakarta-gump/python/gump/model/loader.py,v 1.5 2004/02/01 18:44:44 ajack Exp $
  # $Revision: 1.5 $
  # $Date: 2004/02/01 18:44:44 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  """
      This module contains information on
  """
  import os, os.path
  
  from gump import log
  from gump.results.rawmodel import XMLWorkspaceResult,XMLProfileResult,	\
              XMLModuleResult, XMLProjectResult
  from gump.results.model import WorkspaceResult
  from gump.utils.xmlutils import SAXDispatcher
  from gump.utils.note import transferAnnotations, Annotatable
  from gump.utils import dump
  from gump.config import gumpPath
  
  class WorkspaceResultLoader:
      def __init__(self):
          self.annotations=[]
          
      def loadFromUrl(self,url):
          """Builds in memory from the xml file. Return the generated objects."""
        
          # Download (relative to base)
          if not url.startswith('http://'):
              newurl=gumpPath(url,'.');
          else:
              newurl=cacheHTTP(url)
              
          return self.load(newurl)
          
      def load(self,file):
        """Builds in memory from the xml file. Return the generated objects."""
  
        if not os.path.exists(file):
          log.error('WorkspaceResult metadata file ['+file+'] not found')
          raise IOError, """WorkspaceResult %s not found!""" % file 
      
        #
        # Clear out the maps
        #
      
        log.debug("Launch SAX Dispatcher onto : " + file);
                
        parser=SAXDispatcher(file,'workspaceresult',XMLWorkspaceResult)
      
        # Extract the root XML
        xmlworkspace=parser.docElement
      
        if not xmlworkspace:
          raise IOError, "Failed to load workspace result: " + file
      
        # Construct object around XML.
        workspaceResult=WorkspaceResult(xmlworkspace.name, xmlworkspace)
        
        # Copy over any XML errors/warnings
        transferAnnotations(parser, workspaceResult)
    
        #
        # Cook the raw model...
        #
        workspaceResult.complete(XMLProfileResult.map,	\
                            XMLModuleResult.map,	\
                            XMLProjectResult.map	)
  
        #
        # Clear out the maps [so don't continue to use them]
        #
        XMLProfileResult.map.clear()
        XMLModuleResult.map.clear()
        XMLProjectResult.map.clear()
        
        return workspaceResult      
  
  
  1.1                  jakarta-gump/python/gump/results/resulter.py
  
  Index: resulter.py
  ===================================================================
  #!/usr/bin/env python
  
  # $Header: /home/cvs/jakarta-gump/python/gump/output/nag.py,v 1.12 2004/02/15 17:32:05 ajack Exp $
  # $Revision: 1.12 $
  # $Date: 2004/02/15 17:32:05 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  """
      Results (XML document containing states/dates/etc.)
  """
  
  import socket
  import time
  import os
  import sys
  import logging
  
  from string import lower, capitalize
  
  from gump import log
  from gump.results.model import *
  from gump.results.loader import *
  
  class Resulter:
      
      def __init__(self,run):        
          self.run = run
          self.workspace=run.getWorkspace()
          self.gumpSet=run.getGumpSet()
          
          self.serverResults = {}
          
      #def getResultsFor(self, object):
      #    for server in self.workspace.getServers():
              
          
      def loadResultsForServers(self):
          for server in self.workspace.getServers():       
              if not server in self.serverResults:
                  results=None
                  try:
                      results=loadResultsForServer(server)            
                  except:
                      pass
                  if results:
                      self.serverResults(server, results)
              
      def loadResultsForServer(self, server):
          return loadResults(server.getUrl() + '/results.xml')
          
      def loadResults(self, url):
      
          loader =  WorkspaceResultLoader()        
          return loader.loadFromUrl(url)
          
      def generateResults(self,where=None):
          """
          Generate a results file
          """
          
          workspaceResults = self.constructResults()
          
          # If not told where to stick it, contstruct...
          if not where: where=workspaceResults.getName()+'.xml'
          
          workspaceResults.writeXMLToFile(where)
          
      def constructResults(self):
          """
          Generate a results file
          """
          # Create
          workspaceResults = WorkspaceResult(self.workspace.getName())
      
          # For all modules...
          for module in self.workspace.getModules():        
                  if not self.gumpSet.inModules(module): continue
                  
                  #
                  # Generate results for this module, and
                  # add all projects.
                  #
                  moduleResults = ModuleResult(module.getName())
  
                  # Set attributes:
                  # Stats?
                  moduleResults.setStatePair(module.getStatePair())
                  
                  # Add projects
                  for project in module.getProjects():
                      if not self.gumpSet.inSequence(project): continue    
                      
                      #
                      # Add a project
                      #
                      projectResults = ProjectResult(project.getName())
                      
                      # Set attributes:
                      projectResults.setStatePair(project.getStatePair())
                  
                      # Stash on moduleResult
                      moduleResults.setProjectResult(projectResults)
                      
                      # Stash on workspaceResult also
                      workspaceResults.setProjectResult(projectResults)                    
                      
                  # Stash moduleResult on workspaceResult
                  workspaceResults.setModuleResult(moduleResults)
                  
          return workspaceResults
              
      
  def generateResults(run):
      
      # Generate results around this run...
      resulter=Resulter(run)
      
      # Generate the output...
      resulter.generateResults()
      
  
  
  1.1                  jakarta-gump/python/gump/results/rawmodel.py
  
  Index: rawmodel.py
  ===================================================================
  #!/usr/bin/env python
  
  # $Header: /home/cvs/jakarta-gump/python/gump/model/rawmodel.py,v 1.13 2004/02/10 00:43:19 ajack Exp $
  # $Revision: 1.13 $
  # $Date: 2004/02/10 00:43:19 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  import os,types
  
  import logging
  
  from gump.utils.xmlutils import SAXDispatcher, GumpXMLObject, \
                              Single, Multiple, Named
  
  """
    Gump XML metadata loading depends on this object model.
  
    An instance of this object model is imported from a set of XML files.
    
    Gump uses a SAX dispatcher tool, a dependency walker, and this 
    object model (GOM).
  
    The idea is that a subclass of GumpModelObject is used for each of the various
    xml tags which can appear in a gump profile, with a saxdispatcher
    generating a tree of GumpModelObject objects from the profile, dynamically
    merging as it finds href references.
  
    Then there's some basic procedures to work with the GOM, like load().
  
  """
  from gump import log
  
  ###############################################################################
  # Initialize
  ###############################################################################
        
  class XMLWorkspaceResult(GumpXMLObject):
    """Represents a <workspaceResult/> element."""  
    #map={}
    def init(self):
      self.projectResult=Multiple(XMLProjectResult)
      self.moduleResult=Multiple(XMLModuleResult)
  
      
  # represents a <profile/> element
  class XMLProfileResult(Named,GumpXMLObject):
    map={}
    def init(self):
      self.projectResult=Multiple(XMLProjectResult)
      self.moduleResult=Multiple(XMLModuleResult)
  
  # represents a <module/> element
  class XMLModuleResult(Named):
    map={}
    def init(self):
      self.projectResult=Multiple(XMLProjectResult)
  
  
  # represents a <project/> element
  class XMLProjectResult(Named):
    map={}
    def init(self):
      #self.state=Single(GumpXMLObject)
      pass
  
  
  
  1.1                  jakarta-gump/python/gump/results/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  *.pyc
  
  
  1.2       +2 -1      jakarta-gump/python/gump/test/resources/broken1/broken_workspace.xml
  
  Index: broken_workspace.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/broken1/broken_workspace.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- broken_workspace.xml	17 Nov 2003 22:10:52 -0000	1.1
  +++ broken_workspace.xml	17 Feb 2004 21:54:21 -0000	1.2
  @@ -1,5 +1,6 @@
   <?xml version="1.0" ?>
  -<workspace basedir="/data/gump" 
  +<workspace name="test"
  +	       basedir="/data/gump" 
              jardir="/data/gump/jars/latest"
              pkgdir="/data/package"
              sync="rsync -r -a --delete" version="0.3">
  
  
  
  1.14      +16 -8     jakarta-gump/python/gump/test/model.py
  
  Index: model.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/model.py,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- model.py	12 Feb 2004 13:41:52 -0000	1.13
  +++ model.py	17 Feb 2004 21:54:21 -0000	1.14
  @@ -201,8 +201,8 @@
           (classpath,bootclasspath)=self.project4.getClasspaths()
           (classpath,bootclasspath)=self.alias1.getClasspaths()
           (classpath,bootclasspath)=self.project5.getClasspaths(1)        
  -        print "Classpath:" + classpath     
  -        print "Bootclasspath:" + bootclasspath
  +        #print "Classpath:" + classpath     
  +        #print "Bootclasspath:" + bootclasspath
           
       def testMaven(self):
                   
  @@ -223,7 +223,15 @@
           #    print `property`
           
           commandLine=self.project2.getBuildCommand().formatCommandLine()        
  -        self.assertIn('Need ant.home', 'ant.home', commandLine)
  -        self.assertIn('Need project1.jar', 'project1.jar', commandLine)      
  +        self.assertInString('Need ant.home', 'ant.home', commandLine)
  +        self.assertInString('Need project1.jar', 'project1.jar', commandLine)      
           
  -        print commandLine  
  \ No newline at end of file
  +        # print commandLine  
  +        
  +    def testServers(self):
  +        self.assertNotEmpty('Some servers ought be found', self.workspace.getServers())
  +        
  +    def testTrackers(self):
  +        self.assertNotEmpty('Some trackers ought be found', self.workspace.getTrackers())
  +        
  +        
  \ No newline at end of file
  
  
  
  1.5       +1 -1      jakarta-gump/python/gump/test/maven.py
  
  Index: maven.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/maven.py,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- maven.py	9 Jan 2004 19:57:19 -0000	1.4
  +++ maven.py	17 Feb 2004 21:54:21 -0000	1.5
  @@ -91,7 +91,7 @@
                   
           self.assertTrue('Maven project has a Maven object', self.maven1.hasMaven())
           
  -        self.maven1.generateMavenProperties()
  +        self.maven1.generateMavenProperties('test/unit-testing-maven.properties')
           
           cmd=self.maven1.getMavenCommand()
           
  
  
  
  1.4       +25 -10    jakarta-gump/python/gump/test/nagging.py
  
  Index: nagging.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/nagging.py,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- nagging.py	12 Feb 2004 00:24:16 -0000	1.3
  +++ nagging.py	17 Feb 2004 21:54:21 -0000	1.4
  @@ -91,11 +91,24 @@
           
           # For all modules...
           for module in self.workspace.getModules():                    
  -            print 'Get Content For Module : ' + module.getName()
  -            print nagger.getNamedTypedContent(module,'test')
  +            #print 'Get Content For Module : ' + module.getName()
  +            nagger.getNamedTypedContent(module,'test')
               for project in module.getProjects():
  -                print 'Get Content For Project : ' + project.getName()
  -                print nagger.getNamedTypedContent(project,'test')
  +                #print 'Get Content For Project : ' + project.getName()
  +                nagger.getNamedTypedContent(project,'test')
  +                
  +    def testNagUnwantedUnsent(self):
  +    
  +        nagger=Nagger(self.run)
  +        
  +        self.assertFalse( 'No Unwanted', nagger.hasUnwanted() )
  +        self.assertFalse( 'No Unsent', nagger.hasUnsent() )
  +        
  +        nagger.addUnwanted('test subject','test content')
  +        nagger.addUnsent('test subject','test content')
  +        
  +        self.assertTrue( 'Has Unwanted', nagger.hasUnwanted() )
  +        self.assertTrue( 'Has Unsent', nagger.hasUnsent() )
                   
       def testNagAddresses(self):
       
  @@ -103,15 +116,17 @@
              
           # For all modules...
           for module in self.workspace.getModules():                    
  -            print 'Get Addresses For Module : ' + module.getName()
  +            #print 'Get Addresses For Module : ' + module.getName()
               addresses=nagger.getAddressPairs(module)
               for addr in addresses:
  -                print 'AddressPair : ' + str(addr)
  +                #print 'AddressPair : ' + str(addr)
  +                pass
               for project in module.getProjects():
  -                print 'Get Addresses For Project : ' + project.getName()
  +                #print 'Get Addresses For Project : ' + project.getName()
                   addresses=nagger.getAddressPairs(project)
                   for addr in addresses:
  -                    print 'AddressPair : ' + str(addr)         
  +                    #print 'AddressPair : ' + str(addr)      
  +                    pass   
                                
       def testNagEmails(self):
       
  @@ -120,7 +135,7 @@
           # For all modules...
           for module in self.workspace.getModules(): 
               for project in module.getProjects():
  -                print 'Get E-mail For Project : ' + project.getName()
  +                #print 'Get E-mail For Project : ' + project.getName()
                   addresses=nagger.getAddressPairs(project)
                   for addr in addresses:   
                       toAddrs=[ addr.getToAddress() ]
  @@ -128,7 +143,7 @@
                               addr.getFromAddress(), \
                               'Test Subject', \
                               'Test Content')       
  -                    print str(email)
  +                    #print str(email)
                   
       def testNag(self):  
           nag(self.run)
  
  
  
  1.4       +1 -1      jakarta-gump/python/gump/test/xdoc_tests.py
  
  Index: xdoc_tests.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/xdoc_tests.py,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- xdoc_tests.py	9 Jan 2004 19:57:19 -0000	1.3
  +++ xdoc_tests.py	17 Feb 2004 21:54:21 -0000	1.4
  @@ -98,7 +98,7 @@
       
       table1=section1.createTable(['H1','H2'])
       
  -    #dump(doc1)
  +    dump(doc1)
       doc1.serialize()
       
       stream.seek(0)
  
  
  
  1.8       +4 -4      jakarta-gump/python/gump/test/stats.py
  
  Index: stats.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/stats.py,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- stats.py	9 Jan 2004 23:28:40 -0000	1.7
  +++ stats.py	17 Feb 2004 21:54:21 -0000	1.8
  @@ -138,7 +138,7 @@
               self.assertGreater('Incremented Prereqs', ps2.prereqs, ps1p )
               self.assertGreater('Incremented SequenceInState', ps2.sequenceInState, ps1seq )
           
  -        print str(ps1s) + ' : ' + str(ps1f) + ' : ' + str(ps1p) + ' : ' + str(ps1seq)
  +        #print str(ps1s) + ' : ' + str(ps1f) + ' : ' + str(ps1p) + ' : ' + str(ps1seq)
           
           self.statsDB.sync()
           
  
  
  
  1.20      +20 -3     jakarta-gump/python/gump/test/pyunit.py
  
  Index: pyunit.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/pyunit.py,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- pyunit.py	13 Feb 2004 22:12:37 -0000	1.19
  +++ pyunit.py	17 Feb 2004 21:54:21 -0000	1.20
  @@ -61,6 +61,7 @@
   """
       This module contains information on unit testing
   """
  +import os
   import sys
   from types import NoneType, StringType, TypeType, MethodType
   import types
  @@ -114,6 +115,10 @@
           if object:
               self.raiseIssue(['Ought evaluate as false', message, object])
               
  +    def assertInString(self,message,substr,str):
  +        if not -1 == str.find(substr):
  +            self.raiseIssue(['Ought evaluate as in', message, substr, str])
  +            
       def assertIn(self,message,object,sequence):
           if not object in sequence:
               self.raiseIssue(['Ought evaluate as in', message, object, sequence])
  @@ -123,6 +128,10 @@
               self.raiseIssue(['Ought evaluate as a substring', \
                   message, subString, mainString, mainString.find(subString)])
               
  +    def assertNotEmpty(self,message,sequence):
  +        if not sequence or not len(sequence) > 0:
  +            self.raiseIssue(['Ought NOT evaluate as empty', message, sequence])
  +            
       def assertNotIn(self,message,object,sequence):
           if object in sequence:
               self.raiseIssue(['Ought NOT evaluate as in', message, object, sequence])
  @@ -204,6 +213,11 @@
           tests=[]
           results=[]
           
  +        # log.setLevel(logging.DEBUG ) 
  +                
  +        # Give a place to work in..
  +        if not os.path.exists('./test'): os.mkdir('./test')
  +        
           # iterate over this suites properties
           for name in self.__class__.__dict__:
               if name.startswith('__') and name.endswith('__'): continue
  @@ -352,6 +366,9 @@
       
       from gump.test.nagging import NaggingTestSuite  
       runner.addSuite(NaggingTestSuite())
  +    
  +    from gump.test.resulting import ResultingTestSuite  
  +    runner.addSuite(ResultingTestSuite())
       
       # Any args are pattern matches
       patterns=list(sys.argv)
  
  
  
  1.5       +17 -17    jakarta-gump/python/gump/test/utils.py
  
  Index: utils.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/utils.py,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- utils.py	13 Feb 2004 22:12:37 -0000	1.4
  +++ utils.py	17 Feb 2004 21:54:21 -0000	1.5
  @@ -86,34 +86,34 @@
           twoYearsBefore=self.now - (60*60*24*365*2)
           
           rough=getGeneralDifferenceDescription(self.now, oneHourBefore)
  -        self.assertIn('Date Diff String', '1 hour', rough)
  +        self.assertInString('Date Diff String', '1 hour', rough)
           
           rough=getGeneralDifferenceDescription(self.now, twoHoursBefore)
  -        self.assertIn('Date Diff String', '2 hours', rough)
  +        self.assertInString('Date Diff String', '2 hours', rough)
         
           rough=getGeneralDifferenceDescription(self.now, oneDayBefore)
  -        self.assertIn('Date Diff String', '1 day', rough)
  +        self.assertInString('Date Diff String', '1 day', rough)
           
           rough=getGeneralDifferenceDescription(self.now, twoDaysBefore)
  -        self.assertIn('Date Diff String', '2 days', rough)
  +        self.assertInString('Date Diff String', '2 days', rough)
         
           rough=getGeneralDifferenceDescription(self.now, oneWeekBefore)
  -        self.assertIn('Date Diff String', '1 week', rough)
  +        self.assertInString('Date Diff String', '1 week', rough)
           
           rough=getGeneralDifferenceDescription(self.now, twoWeeksBefore)
  -        self.assertIn('Date Diff String', '2 weeks', rough)
  +        self.assertInString('Date Diff String', '2 weeks', rough)
         
           rough=getGeneralDifferenceDescription(self.now, oneMonthBefore)
  -        self.assertIn('Date Diff String', '1 month', rough)
  +        self.assertInString('Date Diff String', '1 month', rough)
           
           rough=getGeneralDifferenceDescription(self.now, twoMonthsBefore)
  -        self.assertIn('Date Diff String', '2 months', rough)        
  +        self.assertInString('Date Diff String', '2 months', rough)        
           
           rough=getGeneralDifferenceDescription(self.now, oneYearBefore)
  -        self.assertIn('Date Diff String', '1 year', rough)
  +        self.assertInString('Date Diff String', '1 year', rough)
           
           rough=getGeneralDifferenceDescription(self.now, twoYearsBefore)
  -        self.assertIn('Date Diff String', '2 years', rough)
  +        self.assertInString('Date Diff String', '2 years', rough)
           
       def testSpacesInCommandLines(self):
           params=Parameters()
  @@ -123,7 +123,7 @@
           params.addParameter('WithQuotesAndSpaces', 'aa \' \" aa a','=')
           params.addParameter('WithEscapes', 'aa\\a','=')
           
  -        print params.formatCommandLine()
  +        #print params.formatCommandLine()
           
           params=Parameters()
           params.addPrefixedParameter('-D','X', 'aaaaa','=')
  @@ -131,11 +131,11 @@
           params.addPrefixedParameter('-D','Z', 'aa \' aa a','=')
           params.addPrefixedParameter('-D','Z', 'aa \" aa a','=')
           
  -        print params.formatCommandLine()
  +        #print params.formatCommandLine()
           
       def testWrap(self):
           line='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
  -        print wrapLine(line)
  +        #print wrapLine(line)
           line='1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
  -        print wrapLine(line)
  +        #print wrapLine(line)
           
  
  
  
  1.4       +1 -1      jakarta-gump/python/gump/test/gumpset_tests.py
  
  Index: gumpset_tests.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/gumpset_tests.py,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- gumpset_tests.py	9 Jan 2004 19:57:19 -0000	1.3
  +++ gumpset_tests.py	17 Feb 2004 21:54:21 -0000	1.4
  @@ -70,7 +70,7 @@
   from gump.engine import GumpSet
   
   def testWorkspace(file):
  -   print "Workspace File: " + str(file)
  +print "Workspace File: " + str(file)
      
      ws = WorkspaceLoader().load(file)
      
  
  
  
  1.1                  jakarta-gump/python/gump/test/resulting.py
  
  Index: resulting.py
  ===================================================================
  #!/usr/bin/env python
  # $Header:  1.7 2003/05/10 18:20:36 nicolaken Exp $
  # $Revision: 1.7 $
  # $Date: 2003/05/10 18:20:36 $
  #
  # ====================================================================
  #
  # The Apache Software License, Version 1.1
  #
  # Copyright (c) 2003 The Apache Software Foundation.  All rights
  # reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  #
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #
  # 3. The end-user documentation included with the redistribution, if
  #    any, must include the following acknowlegement:
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowlegement may appear in the software itself,
  #    if and wherever such third-party acknowlegements normally appear.
  #
  # 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
  #    Foundation" must not be used to endorse or promote products derived
  #    from this software without prior written permission. For written
  #    permission, please contact apache@apache.org.
  #
  # 5. Products derived from this software may not be called "Apache"
  #    nor may "Apache" appear in their names without prior written
  #    permission of the Apache Group.
  #
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  #
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation.  For more
  # information on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  
  """
      Model Testing
  """
  
  import os
  import logging
  
  from gump import log
  import gump.config
  from gump.gumprun import GumpRun
  from gump.test import getWorkedTestWorkspace
  from gump.test.pyunit import UnitTestSuite
  from gump.results.resulter import generateResults,Resulter
  from gump.results.loader import WorkspaceResultLoader
  from gump.net.mailer import *
  
  class ResultingTestSuite(UnitTestSuite):
      def __init__(self):
          UnitTestSuite.__init__(self)
          
          self.testFile = 'test/test.xml'
          
      def suiteSetUp(self):
          #
          # Load a decent Workspace
          #
          self.workspace=getWorkedTestWorkspace()          
          self.assertNotNone('Needed a workspace', self.workspace)
          self.run=GumpRun(self.workspace)
          
      def checkWorkspaceResult(self,wsr):
          self.assertTrue('Has some ModuleResults', wsr.hasModuleResults())
          self.assertTrue('Has some ProjectResults', wsr.hasProjectResults())
          
          for moduleResult in wsr.getModuleResults():
              self.assertTrue('Has some ProjectResults', moduleResult.hasProjectResults())
              
      def testResultContents(self):
      
          resulter=Resulter(self.run)
          
          # Construct from run
          wsr = resulter.constructResults()
          
          # Check out these results
          self.checkWorkspaceResult(wsr)
          
      def testResultWrite(self):
      
          resulter=Resulter(self.run)
          
          # Write to file...
          resulter.generateResults(self.testFile)   
          
          self.assertTrue('Wrote a file', os.path.exists(self.testFile))       
          
      def testResultRead(self):
      
          resulter=Resulter(self.run)
  
          # Write to file...
          resulter.generateResults(self.testFile)        
          
          # Read the file...      
          wsr = resulter.loadResults(self.testFile)
          
          self.checkWorkspaceResult(wsr)
                  
          wsr.dump()
          
      def testServers(self):
      
          resulter=Resulter(self.run)
  
          # Load for all servers...
          resulter.loadResultsForServers()        
          
  
  
  1.2       +2 -1      jakarta-gump/python/gump/test/resources/simple1/standalone_workspace.xml
  
  Index: standalone_workspace.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/simple1/standalone_workspace.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- standalone_workspace.xml	17 Nov 2003 22:10:56 -0000	1.1
  +++ standalone_workspace.xml	17 Feb 2004 21:54:21 -0000	1.2
  @@ -1,5 +1,6 @@
   <?xml version="1.0" ?>
  -<workspace basedir="/data/gump" 
  +<workspace name="test"
  +	       basedir="/data/gump" 
              jardir="/data/gump/jars/latest"
              logdir="/data/gump/log"
              pkgdir="/data/package"
  
  
  
  1.19      +7 -7      jakarta-gump/python/gump/syndication/syndicator.py
  
  Index: syndicator.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/syndication/syndicator.py,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- syndicator.py	10 Feb 2004 20:18:40 -0000	1.18
  +++ syndicator.py	17 Feb 2004 21:54:21 -0000	1.19
  @@ -80,7 +80,7 @@
       #
       def syndicate(self,run):
           if not hasattr(self,'syndicateRun'):
  -            raise RuntimeException, 'Complete [' + `self.__class__` + '] with syndicateRun(self,run)'
  +            raise RuntimeError, 'Complete [' + `self.__class__` + '] with syndicateRun(self,run)'
           
           if not callable(self.syndicateRun):
               raise RuntimeException, 'Complete [' + `self.__class__` + '] with a callable syndicateRun(self,run)'
  @@ -104,7 +104,7 @@
           if not stats.previousState == STATE_NONE \
               and not stats.previousState == STATE_UNSET:
               content += ', Previous state: <b>' \
  -                                    + stateName(stats.previousState)  \
  +                                    + stateDescription(stats.previousState)  \
                                       + '</b>'
       
           content += '</p>'
  @@ -138,7 +138,7 @@
           if not stats.previousState == STATE_NONE \
               and not stats.previousState == STATE_UNSET:
               content += ', Previous state: <b>' \
  -                                    + stateName(stats.previousState) \
  +                                    + stateDescription(stats.previousState) \
                                       + '</b>'
                                       
           content += '</p>'
  @@ -191,7 +191,7 @@
           #    content += '<p><table>'    
           #    for work in object.worklist:
           #        url=resolver.getAbsoluteUrl(work)
  -        #        state=stateName(work.state)                 
  +        #        state=stateDescription(work.state)                 
           #        content += ('<tr><td><a href=\'' + 	\
           #            url + '\'>' + work.getName() + 	\
           #            '</a></td><td>' + state + 		\
  
  
  
  1.9       +7 -7      jakarta-gump/python/gump/document/documenter.py
  
  Index: documenter.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/document/documenter.py,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- documenter.py	10 Feb 2004 20:18:40 -0000	1.8
  +++ documenter.py	17 Feb 2004 21:54:21 -0000	1.9
  @@ -78,10 +78,10 @@
       #
       def document(self,run):
           if not hasattr(self,'documentRun'):
  -            raise RuntimeException, 'Complete [' + `self.__class__` + '] with documentRun(self,run)'
  +            raise RuntimeError, 'Complete [' + `self.__class__` + '] with documentRun(self,run)'
           
           if not callable(self.documentRun):
  -            raise RuntimeException, 'Complete [' + `self.__class__` + '] with a callable documentRun(self,run)'
  +            raise RuntimeError, 'Complete [' + `self.__class__` + '] with a callable documentRun(self,run)'
           
           log.info('Document run using [' + `self` + ']')
           
  @@ -89,9 +89,9 @@
           
       def getResolver(self,run):
           if not hasattr(self,'getResolverForRun'):
  -            raise RuntimeException, 'Complete [' + `self.__class__` + '] with getResolverForRun(self,run)'
  +            raise RuntimeError, 'Complete [' + `self.__class__` + '] with getResolverForRun(self,run)'
           
           if not callable(self.getResolverForRun):
  -            raise RuntimeException, 'Complete [' + `self.__class__` + '] with a callable getResolverForRun(self,run)'
  +            raise RuntimeError, 'Complete [' + `self.__class__` + '] with a callable getResolverForRun(self,run)'
               
           return self.getResolverForRun(run)
  
  
  
  1.75      +13 -14    jakarta-gump/python/gump/document/forrest.py
  
  Index: forrest.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/document/forrest.py,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- forrest.py	15 Feb 2004 17:32:05 -0000	1.74
  +++ forrest.py	17 Feb 2004 21:54:21 -0000	1.75
  @@ -976,7 +976,6 @@
           pcount=0
           for project in module.getProjects():     
               if not gumpSet.inSequence(project): continue  
  -            pname=project.getName()
               pcount+=1
               
               projectRow=pallTable.createRow()
  @@ -1100,7 +1099,7 @@
           stateList=stateSection.createList()
           stateList.createEntry("Current State: ", project.getStateDescription())  
           if not project.getReason() == REASON_UNSET:
  -            stateList.createEntry("Reason: " + reasonString(project.getReason()))            
  +            stateList.createEntry("Reason: " + reasonDescription(project.getReason()))            
           if project.cause and not project==project.cause:
                self.insertTypedLink( project.cause, project, stateList.createEntry( "Root Cause: ")) 
                
  @@ -1157,10 +1156,10 @@
           statsTable.createEntry("Successes: ", stats.successes)
           statsTable.createEntry("Failures: ", stats.failures)
           statsTable.createEntry("Prerequisite Failures: ", stats.prereqs)
  -        statsTable.createEntry("Current State: ", stateName(stats.currentState))
  +        statsTable.createEntry("Current State: ", stateDescription(stats.currentState))
           statsTable.createEntry("Duration in state: ", stats.sequenceInState)
           statsTable.createEntry("Start of state: ", secsToDate(stats.startOfState))
  -        statsTable.createEntry("Previous State: ", stateName(stats.previousState))
  +        statsTable.createEntry("Previous State: ", stateDescription(stats.previousState))
           
           if stats.first:
               statsTable.createEntry("First Success: ", secsToDate(stats.first))
  @@ -1437,7 +1436,7 @@
               workRow.createComment(work.getName())
               
               self.insertLink(work,workable,workRow.createData())  
  -            workRow.createData(stateName(work.state))
  +            workRow.createData(stateDescription(work.state))
               workRow.createData(secsToDate(work.result.start_time))
               workRow.createData(secsToElapsedString(work.getElapsedSecs()))
           
  @@ -1472,7 +1471,7 @@
               workSection=wdocument.createSection('Details')
               
               workList=workSection.createList() 
  -            workList.createEntry("State: ", stateName(work.state))
  +            workList.createEntry("State: ", stateDescription(work.state))
               
               self.insertTypedLink(work.getOwner(),	\
                       work,	\
  @@ -1607,9 +1606,9 @@
           return '<fork href=\'%s\'>%s</fork>' % (escape(href),escape(name))
               
       def insertStateDescription(self,toObject,fromObject,xdocNode):
  -        node=xdocNode.createText(stateName(toObject.getState()))
  +        node=xdocNode.createText(stateDescription(toObject.getState()))
           if not toObject.getReason()==REASON_UNSET: 
  -            xdocNode.createText(' with reason '+reasonString(toObject.getReason()))
  +            xdocNode.createText(' with reason '+reasonDescription(toObject.getReason()))
               
           if toObject.cause and not toObject.cause == toObject:
           
  @@ -1697,8 +1696,8 @@
           depth=getDepthForObject(fromObject)
           
           # :TODO: Move this to some resolver, and share with RSS
  -        sname=stateName(pair.state)
  -        rstring=reasonString(pair.reason)    
  +        sname=stateDescription(pair.state)
  +        rstring=reasonDescription(pair.reason)    
   
           description=sname    
           uniqueName=sname
  @@ -2024,7 +2023,7 @@
               pstats=project.getStats()
               
               durRow.createData(pstats.sequenceInState)
  -            durRow.createData(stateName(pstats.currentState))
  +            durRow.createData(stateDescription(pstats.currentState))
               
           document.serialize()
           
  
  
  
  1.9       +4 -4      jakarta-gump/python/gump/document/text.py
  
  Index: text.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/document/text.py,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- text.py	15 Feb 2004 17:32:05 -0000	1.8
  +++ text.py	17 Feb 2004 21:54:21 -0000	1.9
  @@ -150,7 +150,7 @@
                   + "] [" + str(workable.getElapsedSecs()) + "] secs."  + "\n")
       
           for work in workable.worklist:
  -            output.write(indent+"Work : " + stateName(work.state) + "\n")
  +            output.write(indent+"Work : " + stateDescription(work.state) + "\n")
               if isinstance(work,CommandWorkItem):
                   output.write(indent+"Work Name : " + work.command.name + "\n")
                   output.write(indent+"Work Cmd  : " + work.command.formatCommandLine() + "\n")
  
  
  
  1.7       +2 -0      jakarta-gump/python/gump/test/resources/full1/profile.xml
  
  Index: profile.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/full1/profile.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- profile.xml	1 Feb 2004 18:44:44 -0000	1.6
  +++ profile.xml	17 Feb 2004 21:54:21 -0000	1.7
  @@ -18,6 +18,8 @@
   
     <server href="server1.xml"/>
     
  +  <server href="tracker1.xml"/>
  +  
     <!-- Repository definitions -->
   
     <repository href="repository1.xml"/>
  
  
  
  1.3       +2 -1      jakarta-gump/python/gump/test/resources/full1/workspace.xml
  
  Index: workspace.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/full1/workspace.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- workspace.xml	26 Nov 2003 16:08:39 -0000	1.2
  +++ workspace.xml	17 Feb 2004 21:54:21 -0000	1.3
  @@ -1,5 +1,6 @@
   <?xml version="1.0" ?>
  -<workspace basedir="./test/gump" 
  +<workspace name="test"
  +	       basedir="./test/gump" 
              jardir="./test/gump/jars"
              logdir="./test/gump/log"
              pkgdir="./test/package"
  
  
  
  1.1                  jakarta-gump/python/gump/test/resources/full1/tracker1.xml
  
  Index: tracker1.xml
  ===================================================================
  <?xml version="1.0" encoding="ISO-8859-1"?>
  
  <tracker name="tracker1" type="jira">
    <title>tracker 1</title>
    <url>http://gump.apache.org</url>
  </tracker>
  
  
  
  1.2       +2 -1      jakarta-gump/python/gump/test/resources/simple2/workspace.xml
  
  Index: workspace.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/simple2/workspace.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- workspace.xml	17 Nov 2003 22:10:54 -0000	1.1
  +++ workspace.xml	17 Feb 2004 21:54:22 -0000	1.2
  @@ -1,5 +1,6 @@
   <?xml version="1.0" ?>
  -<workspace basedir="/data/gump" 
  +<workspace name="test"
  +	       basedir="/data/gump" 
              jardir="/data/gump/jars/latest"
              logdir="/data/gump/log"
              pkgdir="/data/package"
  
  
  
  1.2       +2 -1      jakarta-gump/python/gump/test/resources/circular1/workspace.xml
  
  Index: workspace.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/resources/circular1/workspace.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- workspace.xml	17 Nov 2003 22:10:52 -0000	1.1
  +++ workspace.xml	17 Feb 2004 21:54:22 -0000	1.2
  @@ -1,5 +1,6 @@
   <?xml version="1.0" ?>
  -<workspace basedir="/data/gump" 
  +<workspace name="test"
  +	       basedir="/data/gump" 
              jardir="/data/gump/jars/latest"
              pkgdir="/data/package"
              sync="rsync -r -a --delete" version="0.3">