version bump to 2.1.0 (bug 110388) with a lot of ebuild changes to fix part of bug...
authorMarien Zwart <marienz@gentoo.org>
Wed, 23 Nov 2005 17:39:01 +0000 (17:39 +0000)
committerMarien Zwart <marienz@gentoo.org>
Wed, 23 Nov 2005 17:39:01 +0000 (17:39 +0000)
Package-Manager: portage-2.0.53_rc7

dev-python/twisted/ChangeLog
dev-python/twisted/files/digest-twisted-2.1.0 [new file with mode: 0644]
dev-python/twisted/files/twistd.conf [new file with mode: 0644]
dev-python/twisted/files/twistd.init [new file with mode: 0644]
dev-python/twisted/files/twisted-2.1.0-trial-tests.patch [new file with mode: 0644]
dev-python/twisted/files/twisted-2.1.0-trial-tests2.patch [new file with mode: 0644]
dev-python/twisted/files/twisted-2.1.0-zsh-head.patch [new file with mode: 0644]
dev-python/twisted/metadata.xml
dev-python/twisted/twisted-2.1.0.ebuild [new file with mode: 0644]

index c3465b62fb233a4d7764dac3df5947efe5e09294..c26b48ca6f75fc99d4551e2154d90f01d7edb0dc 100644 (file)
@@ -1,6 +1,16 @@
 # ChangeLog for dev-python/twisted
 # Copyright 2002-2005 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/dev-python/twisted/ChangeLog,v 1.51 2005/11/05 21:42:52 ferdy Exp $
+# $Header: /var/cvsroot/gentoo-x86/dev-python/twisted/ChangeLog,v 1.52 2005/11/23 17:39:00 marienz Exp $
+
+*twisted-2.1.0 (23 Nov 2005)
+
+  23 Nov 2005; Marien Zwart <marienz@gentoo.org>
+  +files/twisted-2.1.0-trial-tests.patch,
+  +files/twisted-2.1.0-trial-tests2.patch,
+  +files/twisted-2.1.0-zsh-head.patch, +files/twistd.conf,
+  +files/twistd.init, metadata.xml, +twisted-2.1.0.ebuild:
+  version bump to 2.1.0 to fix bug 110388, and a lot of ebuild changes to fix
+  part of bug 80639. Taking over maintainership.
 
   05 Nov 2005; Fernando J. Pereda <ferdy@gentoo.org> twisted-2.0.0.ebuild:
   marked ~alpha wrt bug #110575
