Changeset 630

Show
Ignore:
Timestamp:
04/12/08 12:58:59 (9 months ago)
Author:
dustin@v.igoro.us
Message:

#124:properties-class.patch
Add and use a Properties class, refactor the way properties are rendered,
and update unit tests accordingly.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • buildbot/process/base.py

    r625 r630  
    208208        return self.source 
    209209 
    210     def setProperty(self, propname, value): 
     210    def setProperty(self, propname, value, source): 
    211211        """Set a property on this build. This may only be called after the 
    212212        build has started, so that it has a BuildStatus object where the 
    213213        properties can live.""" 
    214         self.build_status.setProperty(propname, value
     214        self.build_status.setProperty(propname, value, source
    215215 
    216216    def getCustomProperties(self): 
    217217        return self.custom_properties 
     218 
     219    def getProperties(self): 
     220        return self.build_status.getProperties() 
    218221 
    219222    def getProperty(self, propname): 
     
    278281    def setupStatus(self, build_status): 
    279282        self.build_status = build_status 
    280         self.setProperty("buildername", self.builder.name
    281         self.setProperty("buildnumber", self.build_status.number
    282         self.setProperty("branch", self.source.branch
    283         self.setProperty("revision", self.source.revision
     283        self.setProperty("buildername", self.builder.name, "build"
     284        self.setProperty("buildnumber", self.build_status.number, "build"
     285        self.setProperty("branch", self.source.branch, "build"
     286        self.setProperty("revision", self.source.revision, "build"
    284287        if self.scheduler is None: 
    285             self.setProperty("scheduler", "none"
     288            self.setProperty("scheduler", "none", "build"
    286289        else: 
    287             self.setProperty("scheduler", self.scheduler.name
     290            self.setProperty("scheduler", self.scheduler.name, "build"
    288291        for key, userProp in self.custom_properties.items(): 
    289             self.setProperty(key, userProp
     292            self.setProperty(key, userProp, "custom_props"
    290293 
    291294    def setupSlaveBuilder(self, slavebuilder): 
     
    293296        self.slavename = slavebuilder.slave.slavename 
    294297        self.build_status.setSlavename(self.slavename) 
    295         self.setProperty("slavename", self.slavename
     298        self.setProperty("slavename", self.slavename, "build"
    296299 
    297300    def startBuild(self, build_status, expectations, slavebuilder): 
  • buildbot/process/buildstep.py

    r580 r630  
    633633        return self.build.getProperty(propname) 
    634634 
    635     def setProperty(self, propname, value): 
    636         self.build.setProperty(propname, value
     635    def setProperty(self, propname, value, source): 
     636        self.build.setProperty(propname, value, source
    637637 
    638638    def startStep(self, remote): 
     
    10931093        self.step_status.setText2(self.maybeGetText2(cmd, results)) 
    10941094 
    1095 class _BuildPropertyMapping: 
    1096     def __init__(self, build): 
    1097         self.build = build 
    1098     def __getitem__(self, name): 
    1099         p = self.build.getProperty(name) 
    1100         if p is None: 
    1101             p = "" 
    1102         return p 
    1103  
    1104 class WithProperties(util.ComparableMixin): 
    1105     """This is a marker class, used in ShellCommand's command= argument to 
    1106     indicate that we want to interpolate a build property. 
    1107     """ 
    1108  
    1109     compare_attrs = ('fmtstring', 'args') 
    1110  
    1111     def __init__(self, fmtstring, *args): 
    1112         self.fmtstring = fmtstring 
    1113         self.args = args 
    1114  
    1115     def render(self, build): 
    1116         pmap = _BuildPropertyMapping(build) 
    1117         if self.args: 
    1118             strings = [] 
    1119             for name in self.args: 
    1120                 strings.append(pmap[name]) 
    1121             s = self.fmtstring % tuple(strings) 
    1122         else: 
    1123             s = self.fmtstring % pmap 
    1124         return s 
    1125  
    1126 def render_properties(s, build): 
    1127     """Return a string based on s and build that is suitable for use 
    1128     in a running BuildStep.  If s is a string, return s.  If s is a 
    1129     WithProperties object, return the result of s.render(build). 
    1130     Otherwise, return str(s). 
    1131     """ 
    1132     if isinstance(s, (str, unicode)): 
    1133         return s 
    1134     elif isinstance(s, WithProperties): 
    1135         return s.render(build) 
    1136     else: 
    1137         return str(s) 
     1095# (WithProeprties used to be available in this module) 
     1096from buildbot.process.properties import WithProperties 
  • buildbot/status/builder.py

    r629 r630  
    66from twisted.internet import reactor, defer 
    77from twisted.protocols import basic 
     8from buildbot.process.properties import Properties 
    89 
    910import os, shutil, sys, re, urllib, itertools 
     
    889890class BuildStatus(styles.Versioned): 
    890891    implements(interfaces.IBuildStatus, interfaces.IStatusEvent) 
    891     persistenceVersion = 2 
     892    persistenceVersion = 3 
    892893 
    893894    source = None 
     
    925926        self.steps = [] 
    926927        self.testResults = {} 
    927         self.properties = {} 
     928        self.properties = Properties() 
    928929 
    929930    # IBuildStatus 
     
    937938    def getProperty(self, propname): 
    938939        return self.properties[propname] 
     940 
     941    def getProperties(self): 
     942        return self.properties 
    939943 
    940944    def getNumber(self): 
     
    10751079        return s 
    10761080 
    1077     def setProperty(self, propname, value): 
    1078         self.properties[propname] = value 
     1081    def setProperty(self, propname, value, source): 
     1082        self.properties.setProperty(propname, value, source) 
    10791083 
    10801084    def addTestResult(self, result): 
     
    12291233    def upgradeToVersion2(self): 
    12301234        self.properties = {} 
     1235 
     1236    def upgradeToVersion3(self): 
     1237        # in version 3, self.properties became a Properties object 
     1238        propdict = self.properties 
     1239        self.properties = Properties() 
     1240        self.properties.update(propdict) 
    12311241 
    12321242    def upgradeLogfiles(self): 
  • buildbot/steps/python.py

    r241 r630  
    9797                self.descriptionDone.append("%s=%d" % (m, counts[m])) 
    9898                self.addCompleteLog(m, "".join(summaries[m])) 
    99             self.setProperty("pyflakes-%s" % m, counts[m]
    100         self.setProperty("pyflakes-total", sum(counts.values())
     99            self.setProperty("pyflakes-%s" % m, counts[m], "pyflakes"
     100        self.setProperty("pyflakes-total", sum(counts.values()), "pyflakes"
    101101 
    102102 
  • buildbot/steps/shell.py

    r628 r630  
    33import re 
    44from twisted.python import log 
    5 from buildbot.process.buildstep import LoggingBuildStep, RemoteShellCommand, \ 
    6      render_properties 
     5from buildbot.process.buildstep import LoggingBuildStep, RemoteShellCommand 
    76from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE 
    87 
    9 # for existing configurations that import WithProperties from here 
    10 from buildbot.process.buildstep import WithProperties 
     8# for existing configurations that import WithProperties from here.  We like 
     9# to move this class around just to keep our readers guessing. 
     10from buildbot.process.properties import WithProperties 
    1111 
    1212class ShellCommand(LoggingBuildStep): 
     
    119119            return self.description 
    120120 
     121        properties = self.build.getProperties() 
    121122        words = self.command 
    122123        if isinstance(words, (str, unicode)): 
    123124            words = words.split() 
    124125        # render() each word to handle WithProperties objects 
    125         words = [render_properties(word, self.build) for word in words] 
     126        words = [properties.render(word) for word in words] 
    126127        if len(words) < 1: 
    127128            return ["???"] 
     
    132133        return ["'%s" % words[0], "%s" % words[1], "...'"] 
    133134 
    134     def _interpolateProperties(self, value): 
    135         """ 
    136         Expand the L{WithProperties} objects in L{value} 
    137         """ 
    138         if isinstance(value, (str, unicode, bool, int, float, type(None))): 
    139             return value 
    140  
    141         if isinstance(value, list): 
    142             return [self._interpolateProperties(val) for val in value] 
    143  
    144         if isinstance(value, tuple): 
    145             return tuple([self._interpolateProperties(val) for val in value]) 
    146  
    147         if isinstance(value, dict): 
    148             new_dict = { } 
    149             for key, val in value.iteritems(): 
    150                 new_key = self._interpolateProperties(key) 
    151                 new_dict[new_key] = self._interpolateProperties(val) 
    152             return new_dict 
    153  
    154         # To make sure we catch anything we forgot 
    155         assert isinstance(value, WithProperties), \ 
    156                "%s (%s) is not a WithProperties" % (value, type(value)) 
    157  
    158         return value.render(self.build) 
    159  
    160     def _interpolateWorkdir(self, workdir): 
    161         return render_properties(workdir, self.build) 
    162  
    163135    def setupEnvironment(self, cmd): 
     136        # XXX is this used? documented? replaced by properties? 
    164137        # merge in anything from Build.slaveEnvironment . Earlier steps 
    165138        # (perhaps ones which compile libraries or sub-projects that need to 
    166139        # be referenced by later steps) can add keys to 
    167140        # self.build.slaveEnvironment to affect later steps. 
     141        properties = self.build.getProperties() 
    168142        slaveEnv = self.build.slaveEnvironment 
    169143        if slaveEnv: 
    170144            if cmd.args['env'] is None: 
    171145                cmd.args['env'] = {} 
    172             cmd.args['env'].update(self._interpolateProperties(slaveEnv)) 
     146            cmd.args['env'].update(properties.render(slaveEnv)) 
    173147            # note that each RemoteShellCommand gets its own copy of the 
    174148            # dictionary, so we shouldn't be affecting anyone but ourselves. 
     
    200174        # to set up an argv array, an environment, or extra logfiles= (like 
    201175        # the Source subclasses) can just skip straight to startCommand() 
    202         command = self._interpolateProperties(self.command
    203         assert isinstance(command, (list, tuple, str)) 
     176        properties = self.build.getProperties(
     177 
    204178        # create the actual RemoteShellCommand instance now 
    205         kwargs = self._interpolateProperties(self.remote_kwargs) 
    206         kwargs['workdir'] = self._interpolateWorkdir(kwargs['workdir']) 
    207         kwargs['command'] = command 
     179        kwargs = properties.render(self.remote_kwargs) 
     180        kwargs['command'] = properties.render(self.command) 
    208181        kwargs['logfiles'] = self.logfiles 
    209182        cmd = RemoteShellCommand(**kwargs) 
     
    225198        if m: 
    226199            self.kib = int(m.group(1)) 
    227             self.setProperty("tree-size-KiB", self.kib
     200            self.setProperty("tree-size-KiB", self.kib, "treesize"
    228201 
    229202    def evaluateCommand(self, cmd): 
     
    299272        except KeyError: 
    300273            old_count = 0 
    301         self.setProperty("warnings-count", old_count + self.warnCount
     274        self.setProperty("warnings-count", old_count + self.warnCount, "WarningCountingShellCommand"
    302275 
    303276 
  • buildbot/steps/source.py

    r612 r630  
    188188        if cmd.updates.has_key("got_revision"): 
    189189            got_revision = str(cmd.updates["got_revision"][-1]) 
    190         self.setProperty("got_revision", got_revision
     190        self.setProperty("got_revision", got_revision, "source"
    191191 
    192192 
  • buildbot/steps/transfer.py

    r568 r630  
    55from twisted.spread import pb 
    66from twisted.python import log 
    7 from buildbot.process.buildstep import RemoteCommand, BuildStep, \ 
    8      render_properties 
     7from buildbot.process.buildstep import RemoteCommand, BuildStep 
    98from buildbot.process.buildstep import SUCCESS, FAILURE 
    109from buildbot.interfaces import BuildSlaveTooOldError 
     
    112111    def start(self): 
    113112        version = self.slaveVersion("uploadFile") 
     113        properties = self.build.getProperties() 
     114 
    114115        if not version: 
    115116            m = "slave is too old, does not know about uploadFile" 
    116117            raise BuildSlaveTooOldError(m) 
    117118 
    118         source = render_properties(self.slavesrc, self.build
    119         masterdest = render_properties(self.masterdest, self.build
     119        source = properties.render(self.slavesrc
     120        masterdest = properties.render(self.masterdest
    120121        # we rely upon the fact that the buildmaster runs chdir'ed into its 
    121122        # basedir to make sure that relative paths in masterdest are expanded 
     
    238239 
    239240    def start(self): 
     241        properties = self.build.getProperties() 
     242 
    240243        version = self.slaveVersion("downloadFile") 
    241244        if not version: 
     
    245248        # we are currently in the buildmaster's basedir, so any non-absolute 
    246249        # paths will be interpreted relative to that 
    247         source = os.path.expanduser(render_properties(self.mastersrc, 
    248                                                       self.build)) 
    249         slavedest = render_properties(self.slavedest, self.build) 
     250        source = os.path.expanduser(properties.render(self.mastersrc)) 
     251        slavedest = properties.render(self.slavedest) 
    250252        log.msg("FileDownload started, from master %r to slave %r" % 
    251253                (source, slavedest)) 
  • buildbot/test/test_properties.py

    r615 r630  
    77from buildbot.sourcestamp import SourceStamp 
    88from buildbot.process import base 
    9 from buildbot.steps.shell import ShellCommand, WithProperties 
     9from buildbot.process.properties import WithProperties, Properties 
     10from buildbot.steps.shell import ShellCommand 
    1011from buildbot.status import builder 
    1112from buildbot.slave.commands import rmdirRecursive 
     
    2728    name = "fakescheduler" 
    2829 
    29 class Interpolate(unittest.TestCase): 
     30class TestProperties(unittest.TestCase): 
     31    def setUp(self): 
     32        self.props = Properties() 
     33 
     34    def testDictBehavior(self): 
     35        self.props.setProperty("do-tests", 1, "scheduler") 
     36        self.props.setProperty("do-install", 2, "scheduler") 
     37 
     38        self.assert_(self.props.has_key('do-tests')) 
     39        self.failUnlessEqual(self.props['do-tests'], 1) 
     40        self.failUnlessEqual(self.props['do-install'], 2) 
     41        self.assertRaises(KeyError, lambda : self.props['do-nothing']) 
     42        self.failUnlessEqual(self.props.getProperty('do-install'), (2, 'scheduler')) 
     43 
     44    def testEmpty(self): 
     45        # test the special case for Null 
     46        self.props.setProperty("x", None, "hi") 
     47        self.failUnlessEqual(self.props.getProperty('x'), (None, 'hi')) 
     48        self.failUnlessEqual(self.props['x'], '') 
     49 
     50    def testUpdate(self): 
     51        self.props.setProperty("x", 24, "old") 
     52        newprops = { 'a' : 1, 'b' : 2 } 
     53        self.props.update(newprops, "new") 
     54 
     55        self.failUnlessEqual(self.props.getProperty('x'), (24, 'old')) 
     56        self.failUnlessEqual(self.props.getProperty('a'), (1, 'new')) 
     57 
     58    def testUpdateFromProperties(self): 
     59        self.props.setProperty("x", 24, "old") 
     60        newprops = Properties() 
     61        newprops.setProperty('a', 1, "new") 
     62        newprops.setProperty('b', 2, "new") 
     63        self.props.updateFromProperties(newprops) 
     64 
     65        self.failUnlessEqual(self.props.getProperty('x'), (24, 'old')) 
     66        self.failUnlessEqual(self.props.getProperty('a'), (1, 'new')) 
     67 
     68    # render() is pretty well tested by TestWithProperties 
     69 
     70class TestWithProperties(unittest.TestCase): 
     71    def setUp(self): 
     72        self.props = Properties() 
     73 
     74    def testBasic(self): 
     75        # test basic substitution with WithProperties 
     76        self.props.setProperty("revision", "47", "test") 
     77        command = WithProperties("build-%s.tar.gz", "revision") 
     78        self.failUnlessEqual(self.props.render(command), 
     79                             "build-47.tar.gz") 
     80 
     81    def testDict(self): 
     82        # test dict-style substitution with WithProperties 
     83        self.props.setProperty("other", "foo", "test") 
     84        command = WithProperties("build-%(other)s.tar.gz") 
     85        self.failUnlessEqual(self.props.render(command), 
     86                             "build-foo.tar.gz") 
     87 
     88    def testEmpty(self): 
     89        # None should render as '' 
     90        self.props.setProperty("empty", None, "test") 
     91        command = WithProperties("build-%(empty)s.tar.gz") 
     92        self.failUnlessEqual(self.props.render(command), 
     93                             "build-.tar.gz") 
     94 
     95    def testRecursiveList(self): 
     96        self.props.setProperty("x", 10, "test") 
     97        self.props.setProperty("y", 20, "test") 
     98        command = [ WithProperties("%(x)s %(y)s"), "and", 
     99                    WithProperties("%(y)s %(x)s") ] 
     100        self.failUnlessEqual(self.props.render(command), 
     101                             ["10 20", "and", "20 10"]) 
     102 
     103    def testRecursiveTuple(self): 
     104        self.props.setProperty("x", 10, "test") 
     105        self.props.setProperty("y", 20, "test") 
     106        command = ( WithProperties("%(x)s %(y)s"), "and", 
     107                    WithProperties("%(y)s %(x)s") ) 
     108        self.failUnlessEqual(self.props.render(command), 
     109                             ("10 20", "and", "20 10")) 
     110 
     111    def testRecursiveDict(self): 
     112        self.props.setProperty("x", 10, "test") 
     113        self.props.setProperty("y", 20, "test") 
     114        command = { WithProperties("%(x)s %(y)s") :  
     115                    WithProperties("%(y)s %(x)s") } 
     116        self.failUnlessEqual(self.props.render(command), 
     117                             {"10 20" : "20 10"}) 
     118 
     119class BuildProperties(unittest.TestCase): 
     120    """Test the properties that a build should have.""" 
    30121    def setUp(self): 
    31122        self.builder = FakeBuilder() 
     
    37128        self.build_status = self.builder_status.newBuild() 
    38129        req = base.BuildRequest("reason", SourceStamp(branch="branch2", 
    39                                                       revision=1234)) 
     130                                                      revision="1234")) 
    40131        self.build = base.Build([req]) 
    41132        self.build.setBuilder(self.builder) 
     
    43134        self.build.setupSlaveBuilder(FakeSlaveBuilder()) 
    44135 
    45     def testWithProperties(self): 
    46         self.build.setProperty("revision", 47) 
    47         self.failUnlessEqual(self.build_status.getProperty("revision"), 47) 
    48         c = ShellCommand(workdir=dir, 
    49                          command=["tar", "czf", 
    50                                   WithProperties("build-%s.tar.gz", 
    51                                                  "revision"), 
    52                                   "source"]) 
    53         c.setBuild(self.build) 
    54         cmd = c._interpolateProperties(c.command) 
    55         self.failUnlessEqual(cmd, 
    56                              ["tar", "czf", "build-47.tar.gz", "source"]) 
     136    def testProperties(self): 
     137        # if not started from a scheduler, the 'scheduler' property 
     138        # should be 'none' 
    57139        self.failUnlessEqual(self.build.getProperty("scheduler"), "none") 
    58  
    59     def testWorkdir(self): 
    60         self.build.setProperty("revision", 47) 
    61         self.failUnlessEqual(self.build_status.getProperty("revision"), 47) 
    62         c = ShellCommand(command=["tar", "czf", "foo.tar.gz", "source"]) 
    63         c.setBuild(self.build) 
    64         workdir = WithProperties("workdir-%d", "revision") 
    65         workdir = c._interpolateWorkdir(workdir) 
    66         self.failUnlessEqual(workdir, "workdir-47") 
    67  
    68     def testWithPropertiesDict(self): 
    69         self.build.setProperty("other", "foo") 
    70         self.build.setProperty("missing", None) 
    71         c = ShellCommand(workdir=dir, 
    72                          command=["tar", "czf", 
    73                                   WithProperties("build-%(other)s.tar.gz"), 
    74                                   "source"]) 
    75         c.setBuild(self.build) 
    76         cmd = c._interpolateProperties(c.command) 
    77         self.failUnlessEqual(cmd, 
    78                              ["tar", "czf", "build-foo.tar.gz", "source"]) 
    79  
    80     def testWithPropertiesEmpty(self): 
    81         self.build.setProperty("empty", None) 
    82         c = ShellCommand(workdir=dir, 
    83                          command=["tar", "czf", 
    84                                   WithProperties("build-%(empty)s.tar.gz"), 
    85                                   "source"]) 
    86         c.setBuild(self.build) 
    87         cmd = c._interpolateProperties(c.command) 
    88         self.failUnlessEqual(cmd, 
    89                              ["tar", "czf", "build-.tar.gz", "source"]) 
    90  
    91     def testSourceStamp(self): 
    92         c = ShellCommand(workdir=dir, 
    93                          command=["touch", 
    94                                   WithProperties("%s-dir", "branch"), 
    95                                   WithProperties("%s-rev", "revision"), 
    96                                   ]) 
    97         c.setBuild(self.build) 
    98         cmd = c._interpolateProperties(c.command) 
    99         self.failUnlessEqual(cmd, 
    100                              ["touch", "branch2-dir", "1234-rev"]) 
    101  
    102     def testSlaveName(self): 
    103         c = ShellCommand(workdir=dir, 
    104                          command=["touch", 
    105                                   WithProperties("%s-slave", "slavename"), 
    106                                   ]) 
    107         c.setBuild(self.build) 
    108         cmd = c._interpolateProperties(c.command) 
    109         self.failUnlessEqual(cmd, 
    110                              ["touch", "bot12-slave"]) 
    111  
    112     def testBuildNumber(self): 
    113         c = ShellCommand(workdir=dir, 
    114                          command=["touch", 
    115                                   WithProperties("build-%d", "buildnumber"), 
    116                                   WithProperties("builder-%s", "buildername"), 
    117                                   ]) 
    118         c.setBuild(self.build) 
    119         cmd = c._interpolateProperties(c.command) 
    120         self.failUnlessEqual(cmd, 
    121                              ["touch", "build-5", "builder-fakebuilder"]) 
     140        self.failUnlessEqual(self.build.getProperty("branch"), "branch2") 
     141        self.failUnlessEqual(self.build.getProperty("revision"), "1234") 
     142        self.failUnlessEqual(self.build.getProperty("slavename"), "bot12") 
     143        self.failUnlessEqual(self.build.getProperty("buildnumber"), 5) 
     144        self.failUnlessEqual(self.build.getProperty("buildername"), "fakebuilder") 
    122145 
    123146class SchedulerTest(unittest.TestCase): 
  • buildbot/test/test_steps.py

    r532 r630  
    237237        bs = s.step_status.getBuild() 
    238238 
    239         s.setProperty("prop1", "value1"
    240         s.setProperty("prop2", "value2"
     239        s.setProperty("prop1", "value1", "test"
     240        s.setProperty("prop2", "value2", "test"
    241241        self.failUnlessEqual(s.getProperty("prop1"), "value1") 
    242242        self.failUnlessEqual(bs.getProperty("prop1"), "value1") 
    243243        self.failUnlessEqual(s.getProperty("prop2"), "value2") 
    244244        self.failUnlessEqual(bs.getProperty("prop2"), "value2") 
    245         s.setProperty("prop1", "value1a"
     245        s.setProperty("prop1", "value1a", "test"
    246246        self.failUnlessEqual(s.getProperty("prop1"), "value1a") 
    247247        self.failUnlessEqual(bs.getProperty("prop1"), "value1a") 
     
    602602ending line 
    603603""" 
    604         step.setProperty("warnings-count", 10
     604        step.setProperty("warnings-count", 10, "test"
    605605        log = step.addLog("stdio") 
    606606        log.addStdout(output) 
  • buildbot/test/test_vc.py

    r588 r630  
    542542        if self.metadir: 
    543543            self.shouldExist(self.workdir, self.metadir) 
    544         self.failUnlessEqual(bs.getProperty("revision"), None
    545         self.failUnlessEqual(bs.getProperty("branch"), None
     544        self.failUnlessEqual(bs.getProperty("revision"), ''
     545        self.failUnlessEqual(bs.getProperty("branch"), ''
    546546        self.checkGotRevisionIsLatest(bs) 
    547547 
     
    566566        if self.metadir: 
    567567            self.shouldExist(self.workdir, self.metadir) 
    568         self.failUnlessEqual(bs.getProperty("revision"), self.helper.trunk[0]
    569         self.failUnlessEqual(bs.getProperty("branch"), None
     568        self.failUnlessEqual(bs.getProperty("revision"), self.helper.trunk[0] or ''
     569        self.failUnlessEqual(bs.getProperty("branch"), ''
    570570        self.checkGotRevision(bs, self.helper.trunk[0]) 
    571571        # leave the tree at HEAD 
     
    586586        if self.metadir: 
    587587            self.shouldExist(self.workdir, self.metadir) 
    588         self.failUnlessEqual(bs.getProperty("revision"), None
     588        self.failUnlessEqual(bs.getProperty("revision"), ''
    589589        self.checkGotRevisionIsLatest(bs) 
    590590 
     
    610610                           "version=%d" % self.helper.version) 
    611611        self.shouldExist(self.workdir, "newfile") 
    612         self.failUnlessEqual(bs.getProperty("revision"), None
     612        self.failUnlessEqual(bs.getProperty("revision"), ''
    613613        self.checkGotRevisionIsLatest(bs) 
    614614 
     
    624624                           "version=%d" % (self.helper.version-1)) 
    625625        self.failUnlessEqual(bs.getProperty("revision"), 
    626                              self.helper.trunk[-2]
     626                             self.helper.trunk[-2] or ''
    627627        self.checkGotRevision(bs, self.helper.trunk[-2]) 
    628628 
     
    638638                           "version=%d" % self.helper.version) 
    639639        self.failUnlessEqual(bs.getProperty("revision"), 
    640                              self.helper.trunk[-1]
     640                             self.helper.trunk[-1] or ''
    641641        self.checkGotRevision(bs, self.helper.trunk[-1]) 
    642642 
     
    675675        self.touch(self.workdir, "newfile") 
    676676        self.touch(self.vcdir, "newvcfile") 
    677         self.failUnlessEqual(bs.getProperty("revision"), None
     677        self.failUnlessEqual(bs.getProperty("revision"), ''
    678678        self.checkGotRevisionIsLatest(bs) 
    679679 
     
    688688        self.shouldExist(self.vcdir, "newvcfile") 
    689689        self.shouldExist(self.workdir, "newvcfile") 
    690         self.failUnlessEqual(bs.getProperty("revision"), None
     690        self.failUnlessEqual(bs.getProperty("revision"), ''
    691691        self.checkGotRevisionIsLatest(bs) 
    692692        self.touch(self.workdir, "newfile") 
     
    699699        self.shouldNotExist(self.workdir, self.metadir) 
    700700        self.shouldNotExist(self.workdir, "newfile") 
    701         self.failUnlessEqual(bs.getProperty("revision"), None
     701        self.failUnlessEqual(bs.getProperty("revision"), ''
    702702        #self.checkGotRevisionIsLatest(bs) 
    703703        # VC 'export' is not required to have a got_revision 
     
    710710        self.shouldNotExist(self.workdir, self.metadir) 
    711711        self.shouldNotExist(self.workdir, "newfile") 
    712         self.failUnlessEqual(bs.getProperty("revision"), None
     712        self.failUnlessEqual(bs.getProperty("revision"), ''
    713713        #self.checkGotRevisionIsLatest(bs) 
    714714        # VC 'export' is not required to have a got_revision 
     
    745745        self.failUnlessIn("Hello patched subdir.\\n", data) 
    746746        self.failUnlessEqual(bs.getProperty("revision"), 
    747                              self.helper.trunk[-1]
     747                             self.helper.trunk[-1] or ''
    748748        self.checkGotRevision(bs, self.helper.trunk[-1]) 
    749749 
     
    759759        data = open(subdir_c, "r").read() 
    760760        self.failUnlessIn("Hello subdir.\\n", data) 
    761         self.failUnlessEqual(bs.getProperty("revision"), None
     761        self.failUnlessEqual(bs.getProperty("revision"), ''
    762762        self.checkGotRevisionIsLatest(bs) 
    763763 
     
    784784        self.failUnlessIn("Hello patched subdir.\\n", data) 
    785785        self.failUnlessEqual(bs.getProperty("revision"), 
    786                              self.helper.trunk[-2]
     786                             self.helper.trunk[-2] or ''
    787787        self.checkGotRevision(bs, self.helper.trunk[-2]) 
    788788 
     
    803803        self.failUnlessIn("Hello patched subdir.\\n", data) 
    804804        self.failUnlessEqual(bs.getProperty("revision"), 
    805                              self.helper.branch[-1]
    806         self.failUnlessEqual(bs.getProperty("branch"), self.helper.branchname
     805                             self.helper.branch[-1] or ''
     806        self.failUnlessEqual(bs.getProperty("branch"), self.helper.branchname or ''
    807807        self.checkGotRevision(bs, self.helper.branch[-1]) 
    808808