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 2003/12/15 20:36:52 UTC

cvs commit: jakarta-gump/python/gump/gui view.py

ajack       2003/12/15 11:36:52

  Modified:    python/gump/output statsdb.py repository.py
               python/gump engine.py config.py
               python/gump/model module.py workspace.py rawmodel.py ant.py
                        project.py object.py loader.py repository.py
               python/gump/test/resources/full1 profile.xml
               python/gump/utils note.py xmlutils.py
               python/gump/test loader_tests.py
               python/gump/document forrest.py
               python/gump/gui view.py
  Added:       python/gump continuous.py
               python/gump/model profile.py
               python/gump/test/resources/full1 broken1.xml broken2.xml
  Log:
  1) Exit if bad environment
  2) Try to store (to log) XML errors.
  3) Added 'bad XML' to unit tests
  4) Cope w/ duplicate project names (in different modules)
  
  Revision  Changes    Path
  1.5       +1 -1      jakarta-gump/python/gump/output/statsdb.py
  
  Index: statsdb.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/output/statsdb.py,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- statsdb.py	12 Dec 2003 16:32:50 -0000	1.4
  +++ statsdb.py	15 Dec 2003 19:36:51 -0000	1.5
  @@ -81,7 +81,7 @@
       def __init__(self,dbdir=None,name=None):
           if not name: name='stats.db'
           if not dbdir: dbdir=dir.work
  -        self.dbpath    = os.path.normpath('%s/%s' % (dbdir,name))
  +        self.dbpath    = os.path.abspath('%s/%s' % (dbdir,name))
           log.debug('Open Statistic Database:' + self.dbpath)
           if not os.name == 'dos' and not os.name == 'nt':
               self.db		=	anydbm.open(self.dbpath,'c')
  
  
  
  1.2       +1 -1      jakarta-gump/python/gump/output/repository.py
  
  Index: repository.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/output/repository.py,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- repository.py	17 Nov 2003 22:10:54 -0000	1.1
  +++ repository.py	15 Dec 2003 19:36:51 -0000	1.2
  @@ -89,7 +89,7 @@
           return cmp(self.root,other.root)
               
       def getRepositoryDir(self):
  -        rdir=os.path.abspath(os.path.normpath(self.root))
  +        rdir=os.path.abspath(self.root)
           if not os.path.exists(rdir): os.mkdir(rdir)
           return rdir  
       
  
  
  
  1.42      +8 -1      jakarta-gump/python/gump/engine.py
  
  Index: engine.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/engine.py,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- engine.py	11 Dec 2003 18:56:26 -0000	1.41
  +++ engine.py	15 Dec 2003 19:36:51 -0000	1.42
  @@ -57,7 +57,7 @@
   
   class GumpEngine:
       
  -    def preprocess(self,run,exitOnError=0):
  +    def preprocess(self,run,exitOnError=1):
   
           #
           # Perform start-up logic 
  @@ -90,8 +90,15 @@
               message='Workspace version ['+workspace.getVersion()+'] below expected [' + setting.ws_version + ']'
               workspace.addWarning(message)
               log.warn(message)   
  +            
  +        # Write workspace to a 'merge' file
  +        workspace.writeXMLToFile(default.merge)
  +        workspace.setMergeFile(default.merge)
   
       def continuous(self):
  +        
  +        
  +        # :TODO: WORK IN PROGRESS NOT COMPLETE!!!
           
           while 0:
               
  
  
  
  1.11      +9 -9      jakarta-gump/python/gump/config.py
  
  Index: config.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/config.py,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- config.py	11 Dec 2003 18:56:26 -0000	1.10
  +++ config.py	15 Dec 2003 19:36:51 -0000	1.11
  @@ -75,14 +75,14 @@
       """Configuration of paths"""
   
       cmdpath   = os.path.abspath(sys.argv[0])
  -    base      = os.path.normpath('%s/%s' % (os.path.dirname(cmdpath),'../..'))
  +    base      = os.path.abspath('%s/%s' % (os.path.dirname(cmdpath),'../..'))
       
  -    cache     = os.path.normpath('%s/%s' % (base,'cache'))
  -    work      = os.path.normpath('%s/%s' % (base,'work'))
  -    tmp       = os.path.normpath('%s/%s' % (base,'tmp'))
  -    template  = os.path.normpath('%s/%s' % (base,'template'))
  +    cache     = os.path.abspath('%s/%s' % (base,'cache'))
  +    work      = os.path.abspath('%s/%s' % (base,'work'))
  +    tmp       = os.path.abspath('%s/%s' % (base,'tmp'))
  +    template  = os.path.abspath('%s/%s' % (base,'template'))
           
  -    test      = os.path.normpath('%s/%s' % (base,'test'))
  +    test      = os.path.abspath('%s/%s' % (base,'test'))
   
   def gumpPath(path,basedir=None):
     """returns the path absolutized relative to the base gump dir"""
  @@ -95,9 +95,9 @@
       gumpfullhost   = socket.gethostname()   
       gumphost   = socket.gethostname().split('.')[0]
       gumpid	   = os.getpid()    
  -    workspace  = os.path.normpath('%s/%s.xml' % (dir.base, gumphost))
  -    globalws   = os.path.normpath('%s/%s' % (dir.base, 'global-workspace.xml'))
  -    merge      = os.path.normpath('%s/%s' % (dir.work, 'merge.xml'))
  +    workspace  = os.path.abspath('%s/%s.xml' % (dir.base, gumphost))
  +    globalws   = os.path.abspath('%s/%s' % (dir.base, 'global-workspace.xml'))
  +    merge      = os.path.abspath('%s/%s' % (dir.work, 'merge.xml'))
       date       = time.strftime('%Y%m%d')
       logLevel   = logging.INFO # logging.DEBUG
       classpath = (os.getenv('CLASSPATH') or '').split(os.pathsep)  
  
  
  
  1.1                  jakarta-gump/python/gump/continuous.py
  
  Index: continuous.py
  ===================================================================
  #!/usr/bin/python
  """
    This is the commandline entrypoint into gump.
  
    It at the moment basically
    calls gump.load() to get the workspace, then dumps
    information about what it should be doing to stdout.
  
    The main thing to do here is to clone dumpDeps to create a
    build() method which executes the appropriate script
    (probably only ant at the moment; would be nice to have
    support for maven) for each of the dependencies.
  """
  
  import os.path
  import os
  import sys
  import logging
  
  from gump import log
  from gump.engine import GumpEngine
  from gump.gumprun import GumpRun, GumpRunOptions, GumpSet
  from gump.utils.commandLine import handleArgv
  from gump.model.loader import WorkspaceLoader
  
  
  ###############################################################################
  # Initialize
  ###############################################################################
  
  
  ###############################################################################
  # Functions
  ###############################################################################
  
  # static void main()
  if __name__=='__main__':
  
      # Process command line
      args = handleArgv(sys.argv)
      ws=args[0]
      ps=args[1]
      
      # get parsed workspace definition
      workspace=WorkspaceLoader().load(ws)
        
      
      # TODO populate...
      options=GumpRunOptions()
    
      #
      # Dated means add the date to the log dir...
      #
      if '-d' in args or '--dated' in args:
          options.setDated(1)
      
      # The Run Details...
      run=GumpRun(workspace,ps,options)
      
      #
      #    Perform this integration run...
      #
      result = GumpEngine().continuous(run)
  
      #
      log.info('Gump Continuous Integration complete. Exit code:' + str(result))
            
      # bye!
      sys.exit(result)
  
  
  1.22      +12 -4     jakarta-gump/python/gump/model/module.py
  
  Index: module.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/module.py,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- module.py	12 Dec 2003 16:32:50 -0000	1.21
  +++ module.py	15 Dec 2003 19:36:51 -0000	1.22
  @@ -69,6 +69,7 @@
   from gump.model.project import *
   from gump.model.object import NamedModelObject
   from gump.utils import getIndent
  +from gump.utils.note import transferAnnotations, Annotatable
   
   class ModuleCvs(ModelObject):
       def __init__(self,xml,repository):
  @@ -226,10 +227,13 @@
                   #
                   project=workspace.getProject(xmlproject.name)
                   
  -                #
  -                # Claim ownership
  -                #
  -                self.addProject(project)
  +                if not project.inModule():
  +                    #
  +                    # Claim ownership
  +                    #
  +                    self.addProject(project)
  +                else:
  +                    workspace.addError('Duplicate project [' + xmlproject.name + ']')
                   
                   #
                   # Check for packaged
  @@ -332,6 +336,9 @@
           # For prettiness
           self.sortedProjects=createOrderedList(self.getProjects())
                               
  +        # Copy over any XML errors/warnings
  +        transferAnnotations(self.xml, self)  
  +                
           self.setComplete(1)            
           
       def addProject(self,project):
  @@ -466,6 +473,7 @@
       
       def dump(self, indent=0, output=sys.stdout):
           output.write(getIndent(indent)+'Module : ' + self.name + '\n')
  +        NamedModelObject.dump(self, indent+1, output)
           
       def getSourceDirectory(self):
           return self.absSrcDir
  
  
  
  1.17      +50 -2     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.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- workspace.py	9 Dec 2003 00:48:36 -0000	1.16
  +++ workspace.py	15 Dec 2003 19:36:51 -0000	1.17
  @@ -73,8 +73,10 @@
   from gump.model.repository import Repository
   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.property import PropertyContainer
  +from gump.utils.note import transferAnnotations, Annotatable
   
   
   class Workspace(ModelObject,PropertyContainer):
  @@ -86,11 +88,13 @@
       	#
       	# Named repositories (e.g. CVS,SVN,etc.)
       	# Named modules
  -    	# named projects
  +    	# Named projects
  +    	# Named profiles
       	#
       	self.repositories={}
           self.modules={}
           self.projects={}
  +        self.profiles={}
           
           #
       	PropertyContainer.importProperties(self,self.xml)    	
  @@ -114,6 +118,9 @@
                                   time.localtime())
           self.timezone=str(time.tzname)    
   
  +        # Where the merged XML was put
  +        self.mergeFile=None
  +        
       def getChildren(self):
           return self.getModules() 
       
  @@ -133,6 +140,20 @@
           return self.sortedRepositories
   
   
  +    # Profile Interface
  +        
  +    def hasProfile(self,mname):
  +        return self.profiles.has_key(mname)
  +        
  +    def getProfile(self,mname):
  +        return self.profiles.get(mname,None)
  +
  +    def getProfiles(self):
  +        return self.profiles.values()              
  +                
  +    def getSortedProfiles(self):
  +        return self.sortedProfiles   
  +                
       # Module Interface
           
       def hasModule(self,mname):
  @@ -226,6 +247,19 @@
               self.signature=self.xml.signature          
         
           #
  +        # Import all profiles
  +        #  
  +        for xmlprofile in xmlprofiles.values(): 
  +            profile=Profile(xmlprofile,self)
  +            profileName=profile.getName()
  +            if profileName in self.profiles:
  +                # Duplicate, uh oh...
  +                self.addError("Duplicate profile name [" + profileName + "]")
  +            else:        
  +                profile.complete(self)
  +                self.profiles[profileName] = profile
  +
  +        #
           # Import all repositories
           #  
           for xmlrepository in xmlrepositories.values(): 
  @@ -304,7 +338,11 @@
           self.sortedModules=createOrderedList(self.getModules())
           self.sortedProjects=createOrderedList(self.getProjects())
           self.sortedRepositories=createOrderedList(self.getRepositories())
  +        self.sortedProfiles=createOrderedList(self.getProfiles())
           
  +        # Copy over any XML errors/warnings
  +        transferAnnotations(self.xml, self)  
  +                
           self.setComplete(1)
   
       def completeDirectories(self):
  @@ -392,7 +430,11 @@
           
       def dump(self, indent=0, output=sys.stdout):
           output.write('Workspace : \n')
  +        ModelObject.dump(self, indent+1, output)
           
  +        for profile in self.profiles.values():
  +            profile.dump(indent+1,output)
  +            
           for repo in self.repositories.values():
               repo.dump(indent+1,output)
           
  @@ -417,6 +459,12 @@
               
       def getLogUrl(self):
           return self.logurl            
  +        
  +    def setMergeFile(self,file):
  +        self.mergeFile=file
  +    
  +    def getMergeFile(self):
  +        return self.mergeFile
       
       # :TODO: Inefficient, ought store sorted
       def getProjectIterator(self):
  @@ -538,7 +586,7 @@
               print
               print " Unable to detect/test mandatory [" + command+ "] in path (see next)."
               for p in sys.path:
  -                print "  " + str(os.path.normpath(p))
  +                print "  " + str(os.path.abspath(p))
               sys.exit(MISSING_UTILITY)
           
           # Store the output
  
  
  
  1.8       +1 -1      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.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- rawmodel.py	11 Dec 2003 18:56:27 -0000	1.7
  +++ rawmodel.py	15 Dec 2003 19:36:51 -0000	1.8
  @@ -104,7 +104,7 @@
       
       # parse out '@@DATE@@'
       for (name,value) in attrs.items():
  -      if not name == '@basedir':
  +      if not name == '@basedir' and not name == 'annotations':
             self.__dict__[name]=value.replace('@@DATE@@',gump.default.date)
         
   class XMLWorkspace(GumpXMLModelObject):
  
  
  
  1.11      +0 -2      jakarta-gump/python/gump/model/ant.py
  
  Index: ant.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/ant.py,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ant.py	11 Dec 2003 18:56:27 -0000	1.10
  +++ ant.py	15 Dec 2003 19:36:51 -0000	1.11
  @@ -136,8 +136,6 @@
                               0,	\
                               ids)
                               
  -            dependency.addInfo("Property Based Dependency " + `property`)
  -            
               # :TODOs:
               # if not property.classpath: depend['noclasspath']=Single({})
               
  
  
  
  1.24      +13 -4     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.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- project.py	12 Dec 2003 16:32:50 -0000	1.23
  +++ project.py	15 Dec 2003 19:36:51 -0000	1.24
  @@ -73,6 +73,7 @@
   from gump.model.rawmodel import Single
   from gump.utils import getIndent
   from gump.model.depend import *
  +from gump.utils.note import transferAnnotations, Annotatable
   
   #
   # An annotated path has a path entry, plus the context
  @@ -510,7 +511,10 @@
                       self.addWarning("Bad *Optional* Dependency. Project: " + xmloption.project + " unknown to *this* workspace")
           else:
               self.addInfo("This is a packaged project, location: " + str(self.home))        
  -            
  +                                    
  +        # Copy over any XML errors/warnings
  +        transferAnnotations(self.xml, self)  
  +                
           self.setComplete(1)
   
       def  checkPackage(self):
  @@ -748,6 +752,10 @@
           cmd.addPrefixedParameter('-D','build.sysclasspath','only','=')
           cmd.addPrefixedParameter('-D','build.clonevm','true','=')
       
  +        mergeFile=self.getWorkspace().getMergeFile()
  +        if mergeFile:
  +            cmd.addPrefixedParameter('-D','gump.merge',str(mergeFile),'=')        
  +    
           # These are module level plus project level
           cmd.addNamedParameters(properties)
       
  @@ -779,7 +787,7 @@
           #	plus:
           #	The specifier for ANT, or nothing.
           #
  -        basedir = os.path.normpath(os.path.join(self.getModule().getSourceDirectory() or dir.base,	\
  +        basedir = os.path.abspath(os.path.join(self.getModule().getSourceDirectory() or dir.base,	\
                                                       maven.basedir or ''))
       
           #
  @@ -910,7 +918,7 @@
           """ Return the command object for a <script entry """
           script=self.xml.script 
              
  -        basedir=os.path.normpath(os.path.join(self.getModule().getSourceDirectory() or dir.base,\
  +        basedir=os.path.abspath(os.path.join(self.getModule().getSourceDirectory() or dir.base,\
                           script.basedir or ''))
   
           # Add .sh  or .bat as appropriate to platform
  @@ -924,7 +932,7 @@
           verbose=script.verbose
           debug=script.debug
          
  -        scriptfile=os.path.normpath(os.path.join(basedir, scriptfullname))
  +        scriptfile=os.path.abspath(os.path.join(basedir, scriptfullname))
           (classpath,bootclasspath)=self.getClasspaths()
   
           cmd=Cmd(scriptfile,'buildscript_'+self.getModule().getName()+'_'+self.getName(),\
  @@ -956,6 +964,7 @@
       def dump(self, indent=0, output=sys.stdout):
           """ Display the contents of this object """
           output.write(getIndent(indent)+'Project: ' + self.getName() + '\n')
  +        NamedModelObject.dump(self, indent+1, output)
           
           for dependency in self.depends:
               dependency.dump(indent+1,output)
  
  
  
  1.13      +15 -7     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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- object.py	3 Dec 2003 18:36:13 -0000	1.12
  +++ object.py	15 Dec 2003 19:36:51 -0000	1.13
  @@ -182,18 +182,26 @@
           """ Display the contents of this object """
           Annotatable.dump(self,indent,output)
       
  -    def hasViewData(self):
  -        return hasattr(self,'viewdata')
  +    def hasXMLData(self):
  +        return hasattr(self,'xmldata')
           
  -    def getViewData(self):
  -        if not self.hasViewData():
  +    def getXMLData(self):
  +        if not self.hasXMLData():
               stream=StringIO.StringIO() 
               xmlize(self.xml.getTagName(),self.xml,stream)
               stream.seek(0)
  -            self.viewdata=stream.read()
  +            self.xmldata=stream.read()
               stream.close()
       
  -        return self.viewdata
  +        return self.xmldata
  +        
  +    def writeXMLToFile(self, outputFile):
  +        try:            
  +            f=open(outputFile, 'w')
  +            f.write(self.getXMLData())
  +        finally:
  +            # Since we may exit via an exception, close explicitly.
  +            if f: f.close()    
           
       # Somewhat bogus...
       
  @@ -257,7 +265,7 @@
       def dump(self, indent=0, output=sys.stdout):
           """ Display the contents of this object """
           output.write(getIndent(indent)+'Name: ' + self.name + '\n')
  -        ModelObject.dump(self,indent,output)
  +        ModelObject.dump(self,indent+1,output)
   
   # represents a <nag/> element
   class Nag(ModelObject):
  
  
  
  1.2       +9 -1      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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- loader.py	17 Nov 2003 22:10:50 -0000	1.1
  +++ loader.py	15 Dec 2003 19:36:51 -0000	1.2
  @@ -68,6 +68,7 @@
   from gump.model.workspace import Workspace
   from gump.model.module import Module
   from gump.utils.xmlutils import SAXDispatcher
  +from gump.utils.note import transferAnnotations, Annotatable
   
   class WorkspaceLoader:
       def __init__(self):
  @@ -94,13 +95,20 @@
         XMLProject.map={}
       
         log.debug("Launch SAX Dispatcher onto : " + file);
  +              
  +      parser=SAXDispatcher(file,'workspace',XMLWorkspace)
       
  -      xmlworkspace=SAXDispatcher(file,'workspace',XMLWorkspace).docElement
  +      # Extract the root XML
  +      xmlworkspace=parser.docElement
       
         if not xmlworkspace:
           raise IOError, "Failed to load workspace" + file
       
  +      # Construct object around XML.
         workspace=Workspace(xmlworkspace)
  +      
  +      # Copy over any XML errors/warnings
  +      transferAnnotations(parser, workspace)
     
         #
         # Cook the raw model...
  
  
  
  1.6       +1 -1      jakarta-gump/python/gump/model/repository.py
  
  Index: repository.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/model/repository.py,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- repository.py	26 Nov 2003 16:08:39 -0000	1.5
  +++ repository.py	15 Dec 2003 19:36:51 -0000	1.6
  @@ -124,7 +124,7 @@
       
       def dump(self, indent=0, output=sys.stdout):
           output.write(getIndent(indent)+'Repository : ' + self.name + '\n')   
  -        NamedModelObject.dump(self)
  +        NamedModelObject.dump(self,indent+1,output)
           
       def hasTitle(self): 
           return hasattr(self.xml,'title') and self.xml.title
  
  
  
  1.1                  jakarta-gump/python/gump/model/profile.py
  
  Index: profile.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/>.
  
  """
      This module contains information on
  """
  
  from time import localtime, strftime, tzname
  from string import lower, capitalize
  
  from gump.utils.work import *
  from gump.utils.launcher import *
  from gump.utils.tools import *
  
  from gump.model.state import *
  from gump.model.object import NamedModelObject
  from gump.utils.note import transferAnnotations, Annotatable
  
  
  class Profile(NamedModelObject):
      """Gump Profile"""
      def __init__(self,xml,workspace):
      	NamedModelObject.__init__(self,xml.getName(),xml,workspace) 
      	
      def complete(self,workspace):        
          if self.isComplete(): return
          
          # Copy over any XML errors/warnings
          transferAnnotations(self.xml, workspace)  
          # :TODO: Until we document the profile
          # add these to workspace transferAnnotations(self.xml, self)  
                  
          self.setComplete(1)                
      
      def dump(self, indent=0, output=sys.stdout):
          output.write(getIndent(indent)+'Profile : ' + self.name + '\n')   
          NamedModelObject.dump(self, indent+1, output)
  
  
  
  1.4       +3 -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.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- profile.xml	1 Dec 2003 17:34:08 -0000	1.3
  +++ profile.xml	15 Dec 2003 19:36:52 -0000	1.4
  @@ -10,6 +10,9 @@
     <module href="module4.xml"/>
     <module href="module5.xml"/>
     
  +  <module href="broken1.xml"/>
  +  <module href="broken2.xml"/>
  +  
     <module href="svn_module1.xml"/>
     <module href="maven1.xml"/>
   
  
  
  
  1.1                  jakarta-gump/python/gump/test/resources/full1/broken1.xml
  
  Index: broken1.xml
  ===================================================================
  <module name="broken1">
  
    <url  href="http://ant.apache.org/index.html"/>
    <description>
      Java based build tool
    </description>
  
    <!-- Bad repository -->
    <cvs repository="repositoryNoSuch"/>
  
    <!-- Duplicates -->
    <project name="duplicateProject1">
    	<ant />
    </project>
    <project name="duplicateProject1">
    	<ant />
    </project>
    
    <!-- Missing -->
    <project href="http://no_such_url_to_test_missing" />
    
  </module>
  
  
  
  
  1.1                  jakarta-gump/python/gump/test/resources/full1/broken2.xml
  
  Index: broken2.xml
  ===================================================================
  <module name="broken2">
  
    <bad xml>
    
  </module>
  
  
  
  
  1.4       +7 -2      jakarta-gump/python/gump/utils/note.py
  
  Index: note.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/utils/note.py,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- note.py	4 Dec 2003 23:16:24 -0000	1.3
  +++ note.py	15 Dec 2003 19:36:52 -0000	1.4
  @@ -124,8 +124,8 @@
       def addAnnotation(self,level,text):
           self.addAnnotationObject(Annotation(level,text))
           
  -    def addAnnotationObject(self,message):
  -        self.annotations.append(message)
  +    def addAnnotationObject(self,note):
  +        self.annotations.append(note)
           
       def getAnnotations(self):
           return self.annotations
  @@ -146,5 +146,10 @@
          
               for note in self.annotations:
                   note.dump(indent+1,output)
  +                
  +def transferAnnotations(source,destination):
  +    for note in source.annotations:
  +        destination.addAnnotationObject(note)
  +    
     
           
  
  
  
  1.5       +42 -20    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.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- xmlutils.py	19 Nov 2003 20:09:44 -0000	1.4
  +++ xmlutils.py	15 Dec 2003 19:36:52 -0000	1.5
  @@ -72,18 +72,21 @@
   
   from gump import log
   from gump.utils.http import cacheHTTP
  +from gump.utils.note import *
   from gump.config import gumpPath
   
   ###############################################################################
   # SAX Dispatcher mechanism
   ###############################################################################
      
  -class SAXDispatcher(ContentHandler,ErrorHandler):
  +class SAXDispatcher(ContentHandler,ErrorHandler,Annotatable):
     """a stack of active xml elements"""
   
     def __init__(self,file,name,cls,basedir=None):
  -    """
  +      
  +    Annotatable.__init__(self)
       
  +    """    
           Creates a DocRoot and parses the specified file into a GOM tree.
   
           The GOM tree is stored in the self.docElement attribute.
  @@ -110,7 +113,14 @@
           attributes['@basedir']=self.basedir
           
           # The newly loaded object moves to top of stack
  -        self.topOfStack=self.topOfStack.startElement(name,attributes)
  +        extractedObject=self.topOfStack.startElement(name,attributes)
  +        if not isinstance(extractedObject,Annotation):
  +            self.topOfStack=extractedObject
  +        else:
  +            # Nasty hack to try to return/annotate errors
  +            if self.topOfStack and isinstance(self.topOfStack,Annotatable):  
  +                self.topOfStack.addAnnotationObject(extractedObject)
  +                self.topOfStack.dump()
           
       self.elementStack.append(self.topOfStack)
   
  @@ -124,18 +134,19 @@
       self.topOfStack=self.elementStack[-1]
    
     def error(self, exception):
  -        log.error("Handle a recoverable error.")
  -        raise exception
  -
  +    self.addError('XML error : ' + str(exception))
  +    log.error("Handle a recoverable error." + str(exception), exc_info=1)
  +    raise exception
  +    
     def fatalError(self, exception):
  -        log.error("Handle a non-recoverable error.")
  -        raise exception
  +    self.addError('XML error : ' + str(exception))
  +    log.error("Handle a non-recoverable error." + str(exception), exc_info=1)
  +    raise exception
   
     def warning(self, exception):
  -        log.warn("Handle a warning.")
  -        print exception
  -
  -
  +    self.addWarning('XML warning' + str(exception))
  +    log.warn("Handle a warning." + str(exception), exc_info=1)
  +    
   ###############################################################################
   # Base classes for the Gump object model
   #
  @@ -143,7 +154,7 @@
   # allowing the actual model to be rather simple and compact. All
   # elements of the GOM should extend GumpXMLObject or a subclass of GumpXMLObject.
   ###############################################################################
  -class GumpXMLObject(object):
  +class GumpXMLObject(Annotatable,object):
     """Helper XML Object.
   
       Attributes become properties.  Characters become the string value
  @@ -152,9 +163,12 @@
       attributes)."""
   
     def __init__(self,attrs):
  +      
  +    Annotatable.__init__(self)    
  +    
       # Transfer attributes
       for (name,value) in attrs.items():
  -        if not name == '@basedir':
  +        if not name == '@basedir' and not name=='annotations':
               self.__dict__[name]=value
       # Setup internal character field
       if not '@text' in self.__dict__: self.init()
  @@ -277,20 +291,28 @@
               tag =  cls.__name__.lower().replace('xml','')
                           
               try:
  -                element=SAXDispatcher(newHref, \
  +                parser=SAXDispatcher(newHref, \
                                     tag, cls,\
  -                                  basedir).docElement        
  +                                  basedir)
  +                                  
  +                element=parser.docElement     
  +                
  +                # Copy over any XML errors/warnings
  +                transferAnnotations(parser, element)  
  +                
               except Exception, detail:
  -                log.error('Failed to parse XML @ [' + newHref + ']. Details: ' + str(detail))   
  -                element=None 
  +                message='Failed to parse XML @ [' + newHref + ']. Details: ' + str(detail)
  +                log.error(message, exc_info=1)   
  +                element=Annotation(LEVEL_ERROR, message)
           else:
               # :TODO: Set any object "invalid"?
  -            log.warn("HREF: ["+href+"] not loaded")
  +            log.warn("HREF: ["+href+"] not loaded", exc_info=1)
  +            element=Annotation(LEVEL_ERROR, message)
           
           #
           # Stash for general reference/interest
           #
  -        if element:
  +        if element and not isinstance(element,Annotation):
               element.href=href                    
           
           # Return the downloaded element instead...
  
  
  
  1.3       +6 -6      jakarta-gump/python/gump/test/loader_tests.py
  
  Index: loader_tests.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/test/loader_tests.py,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- loader_tests.py	21 Nov 2003 19:04:10 -0000	1.2
  +++ loader_tests.py	15 Dec 2003 19:36:52 -0000	1.3
  @@ -94,19 +94,19 @@
   
       #testWorkspace('gump/test/resources/simple2/workspace.xml').dump()
       
  -    #testWorkspace('gump/test/resources/full1/workspace.xml').dump()
  +    testWorkspace('gump/test/resources/full1/workspace.xml').dump()
   
       #try:
       #    testWorkspace('gump/test/resources/broken1/broken_workspace.xml') 
       #except:
       #    print "Fixme" # :TODO: Just set status on bad sub-elements, not fail whole
       #    
  -    ws = createTestWorkspace()
  +    #ws = createTestWorkspace()
       
  -    module=testModule('http://cvs.apache.org/viewcvs.cgi/*checkout*/avalon/buildsystem/gump-integration/project/avalon.xml',ws)
  +    #module=testModule('http://cvs.apache.org/viewcvs.cgi/*checkout*/avalon/buildsystem/gump-integration/project/avalon.xml',ws)
       
  -    dump(module)
  +    #dump(module)
       
  -    printSeparator()
  -    print xmlize('module', module, ws)
  +    #printSeparator()
  +    #print xmlize('module', module, ws)
     
  
  
  
  1.38      +1 -1      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.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- forrest.py	14 Dec 2003 17:57:39 -0000	1.37
  +++ forrest.py	15 Dec 2003 19:36:52 -0000	1.38
  @@ -1067,7 +1067,7 @@
               propertyRow=propertiesTable.createRow()
               propertyRow.createData(property.getName())
               propertyRow.createData(property.getValue())
  -            propertyRow.createData(property.getViewData())
  +            propertyRow.createData(property.getXMLData())
                           
       def documentXML(self,xdocNode,xmlOwner):
           
  
  
  
  1.4       +4 -4      jakarta-gump/python/gump/gui/view.py
  
  Index: view.py
  ===================================================================
  RCS file: /home/cvs/jakarta-gump/python/gump/gui/view.py,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- view.py	26 Nov 2003 20:01:16 -0000	1.3
  +++ view.py	15 Dec 2003 19:36:52 -0000	1.4
  @@ -347,7 +347,7 @@
           self.history.append(project)
   
     def showProject(self,project):
  -    if self.history: self.history[-1]['viewdata']=self.data.GetValue()
  +    if self.history: self.history[-1]['xmldata']=self.data.GetValue()
       self.frame.SetTitle(project.name)
   
       # gather a list of projects which reference this project
  @@ -368,13 +368,13 @@
   
       # display the project definition
       self.data.Clear()
  -    #if project.viewdata:
  -    #  self.data.AppendText(project.viewdata)
  +    #if project.xmldata:
  +    #  self.data.AppendText(project.xmldata)
       #else:
       #  self.data.AppendText(xmlize('project',project))
       #  self.data.ShowPosition(0)
       
  -    self.data.AppendText(project.getViewData())
  +    self.data.AppendText(project.getXMLData())
       self.data.ShowPosition(0)
   
       # gather a list of project dependencies unrolled to build