ajack 2004/05/24 09:39:09
Modified: python/gump/runner tasks.py runner.py
python/gump/notify notifier.py __init__.py
project gump-test.xml gumpy.xml
python/gump/core config.py gumprun.py
python/gump/stats statistician.py statsdb.py
python/gump/model workspace.py stats.py
python/gump/test notifying.py pyunit.py
python/gump/document/xdocs documenter.py
Added: python/gump/notify notification.py logic.py
Removed: python/gump/test tasks.py
Log:
Reworking notification.
Revision Changes Path
1.3 +2 -7 gump/python/gump/runner/tasks.py
Index: tasks.py
===================================================================
RCS file: /home/cvs/gump/python/gump/runner/tasks.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- tasks.py 21 May 2004 23:15:09 -0000 1.2
+++ tasks.py 24 May 2004 16:39:08 -0000 1.3
@@ -181,13 +181,8 @@
def notify(self):
- #
- # Only an 'all' is an official build, for them:
- #
- # Send Naggin E-mails
- #
- if self.run.getOptions().isOfficial() \
- and self.run.getGumpSet().isFull() \
+ # Anything but 'all' is likely debugging.
+ if self.run.getGumpSet().isFull() \
and self.run.getWorkspace().isNotify():
log.info('Notify about failures... ')
1.3 +0 -3 gump/python/gump/runner/runner.py
Index: runner.py
===================================================================
RCS file: /home/cvs/gump/python/gump/runner/runner.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- runner.py 21 May 2004 23:15:09 -0000 1.2
+++ runner.py 24 May 2004 16:39:08 -0000 1.3
@@ -132,8 +132,5 @@
self.run.dispatchEvent(FinalizeRunEvent(self.run))
def getRunner(run):
- #from gump.runner.tasks import SequentialTaskRunner
- #return SequentialTaskRunner(run)
-
from gump.runner.demand import OnDemandRunner
return OnDemandRunner(run)
1.3 +37 -147 gump/python/gump/notify/notifier.py
Index: notifier.py
===================================================================
RCS file: /home/cvs/gump/python/gump/notify/notifier.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- notifier.py 21 May 2004 23:15:05 -0000 1.2
+++ notifier.py 24 May 2004 16:39:08 -0000 1.3
@@ -35,6 +35,9 @@
from gump.net.smtp import *
from gump.utils import *
+from gump.notify.logic import NotificationLogic
+from gump.notify.notification import Notification
+
LINE ='-- -- -- -- -- -- -- -- -- -- -- -- G U M P'
SEPARATOR='*********************************************************** G U M P'
@@ -54,7 +57,7 @@
class Notifier(AbstractRunActor):
- def __init__(self,run):
+ def __init__(self,run,resolver=None):
AbstractRunActor.__init__(self,run)
@@ -66,8 +69,9 @@
self.unwantedSubjects=''
self.unwanteds=0
-
-
+ self.resolver=self.run.getOptions().getResolver()
+ self.logic=NotificationLogic(self.run)
+
def processOtherEvent(self,event):
if isinstance(event,FinalizeRunEvent):
# Notifications are wanted...
@@ -87,17 +91,20 @@
#
# Notify about the workspace (if it needs it)
#
- if self.workspace.isFailed():
- self.notifyWorkspace(run,self.workspace)
+ notification = self.logic.notification(self.workspace)
+ if notification:
+ self.notifyWorkspace(notification)
# For all modules...
for module in self.workspace.getModules():
if not self.gumpSet.inModuleSequence(module): continue
- if module.isFailed():
+ notification = self.logic.notification(module)
+
+ if notification:
try:
log.info('Notify for module: ' + module.getName())
- self.notifyModule(module)
+ self.notifyModule(module,notification)
except Exception, details:
log.error("Failed to send notify e-mails for module " +
module.getName()\
@@ -106,15 +113,16 @@
#
# Notify for each project...
- #
-
+ #
for project in module.getProjects():
- if project.isFailed() :
- if not self.gumpSet.inProjectSequence(project):
continue
+ if not self.gumpSet.inProjectSequence(project): continue
+ # Do a notification, positive (fixed) or negative (failed)
+ notification = self.logic.notification(project)
+ if notification:
try:
log.info('Notify for project: ' +
project.getName())
- self.notifyProject(project)
+ self.notifyProject(project,notification)
except Exception, details:
log.error("Failed to send notify e-mails for
project " + project.getName()\
@@ -154,7 +162,7 @@
self.unsents=0
else:
log.debug('No unsent notifys.')
-
+
def addUnwanted(self,subject,content):
if self.unwanted:
self.unwanted += SEPARATOR
@@ -220,25 +228,24 @@
return 0
- def notifyWorkspace(self):
+ def notifyWorkspace(self,notification):
""" Notify for the workspace """
- content=self.getGenericContent(self.workspace,'There is a workspace
problem... \n')
- self.sendEmail(self.workspace.mailinglist, \
- self.workspace.email, \
- self.workspace.prefix+': Gump Workspace Problem ',content)
+ content=notification.resolveContent(self.resolver)
+
+ subject=self.workspace.prefix+': Gump Workspace ' + self.workspace.getName()
+
+ self.sendEmail(self.workspace.mailinglist,
+ self.workspace.email,
+ subject,content)
- def notifyModule(self,module):
+ def notifyModule(self,module,notification):
""" Notify to a specific module's <notify entry """
- #
# Form the content...
- #
- content=self.getNamedTypedContent(module)
+ content=notification.resolveContent(self.resolver)
- #
# Form the subject
- #
subject=self.workspace.prefix+ \
': '+module.getName()+' '+ \
lower(stateDescription(module.getState()))
@@ -246,20 +253,20 @@
self.sendEmails(self.getAddressPairs(module),subject,content)
- def notifyProject(self,project):
+ def notifyProject(self,project,notification):
""" Notify to a specific project's <notify entry """
module=project.getModule()
#
# Form the content...
#
- content=self.getNamedTypedContent(project )
+ content=notification.resolveContent(self.resolver)
#
# Form the subject
#
subject=self.workspace.prefix+': ' \
- +module.getName()+'/'+project.getName() \
+ + module.getName() + '/' +project.getName() \
+' '+lower(stateDescription(project.getState()))
# Send those e-mails
@@ -310,9 +317,9 @@
sent=0
try:
- log.info('Send Notify e-mail to: ' + str(toaddr) + \
- ' from: ' + str(fromaddr) + \
- 'Subject: ' + str(subject))
+ log.info('Send Notify e-mail:\n To: ' + str(toaddr) + \
+ '\n From: ' + str(fromaddr) + \
+ '\n Subject: ' + str(subject))
#
# Form the user visable part ...
@@ -344,124 +351,7 @@
log.error('Failed with to: ['+str(toaddr)+'] from: ['+str(fromaddr)+']'
)
return sent
-
- def getNamedTypedContent(self,object,message=None):
- content="""To whom it may engage...
-
-This is an automated request, but not an unsolicited one. For help
-understanding the request please visit
-http://gump.apache.org/nagged.html,
-and/or contact [EMAIL PROTECTED]
-"""
-
- # Get our facts straight.
- name=object.getName()
- type=object.__class__.__name__
- affected=object.determineAffected()
- duration=object.getStats().sequenceInState
-
- # Optional message
- if message:
- content+=message
-
- content += type + ' ' + name + ' has an issue affecting its community
integration'
-
- if affected:
- content += '.\nThis issue affects ' + `affected` + ' projects'
-
- if duration and duration > 1:
- content += ', and has been outstanding for ' + `duration` + ' runs'
-
- content += '.\n'
-
- if isinstance(object,Project) and affected:
- affectedProjects=object.determineAffectedProjects()
- if 1 or ((duration and duration > 3) and affectedProjects):
- #
- # Show those negatively affected
- #
- content += 'The following are affected:\n'
-
- for project in affectedProjects:
- content += ' - ' + project.getName()
-
- if project.hasDescription():
- content += ' : '
- content += project.getLimitedDescription()
-
- content += '\n'
-
- content += '\n'
-
- content += self.getGenericContent(object)
-
- return content
-
- def getGenericContent(self,object,message=None):
- content=''
-
- # Optional message
- if message:
- content=message
-
- #
- # Add State (and reason)
- #
- content += 'The current state is \'' + object.getStateDescription() + '\''
-
- if object.hasReason():
- content += ', for reason \'' + object.getReasonDescription() + '\''
-
- content += '\n'
-
- #
- # Link them back here...
- #
- url=self.run.getOptions().getResolver().getUrl(object)
- content += "\nFull details are available at:\n "
- content += url
- content += "\n"
-
- if object.annotations or object.worklist:
- content += 'That said, some snippets follow:\n'
-
- content += '\n'
-
- #
- # Add an info/error/etc...
- #
- if object.annotations:
- #content += LINE
- content += "\n"
- content += "Gump provided these annotations:\n"
- for note in object.annotations:
- content += (' - %s - %s\n' % (levelName(note.level), note.text))
-
- #
- # Work
- #
- if object.worklist:
- content+="\n\n"
- #content += LINE
- content += "Gump performed this work:\n"
- for workitem in object.worklist:
- workurl=self.run.getOptions().getResolver().getUrl(workitem)
- content+=workurl+'\n'
- content+=workitem.overview()+'\n'
-
- content += '\n\nTo subscribe to this information via syndicated feeds:\n'
-
- #
- # Link them back here...
- #
- rssurl=self.run.getOptions().getResolver().getUrl(object,'rss','.xml')
- atomurl=self.run.getOptions().getResolver().getUrl(object,'atom','.xml')
-
- content += "RSS: " + rssurl + '\n'
- content += "Atom: " + atomurl + '\n'
-
- return content
def notify(run):
notifier=Notifier(run)
1.3 +1 -1 gump/python/gump/notify/__init__.py
Index: __init__.py
===================================================================
RCS file: /home/cvs/gump/python/gump/notify/__init__.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- __init__.py 21 May 2004 23:15:05 -0000 1.2
+++ __init__.py 24 May 2004 16:39:08 -0000 1.3
@@ -15,4 +15,4 @@
# limitations under the License.
# tell Python what modules make up the gump.nofity package
-__all__ = ["notifier"]
+__all__ = ["notifier","notification","logic"]
1.1 gump/python/gump/notify/notification.py
Index: notification.py
===================================================================
#!/usr/bin/env python
# Copyright 2003-2004 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
'Nag' (notification) e-mail generation...
"""
import socket
import time
import os
import sys
import logging
import types
import StringIO
from string import lower, upper, capitalize
from gump import log
from gump.core.config import *
from gump.core.gumprun import *
from gump.core.actor import AbstractRunActor
from gump.model.project import *
from gump.model.module import *
from gump.model.state import *
from gump.net.smtp import *
from gump.utils import *
LINE ='-- -- -- -- -- -- -- -- -- -- -- -- G U M P'
SEPARATOR='*********************************************************** G U M P'
class Notification(RunSpecific):
def __init__(self,run,entity,positive=0,intro=''):
RunSpecific.__init__(self,run)
self.entity=entity
self.positive=positive
self.intro=intro
# Init
self.title=''
def setTitle(self,message):
self.title=title
def getTitle(self):
return self.title
def setIntroduction(self,message):
self.intro=intro
def getIntroduction(self):
return self.intro
def hasIntroduction(self):
if self.intro: return 1
return 0
def resolveContent(self,resolver,stream=None):
# If not passed, create temporary
if not stream:
stream=StringIO.StringIO()
if self.positive:
stream.write('To whom it may satisfy...')
else:
stream.write('To whom it may engage...')
stream.write("""
This is an automated request, but not an unsolicited one. For
more information please visit http://gump.apache.org/nagged.html,
and/or contact folk at [EMAIL PROTECTED]
""")
# Get our facts straight.
name=self.entity.getName()
type=self.entity.__class__.__name__
affected=0
if not isinstance(self.entity,Workspace):
affected=self.entity.determineAffected()
duration=self.entity.getStats().sequenceInState
stream.write(type + ' ' + name)
if self.hasIntroduction():
stream.write(self.getIntroduction())
if not self.positive:
if affected:
stream.write('.\nThis issue affects ' + `affected` + ' projects')
if duration and duration > 1:
stream.write(', and has been outstanding for ' + `duration` + '
runs')
stream.write('.\n')
# Add State (and reason)
stream.write(type + ' State : \'' + self.entity.getStateDescription() + '\'')
if self.entity.hasReason():
stream.write(', Reason \'' + self.entity.getReasonDescription() + '\'')
stream.write("\n")
# Show thos affected
if isinstance(self.entity,Project) and affected:
affectedProjects=self.entity.determineAffectedProjects()
if 1 or ((duration and duration > 3) and affectedProjects):
# Show those negatively affected
stream.write('The following are affected:\n')
for project in affectedProjects:
stream.write(' - ' + project.getName())
if project.hasDescription():
stream.write(' : ')
stream.write(project.getLimitedDescription())
stream.write('\n')
stream.write('\n')
# Link them back here...
url=resolver.getUrl(self.entity)
stream.write('\nFull details are available at:\n\n ')
stream.write(url)
stream.write('\n')
snippets=0
if isinstance(self.entity,Annotatable):
if self.entity.annotations:
snippets=1
if isinstance(self.entity,Workable):
if self.entity.worklist:
snippets=1
if snippets:
stream.write('\nThat said, some snippets follow:\n')
stream.write('\n')
if isinstance(self.entity,Annotatable):
self.resolveAnnotations(resolver,stream)
if isinstance(self.entity,Workable):
self.resolveWork(resolver,stream)
if isinstance(self.entity,Statable):
self.resolveStats(resolver,stream)
self.resolveSyndication(resolver, stream)
self.resolveFooter(resolver, stream)
# If passed (or created) a StringIO, return String
# containing contents.
if isinstance(stream,StringIO.StringIO):
stream.seek(0)
return stream.read()
return
def resolveAnnotations(self, resolver, stream):
#
# Add an info/error/etc...
#
if self.entity.annotations:
stream.write("\n")
stream.write("The following annotations were provided:")
stream.write("\n")
for note in self.entity.annotations:
stream.write(' -%s- %s\n' % (upper(levelName(note.level)),
note.text))
def resolveWork(self, resolver, stream):
#
# Work
#
if self.entity.worklist:
stream.write('\n\n')
stream.write('The following work was performed:\n')
for workitem in self.entity.worklist:
workurl=resolver.getUrl(workitem)
stream.write(workurl)
stream.write('\n')
stream.write(workitem.overview())
stream.write('\n')
def resolveStats(self, resolver, stream):
stats=self.entity.getStats()
stream.write('\n\n')
def resolveSyndication(self, resolver, stream):
stream.write('\n')
stream.write('To subscribe to this information via syndicated feeds:')
stream.write('\n')
#
# Link them back here...
#
rssurl=resolver.getUrl(self.entity,'rss','.xml')
atomurl=resolver.getUrl(self.entity,'atom','.xml')
stream.write(' RSS: ' + rssurl + '\n')
stream.write(' Atom: ' + atomurl + '\n')
def resolveFooter(self, resolver, stream):
stream.write('\n\n--\n')
stream.write('Produced by Gump %s.\n[Run (%s, %s)]' % \
( setting.version,
default.datetime,
self.run.getRunGuid() ))
stream.write('\n')
topurl=resolver.getUrl(self.run)
opturl=resolver.getUrl(self.run,'options')
stream.write(topurl)
stream.write('\n')
stream.write(opturl)
stream.write('\n')
class PositiveNotification(Notification):
def __init__(self,run,entity,intro=' *no longer* has an issue'):
Notification.__init__(self,run,entity,1,intro)
class NegativeNotification(Notification):
def __init__(self,run,entity,intro=' has an issue affecting its community
integration'):
Notification.__init__(self,run,entity,0,intro)
1.1 gump/python/gump/notify/logic.py
Index: logic.py
===================================================================
#!/usr/bin/env python
# Copyright 2003-2004 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
'Nag' (notification) e-mail generation...
"""
import socket
import time
import os
import sys
import logging
from string import lower, capitalize
from gump import log
from gump.core.config import *
from gump.core.gumprun import *
from gump.model.project import *
from gump.model.module import *
from gump.model.state import *
from gump.utils import *
from gump.notify.notification import PositiveNotification,NegativeNotification
class NotificationLogic(RunSpecific):
def __init__(self,run):
RunSpecific.__init__(self,run)
# :TODO: First Ever?
# :TODO What is M$ (i.e. not dbm) and/or no stats db
def notification(self,entity):
notification=None
# Stats had better have been set
stats=entity.getStats()
#
# Determine if we want to notify
#
if entity.isFailed():
# Notify on first failure, or each official
# run.
if self.run.getOptions().isOfficial() \
or (1 == stats.sequenceInState):
notification=NegativeNotification(self.run,entity)
elif entity.isSuccess():
if (stats.sequenceInState == 1):
if not STATE_PREREQ_FAILED == stats.previousState:
if stats.getTotalRuns() > 1:
notification=PositiveNotification(self.run,entity)
elif entity.isPrereqFailed():
if (stats.sequenceInState == 1):
if not STATE_PREREQ_FAILED == stats.previousState:
notification=PositiveNotification(self.run,entity)
return notification
1.11 +5 -4 gump/project/gump-test.xml
Index: gump-test.xml
===================================================================
RCS file: /home/cvs/gump/project/gump-test.xml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- gump-test.xml 21 May 2004 21:18:52 -0000 1.10
+++ gump-test.xml 24 May 2004 16:39:08 -0000 1.11
@@ -22,6 +22,9 @@
</description>
<svn repository="apache-svn-sandbox" dir="gump-test"/>
+
+ <nag from="Adam Jack <[EMAIL PROTECTED]>"
+ to="[EMAIL PROTECTED]"/>
<project name="gump-test-maven1">
<maven target="dist" basedir="maven-project1" debug="true"/>
@@ -32,10 +35,8 @@
<project name="gump-test-maven2">
<maven target="dist" basedir="maven-project2" debug="true"/>
<home nested="maven-project2/target"/>
- <jar name="gump-test-maven2-0.1.jar"/>
-
- <depend project="gump-test-maven1"/>
-
+ <jar name="gump-test-maven2-0.1.jar"/>
+ <depend project="gump-test-maven1"/>
</project>
</module>
1.4 +2 -2 gump/project/gumpy.xml
Index: gumpy.xml
===================================================================
RCS file: /home/cvs/gump/project/gumpy.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- gumpy.xml 29 Feb 2004 19:03:39 -0000 1.3
+++ gumpy.xml 24 May 2004 16:39:08 -0000 1.4
@@ -27,8 +27,8 @@
<project name="gump-test">
<script name="gumpytest"/>
<home nested="gumpytest"/>
- <!-- nag from="Adam Jack <[EMAIL PROTECTED]>"
- to="[EMAIL PROTECTED]"/ -->
+ <nag from="Adam Jack <[EMAIL PROTECTED]>"
+ to="[EMAIL PROTECTED]"/>
</project>
1.5 +1 -1 gump/python/gump/core/config.py
Index: config.py
===================================================================
RCS file: /home/cvs/gump/python/gump/core/config.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- config.py 21 May 2004 23:15:02 -0000 1.4
+++ config.py 24 May 2004 16:39:08 -0000 1.5
@@ -88,7 +88,7 @@
class setting:
"""Configuration of hardcoded settings"""
- version='2.0.3-alpha-0001'
+ version='2.0.3-alpha-0002'
ws_version="0.4"
ws_minimum_version="0.3"
1.7 +1 -1 gump/python/gump/core/gumprun.py
Index: gumprun.py
===================================================================
RCS file: /home/cvs/gump/python/gump/core/gumprun.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- gumprun.py 21 May 2004 23:15:02 -0000 1.6
+++ gumprun.py 24 May 2004 16:39:08 -0000 1.7
@@ -384,7 +384,7 @@
# the 'forrest' build inlined.
self.xdocs=0
- self.objectivse=OBJECTIVE_INTEGRATE
+ self.objectives=OBJECTIVE_INTEGRATE
self.features=FEATURE_ALL
def isDated(self):
1.3 +18 -17 gump/python/gump/stats/statistician.py
Index: statistician.py
===================================================================
RCS file: /home/cvs/gump/python/gump/stats/statistician.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- statistician.py 21 May 2004 23:15:05 -0000 1.2
+++ statistician.py 24 May 2004 16:39:08 -0000 1.3
@@ -27,7 +27,6 @@
from gump.core.gumprun import *
from gump.core.actor import *
from gump.stats.statsdb import StatisticsDB
-
class Statistician(AbstractRunActor):
def __init__(self,run):
@@ -35,22 +34,24 @@
AbstractRunActor.__init__(self,run)
self.db=StatisticsDB()
-
- def processOtherEvent(self,event):
-
- workspace=self.run.getWorkspace()
-
+ def processOtherEvent(self,event):
if isinstance(event,InitializeRunEvent):
- #
- # Load stats (and stash onto projects)
- #
- self.db.loadStatistics(workspace)
+ self.loadStatistics()
+ elif isinstance(event,FinalizeRunEvent):
+ if self.run.getOptions().isStatistics():
+ self.updateStatistics()
+
+ def loadStatistics(self):
- elif isinstance(event,FinalizeRunEvent):
+ #
+ # Load stats (and stash onto projects)
+ #
+ self.db.loadStatistics(self.workspace)
+
+ def updateStatistics(self):
- if self.run.getOptions().isStatistics():
- #
- # Update stats (and stash onto projects)
- #
- self.db.updateStatistics(workspace)
- self.db.sync()
\ No newline at end of file
+ #
+ # Update stats (and stash onto projects)
+ #
+ self.db.updateStatistics(self.workspace)
+ self.db.sync()
\ No newline at end of file
1.3 +25 -28 gump/python/gump/stats/statsdb.py
Index: statsdb.py
===================================================================
RCS file: /home/cvs/gump/python/gump/stats/statsdb.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- statsdb.py 21 May 2004 23:15:05 -0000 1.2
+++ statsdb.py 24 May 2004 16:39:08 -0000 1.3
@@ -58,11 +58,18 @@
dump(s)
# Workspace
- def getWorkspaceStats(self):
- stats=WorkspaceStatistics()
+ def getWorkspaceStats(self,workspaceName):
+ stats=WorkspaceStatistics(workspaceName)
self.getBaseStats(stats)
return stats
+ def putWorkspaceStats(self,stats):
+ self.putBaseStats(stats)
+
+ def delWorkspaceStats(self,stats):
+ self.delBaseStats(stats)
+
+
# Project
def getProjectStats(self,projectName):
@@ -213,55 +220,55 @@
def loadStatistics(self,workspace):
log.debug('--- Loading Statistics')
+
+ # Load the W/S statistics
+ ws=self.getWorkspaceStats(workspace.getName())
+ workspace.setStats(ws)
+
+
for repo in workspace.getRepositories():
# Load the statistics
rs=self.getRepositoryStats(repo.getName())
- #
# Stash for later...
- #
repo.setStats(rs)
for module in workspace.getModules():
- #
# Load the statistics...
- #
ms=self.getModuleStats(module.getName())
- #
# Stash for later...
- #
module.setStats(ms)
for project in module.getProjects():
- #
# Load the statistics...
- #
ps=self.getProjectStats(project.getName())
- #
# Stash for later...
- #
project.setStats(ps)
def updateStatistics(self,workspace):
log.debug('--- Updating Statistics')
+
+
+ # Load the W/S statistics
+ ws=self.getWorkspaceStats(workspace.getName())
+ # Update for this workspace based off this run
+ ws.update(workspace)
+ workspace.setStats(ws)
+
for repo in workspace.getRepositories():
# Load the statistics
rs=self.getRepositoryStats(repo.getName())
- #
# Update for this repo based off this run
- #
rs.update(repo)
- #
# Stash for later...
- #
repo.setStats(rs)
for module in workspace.getModules():
@@ -269,19 +276,13 @@
# Load the statistics
ms=self.getModuleStats(module.getName())
- #
# Update for this project based off this run
- #
ms.update(module)
- #
# Stash for later...
- #
module.setStats(ms)
- #
# Write out the updates
- #
self.putModuleStats(ms)
for project in module.getProjects():
@@ -289,21 +290,17 @@
# Load the statistics
ps=self.getProjectStats(project.getName())
- #
# Update for this project based off this run
- #
ps.update(project)
- #
# Stash for later...
- #
project.setStats(ps)
- #
# Write out the updates
- #
self.putProjectStats(ps)
+ self.sync()
+
def sync(self):
if hasattr(self.db, 'sync'):
self.db.sync()
1.50 +4 -19 gump/python/gump/model/workspace.py
Index: workspace.py
===================================================================
RCS file: /home/cvs/gump/python/gump/model/workspace.py,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- workspace.py 21 May 2004 23:15:04 -0000 1.49
+++ workspace.py 24 May 2004 16:39:09 -0000 1.50
@@ -625,27 +625,12 @@
class WorkspaceStatistics(Statistics):
"""Statistics Holder"""
- def __init__(self):
- Statistics.__init__(self,'workspace')
- self.lastModified=-1
-
- def getLastModified(self):
- return (self.lastModified)
+ def __init__(self,workspaceName):
+ Statistics.__init__(self,workspaceName)
def getKeyBase(self):
- return self.name
-
- def lastModifiedKey(self):
- return self.getKeyBase() + '-last-updated'
-
- def update(self,module):
- Statistics.update(self,module)
-
- #
- # Track code updates/changes
- #
- if module.isModified():
- self.lastModified=default.time
+ return 'workspace:'+ self.name
+
class ModelEvent(Event):
1.21 +6 -6 gump/python/gump/model/stats.py
Index: stats.py
===================================================================
RCS file: /home/cvs/gump/python/gump/model/stats.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- stats.py 21 May 2004 23:15:04 -0000 1.20
+++ stats.py 24 May 2004 16:39:09 -0000 1.21
@@ -49,24 +49,24 @@
self.sequenceInState=0
self.lastModified=0
- #
- # FOG is (at pressent) effectively the
+
+ # FOG is (at present) effectively the
# 'odds of success' (based off historical results).
#
# We ought find a way to factor in durations and
# age into this
- #
def getFOGFactor(self):
return self.getHistoricalOddsOfSuccess()
-
- #
+
# 'odds of success' (based off historical results).
- #
def getHistoricalOddsOfSuccess(self):
good=self.successes or 0
bad=(self.failures+self.prereqs) or 0
total=(good+bad) or 1
return float(good)/float(total)
+
+ def getTotalRuns(self):
+ return (self.successes+self.failures+self.prereqs)
def getLastModified(self):
return (self.lastModified)
1.3 +22 -4 gump/python/gump/test/notifying.py
Index: notifying.py
===================================================================
RCS file: /home/cvs/gump/python/gump/test/notifying.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- notifying.py 21 May 2004 23:15:00 -0000 1.2
+++ notifying.py 24 May 2004 16:39:09 -0000 1.3
@@ -24,9 +24,13 @@
from gump import log
import gump.core.config
from gump.core.gumprun import GumpRun
+from gump.stats.statistician import Statistician
+
from gump.test import getWorkedTestRun
from gump.test.pyunit import UnitTestSuite
+
from gump.notify.notifier import notify,Notifier
+from gump.notify.notification import PositiveNotification,NegativeNotification
from gump.net.smtp import *
class NotificationTestSuite(UnitTestSuite):
@@ -42,18 +46,32 @@
self.workspace=self.run.getWorkspace()
self.assertNotNone('Needed a workspace', self.workspace)
+ # Prime the information..
+ stats=Statistician(self.run)
+ stats.updateStatistics()
+
def testNotificationContents(self):
-
- notifier=Notifier(self.run)
+ resolver=self.run.getOptions().getResolver()
+ content1=PositiveNotification(self.run,
self.workspace).resolveContent(resolver)
+ content2=NegativeNotification(self.run,
self.workspace).resolveContent(resolver)
+ print content1
+ print content2
+
# For all modules...
for module in self.workspace.getModules():
#print 'Get Content For Module : ' + module.getName()
- notifier.getNamedTypedContent(module,'test')
+ content1=PositiveNotification(self.run, module).resolveContent(resolver)
+ content2=NegativeNotification(self.run,
module).resolveContent(resolver)
+ print content1
+ print content2
for project in module.getProjects():
#print 'Get Content For Project : ' + project.getName()
# print
- notifier.getNamedTypedContent(project,'test')
+ content1=PositiveNotification(self.run,
project).resolveContent(resolver)
+ content2=NegativeNotification(self.run,
project).resolveContent(resolver)
+ print content1
+ print content2
def testNotifyUnwantedUnsent(self):
1.32 +0 -3 gump/python/gump/test/pyunit.py
Index: pyunit.py
===================================================================
RCS file: /home/cvs/gump/python/gump/test/pyunit.py,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- pyunit.py 21 May 2004 23:15:00 -0000 1.31
+++ pyunit.py 24 May 2004 16:39:09 -0000 1.32
@@ -337,9 +337,6 @@
from gump.test.unicode import UnicodeTestSuite
runner.addSuite(UnicodeTestSuite())
- from gump.test.tasks import TasksTestSuite
- runner.addSuite(TasksTestSuite())
-
from gump.test.diagram import DiagramTestSuite
runner.addSuite(DiagramTestSuite())
1.3 +23 -16 gump/python/gump/document/xdocs/documenter.py
Index: documenter.py
===================================================================
RCS file: /home/cvs/gump/python/gump/document/xdocs/documenter.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- documenter.py 21 May 2004 23:15:07 -0000 1.2
+++ documenter.py 24 May 2004 16:39:09 -0000 1.3
@@ -44,7 +44,7 @@
from gump.model.module import Module
from gump.model.project import Project
-from gump.notify.notifier import Notifier
+from gump.notify.logic import NotificationLogic
from gump.guru.stats import StatisticsGuru
from gump.guru.xref import XRefGuru
@@ -67,7 +67,10 @@
def __init__(self, run, dirBase, urlBase):
Documenter.__init__(self, run)
- self.setResolver(XDocResolver(dirBase,urlBase))
+ resolver=XDocResolver(dirBase,urlBase)
+ self.setResolver(resolver)
+
+ self.notifyLogic=NotificationLogic(self.run)
def prepareRun(self):
@@ -437,15 +440,11 @@
for server in self.workspace.getServers():
self.documentServer(server)
- #
# Document individual trackers
- #
for tracker in self.workspace.getTrackers():
self.documentTracker(tracker)
- #
# Document individual modules
- #
for module in self.workspace.getModules():
if not self.gumpSet.inModuleSequence(module): continue
self.documentModule(module)
@@ -1669,7 +1668,7 @@
gumpSafeName(project.getName()) + '_notify.html',
'Contents')
elif not project.isPackaged() and project.hasBuildCommand():
- document.createWarning('This project does not utilize Gump nagging.')
+ document.createWarning('This project does not utilize Gump
notification.')
metadataLocation=project.getMetadataLocation()
metadataUrl=project.getMetadataViewUrl()
@@ -1829,18 +1828,26 @@
document.serialize()
- if project.xml.nag and project.isFailed():
+ # Document notifications
+ notification = self.notifyLogic.notification(project)
+ if notification:
document=XDocDocument('Project Details : ' + project.getName(), \
- self.resolver.getFile(project, \
- project.getName() + '_notify', \
- '.xml'))
+ self.resolver.getFile(project, \
+ project.getName() + '_notify', \
+ '.xml'))
+
+ # If they don't ask for it, they won't see it.
+ part1='could'
+ part2=', if request in the metadata.'
+ if project.xml.nag:
+ part1='ought'
+ part2='.'
nagSection=document.createSection('Notification')
- nagSection.createParagraph('This is the notification mail that is to be
sent')
- nagger=Notifier(self.run)
- content=nagger.getNamedTypedContent(project)
- nagSection.createSource(content)
-
+ nagSection.createParagraph(('This is the notification mail that %s have
been sent%s') \
+ % (part1,part2))
+ nagSection.createSource(notification.resolveContent(self.resolver))
+
document.serialize()
# Document the project XML
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]