You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gump.apache.org by le...@apache.org on 2005/01/01 17:30:28 UTC

svn commit: r123844 - in gump/branches/Dec04MajorCleanup/pygump: . python/gump python/gump/engine python/gump/model python/gump/util

Author: leosimons
Date: Sat Jan  1 08:30:27 2005
New Revision: 123844

URL: http://svn.apache.org/viewcvs?view=rev&rev=123844
Log:
Work on implementing the VFS, more pieces of the model, code cleanup, addition of documentation (mostly module-level), moving some bits and pieces around.
Modified:
   gump/branches/Dec04MajorCleanup/pygump/__init__.py
   gump/branches/Dec04MajorCleanup/pygump/main.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/   (props changed)
   gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/model/   (props changed)
   gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py
   gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py

Modified: gump/branches/Dec04MajorCleanup/pygump/__init__.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/__init__.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/__init__.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/__init__.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/__init__.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/__init__.py	Sat Jan  1 08:30:27 2005
@@ -14,6 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""Pygump downloads and compiles source code and interprets the results.
+
+See http://gump.apache.org/ for more information. There is a small module
+main that serves as the command line entrypoint which gives control to the
+gump.engine module, which again interacts with all the other materials
+inside the gump module.
+"""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
 

Modified: gump/branches/Dec04MajorCleanup/pygump/main.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/main.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/main.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/main.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/main.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/main.py	Sat Jan  1 08:30:27 2005
@@ -17,17 +17,18 @@
 #
 # $Header: $
 
-"""
-
-  This is the command line entrypoint into pygump.
-  
-  It parses the environment variables, command line arguments and
-  some workspace settings and populates an options object with what
-  it finds. With this, it starts up the main gump engine.
+"""The command line entrypoint into pygump.
   
-  Additionally, this module has some pretty much self-contained logging
-  and error handling. In the event of severe problems, it'll send e-mail
-  to the administrator configured in the workspace for this machine.
+It parses the environment variables, command line arguments and
+some workspace settings and populates an options object with what
+it finds. With this, it starts up the main gump engine.
+
+Additionally, this module has some pretty much self-contained logging
+and error handling. In the event of severe problems, it'll send e-mail
+to the administrator configured in the workspace for this machine.
+
+Don't run pygump directly. Rather, use the 'gump' shell script. See
+its documentation for information on command line options and the like.
 """
 
 import os
@@ -47,12 +48,19 @@
 ERROR = 2
 CRITICAL = 1
 