diff --git a/dev-python/twisted/files/digest-twisted-2.1.0 b/dev-python/twisted/files/digest-twisted-2.1.0
new file mode 100644 (file)
index 0000000..a164b64
--- /dev/null
@@ -0,0 +1 @@
+MD5 0aa4b877c4e34750e52c9f0b93959913 Twisted-2.1.0.tar.bz2 1078044
diff --git a/dev-python/twisted/files/twistd.conf b/dev-python/twisted/files/twistd.conf
new file mode 100644 (file)
index 0000000..53788cd
--- /dev/null
@@ -0,0 +1,7 @@
+
+# These are passed to twistd.
+# TWISTD_OPTS="--no_save --logfile=/var/log/twistd -y /etc/twistd.tac"
+# TWISTD_OPTS="--no_save --logfile=/var/log/twistd -f /etc/twistd.tap"
+
+# Make any additions to PYTHONPATH the twistd needs here.
+# PYTHONPATH="/path/to/extra/python/modules"
diff --git a/dev-python/twisted/files/twistd.init b/dev-python/twisted/files/twistd.init
new file mode 100644 (file)
index 0000000..0f79667
--- /dev/null
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+
+depend() {
+       need net
+}
+
+start() {
+       if [[ -z "${TWISTD_OPTS}" ]]; then
+               eerror "TWISTD_OPTS is not set!"
+               eerror "You need to configure twistd in /etc/conf.d/twistd."
+               return 1
+       fi
+       ebegin "Starting twistd"
+       start-stop-daemon --start --quiet --pidfile /var/run/twistd.pid \
+               --exec /usr/bin/twistd -- --pidfile /var/run/twistd.pid \
+                       ${TWISTD_OPTS}
+       eend $? "Failed to start twistd"
+}
+
+stop() {
+       ebegin "Stopping twistd"
+       start-stop-daemon --stop --quiet --pidfile /var/run/twistd.pid 
+       eend $? "Failed to stop twistd"
+}
diff --git a/dev-python/twisted/files/twisted-2.1.0-trial-tests.patch b/dev-python/twisted/files/twisted-2.1.0-trial-tests.patch
new file mode 100644 (file)
index 0000000..892b066
--- /dev/null
@@ -0,0 +1,359 @@
+Index: Twisted/twisted/trial/test/test_output.py
+===================================================================
+--- Twisted/twisted/trial/test/test_output.py  (revision 14794)
++++ Twisted/twisted/trial/test/test_output.py  (revision 14797)
+@@ -1,17 +1,14 @@
+ from twisted.trial import unittest
++from twisted.trial.test import packages
+ from twisted.python import util
+ from twisted.internet import utils, reactor, interfaces
+-import os, re
++import os, re, sys
+ 
+-def getTrialPath():
+-    fp = os.path.abspath(unittest.__file__)
+-    trialPath = fp.split(os.sep)[:-3] + ['bin', 'trial']
+-    return os.path.normpath(os.path.join(fp, os.pardir, os.pardir,
+-                                         os.pardir, 'bin', 'trial'))
+ 
+-
+ def runTrialWithEnv(env, *args):
+-    return utils.getProcessOutput(getTrialPath(), args=args, errortoo=1,
++    params = [ '-c', 'from twisted.scripts.trial import run; run()' ]
++    params.extend(args)
++    return utils.getProcessOutput(sys.executable, args=params, errortoo=1,
+                                   env=env)
+ 
+ 
+@@ -27,16 +24,14 @@
+     ## shell out for this stuff.
+ 
+     debug = False
++    parent = "_testImportErrors"
+ 
+-    def _getMockEnvironment(self):
+-        path = self._getMockPath()
+-        env = os.environ.copy()
+-        if not env.has_key('PYTHONPATH'):
+-            env['PYTHONPATH'] = path
+-        else:
+-            env['PYTHONPATH'] += os.pathsep + path
+-        return env
++    def setUp(self):
++        packages.setUp(self.parent)
+ 
++    def tearDown(self):
++        packages.tearDown(self.parent)
++
+     def _runTrial(self, env, *args):
+         d = runTrialWithEnv(env, *args)
+         if self.debug:
+@@ -44,42 +39,29 @@
+         return d
+         
+     def runTrial(self, *args):
+-        return self._runTrial(self._getMockEnvironment(), *args)
++        env = os.environ.copy()
++        env['PYTHONPATH'] = os.pathsep.join([self.parent] + sys.path)
++        return self._runTrial(env, *args)
+ 
+     def runTrialPure(self, *args):
+-        return self._runTrial(os.environ, *args)
+-
++        env = os.environ.copy()
++        env['PYTHONPATH'] = os.pathsep.join(sys.path)
++        return self._runTrial(env, *args)
++ 
+     def _print(self, stuff):
+         print stuff
+         return stuff
+ 
+-    def _getMockPath(self):
+-        from twisted.trial import test
+-        return os.path.normpath(util.sibpath(test.__file__, 'foo'))
+-
+     def failUnlessIn(self, container, containee, *args, **kwargs):
+         # redefined to be useful in callbacks
+-        unittest.TestCase.failUnlessSubstring(self, containee, container,
+-                                              *args, **kwargs)
++        self.failUnlessSubstring(containee, container, *args, **kwargs)
+         return container
+ 
+     def failIfIn(self, container, containee, *args, **kwargs):
+         # redefined to be useful in callbacks
+-        unittest.TestCase.failIfSubstring(self, containee, container,
+-                                          *args, **kwargs)
++        self.failIfSubstring(containee, container, *args, **kwargs)
+         return container
+ 
+-    def test_trialFound(self):
+-        self.failUnless(os.path.isfile(getTrialPath()), getTrialPath())
+-
+-    def test_mockPathCorrect(self):
+-        # This doesn't test a feature.  This tests that we are accurately finding
+-        # the directory with all of the mock modules and packages.
+-        path = self._getMockPath()
+-        self.failUnless(path.endswith('twisted/trial/test/foo'), 
+-                        'got path: %r' % path)
+-        self.failUnless(os.path.isdir(path))
+-
+     def test_trialRun(self):
+         d = self.runTrial('--help')
+         d.addCallback(self.failUnless, 'trial')
+@@ -155,7 +137,7 @@
+         return d
+ 
+     def test_nonRecurseImportErrors(self):
+-        d = self.runTrial('package2')
++        d = self.runTrial('-N', 'package2')
+         d.addCallback(self.failUnlessIn, 'IMPORT ERROR')
+         d.addCallback(self.failUnlessIn, "No module named frotz")
+         d.addCallback(self.failIfIn, '<module')
+@@ -170,8 +152,8 @@
+         return d
+     
+     def test_filename(self):
+-        path = self._getMockPath()
+-        d = self.runTrialPure(os.path.join(path, 'package/test_module.py'))
++        d = self.runTrialPure(os.path.join(self.parent,
++                                           'package', 'test_module.py'))
+         d.addCallback(self.failIfIn, 'IMPORT ERROR')
+         d.addCallback(self.failIfIn, 'IOError')
+         d.addCallback(self.failUnlessIn, 'OK')
+@@ -180,8 +162,8 @@
+ 
+     def test_dosFile(self):
+         ## XXX -- not really an output test, more of a script test
+-        path = self._getMockPath()
+-        d = self.runTrialPure(os.path.join(path, 'package/test_dos_module.py'))
++        d = self.runTrialPure(os.path.join(self.parent,
++                                           'package', 'test_dos_module.py'))
+         d.addCallback(self.failIfIn, 'IMPORT ERROR')
+         d.addCallback(self.failIfIn, 'IOError')
+         d.addCallback(self.failUnlessIn, 'OK')
+Index: Twisted/twisted/trial/test/test_loader.py
+===================================================================
+--- Twisted/twisted/trial/test/test_loader.py  (revision 14794)
++++ Twisted/twisted/trial/test/test_loader.py  (revision 14797)
+@@ -1,13 +1,18 @@
+ import sys, os
+ from twisted.python import util
++from twisted.trial.test import packages
+ from twisted.trial import unittest
+ from twisted.trial import runner
+ 
+ 
+ class FinderTest(unittest.TestCase):
+     def setUp(self):
++        packages.setUp()
+         self.loader = runner.TestLoader()
+ 
++    def tearDown(self):
++        packages.tearDown()
++
+     def test_findPackage(self):
+         sample1 = self.loader.findByName('twisted')
+         import twisted as sample2
+@@ -45,7 +50,12 @@
+         
+         
+ class FileTest(unittest.TestCase):
+-    samplePath = util.sibpath(__file__, 'foo')
++    parent = '_test_loader_FileTest'
++    
++    def setUp(self):
++        self.oldPath = sys.path[:]
++        sys.path.append(self.parent)
++        packages.setUp(self.parent)
+ 
+     def tearDown(self):
+         importedModules = ['goodpackage',
+@@ -55,6 +65,8 @@
+         for moduleName in importedModules:
+             if sys.modules.has_key(moduleName):
+                 del sys.modules[moduleName]
++        packages.tearDown(self.parent)
++        sys.path = self.oldPath
+ 
+     def test_notFile(self):
+         self.failUnlessRaises(ValueError,
+@@ -66,39 +78,33 @@
+         self.failUnlessEqual(sample2, sample1)
+ 
+     def test_moduleNotInPath(self):
+-        sample1 = runner.filenameToModule(os.path.join(self.samplePath,
++        sys.path, newPath = self.oldPath, sys.path
++        sample1 = runner.filenameToModule(os.path.join(self.parent,
+                                                        'goodpackage',
+                                                        'test_sample.py'))
+-        sys.path.append(self.samplePath)
++        sys.path = newPath
+         from goodpackage import test_sample as sample2
+-        try:
+-            self.failUnlessEqual(os.path.splitext(sample2.__file__)[0],
+-                                 os.path.splitext(sample1.__file__)[0])
+-        finally:
+-            sys.path.remove(self.samplePath)
++        self.failUnlessEqual(os.path.splitext(sample2.__file__)[0],
++                             os.path.splitext(sample1.__file__)[0])
+ 
+     def test_packageInPath(self):
+-        sys.path.append(self.samplePath)
+-        try:
+-            package1 = runner.filenameToModule(os.path.join(self.samplePath,
+-                                                            'goodpackage'))
+-            import goodpackage
+-            self.failUnlessEqual(goodpackage, package1)
+-        finally:
+-            sys.path.remove(self.samplePath)
++        package1 = runner.filenameToModule(os.path.join(self.parent,
++                                                        'goodpackage'))
++        import goodpackage
++        self.failUnlessEqual(goodpackage, package1)
+ 
+     def test_packageNotInPath(self):
+-        package1 = runner.filenameToModule(os.path.join(self.samplePath,
++        sys.path, newPath = self.oldPath, sys.path
++        package1 = runner.filenameToModule(os.path.join(self.parent,
+                                                         'goodpackage'))
+-        sys.path.append(self.samplePath)
++        sys.path = newPath
+         import goodpackage
+-        sys.path.remove(self.samplePath)
+         self.failUnlessEqual(os.path.splitext(goodpackage.__file__)[0],
+                              os.path.splitext(package1.__file__)[0])
+ 
+     def test_directoryNotPackage(self):
+         self.failUnlessRaises(ValueError, runner.filenameToModule,
+-                              self.samplePath)
++                              util.sibpath(__file__, 'directory'))
+ 
+     def test_filenameNotPython(self):
+         self.failUnlessRaises(ValueError, runner.filenameToModule,
+@@ -120,14 +126,17 @@
+     ##   * could be a file / directory
+     ##   * could be name of a python object
+ 
+-    samplePath = util.sibpath(__file__, 'foo')
++    parent = '_test_loader'
+     
+     def setUp(self):
+         self.loader = runner.TestLoader()
+-        sys.path.append(self.samplePath)
++        self.oldPath = sys.path[:]
++        sys.path.append(self.parent)
++        packages.setUp(self.parent)
+ 
+     def tearDown(self):
+-        sys.path.remove(self.samplePath)
++        sys.path = self.oldPath
++        packages.tearDown(self.parent)
+ 
+     def test_loadMethod(self):
+         import sample
+Index: Twisted/twisted/trial/test/packages.py
+===================================================================
+--- Twisted/twisted/trial/test/packages.py     (revision 0)
++++ Twisted/twisted/trial/test/packages.py     (revision 14797)
+@@ -0,0 +1,101 @@
++import os, shutil
++
++testModule = """
++from twisted.trial import unittest
++
++class FooTest(unittest.TestCase):
++    def testFoo(self):
++        pass
++"""
++
++dosModule = testModule.replace('\n', '\r\n')
++
++
++testSample = """
++'''This module is used by test_loader to test the Trial test loading
++functionality. Do NOT change the number of tests in this module.
++Do NOT change the names the tests in this module.
++'''
++
++import unittest as pyunit
++from twisted.trial import unittest
++
++class FooTest(unittest.TestCase):
++    def test_foo(self):
++        pass
++
++    def test_bar(self):
++        pass
++
++
++class PyunitTest(pyunit.TestCase):
++    def test_foo(self):
++        pass
++
++    def test_bar(self):
++        pass
++
++
++class NotATest(object):
++    def test_foo(self):
++        pass
++
++
++class AlphabetTest(unittest.TestCase):
++    def test_a(self):
++        pass
++
++    def test_b(self):
++        pass
++
++    def test_c(self):
++        pass
++"""
++
++
++files = [
++    ('badpackage/__init__.py', 'frotz\n'),
++    ('badpackage/test_module.py', ''),
++    ('package2/__init__.py', ''),
++    ('package2/test_module.py', 'import frotz\n'),
++    ('package/__init__.py', ''),
++    ('package/frotz.py', 'frotz\n'),
++    ('package/test_bad_module.py', 'raise ZeroDivisionError("fake error")'),
++    ('package/test_dos_module.py', dosModule),
++    ('package/test_import_module.py', 'import frotz'),
++    ('package/test_module.py', testModule),
++    ('goodpackage/__init__.py', ''),
++    ('goodpackage/test_sample.py', testSample),
++    ('goodpackage/sub/__init__.py', ''),
++    ('goodpackage/sub/test_sample.py', testSample)
++    ]
++
++
++def createFiles(files, parentDir='.'):
++    for filename, contents in files:
++        filename = os.path.join(parentDir, filename)
++        _createDirectory(filename)
++        fd = open(filename, 'w')
++        fd.write(contents)
++        fd.close()
++
++def _createDirectory(filename):
++    directory = os.path.dirname(filename)
++    if not os.path.exists(directory):
++        os.makedirs(directory)
++
++def setUp(parentDir='.'):
++    createFiles(files, parentDir)
++
++def removeFiles(files, parentDir):
++    directories = {}
++    for filename, _ in files:
++        directories[os.path.dirname(os.path.join(parentDir, filename))] = True
++    dirs = directories.keys()
++    dirs.sort()
++    dirs.reverse()
++    for directory in dirs:
++        shutil.rmtree(directory)
++
++def tearDown(parentDir='.'):
++    removeFiles(files, parentDir)
diff --git a/dev-python/twisted/files/twisted-2.1.0-trial-tests2.patch b/dev-python/twisted/files/twisted-2.1.0-trial-tests2.patch
new file mode 100644 (file)
index 0000000..357586b
--- /dev/null
@@ -0,0 +1,21 @@
+Index: twisted/trial/test/test_script.py
+===================================================================
+--- twisted/trial/test/test_script.py  (revision 14825)
++++ twisted/trial/test/test_script.py  (revision 14826)
+@@ -63,12 +63,14 @@
+             raise unittest.SkipTest("This test runs an external process. "
+                                     "This reactor doesn't support it.")
+         import test_output, os
+-        d = test_output.runTrialWithEnv(os.environ, '--testmodule',
++        env = os.environ.copy()
++        env['PYTHONPATH'] = os.pathsep.join(sys.path)
++        d = test_output.runTrialWithEnv(env, '--testmodule',
+                                         sibpath('moduletest.py'))
+         d.addCallback(lambda x : self.assertSubstring(
+             'twisted.trial.test.test_test_visitor', x))
+         return d
+-                             
++        
+     def test_parseLocalVariable(self):
+         declaration = '-*- test-case-name: twisted.trial.test.test_trial -*-'
+         localVars = trial._parseLocalVariables(declaration)
diff --git a/dev-python/twisted/files/twisted-2.1.0-zsh-head.patch b/dev-python/twisted/files/twisted-2.1.0-zsh-head.patch
new file mode 100644 (file)
index 0000000..236610a
--- /dev/null
@@ -0,0 +1,13 @@
+Index: twisted/python/_twisted_zsh_stub
+===================================================================
+--- twisted/python/_twisted_zsh_stub   (revision 14988)
++++ twisted/python/_twisted_zsh_stub   (working copy)
+@@ -30,7 +30,7 @@
+ 
+ function load_twisted_completions() {
+     [[ -z $commands[twistd] ]] && echo 'ERROR: test command "twistd" not found in path' && return 1
+-    shebang=$(head -1 $commands[twistd])
++    shebang=$(head -n1 $commands[twistd])
+     [[ $shebang != \#\!* ]] && echo 'ERROR: invalid shebang line for test script "twistd"' && return 1
+     PYTHON=$shebang[3,-1]
+ 
index 37d1f8e02e49af146ec78b16b8bcabf59c6c42b4..418c76a8dc779399450ba2cb16df66e1f7d86792 100644 (file)
@@ -2,5 +2,11 @@
 <!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
 <pkgmetadata>
 <herd>python</herd>
-<maintainer><email>lordvan@gentoo.org</email></maintainer>
+<maintainer><email>marienz@gentoo.org</email></maintainer>
+<longdescription>
+Twisted is an asynchronous networking framework written in Python,
+supporting TCP, UDP, multicast, SSL/TLS, serial communication and
+more. It is used by most of the servers, clients and protocols that
+are part of other Twisted projects.
+</longdescription>
 </pkgmetadata>
diff --git a/dev-python/twisted/twisted-2.1.0.ebuild b/dev-python/twisted/twisted-2.1.0.ebuild
new file mode 100644 (file)
index 0000000..11e5068
--- /dev/null
@@ -0,0 +1,109 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-python/twisted/twisted-2.1.0.ebuild,v 1.1 2005/11/23 17:39:01 marienz Exp $
+
+inherit eutils distutils versionator
+
+MY_P=Twisted-${PV}
+
+DESCRIPTION="An asynchronous networking framework written in Python"
+HOMEPAGE="http://www.twistedmatrix.com/"
+SRC_URI="http://tmrc.mit.edu/mirror/twisted/Twisted/$(get_version_component_range 1-2)/${MY_P}.tar.bz2"
+
+LICENSE="MIT"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~ppc ~sparc ~x86"
+IUSE="gtk serial crypt"
+
+DEPEND=">=dev-lang/python-2.2
+       >=net-zope/zopeinterface-3.0.1
+       serial? ( dev-python/pyserial )
+       crypt? ( >=dev-python/pyopenssl-0.5.1 )
+       gtk? ( >=dev-python/pygtk-1.99 )"
+
+S="${WORKDIR}/${MY_P}"
+
+DOCS="CREDITS INSTALL NEWS README"
+
+src_unpack() {
+       unpack ${A}
+       cd "${S}"
+       epatch "${FILESDIR}/${P}-trial-tests.patch"
+       epatch "${FILESDIR}/${P}-trial-tests2.patch"
+       epatch "${FILESDIR}/${P}-zsh-head.patch"
+}
+
+src_install() {
+       distutils_src_install
+
+       # get rid of this to prevent collision-protect from killing us. it
+       # is regenerated in pkg_postinst.
+       rm "${D}/usr/$(get_libdir)"/python*/site-packages/twisted/plugins/dropin.cache
+
+       # weird pattern to avoid installing the index.xhtml page
+       doman doc/man/*.?
+       insinto /usr/share/doc/${PF}
+       doins -r $(find doc -mindepth 1 -maxdepth 1 -not -name man)
+
+       # workaround for a possible portage bug
+       mkdir -p "${D}/etc/conf.d/"
+       newconfd "${FILESDIR}/twistd.conf" twistd
+       newinitd "${FILESDIR}/twistd.init" twistd
+
+       # zsh completion
+       insinto /usr/share/zsh/site-functions/
+       doins twisted/python/_twisted_zsh_stub
+}
+
+update_plugin_cache() {
+       python_version
+       local tpath="${ROOT}usr/$(get_libdir)/python${PYVER}/site-packages/twisted"
+       # we have to remove the cache or removed plugins won't be removed
+       # from the cache (http://twistedmatrix.com/bugs/issue926)
+       [[ -e "${tpath}/plugins/dropin.cache" ]] && rm -f "${tpath}/plugins/dropin.cache"
+       if [[ -e "${tpath}/plugin.py" ]]; then
+               # twisted is still installed, update.
+           # we have to use getPlugIns here for <=twisted-2.0.1 compatibility
+               einfo "Regenerating plugin cache"
+               python -c "from twisted.plugin import IPlugin, getPlugIns;list(getPlugIns(IPlugin))"
+       fi
+}
+
+pkg_postinst() {
+       distutils_pkg_postinst
+       update_plugin_cache
+       einfo
+       einfo "If you upgraded from twisted 1.3 or earlier you may want to"
+       einfo
+       einfo " # emerge twisted-sumo"
+       einfo
+       einfo "to get all of the packages back."
+       einfo
+}
+
+pkg_postrm() {
+       distutils_pkg_postrm
+       update_plugin_cache
+}
+
+src_test() {
+       python_version
+
+       if has_version ">=dev-lang/python-2.3"; then
+               "${python}" setup.py install --root="${T}/tests" --no-compile || die
+       else
+               "${python}" setup.py install --root="${T}/tests" || die
+       fi
+
+       cd "${T}/tests/usr/$(get_libdir)/python${PYVER}/site-packages/" || die
+
+       # prevent it from pulling in plugins from already installed
+       # twisted packages
+       rm twisted/plugins/__init__.py || die
+
+       # an empty file doesn't work because the tests check for
+       # docstrings in all packages
+       echo "'''plugins stub'''" > twisted/plugins/__init__.py || die
+
+       "${T}"/tests/usr/bin/trial twisted || die "trial failed"
+}