gump-general mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nicola...@apache.org
Subject cvs commit: jakarta-gump/python build.py gen.py gumpconf.py gumpcore.py gumputil.py gumpview.py
Date Wed, 23 Apr 2003 12:27:21 GMT
nicolaken    2003/04/23 05:27:21

  Added:       python   build.py gen.py gumpconf.py gumpcore.py gumputil.py
                        gumpview.py
  Log:
  New Gump WIP based on Python.
  
  Revision  Changes    Path
  1.1                  jakarta-gump/python/build.py
  
  Index: build.py
  ===================================================================
  #!/usr/bin/python
  """
  	Look for obsolete installed packages, cvs checkouts, and build
  	directories.
  """
  
  import os.path,os,sys
  from gumpcore import *
  from gumpconf import *
  
  os.chdir(dir.base)
  debug=True #False
  
  if len(sys.argv)>1 :
    ws=sys.argv[1]
  else:
    ws=default.workspace
  
  if len(sys.argv)>2 :
    pj=sys.argv[2]
  else:
    pj=default.project
    
  workspace=load(ws)
  projectname=pj
  project=Project.list[pj]
  module=Module.list[project.module]
  ant=project.ant
  
  print 'SRCDIR'
  print '  ',os.path.normpath(os.path.join(module.srcdir,ant.basedir or ''))
  
  print
  print 'CLASSPATH:'
  for depend in project.depend+project.option:
    p=Project.list[depend.project]
    srcdir=Module.list[p.module].srcdir
  
    for jar in p.jar:
      print '  ',os.path.normpath(os.path.join(srcdir,jar.name))
  
  print
  print 'PROPERTIES'
  for property in workspace.property+ant.property:
    print '  ',property.name,'=',property.value
  
  print 'PROJECTS TO BUILD:'
  
  build_sequence = dependencies(projectname, project.depend)
  
  print
  print ' ----- Build sequence for ' + projectname + ' -----'
  print
  for project in build_sequence:
    print '  ' + project.name
  
  
              
  sys.exit(0)
  
  
  
  1.1                  jakarta-gump/python/gen.py
  
  Index: gen.py
  ===================================================================
  #!/usr/bin/python
  """
  	Generate the merged XML description of the workspace
  """
  
  import os.path,os,sys
  from gumpcore import *
  from gumpconf import *
  
  os.chdir(dir.base)
  debug=True #False
  
  if len(sys.argv)>1 :
    ws=sys.argv[1]
  else:
    ws=default.workspace
  
  #########################################################################
  #                     Dump the object module as XML                     #
  #########################################################################
  
  def xmlize(nodeName,object,f,indent='',delta='  '):
    from xml.sax.saxutils import escape
    import types
  
    attrs=[nodeName]
    elements=[]
    text=''
    encoding='latin-1'
  
    # iterate over the object properties
    for name in object.__dict__:
      if name.startswith('__') and name.endswith('__'): continue
      var=getattr(object,name)
  
      # avoid nulls, metadata, and methods
      if not var: continue
      if isinstance(var,types.TypeType): continue
      if isinstance(var,types.MethodType): continue
  
      # determine if the property is text, attribute, or element
      if name=='@text':
        text=var
      elif isinstance(var,types.StringTypes): 
        attrs.append('%s="%s"' % (name,escape(var)))
      else:
        elements.append((name,var))
  
    # format for display
    if not elements:
      # use compact form for elements without children
      if text.strip():
        f.write( '%s<%s>%s</%s>' % (indent.encode(encoding),' '.join(attrs).encode(encoding),text.strip().encode(encoding),nodeName))
      else:
        f.write( '%s<%s/>' % (indent.encode(encoding),' '.join(attrs).encode(encoding)))
    else:
      # use full form for elements with children
      f.write( '%s<%s>' % (indent.encode(encoding),' '.join(attrs).encode(encoding)))
      newindent=indent+delta
      for (name,var) in elements:
        if isinstance(var,list):
          # multiple valued elements
          for e in var: xmlize(name,e,f,newindent,delta)
        elif isinstance(var,Single):
         # single valued elements
          xmlize(name,var.delegate,f,newindent,delta)
      f.write( '%s</%s>' % (indent.encode(encoding),nodeName.encode(encoding)))
  
    
  if __name__=='__main__':
    workspace=load(ws)
  
    try:
     f=open(dir.base+'/'+default.merge, 'w')
     xmlize('workspace',workspace,f)
    finally:
      # Since we may exit via an exception, close fp explicitly.
      if f:
        f.close()
  
  
  
  1.1                  jakarta-gump/python/gumpconf.py
  
  Index: gumpconf.py
  ===================================================================
  #!/usr/bin/python
  """
  	Configuration for Gump, done as Python classes
  """
  
  class dir:
     base      = ".."
     cache     = "cache"
  
  class default:
    workspace  = "rubix.xml"
    project    = "krysalis-ruper-test"
    merge      = "merge.xml"
  
  
  
  
  1.1                  jakarta-gump/python/gumpcore.py
  
  Index: gumpcore.py
  ===================================================================
  #!/usr/bin/python
  """
  	Gump core model
  """
  
  import os.path, os, time, urllib, urlparse, shutil, string, os.path
  from xml.sax import parse
  from xml.sax.handler import ContentHandler
  from gumputil import *
  from gumpconf import *
  #from Cheetah.Template import Template
    
  # output debug messages or not
  debug = False #True
    
  #########################################################################
  #	  SAX Dispatcher: maintain a stack of active elements		#
  #########################################################################
  
  class SAXDispatcher(ContentHandler):
    def __init__(self,file,name,cls):
      self.topOfStack=DocRoot(name,cls)
      self.elementStack=[self.topOfStack]
      parse(file,self)
      self.docElement=self.topOfStack.element
    def startElement (self, name, attrs):
      if self.topOfStack: self.topOfStack=self.topOfStack.startElement(name,attrs)
      self.elementStack.append(self.topOfStack);
    def characters(self, string):
      if self.topOfStack: self.topOfStack.characters(string)
    def endElement (self, name):
      del self.elementStack[-1]
      self.topOfStack=self.elementStack[-1]
  
  def load(file):
    workspace=SAXDispatcher(file,'workspace',Workspace).docElement
    workspace.complete()
    for module in Module.list.values(): module.complete(workspace)
    for project in Project.list.values(): project.complete(workspace)
    return workspace
  
  #########################################################################
  #		  Base classes for the Gump object model		#
  #########################################################################
  
  DATE=time.strftime('%Y%m%d')
  
  # base class for the entire Gump object model.  Attributes become
  # properties.  Characters become the string value of the element.
  class GumpBase(object):
    def __init__(self,attrs):
      for (name,value) in attrs.items():
        self.__dict__[name]=value.replace('@@DATE@@',DATE)
      if not '@text' in self.__dict__: self.init()
      self.__dict__['@text']=''
    def startElement(self, name, attrs):
      try:
        attr=self.__getattribute__(name)
        if isinstance(attr,Single): return attr(attrs)
        if isinstance(attr,Multiple): return attr(attrs)
      except:
        # print self.__class__, name
        pass
    def characters(self,string):
      self.__dict__['@text']+=string
    def __setitem__(self,name,value): 
      self.__dict__[name]=value
    def __getitem__(self,name): 
      if name in self.__dict__: return self.__dict__[name]
    def __getattr__(self,name): 
      pass
    def __str__(self): 
      return self.__dict__['@text'].strip()
    def init(self):
      pass
  
  # Document root: workspaces and targets of hrefs
  class DocRoot(GumpBase):
    def __init__(self,name,cls):
      GumpBase.__init__(self,{})
      self.name=name
      self.cls=cls
      self.element=None
    def startElement(self, name, attrs):
      if name<>self.name: 
        raise "Incorrect element, expected %s, found %s" % (self.name,name)
      self.element=self.cls(attrs)
      return self.element
  
  # Named elements (e.g., project,module,repository).  Supports href and
  # maintains a list of elements.  Duplicate names get merged.  Classes
  # declared of this type must declare a static list property.
  class Named(GumpBase):
    def __new__(cls,attrs):
      href=attrs.get('href')
      
      if href: 
        newHref=gumpCache(href)
        if debug: print 'opening: ' + newHref + '\n'
        element=SAXDispatcher(open(newHref),cls.__name__.lower(),cls).docElement
      else:
        name=attrs.get('name')      
        try:
  	element=cls.list[name]
        except:
  	element=GumpBase.__new__(cls,attrs)
  	if name: cls.list[name]=element
      return element
  
  # properties which are only ever expected to hold a single value 
  class Single(object):
    def __init__(self,cls=GumpBase):
      self.delegate=None
      self.cls=cls
    def __call__(self,attrs):
      if self.delegate: 
        self.delegate.__dict__.update(dict(attrs))
      else:
        self.delegate=self.cls(attrs)
      return self.delegate
    def __getattr__(self,name):
      if self.delegate: 
        try:
          return self.delegate.__getattribute__(name)
        except:
          return self.delegate[name]
    def __str__(self):
      if self.delegate: return self.delegate.__str__()
      return ''
    def __nonzero__(self):
      return self.delegate
  
  # properties which can hold multiple instances
  class Multiple(list):
    def __init__(self,cls=GumpBase):
      list.__init__(self)
      self.cls=cls
    def __call__(self,attrs):
      result=self.cls(attrs)
      self.append(result)
      return result
  
  #########################################################################
  #			    Gump Object Model				#
  #########################################################################
  
  class Workspace(GumpBase):
    def init(self): 
      self.property=Multiple(Property)
      self.project=Multiple(Project)
      self.module=Multiple(Module)
      self.repository=Multiple(Repository)
      self.profile=Multiple(Profile)
    def complete(self):
      if not self['banner-image']:
        self['banner-image']="http://jakarta.apache.org/images/jakarta-logo.gif"
      if not self['banner-link']: self['banner-link']="http://jakarta.apache.org"
      if not self.logdir: self.logdir=self.basedir+"/log"
      if not self.cvsdir: self.cvsdir=self.basedir+"/cvs"
      if not self.pkgdir: self.pkgdir=self.basedir
      if self.deliver:
        if not self.scratchdir: self.scratchdir=self.basedir+"/scratch"
  
  class Profile(Named):
    list={}
    def init(self): 
      self.project=Multiple(Project)
      self.module=Multiple(Module)
      self.repository=Multiple(Repository)
  
  class Module(Named):
    list={}
    def init(self): 
      self.cvs=Single()
      self.url=Single()
      self.description=Single()
      self.redistributable=Single()
      self.project=Multiple(Project)
    def complete(self,workspace):
      self.srcdir=os.path.join(str(workspace.basedir),self.srcdir or self.name)
      for project in self.project: 
        if not project.module: project.module=self.name
  
  class Repository(Named):
    list={}
    def init(self): 
      self['home-page']=Single()
      self.title=Single()
      self.cvsweb=Single()
      self.root=Single(RepositoryRoot)
      self.redistributable=Single()
  
  class RepositoryRoot(GumpBase):
    def init(self): 
      self.method=Single()
      self.user=Single()
      self.password=Single()
      self.hostname=Single()
      self.path=Single()
  
  class Project(Named):
    list={}
    def init(self): 
      self.ant=Single(Ant)
      self.script=Single()
      self.depend=Multiple(Depend)
      self.description=Single()
      self.url=Single()
      self.option=Multiple(Depend)
      self.property=Single(Property)
      self.package=Multiple()
      self.jar=Multiple(Jar)
      self.home=Single(Home)
      self.license=Single()
      self.nag=Multiple(Nag)
      self.javadoc=Single(Javadoc)
      self.junitreport=Single(JunitReport)
      self.work=Multiple(Work)
      self.mkdir=Multiple(Mkdir)
      self.redistributable=Single()
    def complete(self,workspace):
  
      # compute home directory
      if self.home and isinstance(self.home,Single):
        if self.home.nested:
          srcdir=Module.list[self.module].srcdir
  	self.home=srcdir +'/' + self.home.nested
  	
      # complete properties
      if self.ant: self.ant.complete(self)
  
  class Ant(GumpBase): 
    def init(self): 
      self.depend=Multiple(Depend)
      self.property=Multiple(Property)
      self.jvmarg=Multiple()
    def complete(self,project):
      for property in self.property: property.complete(project)
  
  class Nag(GumpBase): 
    def init(self): 
      self.regexp=Multiple()
  
  class Javadoc(GumpBase): 
    def init(self): 
      self.description=Multiple()
  
  class Property(GumpBase): 
    def complete(self,project):
      if self.reference=='home':
        self.value=Project.list[self.project].home
      if self.reference=='srcdir':
        module=Project.list[self.project].module
        self.value=Module.list[module].srcdir
  
  class Depend(GumpBase): pass
  class Description(GumpBase): pass
  class Home(GumpBase): pass
  class Jar(GumpBase): pass
  class JunitReport(GumpBase): pass
  class Mkdir(GumpBase): pass
  class Work(GumpBase): pass
  
  #########################################################################
  #                     Utility functions                                 #
  #########################################################################
  
  #sort project dependencies of a project and returns build sequence
  def dependencies(root, #string
           projects, #hashtable
           state = {}, #hashtable
           visiting= [], #stack
           ret = [], #vector
           internalProjects = [],#vector
           indent = ''):
  
          VISITING = 0
          VISITED = 1
          indent=indent+' '
          state[root] = VISITING
          visiting.append(root)
          project=Project.list[root]
  
          # Make sure we exist
          if not project:
              print  "Project `" + root + "' does not exist in this project. ";
              visiting.pop();
              if visiting:
                  parent = visiting[:];
                  print ("\nIt is needed for project `" + parent + "'.");
                  raise
  
          if debug:
            print '------------------------- VISITING ' + root
            
          for depend in project.depend:#+project.option:
            cur = depend.project
            print indent + '(' + root + ' -- dep --> ' + cur
            
            try:
              p=Project.list[depend.project]
            except:
              print 'ERROR: Cannot find ' + depend.project
              print '  referenced by ' + project.name
              print '  that has the following dependencies:'
              for dep in project.depend:
                print '   ->' + dep.project
              print
              raise
              
            #print state.keys()
            
            if not state.has_key(cur):
              # Not been visited
              dependencies(cur, projects, state, visiting, ret, internalProjects, indent);
            elif (state[cur] == VISITING):
              # Currently visiting this node, so have a cycle
              print 'Circular exception'
              print 'current node: ' + cur
              print 'visited stack: ' + visiting
              raise
  
  
          p = visiting.pop();
          if not (root == p):
              print 'Unexpected internal error: expected to pop ' + root + ' but got ' + p
              raise
  
          print '------------------------- VISITED ' + root
          state[root] = VISITED
  
          ret.append(project)
  
          return ret
        
  #########################################################################
  #			    Demonstration code				#
  #########################################################################
  
  if __name__=='__main__':
    print "*** starting ***"
    os.chdir(dir.base)
    workspace=load('rubix.xml')
  
    print
    print "*** workspace ***"
    print
    print 'basedir:\t', workspace.basedir
    print 'pkgdir:\t\t', workspace.pkgdir
    for property in workspace.property: print 'Property:\t',property.name,property.value
  
    print
    print "*** JDBC ***"
    print
    jdbc=Project.list['jdbc']
    print 'Package:\t', jdbc.package
    for jar in jdbc.jar: print 'Jar:\t\t', jar.name, jar.id
  
    print
    print "*** Junit ***"
    print
  
    junit=Module.list['junit']
    print 'Description:\t', junit.description
    print 'Url:\t\t', junit.url.href
    print 'Cvs:\t\t', junit.cvs.repository
  
    junit=Project.list['junit']
    print 'Package:\t', junit.package[0]
    for depend in junit.depend: print 'Depend:\t\t',depend.project
    for jar in junit.jar: print 'Jar:\t\t', jar.name, jar.id
    
    print
    print "*** Gump ***"
    print
    gump=Project.list['gump']
    for depend in gump.depend: print 'Depend:\t\t',depend.project
    ant=gump.ant
    for property in ant.property: print 'Property:\t',property.name,property.value
    
    print
    print "*** krysalis-ruper-test ***"
    print
    krysalisrupertest=Project.list['krysalis-ruper-test']
    for depend in krysalisrupertest.depend: print 'Depend:\t\t',depend.project
    ant=krysalisrupertest.ant
    for property in ant.property: print 'Property:\t',property.name,property.value
  
  
  
  ##
  ##templateDef = """
  ##<HTML>
  ##<HEAD><TITLE>$gump.ant</TITLE></HEAD>
  ##<BODY>
  ##
  #### this is a single-line Cheetah comment and won't appear in the output
  ###* This is a multi-line comment and won't appear in the output
  ##    blah, blah, blah 
  ##*#
  ##</BODY>
  ##</HTML>"""
  ##nameSpace = {'gump': gump, 'contents': 'Hello World!'}
  ###t = Template(templateDef, searchList=[nameSpace])
  ##t = Template(templateDef)
  ##t.gump=gump
  ##print t
  
  
  
  
  
  1.1                  jakarta-gump/python/gumputil.py
  
  Index: gumputil.py
  ===================================================================
  #!/usr/bin/python
  """
  	Utility functions for Gump
  """
  
  import os, os.path, sys, urllib, urlparse
  from gumpconf import *
  
  # output debug messages or not
  debug = False #True
    
  #########################################################################
  #                     Utility functions                                 #
  #########################################################################
  
   
  # returns the path of the file in the href, cached if remote
  def gumpCache(href):
      
    #if it's a local file get it locally
    if not href.startswith('http://'):
      newHref=href;  
    else:
      if debug: print 'url: ' + href
      if not os.path.exists(dir.cache):  mkdir(dir.cache)
  
      #the name of the cached descriptor
      quotedHref = urllib.quote_plus(href)
      #the path of the cached descriptor
      newHref = dir.cache+'/'+quotedHref
      
      #download the file if not present in the cache
      if os.path.exists(newHref): 
        if debug: print 'using cached descriptor'
      else:  
        if debug: print 'caching...'
        urllib.urlretrieve(href, newHref)
        if debug: print '...done' 
  
    return newHref
  
  
  
  1.1                  jakarta-gump/python/gumpview.py
  
  Index: gumpview.py
  ===================================================================
  #!/usr/bin/python
  """
  	Graphic GUI to navigate a Gump workspace
  """
  
  import sys
  from xml.sax import parse
  from xml.sax.handler import ContentHandler
  
  # http://wxpython.org/
  from wxPython.wx import *
  
  from gumpcore import load,Module,Project,dependencies
  from gen import xmlize
  from gumpconf import *
  
  class gumpview(wxApp):
    # model
    mySubs=None
    items=None
    build_sequence=None
    
    # view
    tree=None
    list=None
    data=None
  
    # tree index
    mItem={}
    pItem={}
  
    def OnInit(self):
      # layout 
      frame = wxFrame(NULL, -1, "Gump Workspace Viewer")
      split1 = wxSplitterWindow(frame,-1)
      notebook = wxNotebook(split1, -1, style=wxCLIP_CHILDREN)
      split2 = wxSplitterWindow(notebook,-1)
      
      # panes 
      self.tree=wxTreeCtrl(split1,-1)
      self.list=wxListCtrl(split2,-1,style=wxLC_REPORT|wxSUNKEN_BORDER)
      self.dependencies=wxListCtrl(notebook,-1,style=wxLC_REPORT|wxSUNKEN_BORDER)
      self.data=wxTextCtrl(split2,-1,style=wxTE_MULTILINE)
  
      # attach the panes to the frame
      split1.SplitVertically(self.tree, notebook)
      notebook.AddPage(split2, 'referenced')
      notebook.AddPage(self.dependencies, 'dependencies')
      split2.SplitHorizontally(self.list, self.data)
      self.SetTopWindow(frame)
      frame.Show(true)
      
      # resize
      split1.SetMinimumPaneSize(20)
      split2.SetMinimumPaneSize(20)
      split1.SetSashPosition(300,true)
      split2.SetSashPosition(200)
      
      # wire up the events
      EVT_TREE_SEL_CHANGED(self, self.tree.GetId(), self.selectTree)
      EVT_LIST_ITEM_SELECTED(self, self.list.GetId(), self.selectItem)
      EVT_LIST_ITEM_SELECTED(self, self.dependencies.GetId(), self.selectItem2)
      return true
      
    # list all modules and their projects
    def load(self,files):
      root = self.tree.AddRoot(files[0])
      self.workspace = load(files[0])
      names=Module.list.keys()
      names.sort()
      for name in names:
        module=Module.list[name]
        parent=self.mItem[name]=self.tree.AppendItem(root,name)
        self.tree.SetPyData(parent,module)
        for project in module.project:
  	self.pItem[project.name]=self.tree.AppendItem(parent,project.name)
  	self.tree.SetPyData(self.pItem[project.name],project)
  
      self.tree.Expand(root)
  
    # select a single feed and display titles from each item
    def selectTree(self, event):
      self.showProject(self.tree.GetPyData(event.GetItem()))
  
    def showProject(self,project):
      if not project or not isinstance(project,Project): return
  
      # gather a list of projects which reference this project
      self.items=[]
      for parent in Project.list.values():
        list=parent.depend+parent.option
        if parent.ant: list+=parent.ant.depend
        for depend in list:
  	if depend.project==project.name:
            self.items.append(parent.name)
  
      # display the list, sorted by name
      self.list.DeleteAllItems()
      if not self.list.GetColumn(0): 
        self.list.InsertColumn(0, 'Cross Reference')
        self.items.sort()
      for i in range(0,len(self.items)): 
        row=self.list.InsertStringItem(i,self.items[i])
        self.list.SetItemData(row,i)
  
      self.list.SetColumnWidth(0,wxLIST_AUTOSIZE_USEHEADER)
  
      # display the project definition
      import StringIO
      data = StringIO.StringIO()
      xmlize('project',project,data,)
      self.data.Clear()
      data.seek(0)
      self.data.AppendText(data.read())
      self.data.ShowPosition(0)
      
      # gather a list of project dependencies unrolled to build
      self.build_sequence = dependencies(project.name, project.depend)
      
      # display the project dependencies
      self.dependencies.DeleteAllItems()
      if not self.dependencies.GetColumn(0): 
        self.dependencies.InsertColumn(0, 'Build sequence')
        
      for i in range(0,len(self.build_sequence)): 
        row=self.dependencies.InsertStringItem(i,self.build_sequence[i].name)
        self.dependencies.SetItemData(row,i)
      
      self.list.SetColumnWidth(0,wxLIST_AUTOSIZE_USEHEADER)
  
      
    # show the xml description for a single item
    def selectItem(self, event):
      project=Project.list[self.items[event.GetItem().GetData()]]
      self.showProject(project)
  
      # expand the associated module and select the project
      self.tree.Expand(self.mItem[project.module])
      self.tree.SelectItem(self.pItem[project.name])
  
    # show the xml description for a single item
    def selectItem2(self, event):
      project=Project.list[self.build_sequence[event.GetItem().GetData()].name]
      self.showProject(project)
  
      # expand the associated module and select the project
      self.tree.Expand(self.mItem[project.module])
      self.tree.SelectItem(self.pItem[project.name])
      
  if __name__ == '__main__':
    app = gumpview(0)
    app.load(sys.argv[1:] or [default.workspace])
    app.MainLoop()
  
  
  

Mime
View raw message