-class Logger:
-    """
-    Very basic "bootstrap" logger to use before getting at a real logger from
-    the logging package. Does react to the most basic form of the commands sent
-    to the logging.Logger class so it can be replaced at any time by one of
-    those.
+
+class Error(Exception):
+    """Generic error thrown for all internal pygump main module exceptions."""
+    pass
+
+
+class _Logger:
+    """A basic logger that sends messages to a file and to the console.
+    
+    This is a very basic "bootstrap" logger to use before getting at a real
+    logger from the logging package. Does react to the most basic form of the
+    commands sent to the logging.Logger class so it can be replaced at any time
+    by one of those.
     """
     
     def __init__(self, logdir, level=DEBUG, console_level=INFO):
@@ -122,7 +130,6 @@
         self.error(buf.getvalue())
         buf.close()
 
-
     def critical(self, msg):
         message = 'CRITICAL: %s\n' % (msg)
         if self.console_level >= CRITICAL:
@@ -130,22 +137,18 @@
         if self.level >= CRITICAL:
             self.target.write(message);
 
-class GumpConfigError(Exception):
-    pass
-
-class GumpEnvironmentError(Exception):
-    pass
 
-def check_version():
-    """
-    Raises exception if python version < 2.3.
-    """
+def _check_version():
+    """Raises exception if python version < 2.3."""
     (major, minor, micro, releaselevel, serial) = sys.version_info
     if not major >=2 and minor >= 3:
-        raise GumpEnvironmentError, 'CRITICAL: Gump requires Python 2.3 or above. The current version is %s.' % sys.version()
-        
-def parse_workspace(filename, options):
-    """
+        raise Error, 'CRITICAL: Gump requires Python 2.3 or above. The ' + \
+                'current version is %s.' % sys.version()
+
+
+def _parse_workspace(filename, options):
+    """Get workspace information and put it in the options instance.
+
     Converts the workspace file to a minidom tree and extract some info to
     put into the options instance. It doesn't merge in the profile or anything
     like that, that is left up to the engine.
@@ -182,10 +185,9 @@
     # clean up
     w.unlink()
 
-def svn_update(log, options):
-    """
-    Updates pygump itself from SVN.
-    """
+
+def _svn_update(log, options):
+    """Updates pygump itself from SVN."""
     command = "sh -c 'svn update --non-interactive "
     if not options.debug: command += "-q " # suppress output
     svnlogfile = os.path.join( options.logdir, "svnuplog.txt" )
@@ -212,14 +214,13 @@
     
             svnlog.close()
             log.target.write(SEP); print SEP,
-            raise GumpEnvironmentError, msg
+            raise Error, msg
     finally:
         os.remove(svnlogfile)
 
-def send_email(toaddr,fromaddr,subject,data,server,port=25):
-    """
-    Utility method for sending out e-mails.
-    """
+
+def _send_email(toaddr,fromaddr,subject,data,server,port=25):
+    """Utility method for sending out e-mails."""
     rawdata = "Date: %s\r\nFrom: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s"	\
            	% (	time.strftime('%d %b %Y %H:%M:%S', time.gmtime()),
            	    fromaddr, toaddr,	subject,	data)
@@ -230,10 +231,9 @@
     server.sendmail(fromaddr, toaddr, rawdata)
     server.quit()
 
+
 def send_error_email(Exception,details,options,log):
-    """
-    Send an error report by e-mail.
-    """
+    """Send an error report by e-mail."""
     if options.mailserver and options.mailport and options.mailto and options.mailfrom:
         subject="Fatal error during pygump run [%s: %s]" % (options.hostname, options.name)
         body="""An unexpected error occurred during the pygump run on
@@ -277,19 +277,18 @@
                        Exception, details, options.logurl, logbody)
         
         # send it off
