[Buildbot-commits] buildbot/buildbot/process step.py,1.83,1.84 base.py,1.62,1.63 step_twisted.py,1.74,1.75
Brian Warner
warner at users.sourceforge.net
Mon Apr 24 06:45:39 UTC 2006
Update of /cvsroot/buildbot/buildbot/buildbot/process
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25669/buildbot/process
Modified Files:
step.py base.py step_twisted.py
Log Message:
Revision: arch at buildbot.sf.net--2004/buildbot--dev--0--patch-506
Creator: Brian Warner <warner at lothar.com>
add 'build properties', update test_vc
2006-04-23 Brian Warner <warner at lothar.com>
* buildbot/test/test_vc.py (VCBase.checkGotRevision): test
'got_revision' build property for all VC systems that implement
accurate ones: SVN, Darcs, Arch, Bazaar, Mercurial.
* buildbot/slave/commands.py (SourceBase._handleGotRevision): try
to determine which revision we actually obtained
(CVS.parseGotRevision): implement this for CVS, which just means
to grab a timestamp. Not ideal, and it depends upon the buildslave
having a clock that is reasonably well syncronized with the server,
but it's better than nothing.
(SVN.parseGotRevision): implement it for SVN, which is accurate
(Darcs.parseGotRevision): same
(Arch.parseGotRevision): same
(Bazaar.parseGotRevision): same
(Mercurial.parseGotRevision): same
* buildbot/process/step.py (LoggedRemoteCommand.remoteUpdate):
keep a record of all non-stdout/stderr/header/rc status updates,
for the benefit of RemoteCommands that send other useful things,
like got_revision
(Source.commandComplete): put any 'got_revision' status values
into a build property of the same name
* buildbot/process/step_twisted.py (Trial): update to deal with
new ShellCommand refactoring
* docs/buildbot.texinfo (Build Properties): document new feature
that allows BuildSteps to get/set Build-wide properties like which
revision was requested and/or checked out.
* buildbot/interfaces.py (IBuildStatus.getProperty): new method
* buildbot/status/builder.py (BuildStatus.getProperty): implement
it. Note that this bumps the persistenceVersion of the saved Build
object, so add the necessary upgrade-old-version logic to include
an empty properties dict.
* buildbot/process/base.py (Build.setProperty): implement it
(Build.getProperty): same
(Build.startBuild): change build startup to set 'branch',
'revision', and 'slavename' properties at the right time
* buildbot/process/step.py (BuildStep.__init__): change setup to
require 'build' argument in a better way
(LoggingBuildStep): split ShellCommand into two pieces, for better
subclassing elsewhere. LoggingBuildStep is a BuildStep which runs
a single RemoteCommand that sends stdout/stderr status text. It
also provides the usual commandComplete / createSummary /
evaluateCommand / getText methods to be overridden...
(ShellCommand): .. whereas ShellCommand is specifically for
running RemoteShellCommands. Other shell-like BuildSteps (like
Source) can inherit from LoggingBuildStep instead of ShellCommand
(WithProperties): marker class to do build-property interpolation
(Source): inherit from LoggingBuildStep instead of ShellCommand
(RemoteDummy): same
* buildbot/test/test_properties.py: test new functionality
2006-04-21 Brian Warner <warner at lothar.com>
* buildbot/test/test_vc.py: rename testBranch to
testCheckoutBranch to keep the tests in about the right
alphabetical order
Index: base.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/process/base.py,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- base.py 12 Mar 2006 11:28:04 -0000 1.62
+++ base.py 24 Apr 2006 06:45:36 -0000 1.63
@@ -157,6 +157,7 @@
@ivar build_status: the L{buildbot.status.builder.BuildStatus} that
collects our status
"""
+
if implements:
implements(interfaces.IBuildControl)
else:
@@ -197,6 +198,16 @@
def getSourceStamp(self):
return self.source
+ def setProperty(self, propname, value):
+ """Set a property on this build. This may only be called after the
+ build has started, so that it has a BuildStatus object where the
+ properties can live."""
+ self.build_status.setProperty(propname, value)
+
+ def getProperty(self, propname):
+ return self.build_status.properties[propname]
+
+
def allChanges(self):
return self.source.changes
@@ -253,6 +264,16 @@
def getSlaveCommandVersion(self, command, oldversion=None):
return self.slavebuilder.getSlaveCommandVersion(command, oldversion)
+ def setupStatus(self, build_status):
+ self.build_status = build_status
+ self.setProperty("branch", self.source.branch)
+ self.setProperty("revision", self.source.revision)
+
+ def setupSlaveBuilder(self, slavebuilder):
+ self.slavebuilder = slavebuilder
+ self.slavename = slavebuilder.slave.slavename
+ self.setProperty("slavename", self.slavename)
+
def startBuild(self, build_status, expectations, slavebuilder):
"""This method sets up the build, then starts it by invoking the
first Step. It returns a Deferred which will fire when the build
@@ -264,9 +285,10 @@
# the Deferred returned by this method.
log.msg("%s.startBuild" % self)
- self.build_status = build_status
- self.slavebuilder = slavebuilder
- self.slavename = slavebuilder.slave.slavename
+ self.setupStatus(build_status)
+ # now that we have a build_status, we can set properties
+ self.setupSlaveBuilder(slavebuilder)
+
# convert all locks into their real forms
self.locks = [self.builder.botmaster.getLockByID(l)
for l in self.locks]
Index: step.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/process/step.py,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -d -r1.83 -r1.84
--- step.py 17 Apr 2006 19:22:33 -0000 1.83
+++ step.py 24 Apr 2006 06:45:36 -0000 1.84
@@ -253,6 +253,7 @@
# orphan LogFile, cannot be subscribed to
self.log = builder.LogFile(None)
self.closeWhenFinished = True
+ self.updates = {}
log.msg("LoggedRemoteCommand.start", self.log)
return RemoteCommand.start(self)
@@ -276,6 +277,11 @@
rc = self.rc = update['rc']
log.msg("%s rc=%s" % (self, rc))
self.addHeader("program finished with exit code %d\n" % rc)
+ for k in update:
+ if k not in ('stdout', 'stderr', 'header', 'rc'):
+ if k not in self.updates:
+ self.updates[k] = []
+ self.updates[k].append(update[k])
def remoteComplete(self, maybeFailure):
if self.closeWhenFinished:
@@ -408,6 +414,14 @@
flunkOnFailure = False
warnOnWarnings = False
warnOnFailure = False
+
+ # 'parms' holds a list of all the parameters we care about, to allow
+ # users to instantiate a subclass of BuildStep with a mixture of
+ # arguments, some of which are for us, some of which are for the subclass
+ # (or a delegate of the subclass, like how ShellCommand delivers many
+ # arguments to the RemoteShellCommand that it creates). Such delegating
+ # subclasses will use this list to figure out which arguments are meant
+ # for us and which should be given to someone else.
parms = ['build', 'name', 'locks',
'haltOnFailure',
'flunkOnWarnings',
@@ -425,8 +439,8 @@
step_status = None
progress = None
- def __init__(self, **kwargs):
- self.build = kwargs['build'] # required
+ def __init__(self, build, **kwargs):
+ self.build = build
for p in self.__class__.parms:
if kwargs.has_key(p):
setattr(self, p, kwargs[p])
@@ -449,6 +463,12 @@
return sp
return None
+ def getProperty(self, propname):
+ return self.build.getProperty(propname)
+
+ def setProperty(self, propname, value):
+ self.build.setProperty(propname, value)
+
def startStep(self, remote):
"""Begin the step. This returns a Deferred that will fire when the
step finishes.
@@ -673,107 +693,32 @@
return d
-class ShellCommand(BuildStep):
- """I run a single shell command on the buildslave. I return FAILURE if
- the exit code of that command is non-zero, SUCCESS otherwise. To change
- this behavior, override my .evaluateCommand method.
-
- I create a single Log named 'log' which contains the output of the
- command. To create additional summary Logs, override my .createSummary
- method.
- The shell command I run (a list of argv strings) can be provided in
- several ways:
- - a class-level .command attribute
- - a command= parameter to my constructor (overrides .command)
- - set explicitly with my .setCommand() method (overrides both)
-
- """
+class LoggingBuildStep(BuildStep):
+ # This is an abstract base class, suitable for inheritance by all
+ # BuildSteps that invoke RemoteCommands which emit stdout/stderr messages
- name = "shell"
- description = None # set this to a list of short strings to override
- descriptionDone = None # alternate description when the step is complete
- command = None # set this to a command, or set in kwargs
progressMetrics = ['output']
- parms = BuildStep.parms + [
- 'description',
- 'descriptionDone',
- ]
-
- def __init__(self, **kwargs):
- # most of our arguments get passed through to the RemoteShellCommand
- # that we create, but first strip out the ones that we pass to
- # BuildStep (like haltOnFailure and friends)
- self.workdir = kwargs['workdir'] # required by RemoteShellCommand
- buildstep_kwargs = {}
- for k in kwargs.keys()[:]:
- if k in self.__class__.parms:
- buildstep_kwargs[k] = kwargs[k]
- del kwargs[k]
- BuildStep.__init__(self, **buildstep_kwargs)
- kwargs['command'] = kwargs.get('command', self.command)
- self.cmd = RemoteShellCommand(**kwargs)
-
- def setCommand(self, command):
- self.cmd.command = command
-
def describe(self, done=False):
- """Return a list of short strings to describe this step, for the
- status display. This uses the first few words of the shell command.
- You can replace this by setting .description in your subclass, or by
- overriding this method to describe the step better.
+ raise NotImplementedError("implement this in a subclass")
- @type done: boolean
- @param done: whether the command is complete or not, to improve the
- way the command is described. C{done=False} is used
- while the command is still running, so a single
- imperfect-tense verb is appropriate ('compiling',
- 'testing', ...) C{done=True} is used when the command
- has finished, and the default getText() method adds some
- text, so a simple noun is appropriate ('compile',
- 'tests' ...)
+ def startCommand(self, cmd, errorMessages=[]):
"""
-
- if done and self.descriptionDone is not None:
- return self.descriptionDone
- if self.description is not None:
- return self.description
-
- words = self.cmd.command
- if type(words) in types.StringTypes:
- words = words.split()
- if len(words) < 1:
- return ["???"]
- if len(words) == 1:
- return ["'%s'" % words[0]]
- if len(words) == 2:
- return ["'%s" % words[0], "%s'" % words[1]]
- return ["'%s" % words[0], "%s" % words[1], "...'"]
-
- def start(self, errorMessages=[]):
- # merge in anything from Build.slaveEnvironment . Earlier steps
- # (perhaps ones which compile libraries or sub-projects that need to
- # be referenced by later steps) can add keys to
- # self.build.slaveEnvironment to affect later steps.
- slaveEnv = self.build.slaveEnvironment
- if slaveEnv:
- if self.cmd.args['env'] is None:
- self.cmd.args['env'] = {}
- self.cmd.args['env'].update(slaveEnv)
- # note that each RemoteShellCommand gets its own copy of the
- # dictionary, so we shouldn't be affecting anyone but ourselves.
-
+ @param cmd: a suitable RemoteCommand which will be launched, with
+ all output being put into a LogFile named 'log'
+ """
+ self.cmd = cmd # so we can interrupt it
self.step_status.setColor("yellow")
self.step_status.setText(self.describe(False))
loog = self.addLog("log")
for em in errorMessages:
loog.addHeader(em)
log.msg("ShellCommand.start using log", loog)
- log.msg(" for cmd", self.cmd)
- self.cmd.useLog(loog, True)
+ log.msg(" for cmd", cmd)
+ cmd.useLog(loog, True)
loog.logProgressTo(self.progress, "output")
- d = self.runCommand(self.cmd)
+ d = self.runCommand(cmd)
d.addCallbacks(self._commandComplete, self.checkDisconnect)
d.addErrback(self.failed)
@@ -896,8 +841,168 @@
self.step_status.setText2(self.maybeGetText2(cmd, results))
+# -*- test-case-name: buildbot.test.test_properties -*-
+
+class _BuildPropertyDictionary:
+ def __init__(self, build):
+ self.build = build
+ def __getitem__(self, name):
+ p = self.build.getProperty(name)
+ if p is None:
+ p = ""
+ return p
+
+class WithProperties:
+ """This is a marker class, used in ShellCommand's command= argument to
+ indicate that we want to interpolate a build property.
+ """
+
+ def __init__(self, fmtstring, *args):
+ self.fmtstring = fmtstring
+ self.args = args
+
+ def render(self, build):
+ if self.args:
+ strings = []
+ for name in self.args:
+ p = build.getProperty(name)
+ if p is None:
+ p = ""
+ strings.append(p)
+ s = self.fmtstring % tuple(strings)
+ else:
+ s = self.fmtstring % _BuildPropertyDictionary(build)
+ return s
+
+class ShellCommand(LoggingBuildStep):
+ """I run a single shell command on the buildslave. I return FAILURE if
+ the exit code of that command is non-zero, SUCCESS otherwise. To change
+ this behavior, override my .evaluateCommand method.
+
+ I create a single Log named 'log' which contains the output of the
+ command. To create additional summary Logs, override my .createSummary
+ method.
+
+ The shell command I run (a list of argv strings) can be provided in
+ several ways:
+ - a class-level .command attribute
+ - a command= parameter to my constructor (overrides .command)
+ - set explicitly with my .setCommand() method (overrides both)
+
+ @ivar command: a list of argv strings (or WithProperties instances).
+ This will be used by start() to create a
+ RemoteShellCommand instance.
+
+ """
+
+ name = "shell"
+ description = None # set this to a list of short strings to override
+ descriptionDone = None # alternate description when the step is complete
+ command = None # set this to a command, or set in kwargs
+
+ def __init__(self, workdir,
+ description=None, descriptionDone=None,
+ command=None,
+ **kwargs):
+ # most of our arguments get passed through to the RemoteShellCommand
+ # that we create, but first strip out the ones that we pass to
+ # BuildStep (like haltOnFailure and friends), and a couple that we
+ # consume ourselves.
+ self.workdir = workdir # required by RemoteShellCommand
+ if description:
+ self.description = description
+ if descriptionDone:
+ self.descriptionDone = descriptionDone
+ if command:
+ self.command = command
+
+ # pull out the ones that BuildStep wants, then upcall
+ buildstep_kwargs = {}
+ for k in kwargs.keys()[:]:
+ if k in self.__class__.parms:
+ buildstep_kwargs[k] = kwargs[k]
+ del kwargs[k]
+ LoggingBuildStep.__init__(self, **buildstep_kwargs)
+
+ # everything left over goes to the RemoteShellCommand
+ kwargs['workdir'] = workdir # including a copy of 'workdir'
+ self.remote_kwargs = kwargs
+
+
+ def setCommand(self, command):
+ self.command = command
+
+ def describe(self, done=False):
+ """Return a list of short strings to describe this step, for the
+ status display. This uses the first few words of the shell command.
+ You can replace this by setting .description in your subclass, or by
+ overriding this method to describe the step better.
+
+ @type done: boolean
+ @param done: whether the command is complete or not, to improve the
+ way the command is described. C{done=False} is used
+ while the command is still running, so a single
+ imperfect-tense verb is appropriate ('compiling',
+ 'testing', ...) C{done=True} is used when the command
+ has finished, and the default getText() method adds some
+ text, so a simple noun is appropriate ('compile',
+ 'tests' ...)
+ """
+
+ if done and self.descriptionDone is not None:
+ return self.descriptionDone
+ if self.description is not None:
+ return self.description
+
+ words = self.command
+ # TODO: handle WithProperties here
+ if isinstance(words, types.StringTypes):
+ words = words.split()
+ if len(words) < 1:
+ return ["???"]
+ if len(words) == 1:
+ return ["'%s'" % words[0]]
+ if len(words) == 2:
+ return ["'%s" % words[0], "%s'" % words[1]]
+ return ["'%s" % words[0], "%s" % words[1], "...'"]
+
+ def _interpolateProperties(self, command):
+ # interpolate any build properties into our command
+ if not isinstance(command, (list, tuple)):
+ return
+ command_argv = []
+ for argv in command:
+ if isinstance(argv, WithProperties):
+ command_argv.append(argv.render(self.build))
+ else:
+ command_argv.append(argv)
+ return command_argv
+
+ def setupEnvironment(self, cmd):
+ # merge in anything from Build.slaveEnvironment . Earlier steps
+ # (perhaps ones which compile libraries or sub-projects that need to
+ # be referenced by later steps) can add keys to
+ # self.build.slaveEnvironment to affect later steps.
+ slaveEnv = self.build.slaveEnvironment
+ if slaveEnv:
+ if cmd.args['env'] is None:
+ cmd.args['env'] = {}
+ cmd.args['env'].update(slaveEnv)
+ # note that each RemoteShellCommand gets its own copy of the
+ # dictionary, so we shouldn't be affecting anyone but ourselves.
+
+ def start(self):
+ command = self._interpolateProperties(self.command)
+ # create the actual RemoteShellCommand instance now
+ kwargs = self.remote_kwargs
+ kwargs['command'] = self.command
+ cmd = RemoteShellCommand(**kwargs)
+ self.setupEnvironment(cmd)
+ self.startCommand(cmd)
+
+
+
-
class TreeSize(ShellCommand):
name = "treesize"
command = ["du", "-s", "."]
@@ -922,7 +1027,7 @@
return ["treesize", "unknown"]
-class Source(ShellCommand):
+class Source(LoggingBuildStep):
"""This is a base class to generate a source tree in the buildslave.
Each version control system has a specialized subclass, and is expected
to override __init__ and implement computeSourceRevision() and
@@ -1018,7 +1123,8 @@
"""
- BuildStep.__init__(self, **kwargs)
+ LoggingBuildStep.__init__(self, **kwargs)
+
assert mode in ("update", "copy", "clobber", "export")
if retry:
delay, repeats = retry
@@ -1042,11 +1148,13 @@
elif mode == "export":
description = ["exporting"]
descriptionDone = ["export"]
- # Initialize descriptions if not already set:
- if self.description is None:
- self.description = description
- if self.descriptionDone is None:
- self.descriptionDone = descriptionDone
+ self.description = description
+ self.descriptionDone = descriptionDone
+
+ def describe(self, done=False):
+ if done:
+ return self.descriptionDone
+ return self.description
def computeSourceRevision(self, changes):
"""Each subclass must implement this method to do something more
@@ -1083,6 +1191,13 @@
self.startVC(branch, revision, patch)
+ def commandComplete(self, cmd):
+ got_revision = None
+ if cmd.updates.has_key("got_revision"):
+ got_revision = cmd.updates["got_revision"][-1]
+ self.setProperty("got_revision", got_revision)
+
+
class CVS(Source):
"""I do CVS checkout/update operations.
@@ -1241,8 +1356,8 @@
self.args['tag'] = self.args['branch']
assert not self.args['patch'] # 0.5.0 slave can't do patch
- self.cmd = LoggedRemoteCommand("cvs", self.args)
- ShellCommand.start(self, warnings)
+ cmd = LoggedRemoteCommand("cvs", self.args)
+ self.startCommand(cmd, warnings)
class SVN(Source):
@@ -1363,8 +1478,8 @@
self.description.extend(revstuff)
self.descriptionDone.extend(revstuff)
- self.cmd = LoggedRemoteCommand("svn", self.args)
- ShellCommand.start(self, warnings)
+ cmd = LoggedRemoteCommand("svn", self.args)
+ self.startCommand(cmd, warnings)
class Darcs(Source):
@@ -1451,8 +1566,8 @@
self.description.extend(revstuff)
self.descriptionDone.extend(revstuff)
- self.cmd = LoggedRemoteCommand("darcs", self.args)
- ShellCommand.start(self)
+ cmd = LoggedRemoteCommand("darcs", self.args)
+ self.startCommand(cmd)
class Git(Source):
@@ -1477,8 +1592,8 @@
if not slavever:
raise BuildSlaveTooOldError("slave is too old, does not know "
"about git")
- self.cmd = LoggedRemoteCommand("git", self.args)
- ShellCommand.start(self)
+ cmd = LoggedRemoteCommand("git", self.args)
+ self.startCommand(cmd)
class Arch(Source):
@@ -1590,8 +1705,8 @@
self.description.extend(revstuff)
self.descriptionDone.extend(revstuff)
- self.cmd = LoggedRemoteCommand("arch", self.args)
- ShellCommand.start(self, warnings)
+ cmd = LoggedRemoteCommand("arch", self.args)
+ self.startCommand(cmd, warnings)
class Bazaar(Arch):
@@ -1636,8 +1751,8 @@
self.description.extend(revstuff)
self.descriptionDone.extend(revstuff)
- self.cmd = LoggedRemoteCommand("bazaar", self.args)
- ShellCommand.start(self, warnings)
+ cmd = LoggedRemoteCommand("bazaar", self.args)
+ self.startCommand(cmd, warnings)
class Mercurial(Source):
"""Check out a source tree from a mercurial repository 'repourl'."""
@@ -1693,8 +1808,8 @@
self.description.extend(revstuff)
self.descriptionDone.extend(revstuff)
- self.cmd = LoggedRemoteCommand("hg", self.args)
- ShellCommand.start(self)
+ cmd = LoggedRemoteCommand("hg", self.args)
+ self.startCommand(cmd)
class todo_P4(Source):
@@ -1714,8 +1829,8 @@
})
def startVC(self, branch, revision, patch):
- self.cmd = LoggedRemoteCommand("p4", self.args)
- ShellCommand.start(self)
+ cmd = LoggedRemoteCommand("p4", self.args)
+ self.startCommand(cmd)
class P4Sync(Source):
"""This is a partial solution for using a P4 source repository. You are
@@ -1755,8 +1870,8 @@
def startVC(self, branch, revision, patch):
slavever = self.slaveVersion("p4sync")
assert slavever, "slave is too old, does not know about p4"
- self.cmd = LoggedRemoteCommand("p4sync", self.args)
- ShellCommand.start(self)
+ cmd = LoggedRemoteCommand("p4sync", self.args)
+ self.startCommand(cmd)
class Dummy(BuildStep):
@@ -1808,8 +1923,7 @@
self.step_status.setColor("red")
self.finished(FAILURE)
-# subclasses from Shell Command to get the output reporting
-class RemoteDummy(ShellCommand):
+class RemoteDummy(LoggingBuildStep):
"""I am a dummy no-op step that runs on the remote side and
simply waits 5 seconds before completing with success.
See L{buildbot.slave.commands.DummyCommand}
@@ -1823,11 +1937,18 @@
@type timeout: int
@param timeout: the number of seconds to delay
"""
- BuildStep.__init__(self, **kwargs)
- args = {'timeout': timeout}
- self.cmd = LoggedRemoteCommand("dummy", args)
+ LoggingBuildStep.__init__(self, **kwargs)
+ self.timeout = timeout
self.description = ["remote", "delay", "%s secs" % timeout]
+ def describe(self, done=False):
+ return self.description
+
+ def start(self):
+ args = {'timeout': self.timeout}
+ cmd = LoggedRemoteCommand("dummy", args)
+ self.startCommand(cmd)
+
class Configure(ShellCommand):
name = "configure"
@@ -1835,7 +1956,7 @@
description = ["configuring"]
descriptionDone = ["configure"]
command = ["./configure"]
-
+
class Compile(ShellCommand):
name = "compile"
Index: step_twisted.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/process/step_twisted.py,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- step_twisted.py 17 Apr 2006 19:22:34 -0000 1.74
+++ step_twisted.py 24 Apr 2006 06:45:37 -0000 1.75
@@ -367,17 +367,8 @@
self.description = ["testing"]
self.descriptionDone = ["tests"]
- def start(self):
- # now that self.build.allFiles() is nailed down, finish building the
- # command
- if self.testChanges:
- for f in self.build.allFiles():
- if f.endswith(".py"):
- self.command.append("--testmodule=%s" % f)
- else:
- self.command.extend(self.tests)
- log.msg("RunUnitTests.start: command is", self.command)
- self.setCommand(self.command)
+ def setupEnvironment(self, cmd):
+ ShellCommand.setupEnvironment(self, cmd)
if self.testpath != None:
e = self.cmd.args['env']
if e is None:
@@ -399,6 +390,17 @@
# KeyError if args['env'] doesn't have ['PYTHONPATH']
# TypeError if args is None
pass
+
+ def start(self):
+ # now that self.build.allFiles() is nailed down, finish building the
+ # command
+ if self.testChanges:
+ for f in self.build.allFiles():
+ if f.endswith(".py"):
+ self.command.append("--testmodule=%s" % f)
+ else:
+ self.command.extend(self.tests)
+ log.msg("Trial.start: command is", self.command)
ShellCommand.start(self)
def _commandComplete(self, cmd):
More information about the Commits
mailing list