| Index: third_party/twisted_8_1/twisted/python/test/test_release.py
|
| diff --git a/third_party/twisted_8_1/twisted/python/test/test_release.py b/third_party/twisted_8_1/twisted/python/test/test_release.py
|
| deleted file mode 100644
|
| index a12eeae7332176932ec9c13836d9dffb767cef75..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/python/test/test_release.py
|
| +++ /dev/null
|
| @@ -1,1516 +0,0 @@
|
| -# Copyright (c) 2007-2008 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -"""
|
| -Tests for L{twisted.python.release} and L{twisted.python._release}.
|
| -"""
|
| -
|
| -import warnings
|
| -import operator
|
| -import os, sys, signal
|
| -from StringIO import StringIO
|
| -import tarfile
|
| -
|
| -from datetime import date
|
| -
|
| -try:
|
| - import pydoctor.driver
|
| - # it might not be installed, or it might use syntax not available in
|
| - # this version of Python.
|
| -except (ImportError, SyntaxError):
|
| - pydoctor = None
|
| -
|
| -from twisted.trial.unittest import TestCase
|
| -
|
| -from twisted.python.compat import set
|
| -from twisted.python.procutils import which
|
| -from twisted.python import release
|
| -from twisted.python.filepath import FilePath
|
| -from twisted.python.util import dsu
|
| -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 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
|
| -
|
| -try:
|
| - from twisted.lore.scripts import lore
|
| -except ImportError:
|
| - lore = None
|
| -
|
| -
|
| -
|
| -class ChangeVersionTest(TestCase):
|
| - """
|
| - 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.assertEquals(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.assertEquals(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())
|
| -
|
| -
|
| -
|
| -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 = dsu(observedProjects,
|
| - key=operator.attrgetter('directory'))
|
| - expectedProjects = dsu(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(
|
| - version.package, 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.assertEquals(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.assertEquals(project.getVersion(), newVersion)
|
| - self.assertEquals(
|
| - 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.assertEquals(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.assertEquals(open('release.replace').read(), expected)
|
| -
|
| -
|
| - expected = expected.replace('2.0.0', '3.0.0')
|
| - replaceInFile('release.replace', {'2.0.0': '3.0.0'})
|
| - self.assertEquals(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("twisted.test_project",
|
| - "test_project", Version("whatever", 0, 82, 7))
|
| - ns = {'__name___': 'twisted.test_project'}
|
| - execfile("test_project", ns)
|
| - self.assertEquals(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("twisted.test_project",
|
| - "test_project", Version("whatever", 0, 82, 7,
|
| - prerelease=8))
|
| - ns = {'__name___': 'twisted.test_project'}
|
| - execfile("test_project", ns)
|
| - self.assertEquals(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 getArbitraryOutput(self, version, counter, prefix=""):
|
| - """
|
| - 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)s</title></head>'
|
| - '<body><div class="content">Hi! %(count)s'
|
| - '<div class="API"><a href="foobar" title="foobar">'
|
| - 'foobar</a></div></div><a href="%(prefix)sindex.html">'
|
| - 'Index</a><span class="version">Version: %(version)s'
|
| - '</span></body></html>')
|
| - return document % {"count": counter, "prefix": prefix,
|
| - "version": version}
|
| -
|
| -
|
| - 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=""):
|
| - """
|
| - 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))
|
| -
|
| -
|
| - 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 ("<html><head>\n<title>MANHOLE.1</title>"
|
| - "</head>\n<body>\n\n<h1>MANHOLE.1</h1>\n\n<h2>NAME</h2>\n\n"
|
| - "<p>manhole - Connect to a Twisted Manhole service\n</p>\n\n"
|
| - "<h2>SYNOPSIS</h2>\n\n<p><strong>manhole</strong> </p>\n\n"
|
| - "<h2>DESCRIPTION</h2>\n\n<p>manhole is a GTK interface to Twisted "
|
| - "Manhole services. You can execute python\ncode as if at an "
|
| - "interactive Python console inside a running Twisted process\nwith"
|
| - " this.</p>\n\n</body>\n</html>\n")
|
| -
|
| -
|
| - 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}
|
| - """
|
| - return ('<?xml version="1.0"?><html><head>'
|
| - '<title>Yo:MANHOLE.1</title></head><body><div class="content">'
|
| - '<span></span><h2>NAME<a name="auto0"></a></h2><p>manhole - '
|
| - 'Connect to a Twisted Manhole service\n</p><h2>SYNOPSIS<a '
|
| - 'name="auto1"></a></h2><p><strong>manhole</strong></p><h2>'
|
| - 'DESCRIPTION<a name="auto2"></a></h2><p>manhole is a GTK '
|
| - 'interface to Twisted Manhole services. You can execute '
|
| - 'python\ncode as if at an interactive Python console inside a '
|
| - 'running Twisted process\nwith this.</p></div><a '
|
| - 'href="%sindex.html">Index</a><span class="version">Version: '
|
| - '%s</span></body></html>' % (prefix, version))
|
| -
|
| -
|
| -
|
| -
|
| -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.
|
| - """
|
| -
|
| - 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.assertEquals(out1.getContent(), output1)
|
| - self.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(linkrel, "../../howto/")
|
| -
|
| -
|
| -
|
| -class APIBuilderTestCase(TestCase):
|
| - """
|
| - Tests for L{APIBuilder}.
|
| - """
|
| - if pydoctor is None or getattr(pydoctor, "version_info", (0,)) < (0, 1):
|
| - skip = "APIBuilder requires Pydoctor 0.1 or newer"
|
| -
|
| - 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"
|
| - badDocstring = "should not 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, badDocstring))
|
| -
|
| - 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">View Source</a>' % (sourceURL, packageName),
|
| - quuxPath.getContent())
|
| - self.assertIn(
|
| - '<a href="%s/%s/__init__.py#L1" class="functionSourceLink">' % (
|
| - sourceURL, packageName),
|
| - quuxPath.getContent())
|
| - self.assertNotIn(badDocstring, quuxPath.getContent())
|
| -
|
| - self.assertEqual(stdout.getvalue(), '')
|
| -
|
| -
|
| -
|
| -class ManBuilderTestCase(TestCase, BuilderTestsMixin):
|
| - """
|
| - Tests for L{ManBuilder}.
|
| - """
|
| -
|
| - 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.assertEquals(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.assertEquals(output, '<?xml version="1.0"?><html><head>'
|
| - '<title>Yo:MANHOLE.1</title></head><body><div class="content">'
|
| - '<span></span><h2>NAME<a name="auto0"></a></h2><p>manhole - '
|
| - 'Connect to a Twisted Manhole service\n</p><h2>SYNOPSIS<a '
|
| - 'name="auto1"></a></h2><p><strong>manhole</strong></p><h2>'
|
| - 'DESCRIPTION<a name="auto2"></a></h2><p>manhole is a GTK '
|
| - 'interface to Twisted Manhole services. You can execute '
|
| - 'python\ncode as if at an interactive Python console inside a '
|
| - 'running Twisted process\nwith 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}.
|
| - """
|
| - if not (which("latex") and which("dvips") and which("ps2pdf13")):
|
| - skip = "Book Builder tests require latex."
|
| - try:
|
| - from popen2 import Popen4
|
| - except ImportError:
|
| - skip = "Book Builder requires popen2.Popen4."
|
| - else:
|
| - del Popen4
|
| -
|
| - def setUp(self):
|
| - """
|
| - Make a directory into which to place temporary files.
|
| - """
|
| - self.docCounter = 0
|
| - self.howtoDir = FilePath(self.mktemp())
|
| - self.howtoDir.makedirs()
|
| -
|
| -
|
| - def getArbitraryOutput(self, version, counter, prefix=""):
|
| - """
|
| - 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
|
| - path = path[len(os.getcwd()) + 1:]
|
| - 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("echo hi; echo bye 1>&2"), "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, "echo hi; false")
|
| - self.assertNotEqual(os.WEXITSTATUS(exc.exitCode), 0)
|
| - 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(
|
| - # This is only a little bit too tricky.
|
| - CommandFailed, builder.run, "echo hi; exec kill -9 $$")
|
| - self.assertTrue(os.WIFSIGNALED(exc.exitCode))
|
| - self.assertEqual(os.WTERMSIG(exc.exitCode), signal.SIGKILL)
|
| - 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.assertTrue(
|
| - latex1.startswith("latex "),
|
| - "LaTeX command %r does not start with 'latex '" % (latex1,))
|
| - self.assertTrue(
|
| - latex1.endswith(" " + bookPath.path),
|
| - "LaTeX command %r does not end with the book path (%r)." % (
|
| - latex1, bookPath.path))
|
| -
|
| - self.assertTrue(
|
| - dvips.startswith("dvips "),
|
| - "dvips command %r does not start with 'dvips '" % (dvips,))
|
| - self.assertTrue(
|
| - ps2pdf13.startswith("ps2pdf13 "),
|
| - "ps2pdf13 command %r does not start with 'ps2pdf13 '" % (
|
| - 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.assertEquals(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.assertEquals(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.assertEquals(filePathDelta(FilePath("/foo/bar"),
|
| - FilePath("/baz/quux")),
|
| - ["..", "..", "baz", "quux"])
|
| -
|
| -
|
| -
|
| -class DistributionBuilderTests(BuilderTestsMixin, TestCase):
|
| - """
|
| - Tests for L{DistributionBuilder}.
|
| - """
|
| -
|
| - def setUp(self):
|
| - BuilderTestsMixin.setUp(self)
|
| -
|
| - self.rootDir = FilePath(self.mktemp())
|
| - self.rootDir.createDirectory()
|
| -
|
| - outputDir = FilePath(self.mktemp())
|
| - outputDir.createDirectory()
|
| - self.builder = DistributionBuilder(self.rootDir, outputDir)
|
| -
|
| -
|
| - 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.
|
| - @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. For example: C{{"foofile":
|
| - "foocontents", "bardir": {"barfile": "barcontents"}}}
|
| - @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])
|
| -
|
| -
|
| - 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)
|
| -
|
| -
|
| - 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()
|
| - self.assertEquals(a, dirDict[x], child.path)
|
| - children.remove(x)
|
| - if children:
|
| - self.fail("There were extra children in %s: %s"
|
| - % (root.path, children))
|
| -
|
| -
|
| - 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_twistedDistributionExcludesWeb2AndVFS(self):
|
| - """
|
| - The main Twisted distribution does not include web2 or vfs.
|
| - """
|
| - loreInput, loreOutput = self.getArbitraryLoreInputAndOutput("10.0.0")
|
| - coreIndexInput, coreIndexOutput = self.getArbitraryLoreInputAndOutput(
|
| - "10.0.0", prefix="howto/")
|
| -
|
| - structure = {
|
| - "README": "Twisted",
|
| - "unrelated": "x",
|
| - "LICENSE": "copyright!",
|
| - "setup.py": "import toplevel",
|
| - "bin": {"web2": {"websetroot": "SET ROOT"},
|
| - "vfs": {"vfsitup": "hee hee"},
|
| - "twistd": "TWISTD"},
|
| - "twisted":
|
| - {"web2":
|
| - {"__init__.py": "import WEB",
|
| - "topfiles": {"setup.py": "import WEBINSTALL",
|
| - "README": "WEB!"}},
|
| - "vfs":
|
| - {"__init__.py": "import VFS",
|
| - "blah blah": "blah blah"},
|
| - "words": {"__init__.py": "import WORDS"},
|
| - "plugins": {"twisted_web.py": "import WEBPLUG",
|
| - "twisted_words.py": "import WORDPLUG",
|
| - "twisted_web2.py": "import WEB2",
|
| - "twisted_vfs.py": "import VFS"}},
|
| - "doc": {"web2": {"excluded!": "yay"},
|
| - "vfs": {"unrelated": "whatever"},
|
| - "core": {"howto": {"template.tpl": self.template},
|
| - "index.xhtml": coreIndexInput}}}
|
| -
|
| - outStructure = {
|
| - "README": "Twisted",
|
| - "unrelated": "x",
|
| - "LICENSE": "copyright!",
|
| - "setup.py": "import toplevel",
|
| - "bin": {"twistd": "TWISTD"},
|
| - "twisted":
|
| - {"words": {"__init__.py": "import WORDS"},
|
| - "plugins": {"twisted_web.py": "import WEBPLUG",
|
| - "twisted_words.py": "import WORDPLUG"}},
|
| - "doc": {"core": {"howto": {"template.tpl": self.template},
|
| - "index.html": coreIndexOutput}}}
|
| - 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/")
|
| - upgradeInput, upgradeOutput = 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},
|
| - "upgrades": {"index.xhtml": upgradeInput},
|
| - "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},
|
| - "upgrades": {"index.html": upgradeOutput},
|
| - "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)
|
| -
|
| -
|
| -
|
| -if lore is None:
|
| - skipMessage = "Lore is not present."
|
| - BookBuilderTests.skip = skipMessage
|
| - DocBuilderTestCase.skip = skipMessage
|
| - ManBuilderTestCase.skip = skipMessage
|
| - DistributionBuilderTests.skip = skipMessage
|
|
|