-        send_email(options.mailfrom, options.mailto, subject, body, options.mailserver,
+        _send_email(options.mailfrom, options.mailto, subject, body, options.mailserver,
                    options.mailport)
     else:
-        raise GumpConfigError, "Insufficient information in the workspace for sending e-mail."
+        raise Error, "Insufficient information in the workspace for sending e-mail."
 
 
-def start_engine(log,options):
-    """
-    Fire up the core pygump engine to do its thing.
-    """
+def _start_engine(log,options):
+    """Fire up the core pygump engine to do its thing."""
     from gump import engine
     engine.main(options)
 
+
 def main():
     """
     The entrypoint into pygump. Extracts information and options from the arguments
@@ -298,7 +297,7 @@
     """
     
     # we need python 2.3
-    check_version()
+    _check_version()
 
     # get basic settings from environment variables
     _homedir = _hostname = _envfile = _workdir = _pythoncmd = _javahome = _projects = None
@@ -364,7 +363,7 @@
     options.starttimeutc = time.strftime('%d %b %Y %H:%M:%S', time.gmtime())
     
     # create logger
-    log = Logger(options.logdir)
+    log = _Logger(options.logdir)
     try:
         if options.debug:
             log.level = DEBUG
@@ -395,15 +394,15 @@
             sys.exit(1)
         
         # get some more options from the workspace
-        parse_workspace(options.workspace, options)
+        _parse_workspace(options.workspace, options)
 
         try:
             # self-update
             if not options.no_updates:
-                svn_update(log, options)
+                _svn_update(log, options)
                 
             # finally: fire us up!
-            start_engine(log, options)
+            _start_engine(log, options)
             log.info("Run completed!")
         except Exception, details:
             # this is not good. Send e-mail to the admin, complaining rather loudly.

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/__init__.py	Sat Jan  1 08:30:27 2005
@@ -14,5 +14,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""Pygump downloads and compiles source code and interprets the results.
+
+See http://gump.apache.org/ for more information.
+
+Pygump is split into several submodules. The gump.engine module contains
+the main() function that creates a gump.engine.Engine instance that is in
+control of running the application.
+
+The gump.engine module has several submodules which help with specific
+tasks. For example, it has utilities for processing the gump xml metadata
+into a DOM tree and into an object-oriented gump.model-based representation.
+
+The gump.util module contains several submodules of its own which are not
+tied to the rest of gump. For example, it has utilities for interacting with
+a mysql database, for sending and formatting e-mail, etc.
+
+The gump.model module provides an object-oriented way to represent all the
+gump metadata.
+
+The gump.plugin module provides several utilities which can be plugged into
+the gump engine for additional functionality. Plugins are responsible for all
+"side effects" of a gump run. For example, there are plugins to push data into
+database, plugins to send e-mails, etc.
+"""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/__init__.py	Sat Jan  1 08:30:27 2005
@@ -14,6 +14,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module contains the main controller that runs pygump.
+
+The function main() is called from the main.main() function, which construcs
+the neccessary helpers for an Engine instance that is then told to perform a
+run.
+
+The engine utilizes several submodules that provide pieces of its
+functionality. Each of these modules usually exports a single class which has
+a clearly defined responsibility. A single instance of such a class is used
+for performing a specific task. In pygump we call such a beast a "component".
+
+All required settings, as well as any other components a component may depend
+on are passed into the constructor when first creating the instance. This is
+all handled by the main() function. Doing things this way greatly decreases
+the amount of coupling between the different modules. For example, the
+gump.engine module is the only module that actually has an "import logging".
+It creates all the log instances to pass into its helpers. This means that
+completely rewiring or disabling logging is a simple as modifying the
+_get_logger() function in this module.
+"""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
 
@@ -59,6 +80,16 @@
     engine.initialize()
     engine.run()
     engine.dispose()
+
+
+def _banner(version):
+    """Print a fancy ASCII-art gump logo."""
+    print "      _____"
+    print "     |   __|_ Apache_ ___"
+    print "     |  |  | | |     | . |"
+    print "     |_____|___|_|_|_|  _|"
+    print "                     |_|     ~ v. " + version + " ~"
+    print
 
 ###
 ### FACTORY METHODS

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/vfs.py	Sat Jan  1 08:30:27 2005
@@ -14,21 +14,174 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module is used by the gump engine for all interaction with files.
+
+It handles access to both local and remote files (like files retrieved over
+HTTP). Note that some of the gump engine helpers run external programs which
+in turn interact with the filesystem directly rather than through this really
+thin Virtual Filesystem Layer.
+"""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
 
+import os
+import string
+import urllib
+import urlparse
+
+
+class Error(Exception):
+    """Generic error thrown for all internal VFS module exceptions."""
+    pass
+
+
 class VFS:
-    """
+    """Component for retrieving local and remote files as streams.
+    
     Provides homogenized access to local files, as well as files residing
-    on remote servers (HTTP or FTP or ...).
+    on remote servers (HTTP or FTP or ...). Remote files are cached
+    efficiently.
+    
+    Currently only provides operations for reading:
+        
+        - get_as_stream(url_or_path) -- determines whether the argument is an
+            actual url or a reference to a local file, then fetches the file
+            identified by the argument and returns it as a file-like object.
+            Note that the returned file must be closed as normal!
     """
     def __init__(self, filesystem_root = None, cachedir = None):
-        self.filesystem_root = filesystem_root
-        self.cachedir = cachedir
+        """
+        Create a new VFS. Arguments:
+            
+            - filesystem_root -- path to the directory on this machine that
+                                 should be used as the virtual root for
+                                 the VFS. Basic care is taken to ensure that
+                                 it is not possible to "escape" from this
+                                 root.
+            - cachedir -- path to the directory on this machine that should
+                          be used as the 
+        """
+        if filesystem_root:
+            self.filesystem_root = os.path.abspath(filesystem_root)
+        else:
+            self.filesystem_root = None
+            
+        if cachedir:
+            self.cachedir = os.path.abspath(cachedir)
+        else:
+            self.cachedir = None
     
     def get_as_stream(self, url_or_path):
         """
-        Get access to a file as a stream. Files that live remotely are cached
-        locally.
+        Get access to a file or url as a stream for reading.
+        
+        A stream is a file-like object that supports basic methods such as
+        readline().
+        
+        Note that if the VFS does not have a cache directory available,
+        operations such as seeking are not available. Also note that if the
+        VFS does not have a local filesystem root, a Error will be thrown
+        if a local file is requested.
+        """
+        
+        if not url_or_path:
+            raise Error, "Bad url or path requested: %s" % url_or_path
+        
+        if string.find(url_or_path, ':') != -1:
+            return self._get_url_as_stream(url_or_path)
+        else:
+            return self._get_file_as_stream(url_or_path)
+        
+    def _get_url_as_stream(self, url):
+        """Get access to a remote file as a stream for reading.
+        
+        Note that if the VFS does not have a cache directory available,
+        operations such as seeking are not available.
         """
-        raise RuntimeError, "not implemented!" # TODO
+        if self.cachedir:
+            path = self._get_cache_path_for_url_and_mkdirs(url)
+            urllib.urlretrieve(url, path)
+            return open(path)
+        else:
+            return urllib.urlopen(path)
+
+    def _get_file_as_stream(self, path):
+        """Get access to a local file as a stream for reading.
+        
+        Note that if the VFS does not have a local filesystem root,
+        a Error will be thrown.
+        """
+        if not self.filesystem_root:
+            raise Error, "This VFS does not support retrieving local files (%s was requested)!" % path
+        
+        relpath = path.lstrip('/') # transform absolute paths into paths
+                                   # relative to the VFS filesystem "root"
+        fullpath = os.path.abspath(os.path.join( self.filesystem_root, relpath ))
+        
+        if not fullpath.startswith(self.filesystem_root):
+            raise Error, "The requested resource %s is not part of the VFS!" % path
+        
+        if not os.path.exists(fullpath):
+            raise Error, "No resource %s found in VFS!" % path
+        if not os.path.isfile(fullpath):
+            raise Error, "Requested resource %s is not a stream!" % path
+        
+        return open(fullpath)
+
+    def _get_cache_path_for_url_and_mkdirs(self, url):
+        """Helper for _get_url_as_stream().
+        
+        Determine the local path within the VFS cache to store the results of
+        getting a particular url at, creating neccessary immediate directories
+        as neccessary.
+        """
+        (addressing_scheme, network_location, path, parameters, query, fragment_identifier) = urlparse.urlparse(url)
+        
+        schemedir = os.path.join(self.cachedir, addressing_scheme)
+        if not os.path.exists(schemedir): os.mkdir(schemedir)
+
+        serverdir = os.path.join(schemedir, network_location)
+        if not os.path.exists(serverdir): os.mkdir(serverdir)
+
+        filebase = string.replace(path, '/', '_')
+        filename = self._safe_filename(filebase + '___' + query + '___' + fragment_idenfitier)
+        
+        # we can be *reasonably* sure there's no two urls that result in
+        # this same path...
+        return os.path.join(serverdir, filename)
+
+    def _safe_filename(self, filename):
+        """Replaces all the "special characters" in a string with '-'."""
+        newpath = filename
+        for unsafe in [' ',
+                       '`',
+                       '~',
+                       '!',
+                       '#',
+                       '$',
+                       '%',
+                       '^',
+                       '&',
+                       '*',
+                       '(',
+                       ')',
+                       '=',
+                       '+',
+                       '{',
+                       '}',
+                       '[',
+                       ']',
+                       '|',
+                       '\\',
+                       ':',
+                       ';',
+                       '"',
+                       "'",
+                       '<',
+                       '>',
+                       ',',
+                       '?',
+                       '/']:
+            newpath = string.replace(newpath, unsafe, '-')
+            return newpath

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/engine/workspace.py	Sat Jan  1 08:30:27 2005
@@ -14,6 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module reads, merges and converts gump xml metadata."""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
 

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/model/__init__.py	Sat Jan  1 08:30:27 2005
@@ -14,21 +14,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module defines an object-oriented representation of gump metadata."""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
 
-class ModelError(Exception):
+class Error(Exception):
+    """Generic error thrown for all internal model module exceptions."""
     pass
 
+
 class ModelObject:
-    """
-    Base object for all gump model elements.
-    """
+    """Base object for all gump model elements."""
     pass
 
+
 class Workspace(ModelObject):
-    """
-    Model gump workspace and profile. Has the following properties:
+    """Model gump workspace and profile.
+
+    Has the following properties:
         
         - name     -- per-host unique identifier
         - repositories -- dictionary of contained repositories
@@ -52,8 +56,9 @@
         self.trackers[tracker.name] = tracker
 
 class Repository(ModelObject):
-    """
-    Model a source control repository. Has the following properties:
+    """Model a source control repository.
+
+    Has the following properties:
         
         - workspace -- reference to the containing workspace
         - name      -- per-run unique identifier
@@ -87,8 +92,9 @@
 CVS_METHOD_PSERVER="pserver"
 
 class CvsRepository(Repository):
-    """
-    Model a CVS repository. Has the following properties:
+    """Model a CVS repository.
+
+    Has the following properties:
         
         - all of the properties a Repository has
         - hostname -- the address of the cvs server
@@ -118,8 +124,9 @@
         self.password = password
 
 class SvnRepository(Repository):
-    """
-    Model a subversion repository. Has the following properties:
+    """Model a subversion repository.
+
+    Has the following properties:
         
         - all of the properties a Repository has
         - url      -- the address of the svn repository
@@ -142,9 +149,9 @@
         self.password = password
 
 class Module(ModelObject):
-    """
-    Model a module within a source control repository. Has the following
-    properties:
+    """Model a module within a source control repository.
+
+    Has the following properties:
         
         - repository  -- the containing repository
         - name        -- per-run unique identifier
@@ -159,9 +166,6 @@
                  directory = None,
                  url = None,
                  description = None):
