gump-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From leosim...@apache.org
Subject svn commit: r168415 - in /gump/branches/Gump3/pygump/python/gump: config.py engine/__init__.py engine/loader.py engine/verifier.py plugins/logreporter.py
Date Thu, 05 May 2005 21:28:25 GMT
Author: leosimons
Date: Thu May  5 14:28:25 2005
New Revision: 168415

URL: http://svn.apache.org/viewcvs?rev=168415&view=rev
Log:
Implement cycle detection and error reporting.

Modified:
    gump/branches/Gump3/pygump/python/gump/config.py
    gump/branches/Gump3/pygump/python/gump/engine/__init__.py
    gump/branches/Gump3/pygump/python/gump/engine/loader.py
    gump/branches/Gump3/pygump/python/gump/engine/verifier.py
    gump/branches/Gump3/pygump/python/gump/plugins/logreporter.py

Modified: gump/branches/Gump3/pygump/python/gump/config.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/config.py?rev=168415&r1=168414&r2=168415&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/config.py (original)
+++ gump/branches/Gump3/pygump/python/gump/config.py Thu May  5 14:28:25 2005
@@ -57,6 +57,8 @@
     config.paths_work      = settings.workdir
     config.paths_logs      = settings.logdir
     config.paths_workspace = settings.workspace
+    # resolve hrefs relative to workspace xml file
+    config.paths_metadata  = os.path.dirname(config.paths_workspace)
     config.start_time      = settings.starttimeutc
     
     config.projects        = settings.projects
@@ -268,10 +270,11 @@
     return Objectifier(log)
 
 
-def get_modeller_verifier(walker):
+def get_modeller_verifier(config, walker):
     """Provide a Verifier implementation."""
-    from gump.engine.verifier import Verifier
-    return Verifier(walker)
+    from gump.engine.verifier import Verifier, LoggingErrorHandler
+    log = get_logger(config, "verifier")
+    return Verifier(walker, LoggingErrorHandler(log))
 
 
 def get_walker(config):

Modified: gump/branches/Gump3/pygump/python/gump/engine/__init__.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/__init__.py?rev=168415&r1=168414&r2=168415&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/__init__.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/__init__.py Thu May  5 14:28:25 2005
@@ -97,7 +97,7 @@
     modeller_loader = get_modeller_loader(modeller_log, vfs)
     modeller_normalizer = get_modeller_normalizer(modeller_log)
     modeller_objectifier = get_modeller_objectifier(modeller_log)
-    modeller_verifier = get_modeller_verifier(walker)
+    modeller_verifier = get_modeller_verifier(config, walker)
     
     mergefile = os.path.join(config.paths_work, _MERGE_FILE_NAME)
     dropfile = os.path.join(config.paths_work, _DROPPED_FILE_NAME)
@@ -256,4 +256,4 @@
             for node in dropped_nodes:
                 dropdocroot.appendChild(node)
             self.drop_to.write( dropdoc.toxml() )
-            self.drop_to.close()        
+            self.drop_to.close()

Modified: gump/branches/Gump3/pygump/python/gump/engine/loader.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/loader.py?rev=168415&r1=168414&r2=168415&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/loader.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/loader.py Thu May  5 14:28:25 2005
@@ -58,7 +58,7 @@
         if child.tagName == 'url': continue
         if child.hasAttribute('href'):
             # yep, this is one to load...
-            _resolve_href(child, dropped_nodes, download_func, error_func)
+            _resolve_href(child, dropped_nodes, found_hrefs, download_func, error_func)
 
         # now recurse to resolve any hrefs within this child
         # note that we duplicate the found_hrefs array. This means that the
@@ -86,7 +86,7 @@
     except Exception, details:
         # swallow this in interest of log readability
         #_drop_module_or_project(node, dropped_nodes)
-        error_func(node, dropped_nodes)
+        error_func(href, node, dropped_nodes)
         return # make sure to stop processing...
     
     new_dom = minidom.parse(stream)
@@ -191,7 +191,7 @@
         self.log.debug( "Resolving HREF: %s" % href )
         return self.vfs.get_as_stream(href)
 
-    def handle_error(self, href):
+    def handle_error(self, href, node, dropped_nodes):
         """Finds the project associated with this node and removes it.
         
         If there is no associated project, the associated module is removed
@@ -201,12 +201,14 @@
         project = _find_project_containing_node(node)
         if project:
             doc = _find_document_containing_node(project)
+            modulename = "Uknown"
             module = _find_module_containing_node(project)
-            modulename = module.getAttribute("name")
-            comment = doc.createComment(" Part of module: %s " % modulename)
-            project.appendChild(comment)
+            if module:
+                modulename = module.getAttribute("name")
+                comment = doc.createComment(" Part of module: %s " % modulename)
+                project.appendChild(comment)
             name = project.getAttribute("name")
-            self.log.warning("Dropping project '%s' from module '%s' because of href resolution
error!" % (name , modulename))
+            self.log.warning("Dropping project '%s' from module '%s' because of href (%s)
resolution error!" % (name , modulename, href))
     
             _do_drop(project, dropped_nodes)
         else:

Modified: gump/branches/Gump3/pygump/python/gump/engine/verifier.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/verifier.py?rev=168415&r1=168414&r2=168415&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/verifier.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/verifier.py Thu May  5 14:28:25 2005
@@ -21,6 +21,7 @@
 
 import logging
 import os
+import sys
 
 from xml import dom
 from xml.dom import minidom
@@ -28,6 +29,7 @@
 from gump.model import *
 
 from gump.engine import EngineError
+from gump.util import ansicolor
 
 class VerificationError(EngineError):
     """Error raised by the verifier if the model is not valid."""
@@ -39,9 +41,17 @@
     a cycle again is an array of projects that together make up a cycle."""
     #TODO think about error hierarchies in gump and decide if this is the way
     #     we want to implement them
