aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py')
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py2598
1 files changed, 0 insertions, 2598 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py
deleted file mode 100755
index a4f868c7..00000000
--- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/test/test_release.py
+++ /dev/null
@@ -1,2598 +0,0 @@
-# Copyright (c) Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Tests for L{twisted.python.release} and L{twisted.python._release}.
-
-All of these tests are skipped on platforms other than Linux, as the release is
-only ever performed on Linux.
-"""
-
-
-import warnings
-import operator
-import os, sys, signal
-from StringIO import StringIO
-import tarfile
-from xml.dom import minidom as dom
-
-from datetime import date
-
-from twisted.trial.unittest import TestCase
-
-from twisted.python.compat import execfile, set
-from twisted.python.procutils import which
-from twisted.python import release
-from twisted.python.filepath import FilePath
-from twisted.python.versions import Version
-from twisted.python._release import _changeVersionInFile, getNextVersion
-from twisted.python._release import findTwistedProjects, replaceInFile
-from twisted.python._release import replaceProjectVersion
-from twisted.python._release import updateTwistedVersionInformation, Project
-from twisted.python._release import generateVersionFileData
-from twisted.python._release import changeAllProjectVersions
-from twisted.python._release import VERSION_OFFSET, DocBuilder, ManBuilder
-from twisted.python._release import NoDocumentsFound, filePathDelta
-from twisted.python._release import CommandFailed, BookBuilder
-from twisted.python._release import DistributionBuilder, APIBuilder
-from twisted.python._release import BuildAPIDocsScript
-from twisted.python._release import buildAllTarballs, runCommand
-from twisted.python._release import UncleanWorkingDirectory, NotWorkingDirectory
-from twisted.python._release import ChangeVersionsScript, BuildTarballsScript
-from twisted.python._release import NewsBuilder
-
-if os.name != 'posix':
- skip = "Release toolchain only supported on POSIX."
-else:
- skip = None
-
-
-# Check a bunch of dependencies to skip tests if necessary.
-try:
- from twisted.lore.scripts import lore
-except ImportError:
- loreSkip = "Lore is not present."
-else:
- loreSkip = skip
-
-
-try:
- import pydoctor.driver
- # it might not be installed, or it might use syntax not available in
- # this version of Python.
-except (ImportError, SyntaxError):
- pydoctorSkip = "Pydoctor is not present."
-else:
- if getattr(pydoctor, "version_info", (0,)) < (0, 1):
- pydoctorSkip = "Pydoctor is too old."
- else:
- pydoctorSkip = skip
-
-
-if which("latex") and which("dvips") and which("ps2pdf13"):
- latexSkip = skip
-else:
- latexSkip = "LaTeX is not available."
-
-
-if which("svn") and which("svnadmin"):
- svnSkip = skip
-else:
- svnSkip = "svn or svnadmin is not present."
-
-
-def genVersion(*args, **kwargs):
- """
- A convenience for generating _version.py data.
-
- @param args: Arguments to pass to L{Version}.
- @param kwargs: Keyword arguments to pass to L{Version}.
- """
- return generateVersionFileData(Version(*args, **kwargs))
-
-
-
-class StructureAssertingMixin(object):
- """
- A mixin for L{TestCase} subclasses which provides some methods for asserting
- the structure and contents of directories and files on the filesystem.
- """
- def createStructure(self, root, dirDict):
- """
- Create a set of directories and files given a dict defining their
- structure.
-
- @param root: The directory in which to create the structure. It must
- already exist.
- @type root: L{FilePath}
-
- @param dirDict: The dict defining the structure. Keys should be strings
- naming files, values should be strings describing file contents OR
- dicts describing subdirectories. All files are written in binary
- mode. Any string values are assumed to describe text files and
- will have their newlines replaced with the platform-native newline
- convention. For example::
-
- {"foofile": "foocontents",
- "bardir": {"barfile": "bar\ncontents"}}
- @type dirDict: C{dict}
- """
- for x in dirDict:
- child = root.child(x)
- if isinstance(dirDict[x], dict):
- child.createDirectory()
- self.createStructure(child, dirDict[x])
- else:
- child.setContent(dirDict[x].replace('\n', os.linesep))
-
- def assertStructure(self, root, dirDict):
- """
- Assert that a directory is equivalent to one described by a dict.
-
- @param root: The filesystem directory to compare.
- @type root: L{FilePath}
- @param dirDict: The dict that should describe the contents of the
- directory. It should be the same structure as the C{dirDict}
- parameter to L{createStructure}.
- @type dirDict: C{dict}
- """
- children = [x.basename() for x in root.children()]
- for x in dirDict:
- child = root.child(x)
- if isinstance(dirDict[x], dict):
- self.assertTrue(child.isdir(), "%s is not a dir!"
- % (child.path,))
- self.assertStructure(child, dirDict[x])
- else:
- a = child.getContent().replace(os.linesep, '\n')
- self.assertEqual(a, dirDict[x], child.path)
- children.remove(x)
- if children:
- self.fail("There were extra children in %s: %s"
- % (root.path, children))
-
-
- def assertExtractedStructure(self, outputFile, dirDict):
- """
- Assert that a tarfile content is equivalent to one described by a dict.
-
- @param outputFile: The tar file built by L{DistributionBuilder}.
- @type outputFile: L{FilePath}.
- @param dirDict: The dict that should describe the contents of the
- directory. It should be the same structure as the C{dirDict}
- parameter to L{createStructure}.
- @type dirDict: C{dict}
- """
- tarFile = tarfile.TarFile.open(outputFile.path, "r:bz2")
- extracted = FilePath(self.mktemp())
- extracted.createDirectory()
- for info in tarFile:
- tarFile.extract(info, path=extracted.path)
- self.assertStructure(extracted.children()[0], dirDict)
-
-
-
-class ChangeVersionTest(TestCase, StructureAssertingMixin):
- """
- Twisted has the ability to change versions.
- """
-
- def makeFile(self, relativePath, content):
- """
- Create a file with the given content relative to a temporary directory.
-
- @param relativePath: The basename of the file to create.
- @param content: The content that the file will have.
- @return: The filename.
- """
- baseDirectory = FilePath(self.mktemp())
- directory, filename = os.path.split(relativePath)
- directory = baseDirectory.preauthChild(directory)
- directory.makedirs()
- file = directory.child(filename)
- directory.child(filename).setContent(content)
- return file
-
-
- def test_getNextVersion(self):
- """
- When calculating the next version to release when a release is
- happening in the same year as the last release, the minor version
- number is incremented.
- """
- now = date.today()
- major = now.year - VERSION_OFFSET
- version = Version("twisted", major, 9, 0)
- self.assertEqual(getNextVersion(version, now=now),
- Version("twisted", major, 10, 0))
-
-
- def test_getNextVersionAfterYearChange(self):
- """
- When calculating the next version to release when a release is
- happening in a later year, the minor version number is reset to 0.
- """
- now = date.today()
- major = now.year - VERSION_OFFSET
- version = Version("twisted", major - 1, 9, 0)
- self.assertEqual(getNextVersion(version, now=now),
- Version("twisted", major, 0, 0))
-
-
- def test_changeVersionInFile(self):
- """
- _changeVersionInFile replaces the old version information in a file
- with the given new version information.
- """
- # The version numbers are arbitrary, the name is only kind of
- # arbitrary.
- packageName = 'foo'
- oldVersion = Version(packageName, 2, 5, 0)
- file = self.makeFile('README',
- "Hello and welcome to %s." % oldVersion.base())
-
- newVersion = Version(packageName, 7, 6, 0)
- _changeVersionInFile(oldVersion, newVersion, file.path)
-
- self.assertEqual(file.getContent(),
- "Hello and welcome to %s." % newVersion.base())
-
-
- def test_changeAllProjectVersions(self):
- """
- L{changeAllProjectVersions} changes all version numbers in _version.py
- and README files for all projects as well as in the the top-level
- README file.
- """
- root = FilePath(self.mktemp())
- root.createDirectory()
- structure = {
- "README": "Hi this is 1.0.0.",
- "twisted": {
- "topfiles": {
- "README": "Hi this is 1.0.0"},
- "_version.py":
- genVersion("twisted", 1, 0, 0),
- "web": {
- "topfiles": {
- "README": "Hi this is 1.0.0"},
- "_version.py": genVersion("twisted.web", 1, 0, 0)
- }}}
- self.createStructure(root, structure)
- changeAllProjectVersions(root, Version("lol", 1, 0, 2))
- outStructure = {
- "README": "Hi this is 1.0.2.",
- "twisted": {
- "topfiles": {
- "README": "Hi this is 1.0.2"},
- "_version.py":
- genVersion("twisted", 1, 0, 2),
- "web": {
- "topfiles": {
- "README": "Hi this is 1.0.2"},
- "_version.py": genVersion("twisted.web", 1, 0, 2),
- }}}
- self.assertStructure(root, outStructure)
-
-
- def test_changeAllProjectVersionsPreRelease(self):
- """
- L{changeAllProjectVersions} changes all version numbers in _version.py
- and README files for all projects as well as in the the top-level
- README file. If the old version was a pre-release, it will change the
- version in NEWS files as well.
- """
- root = FilePath(self.mktemp())
- root.createDirectory()
- coreNews = ("Twisted Core 1.0.0 (2009-12-25)\n"
- "===============================\n"
- "\n")
- webNews = ("Twisted Web 1.0.0pre1 (2009-12-25)\n"
- "==================================\n"
- "\n")
- structure = {
- "README": "Hi this is 1.0.0.",
- "NEWS": coreNews + webNews,
- "twisted": {
- "topfiles": {
- "README": "Hi this is 1.0.0",
- "NEWS": coreNews},
- "_version.py":
- genVersion("twisted", 1, 0, 0),
- "web": {
- "topfiles": {
- "README": "Hi this is 1.0.0pre1",
- "NEWS": webNews},
- "_version.py": genVersion("twisted.web", 1, 0, 0, 1)
- }}}
- self.createStructure(root, structure)
- changeAllProjectVersions(root, Version("lol", 1, 0, 2), '2010-01-01')
- coreNews = (
- "Twisted Core 1.0.0 (2009-12-25)\n"
- "===============================\n"
- "\n")
- webNews = ("Twisted Web 1.0.2 (2010-01-01)\n"
- "==============================\n"
- "\n")
- outStructure = {
- "README": "Hi this is 1.0.2.",
- "NEWS": coreNews + webNews,
- "twisted": {
- "topfiles": {
- "README": "Hi this is 1.0.2",
- "NEWS": coreNews},
- "_version.py":
- genVersion("twisted", 1, 0, 2),
- "web": {
- "topfiles": {
- "README": "Hi this is 1.0.2",
- "NEWS": webNews},
- "_version.py": genVersion("twisted.web", 1, 0, 2),
- }}}
- self.assertStructure(root, outStructure)
-
-
-
-class ProjectTest(TestCase):
- """
- There is a first-class representation of a project.
- """
-
- def assertProjectsEqual(self, observedProjects, expectedProjects):
- """
- Assert that two lists of L{Project}s are equal.
- """
- self.assertEqual(len(observedProjects), len(expectedProjects))
- observedProjects = sorted(observedProjects,
- key=operator.attrgetter('directory'))
- expectedProjects = sorted(expectedProjects,
- key=operator.attrgetter('directory'))
- for observed, expected in zip(observedProjects, expectedProjects):
- self.assertEqual(observed.directory, expected.directory)
-
-
- def makeProject(self, version, baseDirectory=None):
- """
- Make a Twisted-style project in the given base directory.
-
- @param baseDirectory: The directory to create files in
- (as a L{FilePath).
- @param version: The version information for the project.
- @return: L{Project} pointing to the created project.
- """
- if baseDirectory is None:
- baseDirectory = FilePath(self.mktemp())
- baseDirectory.createDirectory()
- segments = version.package.split('.')
- directory = baseDirectory
- for segment in segments:
- directory = directory.child(segment)
- if not directory.exists():
- directory.createDirectory()
- directory.child('__init__.py').setContent('')
- directory.child('topfiles').createDirectory()
- directory.child('topfiles').child('README').setContent(version.base())
- replaceProjectVersion(
- directory.child('_version.py').path, version)
- return Project(directory)
-
-
- def makeProjects(self, *versions):
- """
- Create a series of projects underneath a temporary base directory.
-
- @return: A L{FilePath} for the base directory.
- """
- baseDirectory = FilePath(self.mktemp())
- baseDirectory.createDirectory()
- for version in versions:
- self.makeProject(version, baseDirectory)
- return baseDirectory
-
-
- def test_getVersion(self):
- """
- Project objects know their version.
- """
- version = Version('foo', 2, 1, 0)
- project = self.makeProject(version)
- self.assertEqual(project.getVersion(), version)
-
-
- def test_updateVersion(self):
- """
- Project objects know how to update the version numbers in those
- projects.
- """
- project = self.makeProject(Version("bar", 2, 1, 0))
- newVersion = Version("bar", 3, 2, 9)
- project.updateVersion(newVersion)
- self.assertEqual(project.getVersion(), newVersion)
- self.assertEqual(
- project.directory.child("topfiles").child("README").getContent(),
- "3.2.9")
-
-
- def test_repr(self):
- """
- The representation of a Project is Project(directory).
- """
- foo = Project(FilePath('bar'))
- self.assertEqual(
- repr(foo), 'Project(%r)' % (foo.directory))
-
-
- def test_findTwistedStyleProjects(self):
- """
- findTwistedStyleProjects finds all projects underneath a particular
- directory. A 'project' is defined by the existence of a 'topfiles'
- directory and is returned as a Project object.
- """
- baseDirectory = self.makeProjects(
- Version('foo', 2, 3, 0), Version('foo.bar', 0, 7, 4))
- projects = findTwistedProjects(baseDirectory)
- self.assertProjectsEqual(
- projects,
- [Project(baseDirectory.child('foo')),
- Project(baseDirectory.child('foo').child('bar'))])
-
-
- def test_updateTwistedVersionInformation(self):
- """
- Update Twisted version information in the top-level project and all of
- the subprojects.
- """
- baseDirectory = FilePath(self.mktemp())
- baseDirectory.createDirectory()
- now = date.today()
-
- projectName = 'foo'
- oldVersion = Version(projectName, 2, 5, 0)
- newVersion = getNextVersion(oldVersion, now=now)
-
- project = self.makeProject(oldVersion, baseDirectory)
-
- updateTwistedVersionInformation(baseDirectory, now=now)
-
- self.assertEqual(project.getVersion(), newVersion)
- self.assertEqual(
- project.directory.child('topfiles').child('README').getContent(),
- newVersion.base())
-
-
-
-class UtilityTest(TestCase):
- """
- Tests for various utility functions for releasing.
- """
-
- def test_chdir(self):
- """
- Test that the runChdirSafe is actually safe, i.e., it still
- changes back to the original directory even if an error is
- raised.
- """
- cwd = os.getcwd()
- def chAndBreak():
- os.mkdir('releaseCh')
- os.chdir('releaseCh')
- 1//0
- self.assertRaises(ZeroDivisionError,
- release.runChdirSafe, chAndBreak)
- self.assertEqual(cwd, os.getcwd())
-
-
-
- def test_replaceInFile(self):
- """
- L{replaceInFile} replaces data in a file based on a dict. A key from
- the dict that is found in the file is replaced with the corresponding
- value.
- """
- in_ = 'foo\nhey hey $VER\nbar\n'
- outf = open('release.replace', 'w')
- outf.write(in_)
- outf.close()
-
- expected = in_.replace('$VER', '2.0.0')
- replaceInFile('release.replace', {'$VER': '2.0.0'})
- self.assertEqual(open('release.replace').read(), expected)
-
-
- expected = expected.replace('2.0.0', '3.0.0')
- replaceInFile('release.replace', {'2.0.0': '3.0.0'})
- self.assertEqual(open('release.replace').read(), expected)
-
-
-
-class VersionWritingTest(TestCase):
- """
- Tests for L{replaceProjectVersion}.
- """
-
- def test_replaceProjectVersion(self):
- """
- L{replaceProjectVersion} writes a Python file that defines a
- C{version} variable that corresponds to the given name and version
- number.
- """
- replaceProjectVersion("test_project",
- Version("twisted.test_project", 0, 82, 7))
- ns = {'__name___': 'twisted.test_project'}
- execfile("test_project", ns)
- self.assertEqual(ns["version"].base(), "0.82.7")
-
-
- def test_replaceProjectVersionWithPrerelease(self):
- """
- L{replaceProjectVersion} will write a Version instantiation that
- includes a prerelease parameter if necessary.
- """
- replaceProjectVersion("test_project",
- Version("twisted.test_project", 0, 82, 7,
- prerelease=8))
- ns = {'__name___': 'twisted.test_project'}
- execfile("test_project", ns)
- self.assertEqual(ns["version"].base(), "0.82.7pre8")
-
-
-
-class BuilderTestsMixin(object):
- """
- A mixin class which provides various methods for creating sample Lore input
- and output.
-
- @cvar template: The lore template that will be used to prepare sample
- output.
- @type template: C{str}
-
- @ivar docCounter: A counter which is incremented every time input is
- generated and which is included in the documents.
- @type docCounter: C{int}
- """
- template = '''
- <html>
- <head><title>Yo:</title></head>
- <body>
- <div class="body" />
- <a href="index.html">Index</a>
- <span class="version">Version: </span>
- </body>
- </html>
- '''
-
- def setUp(self):
- """
- Initialize the doc counter which ensures documents are unique.
- """
- self.docCounter = 0
-
-
- def assertXMLEqual(self, first, second):
- """
- Verify that two strings represent the same XML document.
- """
- self.assertEqual(
- dom.parseString(first).toxml(),
- dom.parseString(second).toxml())
-
-
- def getArbitraryOutput(self, version, counter, prefix="", apiBaseURL="%s"):
- """
- Get the correct HTML output for the arbitrary input returned by
- L{getArbitraryLoreInput} for the given parameters.
-
- @param version: The version string to include in the output.
- @type version: C{str}
- @param counter: A counter to include in the output.
- @type counter: C{int}
- """
- document = """\
-<?xml version="1.0"?><html>
- <head><title>Yo:Hi! Title: %(count)d</title></head>
- <body>
- <div class="content">Hi! %(count)d<div class="API"><a href="%(foobarLink)s" title="foobar">foobar</a></div></div>
- <a href="%(prefix)sindex.html">Index</a>
- <span class="version">Version: %(version)s</span>
- </body>
- </html>"""
- # Try to normalize irrelevant whitespace.
- return dom.parseString(
- document % {"count": counter, "prefix": prefix,
- "version": version,
- "foobarLink": apiBaseURL % ("foobar",)}).toxml('utf-8')
-
-
- def getArbitraryLoreInput(self, counter):
- """
- Get an arbitrary, unique (for this test case) string of lore input.
-
- @param counter: A counter to include in the input.
- @type counter: C{int}
- """
- template = (
- '<html>'
- '<head><title>Hi! Title: %(count)s</title></head>'
- '<body>'
- 'Hi! %(count)s'
- '<div class="API">foobar</div>'
- '</body>'
- '</html>')
- return template % {"count": counter}
-
-
- def getArbitraryLoreInputAndOutput(self, version, prefix="",
- apiBaseURL="%s"):
- """
- Get an input document along with expected output for lore run on that
- output document, assuming an appropriately-specified C{self.template}.
-
- @param version: A version string to include in the input and output.
- @type version: C{str}
- @param prefix: The prefix to include in the link to the index.
- @type prefix: C{str}
-
- @return: A two-tuple of input and expected output.
- @rtype: C{(str, str)}.
- """
- self.docCounter += 1
- return (self.getArbitraryLoreInput(self.docCounter),
- self.getArbitraryOutput(version, self.docCounter,
- prefix=prefix, apiBaseURL=apiBaseURL))
-
-
- def getArbitraryManInput(self):
- """
- Get an arbitrary man page content.
- """
- return """.TH MANHOLE "1" "August 2001" "" ""
-.SH NAME
-manhole \- Connect to a Twisted Manhole service
-.SH SYNOPSIS
-.B manhole
-.SH DESCRIPTION
-manhole is a GTK interface to Twisted Manhole services. You can execute python
-code as if at an interactive Python console inside a running Twisted process
-with this."""
-
-
- def getArbitraryManLoreOutput(self):
- """
- Get an arbitrary lore input document which represents man-to-lore
- output based on the man page returned from L{getArbitraryManInput}
- """
- return """\
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html><head>
-<title>MANHOLE.1</title></head>
-<body>
-
-<h1>MANHOLE.1</h1>
-
-<h2>NAME</h2>
-
-<p>manhole - Connect to a Twisted Manhole service
-</p>
-
-<h2>SYNOPSIS</h2>
-
-<p><strong>manhole</strong> </p>
-
-<h2>DESCRIPTION</h2>
-
-<p>manhole is a GTK interface to Twisted Manhole services. You can execute python
-code as if at an interactive Python console inside a running Twisted process
-with this.</p>
-
-</body>
-</html>
-"""
-
- def getArbitraryManHTMLOutput(self, version, prefix=""):
- """
- Get an arbitrary lore output document which represents the lore HTML
- output based on the input document returned from
- L{getArbitraryManLoreOutput}.
-
- @param version: A version string to include in the document.
- @type version: C{str}
- @param prefix: The prefix to include in the link to the index.
- @type prefix: C{str}
- """
- # Try to normalize the XML a little bit.
- return dom.parseString("""\
-<?xml version="1.0" ?><html>
- <head><title>Yo:MANHOLE.1</title></head>
- <body>
- <div class="content">
-
-<span/>
-
-<h2>NAME<a name="auto0"/></h2>
-
-<p>manhole - Connect to a Twisted Manhole service
-</p>
-
-<h2>SYNOPSIS<a name="auto1"/></h2>
-
-<p><strong>manhole</strong> </p>
-
-<h2>DESCRIPTION<a name="auto2"/></h2>
-
-<p>manhole is a GTK interface to Twisted Manhole services. You can execute python
-code as if at an interactive Python console inside a running Twisted process
-with this.</p>
-
-</div>
- <a href="%(prefix)sindex.html">Index</a>
- <span class="version">Version: %(version)s</span>
- </body>
- </html>""" % {
- 'prefix': prefix, 'version': version}).toxml("utf-8")
-
-
-
-class DocBuilderTestCase(TestCase, BuilderTestsMixin):
- """
- Tests for L{DocBuilder}.
-
- Note for future maintainers: The exact byte equality assertions throughout
- this suite may need to be updated due to minor differences in lore. They
- should not be taken to mean that Lore must maintain the same byte format
- forever. Feel free to update the tests when Lore changes, but please be
- careful.
- """
- skip = loreSkip
-
- def setUp(self):
- """
- Set up a few instance variables that will be useful.
-
- @ivar builder: A plain L{DocBuilder}.
- @ivar docCounter: An integer to be used as a counter by the
- C{getArbitrary...} methods.
- @ivar howtoDir: A L{FilePath} representing a directory to be used for
- containing Lore documents.
- @ivar templateFile: A L{FilePath} representing a file with
- C{self.template} as its content.
- """
- BuilderTestsMixin.setUp(self)
- self.builder = DocBuilder()
- self.howtoDir = FilePath(self.mktemp())
- self.howtoDir.createDirectory()
- self.templateFile = self.howtoDir.child("template.tpl")
- self.templateFile.setContent(self.template)
-
-
- def test_build(self):
- """
- The L{DocBuilder} runs lore on all .xhtml files within a directory.
- """
- version = "1.2.3"
- input1, output1 = self.getArbitraryLoreInputAndOutput(version)
- input2, output2 = self.getArbitraryLoreInputAndOutput(version)
-
- self.howtoDir.child("one.xhtml").setContent(input1)
- self.howtoDir.child("two.xhtml").setContent(input2)
-
- self.builder.build(version, self.howtoDir, self.howtoDir,
- self.templateFile)
- out1 = self.howtoDir.child('one.html')
- out2 = self.howtoDir.child('two.html')
- self.assertXMLEqual(out1.getContent(), output1)
- self.assertXMLEqual(out2.getContent(), output2)
-
-
- def test_noDocumentsFound(self):
- """
- The C{build} method raises L{NoDocumentsFound} if there are no
- .xhtml files in the given directory.
- """
- self.assertRaises(
- NoDocumentsFound,
- self.builder.build, "1.2.3", self.howtoDir, self.howtoDir,
- self.templateFile)
-
-
- def test_parentDocumentLinking(self):
- """
- The L{DocBuilder} generates correct links from documents to
- template-generated links like stylesheets and index backreferences.
- """
- input = self.getArbitraryLoreInput(0)
- tutoDir = self.howtoDir.child("tutorial")
- tutoDir.createDirectory()
- tutoDir.child("child.xhtml").setContent(input)
- self.builder.build("1.2.3", self.howtoDir, tutoDir, self.templateFile)
- outFile = tutoDir.child('child.html')
- self.assertIn('<a href="../index.html">Index</a>',
- outFile.getContent())
-
-
- def test_siblingDirectoryDocumentLinking(self):
- """
- It is necessary to generate documentation in a directory foo/bar where
- stylesheet and indexes are located in foo/baz. Such resources should be
- appropriately linked to.
- """
- input = self.getArbitraryLoreInput(0)
- resourceDir = self.howtoDir.child("resources")
- docDir = self.howtoDir.child("docs")
- docDir.createDirectory()
- docDir.child("child.xhtml").setContent(input)
- self.builder.build("1.2.3", resourceDir, docDir, self.templateFile)
- outFile = docDir.child('child.html')
- self.assertIn('<a href="../resources/index.html">Index</a>',
- outFile.getContent())
-
-
- def test_apiLinking(self):
- """
- The L{DocBuilder} generates correct links from documents to API
- documentation.
- """
- version = "1.2.3"
- input, output = self.getArbitraryLoreInputAndOutput(version)
- self.howtoDir.child("one.xhtml").setContent(input)
-
- self.builder.build(version, self.howtoDir, self.howtoDir,
- self.templateFile, "scheme:apilinks/%s.ext")
- out = self.howtoDir.child('one.html')
- self.assertIn(
- '<a href="scheme:apilinks/foobar.ext" title="foobar">foobar</a>',
- out.getContent())
-
-
- def test_deleteInput(self):
- """
- L{DocBuilder.build} can be instructed to delete the input files after
- generating the output based on them.
- """
- input1 = self.getArbitraryLoreInput(0)
- self.howtoDir.child("one.xhtml").setContent(input1)
- self.builder.build("whatever", self.howtoDir, self.howtoDir,
- self.templateFile, deleteInput=True)
- self.assertTrue(self.howtoDir.child('one.html').exists())
- self.assertFalse(self.howtoDir.child('one.xhtml').exists())
-
-
- def test_doNotDeleteInput(self):
- """
- Input will not be deleted by default.
- """
- input1 = self.getArbitraryLoreInput(0)
- self.howtoDir.child("one.xhtml").setContent(input1)
- self.builder.build("whatever", self.howtoDir, self.howtoDir,
- self.templateFile)
- self.assertTrue(self.howtoDir.child('one.html').exists())
- self.assertTrue(self.howtoDir.child('one.xhtml').exists())
-
-
- def test_getLinkrelToSameDirectory(self):
- """
- If the doc and resource directories are the same, the linkrel should be
- an empty string.
- """
- linkrel = self.builder.getLinkrel(FilePath("/foo/bar"),
- FilePath("/foo/bar"))
- self.assertEqual(linkrel, "")
-
-
- def test_getLinkrelToParentDirectory(self):
- """
- If the doc directory is a child of the resource directory, the linkrel
- should make use of '..'.
- """
- linkrel = self.builder.getLinkrel(FilePath("/foo"),
- FilePath("/foo/bar"))
- self.assertEqual(linkrel, "../")
-
-
- def test_getLinkrelToSibling(self):
- """
- If the doc directory is a sibling of the resource directory, the
- linkrel should make use of '..' and a named segment.
- """
- linkrel = self.builder.getLinkrel(FilePath("/foo/howto"),
- FilePath("/foo/examples"))
- self.assertEqual(linkrel, "../howto/")
-
-
- def test_getLinkrelToUncle(self):
- """
- If the doc directory is a sibling of the parent of the resource
- directory, the linkrel should make use of multiple '..'s and a named
- segment.
- """
- linkrel = self.builder.getLinkrel(FilePath("/foo/howto"),
- FilePath("/foo/examples/quotes"))
- self.assertEqual(linkrel, "../../howto/")
-
-
-
-class APIBuilderTestCase(TestCase):
- """
- Tests for L{APIBuilder}.
- """
- skip = pydoctorSkip
-
- def test_build(self):
- """
- L{APIBuilder.build} writes an index file which includes the name of the
- project specified.
- """
- stdout = StringIO()
- self.patch(sys, 'stdout', stdout)
-
- projectName = "Foobar"
- packageName = "quux"
- projectURL = "scheme:project"
- sourceURL = "scheme:source"
- docstring = "text in docstring"
- privateDocstring = "should also appear in output"
-
- inputPath = FilePath(self.mktemp()).child(packageName)
- inputPath.makedirs()
- inputPath.child("__init__.py").setContent(
- "def foo():\n"
- " '%s'\n"
- "def _bar():\n"
- " '%s'" % (docstring, privateDocstring))
-
- outputPath = FilePath(self.mktemp())
- outputPath.makedirs()
-
- builder = APIBuilder()
- builder.build(projectName, projectURL, sourceURL, inputPath, outputPath)
-
- indexPath = outputPath.child("index.html")
- self.assertTrue(
- indexPath.exists(),
- "API index %r did not exist." % (outputPath.path,))
- self.assertIn(
- '<a href="%s">%s</a>' % (projectURL, projectName),
- indexPath.getContent(),
- "Project name/location not in file contents.")
-
- quuxPath = outputPath.child("quux.html")
- self.assertTrue(
- quuxPath.exists(),
- "Package documentation file %r did not exist." % (quuxPath.path,))
- self.assertIn(
- docstring, quuxPath.getContent(),
- "Docstring not in package documentation file.")
- self.assertIn(
- '<a href="%s/%s">View Source</a>' % (sourceURL, packageName),
- quuxPath.getContent())
- self.assertIn(
- '<a href="%s/%s/__init__.py#L1" class="functionSourceLink">' % (
- sourceURL, packageName),
- quuxPath.getContent())
- self.assertIn(privateDocstring, quuxPath.getContent())
-
- # There should also be a page for the foo function in quux.
- self.assertTrue(quuxPath.sibling('quux.foo.html').exists())
-
- self.assertEqual(stdout.getvalue(), '')
-
-
- def test_buildWithPolicy(self):
- """
- L{BuildAPIDocsScript.buildAPIDocs} builds the API docs with values
- appropriate for the Twisted project.
- """
- stdout = StringIO()
- self.patch(sys, 'stdout', stdout)
- docstring = "text in docstring"
-
- projectRoot = FilePath(self.mktemp())
- packagePath = projectRoot.child("twisted")
- packagePath.makedirs()
- packagePath.child("__init__.py").setContent(
- "def foo():\n"
- " '%s'\n" % (docstring,))
- packagePath.child("_version.py").setContent(
- genVersion("twisted", 1, 0, 0))
- outputPath = FilePath(self.mktemp())
-
- script = BuildAPIDocsScript()
- script.buildAPIDocs(projectRoot, outputPath)
-
- indexPath = outputPath.child("index.html")
- self.assertTrue(
- indexPath.exists(),
- "API index %r did not exist." % (outputPath.path,))
- self.assertIn(
- '<a href="http://twistedmatrix.com/">Twisted</a>',
- indexPath.getContent(),
- "Project name/location not in file contents.")
-
- twistedPath = outputPath.child("twisted.html")
- self.assertTrue(
- twistedPath.exists(),
- "Package documentation file %r did not exist."
- % (twistedPath.path,))
- self.assertIn(
- docstring, twistedPath.getContent(),
- "Docstring not in package documentation file.")
- #Here we check that it figured out the correct version based on the
- #source code.
- self.assertIn(
- '<a href="http://twistedmatrix.com/trac/browser/tags/releases/'
- 'twisted-1.0.0/twisted">View Source</a>',
- twistedPath.getContent())
-
- self.assertEqual(stdout.getvalue(), '')
-
-
- def test_apiBuilderScriptMainRequiresTwoArguments(self):
- """
- SystemExit is raised when the incorrect number of command line
- arguments are passed to the API building script.
- """
- script = BuildAPIDocsScript()
- self.assertRaises(SystemExit, script.main, [])
- self.assertRaises(SystemExit, script.main, ["foo"])
- self.assertRaises(SystemExit, script.main, ["foo", "bar", "baz"])
-
-
- def test_apiBuilderScriptMain(self):
- """
- The API building script invokes the same code that
- L{test_buildWithPolicy} tests.
- """
- script = BuildAPIDocsScript()
- calls = []
- script.buildAPIDocs = lambda a, b: calls.append((a, b))
- script.main(["hello", "there"])
- self.assertEqual(calls, [(FilePath("hello"), FilePath("there"))])
-
-
-
-class ManBuilderTestCase(TestCase, BuilderTestsMixin):
- """
- Tests for L{ManBuilder}.
- """
- skip = loreSkip
-
- def setUp(self):
- """
- Set up a few instance variables that will be useful.
-
- @ivar builder: A plain L{ManBuilder}.
- @ivar manDir: A L{FilePath} representing a directory to be used for
- containing man pages.
- """
- BuilderTestsMixin.setUp(self)
- self.builder = ManBuilder()
- self.manDir = FilePath(self.mktemp())
- self.manDir.createDirectory()
-
-
- def test_noDocumentsFound(self):
- """
- L{ManBuilder.build} raises L{NoDocumentsFound} if there are no
- .1 files in the given directory.
- """
- self.assertRaises(NoDocumentsFound, self.builder.build, self.manDir)
-
-
- def test_build(self):
- """
- Check that L{ManBuilder.build} find the man page in the directory, and
- successfully produce a Lore content.
- """
- manContent = self.getArbitraryManInput()
- self.manDir.child('test1.1').setContent(manContent)
- self.builder.build(self.manDir)
- output = self.manDir.child('test1-man.xhtml').getContent()
- expected = self.getArbitraryManLoreOutput()
- # No-op on *nix, fix for windows
- expected = expected.replace('\n', os.linesep)
- self.assertEqual(output, expected)
-
-
- def test_toHTML(self):
- """
- Check that the content output by C{build} is compatible as input of
- L{DocBuilder.build}.
- """
- manContent = self.getArbitraryManInput()
- self.manDir.child('test1.1').setContent(manContent)
- self.builder.build(self.manDir)
-
- templateFile = self.manDir.child("template.tpl")
- templateFile.setContent(DocBuilderTestCase.template)
- docBuilder = DocBuilder()
- docBuilder.build("1.2.3", self.manDir, self.manDir,
- templateFile)
- output = self.manDir.child('test1-man.html').getContent()
-
- self.assertXMLEqual(
- output,
- """\
-<?xml version="1.0" ?><html>
- <head><title>Yo:MANHOLE.1</title></head>
- <body>
- <div class="content">
-
-<span/>
-
-<h2>NAME<a name="auto0"/></h2>
-
-<p>manhole - Connect to a Twisted Manhole service
-</p>
-
-<h2>SYNOPSIS<a name="auto1"/></h2>
-
-<p><strong>manhole</strong> </p>
-
-<h2>DESCRIPTION<a name="auto2"/></h2>
-
-<p>manhole is a GTK interface to Twisted Manhole services. You can execute python
-code as if at an interactive Python console inside a running Twisted process
-with this.</p>
-
-</div>
- <a href="index.html">Index</a>
- <span class="version">Version: 1.2.3</span>
- </body>
- </html>""")
-
-
-
-class BookBuilderTests(TestCase, BuilderTestsMixin):
- """
- Tests for L{BookBuilder}.
- """
- skip = latexSkip or loreSkip
-
- def setUp(self):
- """
- Make a directory into which to place temporary files.
- """
- self.docCounter = 0
- self.howtoDir = FilePath(self.mktemp())
- self.howtoDir.makedirs()
- self.oldHandler = signal.signal(signal.SIGCHLD, signal.SIG_DFL)
-
-
- def tearDown(self):
- signal.signal(signal.SIGCHLD, self.oldHandler)
-
-
- def getArbitraryOutput(self, version, counter, prefix="", apiBaseURL=None):
- """
- Create and return a C{str} containing the LaTeX document which is
- expected as the output for processing the result of the document
- returned by C{self.getArbitraryLoreInput(counter)}.
- """
- path = self.howtoDir.child("%d.xhtml" % (counter,)).path
- return (
- r'\section{Hi! Title: %(count)s\label{%(path)s}}'
- '\n'
- r'Hi! %(count)sfoobar') % {'count': counter, 'path': path}
-
-
- def test_runSuccess(self):
- """
- L{BookBuilder.run} executes the command it is passed and returns a
- string giving the stdout and stderr of the command if it completes
- successfully.
- """
- builder = BookBuilder()
- self.assertEqual(
- builder.run([
- sys.executable, '-c',
- 'import sys; '
- 'sys.stdout.write("hi\\n"); '
- 'sys.stdout.flush(); '
- 'sys.stderr.write("bye\\n"); '
- 'sys.stderr.flush()']),
- "hi\nbye\n")
-
-
- def test_runFailed(self):
- """
- L{BookBuilder.run} executes the command it is passed and raises
- L{CommandFailed} if it completes unsuccessfully.
- """
- builder = BookBuilder()
- exc = self.assertRaises(
- CommandFailed, builder.run,
- [sys.executable, '-c', 'print "hi"; raise SystemExit(1)'])
- self.assertEqual(exc.exitStatus, 1)
- self.assertEqual(exc.exitSignal, None)
- self.assertEqual(exc.output, "hi\n")
-
-
- def test_runSignaled(self):
- """
- L{BookBuilder.run} executes the command it is passed and raises
- L{CommandFailed} if it exits due to a signal.
- """
- builder = BookBuilder()
- exc = self.assertRaises(
- CommandFailed, builder.run,
- [sys.executable, '-c',
- 'import sys; print "hi"; sys.stdout.flush(); '
- 'import os; os.kill(os.getpid(), 9)'])
- self.assertEqual(exc.exitSignal, 9)
- self.assertEqual(exc.exitStatus, None)
- self.assertEqual(exc.output, "hi\n")
-
-
- def test_buildTeX(self):
- """
- L{BookBuilder.buildTeX} writes intermediate TeX files for all lore
- input files in a directory.
- """
- version = "3.2.1"
- input1, output1 = self.getArbitraryLoreInputAndOutput(version)
- input2, output2 = self.getArbitraryLoreInputAndOutput(version)
-
- # Filenames are chosen by getArbitraryOutput to match the counter used
- # by getArbitraryLoreInputAndOutput.
- self.howtoDir.child("1.xhtml").setContent(input1)
- self.howtoDir.child("2.xhtml").setContent(input2)
-
- builder = BookBuilder()
- builder.buildTeX(self.howtoDir)
- self.assertEqual(self.howtoDir.child("1.tex").getContent(), output1)
- self.assertEqual(self.howtoDir.child("2.tex").getContent(), output2)
-
-
- def test_buildTeXRejectsInvalidDirectory(self):
- """
- L{BookBuilder.buildTeX} raises L{ValueError} if passed a directory
- which does not exist.
- """
- builder = BookBuilder()
- self.assertRaises(
- ValueError, builder.buildTeX, self.howtoDir.temporarySibling())
-
-
- def test_buildTeXOnlyBuildsXHTML(self):
- """
- L{BookBuilder.buildTeX} ignores files which which don't end with
- ".xhtml".
- """
- # Hopefully ">" is always a parse error from microdom!
- self.howtoDir.child("not-input.dat").setContent(">")
- self.test_buildTeX()
-
-
- def test_stdout(self):
- """
- L{BookBuilder.buildTeX} does not write to stdout.
- """
- stdout = StringIO()
- self.patch(sys, 'stdout', stdout)
-
- # Suppress warnings so that if there are any old-style plugins that
- # lore queries for don't confuse the assertion below. See #3070.
- self.patch(warnings, 'warn', lambda *a, **kw: None)
- self.test_buildTeX()
- self.assertEqual(stdout.getvalue(), '')
-
-
- def test_buildPDFRejectsInvalidBookFilename(self):
- """
- L{BookBuilder.buildPDF} raises L{ValueError} if the book filename does
- not end with ".tex".
- """
- builder = BookBuilder()
- self.assertRaises(
- ValueError,
- builder.buildPDF,
- FilePath(self.mktemp()).child("foo"),
- None,
- None)
-
-
- def _setupTeXFiles(self):
- sections = range(3)
- self._setupTeXSections(sections)
- return self._setupTeXBook(sections)
-
-
- def _setupTeXSections(self, sections):
- for texSectionNumber in sections:
- texPath = self.howtoDir.child("%d.tex" % (texSectionNumber,))
- texPath.setContent(self.getArbitraryOutput(
- "1.2.3", texSectionNumber))
-
-
- def _setupTeXBook(self, sections):
- bookTeX = self.howtoDir.child("book.tex")
- bookTeX.setContent(
- r"\documentclass{book}" "\n"
- r"\begin{document}" "\n" +
- "\n".join([r"\input{%d.tex}" % (n,) for n in sections]) +
- r"\end{document}" "\n")
- return bookTeX
-
-
- def test_buildPDF(self):
- """
- L{BookBuilder.buildPDF} creates a PDF given an index tex file and a
- directory containing .tex files.
- """
- bookPath = self._setupTeXFiles()
- outputPath = FilePath(self.mktemp())
-
- builder = BookBuilder()
- builder.buildPDF(bookPath, self.howtoDir, outputPath)
-
- self.assertTrue(outputPath.exists())
-
-
- def test_buildPDFLongPath(self):
- """
- L{BookBuilder.buildPDF} succeeds even if the paths it is operating on
- are very long.
-
- C{ps2pdf13} seems to have problems when path names are long. This test
- verifies that even if inputs have long paths, generation still
- succeeds.
- """
- # Make it long.
- self.howtoDir = self.howtoDir.child("x" * 128).child("x" * 128).child("x" * 128)
- self.howtoDir.makedirs()
-
- # This will use the above long path.
- bookPath = self._setupTeXFiles()
- outputPath = FilePath(self.mktemp())
-
- builder = BookBuilder()
- builder.buildPDF(bookPath, self.howtoDir, outputPath)
-
- self.assertTrue(outputPath.exists())
-
-
- def test_buildPDFRunsLaTeXThreeTimes(self):
- """
- L{BookBuilder.buildPDF} runs C{latex} three times.
- """
- class InspectableBookBuilder(BookBuilder):
- def __init__(self):
- BookBuilder.__init__(self)
- self.commands = []
-
- def run(self, command):
- """
- Record the command and then execute it.
- """
- self.commands.append(command)
- return BookBuilder.run(self, command)
-
- bookPath = self._setupTeXFiles()
- outputPath = FilePath(self.mktemp())
-
- builder = InspectableBookBuilder()
- builder.buildPDF(bookPath, self.howtoDir, outputPath)
-
- # These string comparisons are very fragile. It would be better to
- # have a test which asserted the correctness of the contents of the
- # output files. I don't know how one could do that, though. -exarkun
- latex1, latex2, latex3, dvips, ps2pdf13 = builder.commands
- self.assertEqual(latex1, latex2)
- self.assertEqual(latex2, latex3)
- self.assertEqual(
- latex1[:1], ["latex"],
- "LaTeX command %r does not seem right." % (latex1,))
- self.assertEqual(
- latex1[-1:], [bookPath.path],
- "LaTeX command %r does not end with the book path (%r)." % (
- latex1, bookPath.path))
-
- self.assertEqual(
- dvips[:1], ["dvips"],
- "dvips command %r does not seem right." % (dvips,))
- self.assertEqual(
- ps2pdf13[:1], ["ps2pdf13"],
- "ps2pdf13 command %r does not seem right." % (ps2pdf13,))
-
-
- def test_noSideEffects(self):
- """
- The working directory is the same before and after a call to
- L{BookBuilder.buildPDF}. Also the contents of the directory containing
- the input book are the same before and after the call.
- """
- startDir = os.getcwd()
- bookTeX = self._setupTeXFiles()
- startTeXSiblings = bookTeX.parent().children()
- startHowtoChildren = self.howtoDir.children()
-
- builder = BookBuilder()
- builder.buildPDF(bookTeX, self.howtoDir, FilePath(self.mktemp()))
-
- self.assertEqual(startDir, os.getcwd())
- self.assertEqual(startTeXSiblings, bookTeX.parent().children())
- self.assertEqual(startHowtoChildren, self.howtoDir.children())
-
-
- def test_failedCommandProvidesOutput(self):
- """
- If a subprocess fails, L{BookBuilder.buildPDF} raises L{CommandFailed}
- with the subprocess's output and leaves the temporary directory as a
- sibling of the book path.
- """
- bookTeX = FilePath(self.mktemp() + ".tex")
- builder = BookBuilder()
- inputState = bookTeX.parent().children()
- exc = self.assertRaises(
- CommandFailed,
- builder.buildPDF,
- bookTeX, self.howtoDir, FilePath(self.mktemp()))
- self.assertTrue(exc.output)
- newOutputState = set(bookTeX.parent().children()) - set(inputState)
- self.assertEqual(len(newOutputState), 1)
- workPath = newOutputState.pop()
- self.assertTrue(
- workPath.isdir(),
- "Expected work path %r was not a directory." % (workPath.path,))
-
-
- def test_build(self):
- """
- L{BookBuilder.build} generates a pdf book file from some lore input
- files.
- """
- sections = range(1, 4)
- for sectionNumber in sections:
- self.howtoDir.child("%d.xhtml" % (sectionNumber,)).setContent(
- self.getArbitraryLoreInput(sectionNumber))
- bookTeX = self._setupTeXBook(sections)
- bookPDF = FilePath(self.mktemp())
-
- builder = BookBuilder()
- builder.build(self.howtoDir, [self.howtoDir], bookTeX, bookPDF)
-
- self.assertTrue(bookPDF.exists())
-
-
- def test_buildRemovesTemporaryLaTeXFiles(self):
- """
- L{BookBuilder.build} removes the intermediate LaTeX files it creates.
- """
- sections = range(1, 4)
- for sectionNumber in sections:
- self.howtoDir.child("%d.xhtml" % (sectionNumber,)).setContent(
- self.getArbitraryLoreInput(sectionNumber))
- bookTeX = self._setupTeXBook(sections)
- bookPDF = FilePath(self.mktemp())
-
- builder = BookBuilder()
- builder.build(self.howtoDir, [self.howtoDir], bookTeX, bookPDF)
-
- self.assertEqual(
- set(self.howtoDir.listdir()),
- set([bookTeX.basename()] + ["%d.xhtml" % (n,) for n in sections]))
-
-
-
-class FilePathDeltaTest(TestCase):
- """
- Tests for L{filePathDelta}.
- """
-
- def test_filePathDeltaSubdir(self):
- """
- L{filePathDelta} can create a simple relative path to a child path.
- """
- self.assertEqual(filePathDelta(FilePath("/foo/bar"),
- FilePath("/foo/bar/baz")),
- ["baz"])
-
-
- def test_filePathDeltaSiblingDir(self):
- """
- L{filePathDelta} can traverse upwards to create relative paths to
- siblings.
- """
- self.assertEqual(filePathDelta(FilePath("/foo/bar"),
- FilePath("/foo/baz")),
- ["..", "baz"])
-
-
- def test_filePathNoCommonElements(self):
- """
- L{filePathDelta} can create relative paths to totally unrelated paths
- for maximum portability.
- """
- self.assertEqual(filePathDelta(FilePath("/foo/bar"),
- FilePath("/baz/quux")),
- ["..", "..", "baz", "quux"])
-
-
- def test_filePathDeltaSimilarEndElements(self):
- """
- L{filePathDelta} doesn't take into account final elements when
- comparing 2 paths, but stops at the first difference.
- """
- self.assertEqual(filePathDelta(FilePath("/foo/bar/bar/spam"),
- FilePath("/foo/bar/baz/spam")),
- ["..", "..", "baz", "spam"])
-
-
-
-class NewsBuilderTests(TestCase, StructureAssertingMixin):
- """
- Tests for L{NewsBuilder}.
- """
- def setUp(self):
- """
- Create a fake project and stuff some basic structure and content into
- it.
- """
- self.builder = NewsBuilder()
- self.project = FilePath(self.mktemp())
- self.project.createDirectory()
- self.existingText = 'Here is stuff which was present previously.\n'
- self.createStructure(self.project, {
- 'NEWS': self.existingText,
- '5.feature': 'We now support the web.\n',
- '12.feature': 'The widget is more robust.\n',
- '15.feature': (
- 'A very long feature which takes many words to '
- 'describe with any accuracy was introduced so that '
- 'the line wrapping behavior of the news generating '
- 'code could be verified.\n'),
- '16.feature': (
- 'A simpler feature\ndescribed on multiple lines\n'
- 'was added.\n'),
- '23.bugfix': 'Broken stuff was fixed.\n',
- '25.removal': 'Stupid stuff was deprecated.\n',
- '30.misc': '',
- '35.misc': '',
- '40.doc': 'foo.bar.Baz.quux',
- '41.doc': 'writing Foo servers'})
-
-
- def test_today(self):
- """
- L{NewsBuilder._today} returns today's date in YYYY-MM-DD form.
- """
- self.assertEqual(
- self.builder._today(), date.today().strftime('%Y-%m-%d'))
-
-
- def test_findFeatures(self):
- """
- When called with L{NewsBuilder._FEATURE}, L{NewsBuilder._findChanges}
- returns a list of bugfix ticket numbers and descriptions as a list of
- two-tuples.
- """
- features = self.builder._findChanges(
- self.project, self.builder._FEATURE)
- self.assertEqual(
- features,
- [(5, "We now support the web."),
- (12, "The widget is more robust."),
- (15,
- "A very long feature which takes many words to describe with "
- "any accuracy was introduced so that the line wrapping behavior "
- "of the news generating code could be verified."),
- (16, "A simpler feature described on multiple lines was added.")])
-
-
- def test_findBugfixes(self):
- """
- When called with L{NewsBuilder._BUGFIX}, L{NewsBuilder._findChanges}
- returns a list of bugfix ticket numbers and descriptions as a list of
- two-tuples.
- """
- bugfixes = self.builder._findChanges(
- self.project, self.builder._BUGFIX)
- self.assertEqual(
- bugfixes,
- [(23, 'Broken stuff was fixed.')])
-
-
- def test_findRemovals(self):
- """
- When called with L{NewsBuilder._REMOVAL}, L{NewsBuilder._findChanges}
- returns a list of removal/deprecation ticket numbers and descriptions
- as a list of two-tuples.
- """
- removals = self.builder._findChanges(
- self.project, self.builder._REMOVAL)
- self.assertEqual(
- removals,
- [(25, 'Stupid stuff was deprecated.')])
-
-
- def test_findDocumentation(self):
- """
- When called with L{NewsBuilder._DOC}, L{NewsBuilder._findChanges}
- returns a list of documentation ticket numbers and descriptions as a
- list of two-tuples.
- """
- doc = self.builder._findChanges(
- self.project, self.builder._DOC)
- self.assertEqual(
- doc,
- [(40, 'foo.bar.Baz.quux'),
- (41, 'writing Foo servers')])
-
-
- def test_findMiscellaneous(self):
- """
- When called with L{NewsBuilder._MISC}, L{NewsBuilder._findChanges}
- returns a list of removal/deprecation ticket numbers and descriptions
- as a list of two-tuples.
- """
- misc = self.builder._findChanges(
- self.project, self.builder._MISC)
- self.assertEqual(
- misc,
- [(30, ''),
- (35, '')])
-
-
- def test_writeHeader(self):
- """
- L{NewsBuilder._writeHeader} accepts a file-like object opened for
- writing and a header string and writes out a news file header to it.
- """
- output = StringIO()
- self.builder._writeHeader(output, "Super Awesometastic 32.16")
- self.assertEqual(
- output.getvalue(),
- "Super Awesometastic 32.16\n"
- "=========================\n"
- "\n")
-
-
- def test_writeSection(self):
- """
- L{NewsBuilder._writeSection} accepts a file-like object opened for
- writing, a section name, and a list of ticket information (as returned
- by L{NewsBuilder._findChanges}) and writes out a section header and all
- of the given ticket information.
- """
- output = StringIO()
- self.builder._writeSection(
- output, "Features",
- [(3, "Great stuff."),
- (17, "Very long line which goes on and on and on, seemingly "
- "without end until suddenly without warning it does end.")])
- self.assertEqual(
- output.getvalue(),
- "Features\n"
- "--------\n"
- " - Great stuff. (#3)\n"
- " - Very long line which goes on and on and on, seemingly without end\n"
- " until suddenly without warning it does end. (#17)\n"
- "\n")
-
-
- def test_writeMisc(self):
- """
- L{NewsBuilder._writeMisc} accepts a file-like object opened for
- writing, a section name, and a list of ticket information (as returned
- by L{NewsBuilder._findChanges} and writes out a section header and all
- of the ticket numbers, but excludes any descriptions.
- """
- output = StringIO()
- self.builder._writeMisc(
- output, "Other",
- [(x, "") for x in range(2, 50, 3)])
- self.assertEqual(
- output.getvalue(),
- "Other\n"
- "-----\n"
- " - #2, #5, #8, #11, #14, #17, #20, #23, #26, #29, #32, #35, #38, #41,\n"
- " #44, #47\n"
- "\n")
-
-
- def test_build(self):
- """
- L{NewsBuilder.build} updates a NEWS file with new features based on the
- I{<ticket>.feature} files found in the directory specified.
- """
- self.builder.build(
- self.project, self.project.child('NEWS'),
- "Super Awesometastic 32.16")
-
- results = self.project.child('NEWS').getContent()
- self.assertEqual(
- results,
- 'Super Awesometastic 32.16\n'
- '=========================\n'
- '\n'
- 'Features\n'
- '--------\n'
- ' - We now support the web. (#5)\n'
- ' - The widget is more robust. (#12)\n'
- ' - A very long feature which takes many words to describe with any\n'
- ' accuracy was introduced so that the line wrapping behavior of the\n'
- ' news generating code could be verified. (#15)\n'
- ' - A simpler feature described on multiple lines was added. (#16)\n'
- '\n'
- 'Bugfixes\n'
- '--------\n'
- ' - Broken stuff was fixed. (#23)\n'
- '\n'
- 'Improved Documentation\n'
- '----------------------\n'
- ' - foo.bar.Baz.quux (#40)\n'
- ' - writing Foo servers (#41)\n'
- '\n'
- 'Deprecations and Removals\n'
- '-------------------------\n'
- ' - Stupid stuff was deprecated. (#25)\n'
- '\n'
- 'Other\n'
- '-----\n'
- ' - #30, #35\n'
- '\n\n' + self.existingText)
-
-
- def test_emptyProjectCalledOut(self):
- """
- If no changes exist for a project, I{NEWS} gains a new section for
- that project that includes some helpful text about how there were no
- interesting changes.
- """
- project = FilePath(self.mktemp()).child("twisted")
- project.makedirs()
- self.createStructure(project, {
- 'NEWS': self.existingText })
-
- self.builder.build(
- project, project.child('NEWS'),
- "Super Awesometastic 32.16")
- results = project.child('NEWS').getContent()
- self.assertEqual(
- results,
- 'Super Awesometastic 32.16\n'
- '=========================\n'
- '\n' +
- self.builder._NO_CHANGES +
- '\n\n' + self.existingText)
-
-
- def test_preserveTicketHint(self):
- """
- If a I{NEWS} file begins with the two magic lines which point readers
- at the issue tracker, those lines are kept at the top of the new file.
- """
- news = self.project.child('NEWS')
- news.setContent(
- 'Ticket numbers in this file can be looked up by visiting\n'
- 'http://twistedmatrix.com/trac/ticket/<number>\n'
- '\n'
- 'Blah blah other stuff.\n')
-
- self.builder.build(self.project, news, "Super Awesometastic 32.16")
-
- self.assertEqual(
- news.getContent(),
- 'Ticket numbers in this file can be looked up by visiting\n'
- 'http://twistedmatrix.com/trac/ticket/<number>\n'
- '\n'
- 'Super Awesometastic 32.16\n'
- '=========================\n'
- '\n'
- 'Features\n'
- '--------\n'
- ' - We now support the web. (#5)\n'
- ' - The widget is more robust. (#12)\n'
- ' - A very long feature which takes many words to describe with any\n'
- ' accuracy was introduced so that the line wrapping behavior of the\n'
- ' news generating code could be verified. (#15)\n'
- ' - A simpler feature described on multiple lines was added. (#16)\n'
- '\n'
- 'Bugfixes\n'
- '--------\n'
- ' - Broken stuff was fixed. (#23)\n'
- '\n'
- 'Improved Documentation\n'
- '----------------------\n'
- ' - foo.bar.Baz.quux (#40)\n'
- ' - writing Foo servers (#41)\n'
- '\n'
- 'Deprecations and Removals\n'
- '-------------------------\n'
- ' - Stupid stuff was deprecated. (#25)\n'
- '\n'
- 'Other\n'
- '-----\n'
- ' - #30, #35\n'
- '\n\n'
- 'Blah blah other stuff.\n')
-
-
- def test_emptySectionsOmitted(self):
- """
- If there are no changes of a particular type (feature, bugfix, etc), no
- section for that type is written by L{NewsBuilder.build}.
- """
- for ticket in self.project.children():
- if ticket.splitext()[1] in ('.feature', '.misc', '.doc'):
- ticket.remove()
-
- self.builder.build(
- self.project, self.project.child('NEWS'),
- 'Some Thing 1.2')
-
- self.assertEqual(
- self.project.child('NEWS').getContent(),
- 'Some Thing 1.2\n'
- '==============\n'
- '\n'
- 'Bugfixes\n'
- '--------\n'
- ' - Broken stuff was fixed. (#23)\n'
- '\n'
- 'Deprecations and Removals\n'
- '-------------------------\n'
- ' - Stupid stuff was deprecated. (#25)\n'
- '\n\n'
- 'Here is stuff which was present previously.\n')
-
-
- def test_duplicatesMerged(self):
- """
- If two change files have the same contents, they are merged in the
- generated news entry.
- """
- def feature(s):
- return self.project.child(s + '.feature')
- feature('5').copyTo(feature('15'))
- feature('5').copyTo(feature('16'))
-
- self.builder.build(
- self.project, self.project.child('NEWS'),
- 'Project Name 5.0')
-
- self.assertEqual(
- self.project.child('NEWS').getContent(),
- 'Project Name 5.0\n'
- '================\n'
- '\n'
- 'Features\n'
- '--------\n'
- ' - We now support the web. (#5, #15, #16)\n'
- ' - The widget is more robust. (#12)\n'
- '\n'
- 'Bugfixes\n'
- '--------\n'
- ' - Broken stuff was fixed. (#23)\n'
- '\n'
- 'Improved Documentation\n'
- '----------------------\n'
- ' - foo.bar.Baz.quux (#40)\n'
- ' - writing Foo servers (#41)\n'
- '\n'
- 'Deprecations and Removals\n'
- '-------------------------\n'
- ' - Stupid stuff was deprecated. (#25)\n'
- '\n'
- 'Other\n'
- '-----\n'
- ' - #30, #35\n'
- '\n\n'
- 'Here is stuff which was present previously.\n')
-
-
- def createFakeTwistedProject(self):
- """
- Create a fake-looking Twisted project to build from.
- """
- project = FilePath(self.mktemp()).child("twisted")
- project.makedirs()
- self.createStructure(project, {
- 'NEWS': 'Old boring stuff from the past.\n',
- '_version.py': genVersion("twisted", 1, 2, 3),
- 'topfiles': {
- 'NEWS': 'Old core news.\n',
- '3.feature': 'Third feature addition.\n',
- '5.misc': ''},
- 'conch': {
- '_version.py': genVersion("twisted.conch", 3, 4, 5),
- 'topfiles': {
- 'NEWS': 'Old conch news.\n',
- '7.bugfix': 'Fixed that bug.\n'}},
- })
- return project
-
-
- def test_buildAll(self):
- """
- L{NewsBuilder.buildAll} calls L{NewsBuilder.build} once for each
- subproject, passing that subproject's I{topfiles} directory as C{path},
- the I{NEWS} file in that directory as C{output}, and the subproject's
- name as C{header}, and then again for each subproject with the
- top-level I{NEWS} file for C{output}. Blacklisted subprojects are
- skipped.
- """
- builds = []
- builder = NewsBuilder()
- builder.build = lambda path, output, header: builds.append((
- path, output, header))
- builder._today = lambda: '2009-12-01'
-
- project = self.createFakeTwistedProject()
- builder.buildAll(project)
-
- coreTopfiles = project.child("topfiles")
- coreNews = coreTopfiles.child("NEWS")
- coreHeader = "Twisted Core 1.2.3 (2009-12-01)"
-
- conchTopfiles = project.child("conch").child("topfiles")
- conchNews = conchTopfiles.child("NEWS")
- conchHeader = "Twisted Conch 3.4.5 (2009-12-01)"
-
- aggregateNews = project.child("NEWS")
-
- self.assertEqual(
- builds,
- [(conchTopfiles, conchNews, conchHeader),
- (coreTopfiles, coreNews, coreHeader),
- (conchTopfiles, aggregateNews, conchHeader),
- (coreTopfiles, aggregateNews, coreHeader)])
-
-
- def test_changeVersionInNews(self):
- """
- L{NewsBuilder._changeVersions} gets the release date for a given
- version of a project as a string.
- """
- builder = NewsBuilder()
- builder._today = lambda: '2009-12-01'
- project = self.createFakeTwistedProject()
- builder.buildAll(project)
- newVersion = Version('TEMPLATE', 7, 7, 14)
- coreNews = project.child('topfiles').child('NEWS')
- # twisted 1.2.3 is the old version.
- builder._changeNewsVersion(
- coreNews, "Core", Version("twisted", 1, 2, 3),
- newVersion, '2010-01-01')
- expectedCore = (
- 'Twisted Core 7.7.14 (2010-01-01)\n'
- '================================\n'
- '\n'
- 'Features\n'
- '--------\n'
- ' - Third feature addition. (#3)\n'
- '\n'
- 'Other\n'
- '-----\n'
- ' - #5\n\n\n')
- self.assertEqual(
- expectedCore + 'Old core news.\n', coreNews.getContent())
-
-
-
-class DistributionBuilderTestBase(BuilderTestsMixin, StructureAssertingMixin,
- TestCase):
- """
- Base for tests of L{DistributionBuilder}.
- """
- skip = loreSkip
-
- def setUp(self):
- BuilderTestsMixin.setUp(self)
-
- self.rootDir = FilePath(self.mktemp())
- self.rootDir.createDirectory()
-
- self.outputDir = FilePath(self.mktemp())
- self.outputDir.createDirectory()
- self.builder = DistributionBuilder(self.rootDir, self.outputDir)
-
-
-
-class DistributionBuilderTest(DistributionBuilderTestBase):
-
- def test_twistedDistribution(self):
- """
- The Twisted tarball contains everything in the source checkout, with
- built documentation.
- """
- loreInput, loreOutput = self.getArbitraryLoreInputAndOutput("10.0.0")
- manInput1 = self.getArbitraryManInput()
- manOutput1 = self.getArbitraryManHTMLOutput("10.0.0", "../howto/")
- manInput2 = self.getArbitraryManInput()
- manOutput2 = self.getArbitraryManHTMLOutput("10.0.0", "../howto/")
- coreIndexInput, coreIndexOutput = self.getArbitraryLoreInputAndOutput(
- "10.0.0", prefix="howto/")
-
- structure = {
- "README": "Twisted",
- "unrelated": "x",
- "LICENSE": "copyright!",
- "setup.py": "import toplevel",
- "bin": {"web": {"websetroot": "SET ROOT"},
- "twistd": "TWISTD"},
- "twisted":
- {"web":
- {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL",
- "README": "WEB!"}},
- "words": {"__init__.py": "import WORDS"},
- "plugins": {"twisted_web.py": "import WEBPLUG",
- "twisted_words.py": "import WORDPLUG"}},
- "doc": {"web": {"howto": {"index.xhtml": loreInput},
- "man": {"websetroot.1": manInput2}},
- "core": {"howto": {"template.tpl": self.template},
- "man": {"twistd.1": manInput1},
- "index.xhtml": coreIndexInput}}}
-
- outStructure = {
- "README": "Twisted",
- "unrelated": "x",
- "LICENSE": "copyright!",
- "setup.py": "import toplevel",
- "bin": {"web": {"websetroot": "SET ROOT"},
- "twistd": "TWISTD"},
- "twisted":
- {"web": {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL",
- "README": "WEB!"}},
- "words": {"__init__.py": "import WORDS"},
- "plugins": {"twisted_web.py": "import WEBPLUG",
- "twisted_words.py": "import WORDPLUG"}},
- "doc": {"web": {"howto": {"index.html": loreOutput},
- "man": {"websetroot.1": manInput2,
- "websetroot-man.html": manOutput2}},
- "core": {"howto": {"template.tpl": self.template},
- "man": {"twistd.1": manInput1,
- "twistd-man.html": manOutput1},
- "index.html": coreIndexOutput}}}
-
- self.createStructure(self.rootDir, structure)
-
- outputFile = self.builder.buildTwisted("10.0.0")
-
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_excluded(self):
- """
- bin/admin and doc/historic are excluded from the Twisted tarball.
- """
- structure = {
- "bin": {"admin": {"blah": "ADMIN"},
- "twistd": "TWISTD"},
- "twisted":
- {"web":
- {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL",
- "README": "WEB!"}},
- },
- "doc": {"historic": {"hello": "there"},
- "other": "contents",
- },
- }
-
- outStructure = {
- "bin": {"twistd": "TWISTD"},
- "twisted":
- {"web":
- {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL",
- "README": "WEB!"}},
- },
- "doc": {"other": "contents"},
- }
-
- self.createStructure(self.rootDir, structure)
- outputFile = self.builder.buildTwisted("10.0.0")
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_subProjectLayout(self):
- """
- The subproject tarball includes files like so:
-
- 1. twisted/<subproject>/topfiles defines the files that will be in the
- top level in the tarball, except LICENSE, which comes from the real
- top-level directory.
- 2. twisted/<subproject> is included, but without the topfiles entry
- in that directory. No other twisted subpackages are included.
- 3. twisted/plugins/twisted_<subproject>.py is included, but nothing
- else in plugins is.
- """
- structure = {
- "README": "HI!@",
- "unrelated": "x",
- "LICENSE": "copyright!",
- "setup.py": "import toplevel",
- "bin": {"web": {"websetroot": "SET ROOT"},
- "words": {"im": "#!im"}},
- "twisted":
- {"web":
- {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL",
- "README": "WEB!"}},
- "words": {"__init__.py": "import WORDS"},
- "plugins": {"twisted_web.py": "import WEBPLUG",
- "twisted_words.py": "import WORDPLUG"}}}
-
- outStructure = {
- "README": "WEB!",
- "LICENSE": "copyright!",
- "setup.py": "import WEBINSTALL",
- "bin": {"websetroot": "SET ROOT"},
- "twisted": {"web": {"__init__.py": "import WEB"},
- "plugins": {"twisted_web.py": "import WEBPLUG"}}}
-
- self.createStructure(self.rootDir, structure)
-
- outputFile = self.builder.buildSubProject("web", "0.3.0")
-
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_minimalSubProjectLayout(self):
- """
- buildSubProject should work with minimal subprojects.
- """
- structure = {
- "LICENSE": "copyright!",
- "bin": {},
- "twisted":
- {"web": {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINSTALL"}},
- "plugins": {}}}
-
- outStructure = {
- "setup.py": "import WEBINSTALL",
- "LICENSE": "copyright!",
- "twisted": {"web": {"__init__.py": "import WEB"}}}
-
- self.createStructure(self.rootDir, structure)
-
- outputFile = self.builder.buildSubProject("web", "0.3.0")
-
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_subProjectDocBuilding(self):
- """
- When building a subproject release, documentation should be built with
- lore.
- """
- loreInput, loreOutput = self.getArbitraryLoreInputAndOutput("0.3.0")
- manInput = self.getArbitraryManInput()
- manOutput = self.getArbitraryManHTMLOutput("0.3.0", "../howto/")
- structure = {
- "LICENSE": "copyright!",
- "twisted": {"web": {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINST"}}},
- "doc": {"web": {"howto": {"index.xhtml": loreInput},
- "man": {"twistd.1": manInput}},
- "core": {"howto": {"template.tpl": self.template}}
- }
- }
-
- outStructure = {
- "LICENSE": "copyright!",
- "setup.py": "import WEBINST",
- "twisted": {"web": {"__init__.py": "import WEB"}},
- "doc": {"howto": {"index.html": loreOutput},
- "man": {"twistd.1": manInput,
- "twistd-man.html": manOutput}}}
-
- self.createStructure(self.rootDir, structure)
-
- outputFile = self.builder.buildSubProject("web", "0.3.0")
-
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_coreProjectLayout(self):
- """
- The core tarball looks a lot like a subproject tarball, except it
- doesn't include:
-
- - Python packages from other subprojects
- - plugins from other subprojects
- - scripts from other subprojects
- """
- indexInput, indexOutput = self.getArbitraryLoreInputAndOutput(
- "8.0.0", prefix="howto/")
- howtoInput, howtoOutput = self.getArbitraryLoreInputAndOutput("8.0.0")
- specInput, specOutput = self.getArbitraryLoreInputAndOutput(
- "8.0.0", prefix="../howto/")
- tutorialInput, tutorialOutput = self.getArbitraryLoreInputAndOutput(
- "8.0.0", prefix="../")
-
- structure = {
- "LICENSE": "copyright!",
- "twisted": {"__init__.py": "twisted",
- "python": {"__init__.py": "python",
- "roots.py": "roots!"},
- "conch": {"__init__.py": "conch",
- "unrelated.py": "import conch"},
- "plugin.py": "plugin",
- "plugins": {"twisted_web.py": "webplug",
- "twisted_whatever.py": "include!",
- "cred.py": "include!"},
- "topfiles": {"setup.py": "import CORE",
- "README": "core readme"}},
- "doc": {"core": {"howto": {"template.tpl": self.template,
- "index.xhtml": howtoInput,
- "tutorial":
- {"index.xhtml": tutorialInput}},
- "specifications": {"index.xhtml": specInput},
- "examples": {"foo.py": "foo.py"},
- "index.xhtml": indexInput},
- "web": {"howto": {"index.xhtml": "webindex"}}},
- "bin": {"twistd": "TWISTD",
- "web": {"websetroot": "websetroot"}}
- }
-
- outStructure = {
- "LICENSE": "copyright!",
- "setup.py": "import CORE",
- "README": "core readme",
- "twisted": {"__init__.py": "twisted",
- "python": {"__init__.py": "python",
- "roots.py": "roots!"},
- "plugin.py": "plugin",
- "plugins": {"twisted_whatever.py": "include!",
- "cred.py": "include!"}},
- "doc": {"howto": {"template.tpl": self.template,
- "index.html": howtoOutput,
- "tutorial": {"index.html": tutorialOutput}},
- "specifications": {"index.html": specOutput},
- "examples": {"foo.py": "foo.py"},
- "index.html": indexOutput},
- "bin": {"twistd": "TWISTD"},
- }
-
- self.createStructure(self.rootDir, structure)
- outputFile = self.builder.buildCore("8.0.0")
- self.assertExtractedStructure(outputFile, outStructure)
-
-
- def test_apiBaseURL(self):
- """
- DistributionBuilder builds documentation with the specified
- API base URL.
- """
- apiBaseURL = "http://%s"
- builder = DistributionBuilder(self.rootDir, self.outputDir,
- apiBaseURL=apiBaseURL)
- loreInput, loreOutput = self.getArbitraryLoreInputAndOutput(
- "0.3.0", apiBaseURL=apiBaseURL)
- structure = {
- "LICENSE": "copyright!",
- "twisted": {"web": {"__init__.py": "import WEB",
- "topfiles": {"setup.py": "import WEBINST"}}},
- "doc": {"web": {"howto": {"index.xhtml": loreInput}},
- "core": {"howto": {"template.tpl": self.template}}
- }
- }
-
- outStructure = {
- "LICENSE": "copyright!",
- "setup.py": "import WEBINST",
- "twisted": {"web": {"__init__.py": "import WEB"}},
- "doc": {"howto": {"index.html": loreOutput}}}
-
- self.createStructure(self.rootDir, structure)
- outputFile = builder.buildSubProject("web", "0.3.0")
- self.assertExtractedStructure(outputFile, outStructure)
-
-
-
-class BuildAllTarballsTest(DistributionBuilderTestBase):
- """
- Tests for L{DistributionBuilder.buildAllTarballs}.
- """
- skip = svnSkip
-
- def setUp(self):
- self.oldHandler = signal.signal(signal.SIGCHLD, signal.SIG_DFL)
- DistributionBuilderTestBase.setUp(self)
-
-
- def tearDown(self):
- signal.signal(signal.SIGCHLD, self.oldHandler)
- DistributionBuilderTestBase.tearDown(self)
-
-
- def test_buildAllTarballs(self):
- """
- L{buildAllTarballs} builds tarballs for Twisted and all of its
- subprojects based on an SVN checkout; the resulting tarballs contain
- no SVN metadata. This involves building documentation, which it will
- build with the correct API documentation reference base URL.
- """
- repositoryPath = self.mktemp()
- repository = FilePath(repositoryPath)
- checkoutPath = self.mktemp()
- checkout = FilePath(checkoutPath)
- self.outputDir.remove()
-
- runCommand(["svnadmin", "create", repositoryPath])
- runCommand(["svn", "checkout", "file://" + repository.path,
- checkout.path])
- coreIndexInput, coreIndexOutput = self.getArbitraryLoreInputAndOutput(
- "1.2.0", prefix="howto/",
- apiBaseURL="http://twistedmatrix.com/documents/1.2.0/api/%s.html")
-
- structure = {
- "README": "Twisted",
- "unrelated": "x",
- "LICENSE": "copyright!",
- "setup.py": "import toplevel",
- "bin": {"words": {"im": "import im"},
- "twistd": "TWISTD"},
- "twisted":
- {
- "topfiles": {"setup.py": "import TOPINSTALL",
- "README": "CORE!"},
- "_version.py": genVersion("twisted", 1, 2, 0),
- "words": {"__init__.py": "import WORDS",
- "_version.py":
- genVersion("twisted.words", 1, 2, 0),
- "topfiles": {"setup.py": "import WORDSINSTALL",
- "README": "WORDS!"},
- },
- "plugins": {"twisted_web.py": "import WEBPLUG",
- "twisted_words.py": "import WORDPLUG",
- "twisted_yay.py": "import YAY"}},
- "doc": {"core": {"howto": {"template.tpl": self.template},
- "index.xhtml": coreIndexInput}}}
-
- twistedStructure = {
- "README": "Twisted",
- "unrelated": "x",
- "LICENSE": "copyright!",
- "setup.py": "import toplevel",
- "bin": {"twistd": "TWISTD",
- "words": {"im": "import im"}},
- "twisted":
- {
- "topfiles": {"setup.py": "import TOPINSTALL",
- "README": "CORE!"},
- "_version.py": genVersion("twisted", 1, 2, 0),
- "words": {"__init__.py": "import WORDS",
- "_version.py":
- genVersion("twisted.words", 1, 2, 0),
- "topfiles": {"setup.py": "import WORDSINSTALL",
- "README": "WORDS!"},
- },
- "plugins": {"twisted_web.py": "import WEBPLUG",
- "twisted_words.py": "import WORDPLUG",
- "twisted_yay.py": "import YAY"}},
- "doc": {"core": {"howto": {"template.tpl": self.template},
- "index.html": coreIndexOutput}}}
-
- coreStructure = {
- "setup.py": "import TOPINSTALL",
- "README": "CORE!",
- "LICENSE": "copyright!",
- "bin": {"twistd": "TWISTD"},
- "twisted": {
- "_version.py": genVersion("twisted", 1, 2, 0),
- "plugins": {"twisted_yay.py": "import YAY"}},
- "doc": {"howto": {"template.tpl": self.template},
- "index.html": coreIndexOutput}}
-
- wordsStructure = {
- "README": "WORDS!",
- "LICENSE": "copyright!",
- "setup.py": "import WORDSINSTALL",
- "bin": {"im": "import im"},
- "twisted":
- {
- "words": {"__init__.py": "import WORDS",
- "_version.py":
- genVersion("twisted.words", 1, 2, 0),
- },
- "plugins": {"twisted_words.py": "import WORDPLUG"}}}
-
- self.createStructure(checkout, structure)
- childs = [x.path for x in checkout.children()]
- runCommand(["svn", "add"] + childs)
- runCommand(["svn", "commit", checkout.path, "-m", "yay"])
-
- buildAllTarballs(checkout, self.outputDir)
- self.assertEqual(
- set(self.outputDir.children()),
- set([self.outputDir.child("Twisted-1.2.0.tar.bz2"),
- self.outputDir.child("TwistedCore-1.2.0.tar.bz2"),
- self.outputDir.child("TwistedWords-1.2.0.tar.bz2")]))
-
- self.assertExtractedStructure(
- self.outputDir.child("Twisted-1.2.0.tar.bz2"),
- twistedStructure)
- self.assertExtractedStructure(
- self.outputDir.child("TwistedCore-1.2.0.tar.bz2"),
- coreStructure)
- self.assertExtractedStructure(
- self.outputDir.child("TwistedWords-1.2.0.tar.bz2"),
- wordsStructure)
-
-
- def test_buildAllTarballsEnsuresCleanCheckout(self):
- """
- L{UncleanWorkingDirectory} is raised by L{buildAllTarballs} when the
- SVN checkout provided has uncommitted changes.
- """
- repositoryPath = self.mktemp()
- repository = FilePath(repositoryPath)
- checkoutPath = self.mktemp()
- checkout = FilePath(checkoutPath)
-
- runCommand(["svnadmin", "create", repositoryPath])
- runCommand(["svn", "checkout", "file://" + repository.path,
- checkout.path])
-
- checkout.child("foo").setContent("whatever")
- self.assertRaises(UncleanWorkingDirectory,
- buildAllTarballs, checkout, FilePath(self.mktemp()))
-
-
- def test_buildAllTarballsEnsuresExistingCheckout(self):
- """
- L{NotWorkingDirectory} is raised by L{buildAllTarballs} when the
- checkout passed does not exist or is not an SVN checkout.
- """
- checkout = FilePath(self.mktemp())
- self.assertRaises(NotWorkingDirectory,
- buildAllTarballs,
- checkout, FilePath(self.mktemp()))
- checkout.createDirectory()
- self.assertRaises(NotWorkingDirectory,
- buildAllTarballs,
- checkout, FilePath(self.mktemp()))
-
-
-
-class ScriptTests(BuilderTestsMixin, StructureAssertingMixin, TestCase):
- """
- Tests for the release script functionality.
- """
-
- def _testVersionChanging(self, major, minor, micro, prerelease=None):
- """
- Check that L{ChangeVersionsScript.main} calls the version-changing
- function with the appropriate version data and filesystem path.
- """
- versionUpdates = []
- def myVersionChanger(sourceTree, versionTemplate):
- versionUpdates.append((sourceTree, versionTemplate))
- versionChanger = ChangeVersionsScript()
- versionChanger.changeAllProjectVersions = myVersionChanger
- version = "%d.%d.%d" % (major, minor, micro)
- if prerelease is not None:
- version += "pre%d" % (prerelease,)
- versionChanger.main([version])
- self.assertEqual(len(versionUpdates), 1)
- self.assertEqual(versionUpdates[0][0], FilePath("."))
- self.assertEqual(versionUpdates[0][1].major, major)
- self.assertEqual(versionUpdates[0][1].minor, minor)
- self.assertEqual(versionUpdates[0][1].micro, micro)
- self.assertEqual(versionUpdates[0][1].prerelease, prerelease)
-
-
- def test_changeVersions(self):
- """
- L{ChangeVersionsScript.main} changes version numbers for all Twisted
- projects.
- """
- self._testVersionChanging(8, 2, 3)
-
-
- def test_changeVersionsWithPrerelease(self):
- """
- A prerelease can be specified to L{changeVersionsScript}.
- """
- self._testVersionChanging(9, 2, 7, 38)
-
-
- def test_defaultChangeVersionsVersionChanger(self):
- """
- The default implementation of C{changeAllProjectVersions} is
- L{changeAllProjectVersions}.
- """
- versionChanger = ChangeVersionsScript()
- self.assertEqual(versionChanger.changeAllProjectVersions,
- changeAllProjectVersions)
-
-
- def test_badNumberOfArgumentsToChangeVersionsScript(self):
- """
- L{changeVersionsScript} raises SystemExit when the wrong number of
- arguments are passed.
- """
- versionChanger = ChangeVersionsScript()
- self.assertRaises(SystemExit, versionChanger.main, [])
-
-
- def test_tooManyDotsToChangeVersionsScript(self):
- """
- L{changeVersionsScript} raises SystemExit when there are the wrong
- number of segments in the version number passed.
- """
- versionChanger = ChangeVersionsScript()
- self.assertRaises(SystemExit, versionChanger.main,
- ["3.2.1.0"])
-
-
- def test_nonIntPartsToChangeVersionsScript(self):
- """
- L{changeVersionsScript} raises SystemExit when the version number isn't
- made out of numbers.
- """
- versionChanger = ChangeVersionsScript()
- self.assertRaises(SystemExit, versionChanger.main,
- ["my united.states.of prewhatever"])
-
-
- def test_buildTarballsScript(self):
- """
- L{BuildTarballsScript.main} invokes L{buildAllTarballs} with
- 2 or 3 L{FilePath} instances representing the paths passed to it.
- """
- builds = []
- def myBuilder(checkout, destination, template=None):
- builds.append((checkout, destination, template))
- tarballBuilder = BuildTarballsScript()
- tarballBuilder.buildAllTarballs = myBuilder
-
- tarballBuilder.main(["checkoutDir", "destinationDir"])
- self.assertEqual(
- builds,
- [(FilePath("checkoutDir"), FilePath("destinationDir"), None)])
-
- builds = []
- tarballBuilder.main(["checkoutDir", "destinationDir", "templatePath"])
- self.assertEqual(
- builds,
- [(FilePath("checkoutDir"), FilePath("destinationDir"),
- FilePath("templatePath"))])
-
-
- def test_defaultBuildTarballsScriptBuilder(self):
- """
- The default implementation of L{BuildTarballsScript.buildAllTarballs}
- is L{buildAllTarballs}.
- """
- tarballBuilder = BuildTarballsScript()
- self.assertEqual(tarballBuilder.buildAllTarballs, buildAllTarballs)
-
-
- def test_badNumberOfArgumentsToBuildTarballs(self):
- """
- L{BuildTarballsScript.main} raises SystemExit when the wrong number of
- arguments are passed.
- """
- tarballBuilder = BuildTarballsScript()
- self.assertRaises(SystemExit, tarballBuilder.main, [])
- self.assertRaises(SystemExit, tarballBuilder.main, ["a", "b", "c", "d"])
-
-
- def test_badNumberOfArgumentsToBuildNews(self):
- """
- L{NewsBuilder.main} raises L{SystemExit} when other than 1 argument is
- passed to it.
- """
- newsBuilder = NewsBuilder()
- self.assertRaises(SystemExit, newsBuilder.main, [])
- self.assertRaises(SystemExit, newsBuilder.main, ["hello", "world"])
-
-
- def test_buildNews(self):
- """
- L{NewsBuilder.main} calls L{NewsBuilder.buildAll} with a L{FilePath}
- instance constructed from the path passed to it.
- """
- builds = []
- newsBuilder = NewsBuilder()
- newsBuilder.buildAll = builds.append
- newsBuilder.main(["/foo/bar/baz"])
- self.assertEqual(builds, [FilePath("/foo/bar/baz")])