-        """
-        Create the module.
-        """
         self.repository  = repository
         self.name        = name
         self.directory   = directory
@@ -174,10 +178,12 @@
         self.projects[project.name] = project
 
 class Project(ModelObject):
-    """
-    Model a "project", as far as gump is concerned this is the primary
-    "unit of work", something to "build". Projects reside within modules. Has
-    the following properties:
+    """Model a "project".
+
+    As far as gump is concerned a project is the primary "unit of work",
+    something to "build". Projects reside within modules.
+
+    Has the following properties:
         
         - module       -- the containing module
         - name         -- per-run unique identifier
@@ -224,9 +230,11 @@
 DEPENDENCY_INHERIT_JARS          = DEPENDENCY_INHERIT_COPY_OUTPUTS
 
 class Dependency(ModelObject):
-    """
+    """Model a dependency.
+    
     A dependency is a directional link between two projects, where one
     project (the dependency) depends on another project (the dependee).
+    
     Has the following properties:
         
         - dependency -- the project that is depending on the other project
@@ -251,9 +259,11 @@
         self.specific_output_id = specific_output_id
 
 class Command(ModelObject):
-    """
-    A command is something to do as part of a build. Has the following
-    properties:
+    """Model a command.
+    
+    A command is something to do as part of a build.
+
+    Has the following properties:
         
         - project -- the containing project
     """
@@ -262,9 +272,12 @@
     pass
 
 class Mkdir(Command):
-    """
-    Create a directory. The directory is specified relative to the source
-    directory of the project. Has the following properties:
+    """Model a mkdir command.
+    
+    Command to create a directory. The directory is specified relative to the
+    source directory of the project.
+
+    Has the following properties:
         
         - all the properties a Command has
         - directory -- the directory to create
@@ -274,9 +287,12 @@
         self.directory = directory
 
 class Rmdir(Command):
-    """
-    Delete a directory. The directory is specified relative to the source
-    directory of the project. Has the following properties:
+    """Model a delete command.
+    
+    Command to delete a directory. The directory is specified relative to the
+    source directory of the project.
+
+    Has the following properties:
         
         - all the properties a Command has
         - directory -- the directory to delete
@@ -286,8 +302,9 @@
         self.directory = directory
 
 class Script(Command):
-    """
-    Run a script. Has the following properties:
+    """Command to run a script.
+
+    Has the following properties:
         
         - all the properties a Command has
         - name -- the name of the script to run
@@ -301,10 +318,12 @@
 OUTPUT_ID_HOME = "homedir"
 
 class Output(ModelObject):
-    """
-    Something a successful project build will yield. Outputs can be given an
-    id to be able to distinguish multiple outputs from another. Has the
-    following properties:
+    """Model an output, something a successful project build will yield.
+
+    Outputs can be given an id to be able to distinguish multiple outputs from
+    another.
+
+    Has the following properties:
         
         - project -- the containing project
         - id      -- a per-project unique identifier
@@ -314,15 +333,30 @@
         self.id      = id
 
 class Homedir(Output):
-    """
-    A directory containing stuff that can be used by other projects. Has the
-    following properties:
+    """Model a directory containing stuff that can be used by other projects.
+
+    Has the following properties:
 
         - all the properties an Output has
         - directory -- the directory that should be exported as this project
                        its homedirectory
     """
