diff -rN -u old-buildbot_step_props/buildbot/process/buildstep.py new-buildbot_step_props/buildbot/process/buildstep.py
--- old-buildbot_step_props/buildbot/process/buildstep.py	2008-04-06 09:22:14.000000000 +0100
+++ new-buildbot_step_props/buildbot/process/buildstep.py	2008-04-06 09:22:14.000000000 +0100
@@ -632,9 +632,21 @@
     def getProperty(self, propname):
         return self.build.getProperty(propname)
 
+    def getPropertyOrDefault(self, propname, default):
+        return self.build.getPropertyOrDefault(propname, default)
+
     def setProperty(self, propname, value):
         self.build.setProperty(propname, value)
 
+    def getStepProperty(self, propname):
+        return self.step_status.getStepProperty(propname)
+
+    def getStepPropertyOrDefault(self, propname, default):
+        return self.step_status.getStepPropertyOrDefault(propname, default)
+
+    def setStepProperty(self, propname, value):
+        self.step_status.setStepProperty(propname, value)
+
     def startStep(self, remote):
         """Begin the step. This returns a Deferred that will fire when the
         step finishes.
diff -rN -u old-buildbot_step_props/buildbot/status/builder.py new-buildbot_step_props/buildbot/status/builder.py
--- old-buildbot_step_props/buildbot/status/builder.py	2008-04-06 09:22:14.000000000 +0100
+++ new-buildbot_step_props/buildbot/status/builder.py	2008-04-06 09:22:14.000000000 +0100
@@ -670,6 +670,7 @@
     watchers = []
     updates = {}
     finishedWatchers = []
+    properties = {}
 
     def __init__(self, parent):
         assert interfaces.IBuildStatus(parent)
@@ -679,6 +680,7 @@
         self.watchers = []
         self.updates = {}
         self.finishedWatchers = []
+        self.properties = {}
 
     def getName(self):
         """Returns a short string with the name of this step. This string
@@ -706,6 +708,15 @@
     def getLogs(self):
         return self.logs
 
+    def getStepProperty(self, propname):
+        return self.properties[propname]
+
+    def getStepPropertyOrDefault(self, propname, default):
+        if self.properties.has_key(propname):
+            return self.properties[propname]
+        else:
+            return default
+
     def getURLs(self):
         return self.urls.copy()
 
@@ -799,6 +810,9 @@
     def setProgress(self, stepprogress):
         self.progress = stepprogress
 
+    def setStepProperty(self, propname, value):
+        self.properties[propname] = value
+
     def stepStarted(self):
         self.started = util.now()
         if self.build:
@@ -886,6 +900,8 @@
             self.urls = {}
 
 
+import operator
+
 class BuildStatus(styles.Versioned):
     implements(interfaces.IBuildStatus, interfaces.IStatusEvent)
     persistenceVersion = 2
@@ -937,6 +953,12 @@
     def getProperty(self, propname):
         return self.properties[propname]
 
+    def getPropertyOrDefault(self, propname, default):
+        if self.properties.has_key(propname):
+            return self.properties[propname]
+        else:
+            return default
+
     def getNumber(self):
         return self.number
 
@@ -1023,6 +1045,9 @@
     def getTestResults(self):
         return self.testResults
 
+    def sumStepProperty(self, propname):
+        return reduce(operator.add, map(lambda x: x.getStepPropertyOrDefault(propname, 0), self.steps))
+
     def getLogs(self):
         # TODO: steps should contribute significant logs instead of this
         # hack, which returns every log from every step. The logs should get
diff -rN -u old-buildbot_step_props/buildbot/test/test_status.py new-buildbot_step_props/buildbot/test/test_status.py
--- old-buildbot_step_props/buildbot/test/test_status.py	2008-04-06 09:22:14.000000000 +0100
+++ new-buildbot_step_props/buildbot/test/test_status.py	2008-04-06 09:22:14.000000000 +0100
@@ -980,3 +980,25 @@
         self.failUnless(isinstance(b2, client.RemoteBuilder))
         b3 = client.makeRemote(None)
         self.failUnless(b3 is None)
+
+class Properties(unittest.TestCase):
+    def testProperties(self):
+        status = builder.BuildStatus(builder.BuilderStatus("test"), 123)
+        status.addStepWithName('step1')
+        status.addStepWithName('step2')
+        status.addStepWithName('step3')
+        status.addStepWithName('step4')
+
+        steps = status.getSteps()
+        (step1, step2, step3, step4) = steps
+
+        step1.setStepProperty('test-prop', 1)
+        step1.setStepProperty('other-prop', 27) # Just to have some other properties around
+        step3.setStepProperty('test-prop', 2)
+        step4.setStepProperty('test-prop', 4)
+
+        self.failUnlessEqual(step1.getStepProperty('test-prop'), 1, 'Retrieve an existing property')
+        self.failUnlessEqual(step1.getStepPropertyOrDefault('test-prop', 99), 1, 'Don\'t default an existing property')
+        self.failUnlessEqual(step2.getStepPropertyOrDefault('test-prop', 99), 99, 'Default a non-existant property')
+
+        self.failUnlessEqual( status.sumStepProperty('test-prop'), 7, 'Sum property across the build')
diff -rN -u old-buildbot_step_props/docs/buildbot.texinfo new-buildbot_step_props/docs/buildbot.texinfo
--- old-buildbot_step_props/docs/buildbot.texinfo	2008-04-06 09:22:14.000000000 +0100
+++ new-buildbot_step_props/docs/buildbot.texinfo	2008-04-06 09:22:14.000000000 +0100
@@ -187,6 +187,7 @@
 * Transferring Files::          
 * Triggering Schedulers::       
 * Writing New BuildSteps::      
+* BuildStep Properties::
 
 Source Checkout
 
@@ -3763,6 +3764,7 @@
 * Transferring Files::          
 * Triggering Schedulers::       
 * Writing New BuildSteps::      
+* BuildStep Properties::
 @end menu
 
 @node Common Parameters, Source Checkout, Build Steps, Build Steps
@@ -5339,7 +5341,7 @@
 
 
 
-@node BuildStep URLs,  , Adding LogObservers, Writing New BuildSteps
+@node BuildStep URLs, BuildStep Properties , Adding LogObservers, Writing New BuildSteps
 @subsubsection BuildStep URLs
 
 @cindex links
@@ -5416,6 +5418,13 @@
 be merged before the buildbot ever sees them, so such interleaving
 will be unavoidable.
 
+@node BuildStep Properties, , BuildStep URLs, Build Steps
+@subsection BuildStep Properties
+
+BuildSteps may set and retrieve properties.  There is also a facility
+to retrieve a step property's value returning a default value if the
+property was not set.  At the build level, there is a helper to sum a
+property across a whole build.
 
 @node Interlocks, Build Factories, Build Steps, Build Process
 @section Interlocks