-    def __init__(self, cycles):
-        self.cycles = cycles
+    pass
 
+def print_cyclic_trace(cycles, handler):
+    for cycle in cycles: # isn't there a level of nesting too much here???
+        for chain in cycle:
+            msg = "  "
+            for project in chain:
+                msg += "%s --> " % project.name
+            msg = ansicolor.Bright_Red + msg[:-5] + ansicolor.Black
+            handler(msg)
+    
 class AbstractErrorHandler:
     """Base class for supporting configurable error recovery. Instead of
     raising exceptions, supportive classes will pass the error to an instance
@@ -54,10 +64,25 @@
     
     This setup is similar to that used by the SAX libraries."""
     #TODO maybe move this elsewhere?
-    def _handleError(self,error):
-        if not hasattr(self,'handleError'): raise error
-        if not callable(self.handleError): raise error
-        self.handleError(error)
+    def _handleError(self):
+        if not hasattr(self, 'handleError'): raise
+        if not callable(self.handleError): raise
+        self.handleError()
+
+class LoggingErrorHandler(AbstractErrorHandler):
+    """Naive error handler which logs all errors and then swallows them."""
+    def __init__(self, log):
+        self.log = log
+
+    def handleError(self):
+        errorType = sys.exc_info()[0]
+        if errorType is CyclicDependencyError:
+            errorValue = sys.exc_info()[1]
+            self.log.error("Cyclic dependencies occurred:")
+            print_cyclic_trace(errorValue, self.log.error)
+            self.log.error("The projects involved will not be built!")
+        else:
+            raise
 
 class Verifier:
     """Determines whether a finished gump model conforms to certain contracts.
@@ -66,18 +91,19 @@
     possible to digest them from the model documentation. However, the
     verifier itself together with its unit tests is probably the only "hard"
     specification of those contracts."""
-    def __init__(self, walker):
+    def __init__(self, walker, errorHandler=AbstractErrorHandler()):
         assert hasattr(walker, "walk")
         assert callable(walker.walk)
         
         self.walker = walker
+        self.errorHandler = errorHandler
         
-    def verify(self, workspace, errorHandler=AbstractErrorHandler()):
+    def verify(self, workspace):
         """Sends VerificationError objects to the errorHandler argument if the
         provided model contains errors. If no errorHandler is provided, the
         exceptions are 'raise'd."""
         # TODO: get rid of this return statement
-        return
+        #return
         # TODO: Test this code!!!
         from gump.plugins import AbstractPlugin
         visitor = AbstractPlugin(None)
@@ -92,8 +118,13 @@
                     unvisited.append(p)
             
             cycles = self._find_cycles(unvisited[:])
+            workspace.cycles = cycles
+            workspace.unvisited = unvisited
             
-            errorHandler._handleError(CyclicDependencyError(cycles))
+            try:
+                raise CyclicDependencyError, cycles
+            except:
+                self.errorHandler._handleError()
     
     def _find_cycles(self,projects):
         """Brute-force find all cycles.
@@ -118,23 +149,24 @@
         return cycles
     
     def _visit(self,project,visited,stack,needle,cycles):
-        #TODO: test this
+        # debuggging statements...
+        #msg = "Visiting: %s, stack=[" % project.name
+        #for p in stack:
+        #    msg += p.name + ","
+        #msg = msg[:-1] + "]"
+        #print msg
+        
         visited.append(project)
         for relationship in project.dependencies:
             dependency = relationship.dependency
             stack.append(dependency)
             if dependency == needle: # cycle involving needle!
-                cycles.append(stack)
+                cycles.append(stack[:])
                 visited.append(dependency)
-                stack = stack[:-1] # pop this dependency off the stack,
-                      # we'll look at the next dependency in the next
-                      # for loop iteration
             else:
                 if not dependency in visited:
                     self._visit(dependency,visited,stack,needle,cycles)
-                # else we have a cycle not involving the needle,
-                # we'll find it later (or we've found it already)
-        
-            stack = stack[:-1] # pop this dependency off the stack,
-              # we'll look at the next dependency in the next
-              # for loop iteration
+
+            stack.pop() # get rid of this dependency, we'll be looking
+                        # at the next dependency in the next iteration of
+                        # the for loop

Modified: gump/branches/Gump3/pygump/python/gump/plugins/logreporter.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/plugins/logreporter.py?rev=168415&r1=168414&r2=168415&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/plugins/logreporter.py (original)
+++ gump/branches/Gump3/pygump/python/gump/plugins/logreporter.py Thu May  5 14:28:25 2005
@@ -109,6 +109,11 @@
         self.wr(hr)
         self.wr('                           %sBUILD RESULTS%s' % (ansicolor.Bright_Blue,
ansicolor.Black))
         self.wr(hr)
+    
+    def visit_workspace(self, workspace):
+        if hasattr(workspace, "unvisited"):
+            for project in workspace.unvisited:
+                self.wr('%s%s: CYCLIC DEPENDENCY%s' % (ansicolor.Bright_Red, project, ansicolor.Black))
  
     def visit_project(self, project):
         if check_skip(project):



Mime
View raw message