-    def __init__(self, project, id, directory):
-        Output.__init__(self, project, id)
+    def __init__(self, project, directory):
+        Output.__init__(self, project, OUTPUT_ID_HOME)
         self.directory = directory
 
+class Jar(Output):
+    """Model a java archive that can be used by other projects.
+
+    Has the following properties:
+
+        - all the properties an Output has
+        - name -- the path to the jar relative to the project is home
+                directory.
+        - add_to_bootclass_path -- flag specifying if this jar should be
+                added 
+    """
+    def __init__(self, project, name, id = None, add_to_bootclass_path = False ):
+        Output.__init__(self, project, id)
+        self.name = name
+        self.add_to_bootclass_path = add_to_bootclass_path

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/util/__init__.py	Sat Jan  1 08:30:27 2005
@@ -14,13 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module provides several utilities not coupled to pygump itself."""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"
-
-def banner(version):
-    print "      _____"
-    print "     |   __|_ Apache_ ___"
-    print "     |  |  | | |     | . |"
-    print "     |_____|___|_|_|_|  _|"
-    print "                     |_|     ~ v. " + version + " ~"
-    print

Modified: gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py
Url: http://svn.apache.org/viewcvs/gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py?view=diff&rev=123844&p1=gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py&r1=123843&p2=gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py&r2=123844
==============================================================================
--- gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py	(original)
+++ gump/branches/Dec04MajorCleanup/pygump/python/gump/util/mysql.py	Sat Jan  1 08:30:27 2005
@@ -14,6 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""This module provides a thin wrapper around the MySQLdb library."""
+
 __copyright__ = "Copyright (c) 2004-2005 The Apache Software Foundation"
 __license__   = "http://www.apache.org/licenses/LICENSE-2.0"