Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: third_party/twisted_8_1/twisted/python/_release.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.python.test.test_release -*-
2 # Copyright (c) 2007-2008 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 Twisted's automated release system.
7
8 This module is only for use within Twisted's release system. If you are anyone
9 else, do not use it. The interface and behaviour will change without notice.
10 """
11
12 from datetime import date
13 import os
14 from tempfile import mkdtemp
15 import tarfile
16
17 # Popen4 isn't available on Windows. BookBuilder won't work on Windows, but
18 # we don't care. -exarkun
19 try:
20 from popen2 import Popen4
21 except ImportError:
22 Popen4 = None
23
24 from twisted.python.versions import Version
25 from twisted.python.filepath import FilePath
26
27 # This import is an example of why you shouldn't use this module unless you're
28 # radix
29 try:
30 from twisted.lore.scripts import lore
31 except ImportError:
32 pass
33
34 # The offset between a year and the corresponding major version number.
35 VERSION_OFFSET = 2000
36
37
38 class CommandFailed(Exception):
39 """
40 Raised when a child process exits unsuccessfully.
41
42 @type exitCode: C{int}
43 @ivar exitCode: The exit code for the child process.
44
45 @type output: C{str}
46 @ivar output: The bytes read from stdout and stderr of the child process.
47 """
48 def __init__(self, exitCode, output):
49 Exception.__init__(self, exitCode, output)
50 self.exitCode = exitCode
51 self.output = output
52
53
54
55 def _changeVersionInFile(old, new, filename):
56 """
57 Replace the C{old} version number with the C{new} one in the given
58 C{filename}.
59 """
60 replaceInFile(filename, {old.base(): new.base()})
61
62
63
64 def getNextVersion(version, now=None):
65 """
66 Calculate the version number for a new release of Twisted based on
67 the previous version number.
68
69 @param version: The previous version number.
70 @param now: (optional) The current date.
71 """
72 # XXX: This has no way of incrementing the patch number. Currently, we
73 # don't need it. See bug 2915. Jonathan Lange, 2007-11-20.
74 if now is None:
75 now = date.today()
76 major = now.year - VERSION_OFFSET
77 if major != version.major:
78 minor = 0
79 else:
80 minor = version.minor + 1
81 return Version(version.package, major, minor, 0)
82
83
84
85 class Project(object):
86 """
87 A representation of a project that has a version.
88
89 @ivar directory: A L{twisted.python.filepath.FilePath} pointing to the base
90 directory of a Twisted-style Python package. The package should contain
91 a C{_version.py} file and a C{topfiles} directory that contains a
92 C{README} file.
93 """
94
95 def __init__(self, directory):
96 self.directory = directory
97
98
99 def __repr__(self):
100 return '%s(%r)' % (
101 self.__class__.__name__, self.directory)
102
103
104 def getVersion(self):
105 """
106 @return: A L{Version} specifying the version number of the project
107 based on live python modules.
108 """
109 namespace = {}
110 execfile(self.directory.child("_version.py").path, namespace)
111 return namespace["version"]
112
113
114 def updateVersion(self, version):
115 """
116 Replace the existing version numbers in _version.py and README files
117 with the specified version.
118 """
119 oldVersion = self.getVersion()
120 replaceProjectVersion(oldVersion.package,
121 self.directory.child("_version.py").path,
122 version)
123 _changeVersionInFile(
124 oldVersion, version,
125 self.directory.child("topfiles").child("README").path)
126
127
128
129 def findTwistedProjects(baseDirectory):
130 """
131 Find all Twisted-style projects beneath a base directory.
132
133 @param baseDirectory: A L{twisted.python.filepath.FilePath} to look inside.
134 @return: A list of L{Project}.
135 """
136 projects = []
137 for filePath in baseDirectory.walk():
138 if filePath.basename() == 'topfiles':
139 projectDirectory = filePath.parent()
140 projects.append(Project(projectDirectory))
141 return projects
142
143
144
145 def updateTwistedVersionInformation(baseDirectory, now):
146 """
147 Update the version information for Twisted and all subprojects to the
148 date-based version number.
149
150 @param baseDirectory: Where to look for Twisted. If None, the function
151 infers the information from C{twisted.__file__}.
152 @param now: The current date (as L{datetime.date}). If None, it defaults
153 to today.
154 """
155 for project in findTwistedProjects(baseDirectory):
156 project.updateVersion(getNextVersion(project.getVersion(), now=now))
157
158
159
160 def replaceProjectVersion(name, filename, newversion):
161 """
162 Write version specification code into the given filename, which
163 sets the version to the given version number.
164
165 @param filename: A filename which is most likely a "_version.py"
166 under some Twisted project.
167 @param newversion: A version object.
168 """
169 # XXX - this should be moved to Project and renamed to writeVersionFile.
170 # jml, 2007-11-15.
171 f = open(filename, 'w')
172 if newversion.prerelease is not None:
173 prerelease = ", prerelease=%r" % (newversion.prerelease,)
174 else:
175 prerelease = ""
176 f.write('''\
177 # This is an auto-generated file. Do not edit it.
178 from twisted.python import versions
179 version = versions.Version(%r, %s, %s, %s%s)
180 ''' % (name, newversion.major, newversion.minor, newversion.micro, prerelease))
181 f.close()
182
183
184
185 def replaceInFile(filename, oldToNew):
186 """
187 I replace the text `oldstr' with `newstr' in `filename' using science.
188 """
189 os.rename(filename, filename+'.bak')
190 f = open(filename+'.bak')
191 d = f.read()
192 f.close()
193 for k,v in oldToNew.items():
194 d = d.replace(k, v)
195 f = open(filename + '.new', 'w')
196 f.write(d)
197 f.close()
198 os.rename(filename+'.new', filename)
199 os.unlink(filename+'.bak')
200
201
202
203 class NoDocumentsFound(Exception):
204 """
205 Raised when no input documents are found.
206 """
207
208
209
210 class LoreBuilderMixin(object):
211 """
212 Base class for builders which invoke lore.
213 """
214 def lore(self, arguments):
215 """
216 Run lore with the given arguments.
217
218 @param arguments: A C{list} of C{str} giving command line arguments to
219 lore which should be used.
220 """
221 options = lore.Options()
222 options.parseOptions(["--null"] + arguments)
223 lore.runGivenOptions(options)
224
225
226
227 class DocBuilder(LoreBuilderMixin):
228 """
229 Generate HTML documentation for projects.
230 """
231
232 def build(self, version, resourceDir, docDir, template, apiBaseURL=None, del eteInput=False):
233 """
234 Build the documentation in C{docDir} with Lore.
235
236 Input files ending in .xhtml will be considered. Output will written as
237 .html files.
238
239 @param version: the version of the documentation to pass to lore.
240 @type version: C{str}
241
242 @param resourceDir: The directory which contains the toplevel index and
243 stylesheet file for this section of documentation.
244 @type resourceDir: L{twisted.python.filepath.FilePath}
245
246 @param docDir: The directory of the documentation.
247 @type docDir: L{twisted.python.filepath.FilePath}
248
249 @param template: The template used to generate the documentation.
250 @type template: L{twisted.python.filepath.FilePath}
251
252 @type apiBaseURL: C{str} or C{NoneType}
253 @param apiBaseURL: A format string which will be interpolated with the
254 fully-qualified Python name for each API link. For example, to
255 generate the Twisted 8.0.0 documentation, pass
256 C{"http://twistedmatrix.com/documents/8.0.0/api/%s.html"}.
257
258 @param deleteInput: If True, the input documents will be deleted after
259 their output is generated.
260 @type deleteInput: C{bool}
261
262 @raise NoDocumentsFound: When there are no .xhtml files in the given
263 C{docDir}.
264 """
265 linkrel = self.getLinkrel(resourceDir, docDir)
266 inputFiles = docDir.globChildren("*.xhtml")
267 filenames = [x.path for x in inputFiles]
268 if not filenames:
269 raise NoDocumentsFound("No input documents found in %s" % (docDir,))
270 if apiBaseURL is not None:
271 arguments = ["--config", "baseurl=" + apiBaseURL]
272 else:
273 arguments = []
274 arguments.extend(["--config", "template=%s" % (template.path,),
275 "--config", "ext=.html",
276 "--config", "version=%s" % (version,),
277 "--linkrel", linkrel] + filenames)
278 self.lore(arguments)
279 if deleteInput:
280 for inputFile in inputFiles:
281 inputFile.remove()
282
283
284 def getLinkrel(self, resourceDir, docDir):
285 """
286 Calculate a value appropriate for Lore's --linkrel option.
287
288 Lore's --linkrel option defines how to 'find' documents that are
289 linked to from TEMPLATE files (NOT document bodies). That is, it's a
290 prefix for links ('a' and 'link') in the template.
291
292 @param resourceDir: The directory which contains the toplevel index and
293 stylesheet file for this section of documentation.
294 @type resourceDir: L{twisted.python.filepath.FilePath}
295
296 @param docDir: The directory containing documents that must link to
297 C{resourceDir}.
298 @type docDir: L{twisted.python.filepath.FilePath}
299 """
300 if resourceDir != docDir:
301 return '/'.join(filePathDelta(docDir, resourceDir)) + "/"
302 else:
303 return ""
304
305
306
307 class ManBuilder(LoreBuilderMixin):
308 """
309 Generate man pages of the different existing scripts.
310 """
311
312 def build(self, manDir):
313 """
314 Generate Lore input files from the man pages in C{manDir}.
315
316 Input files ending in .1 will be considered. Output will written as
317 -man.xhtml files.
318
319 @param manDir: The directory of the man pages.
320 @type manDir: L{twisted.python.filepath.FilePath}
321
322 @raise NoDocumentsFound: When there are no .1 files in the given
323 C{manDir}.
324 """
325 inputFiles = manDir.globChildren("*.1")
326 filenames = [x.path for x in inputFiles]
327 if not filenames:
328 raise NoDocumentsFound("No manual pages found in %s" % (manDir,))
329 arguments = ["--input", "man",
330 "--output", "lore",
331 "--config", "ext=-man.xhtml"] + filenames
332 self.lore(arguments)
333
334
335
336 class APIBuilder(object):
337 """
338 Generate API documentation from source files using
339 U{pydoctor<http://codespeak.net/~mwh/pydoctor/>}. This requires
340 pydoctor to be installed and usable (which means you won't be able to
341 use it with Python 2.3).
342 """
343 def build(self, projectName, projectURL, sourceURL, packagePath, outputPath) :
344 """
345 Call pydoctor's entry point with options which will generate HTML
346 documentation for the specified package's API.
347
348 @type projectName: C{str}
349 @param projectName: The name of the package for which to generate
350 documentation.
351
352 @type projectURL: C{str}
353 @param projectURL: The location (probably an HTTP URL) of the project
354 on the web.
355
356 @type sourceURL: C{str}
357 @param sourceURL: The location (probably an HTTP URL) of the root of
358 the source browser for the project.
359
360 @type packagePath: L{FilePath}
361 @param packagePath: The path to the top-level of the package named by
362 C{projectName}.
363
364 @type outputPath: L{FilePath}
365 @param outputPath: An existing directory to which the generated API
366 documentation will be written.
367 """
368 from pydoctor.driver import main
369 main(
370 ["--project-name", projectName,
371 "--project-url", projectURL,
372 "--system-class", "pydoctor.twistedmodel.TwistedSystem",
373 "--project-base-dir", packagePath.parent().path,
374 "--html-viewsource-base", sourceURL,
375 "--add-package", packagePath.path,
376 "--html-output", outputPath.path,
377 "--quiet", "--make-html"])
378
379
380
381 class BookBuilder(LoreBuilderMixin):
382 """
383 Generate the LaTeX and PDF documentation.
384
385 The book is built by assembling a number of LaTeX documents. Only the
386 overall document which describes how to assemble the documents is stored
387 in LaTeX in the source. The rest of the documentation is generated from
388 Lore input files. These are primarily XHTML files (of the particular
389 Lore subset), but man pages are stored in GROFF format. BookBuilder
390 expects all of its input to be Lore XHTML format, so L{ManBuilder}
391 should be invoked first if the man pages are to be included in the
392 result (this is determined by the book LaTeX definition file).
393 Therefore, a sample usage of BookBuilder may look something like this:
394
395 man = ManBuilder()
396 man.build(FilePath("doc/core/man"))
397 book = BookBuilder()
398 book.build(
399 FilePath('doc/core/howto'),
400 [FilePath('doc/core/howto'), FilePath('doc/core/howto/tutorial'),
401 FilePath('doc/core/man'), FilePath('doc/core/specifications')],
402 FilePath('doc/core/howto/book.tex'), FilePath('/tmp/book.pdf'))
403 """
404 def run(self, command):
405 """
406 Execute a command in a child process and return the output.
407
408 @type command C{str}
409 @param command: The shell command to run.
410
411 @raise L{RuntimeError}: If the child process exits with an error.
412 """
413 process = Popen4(command)
414 stdout = process.fromchild.read()
415 exitCode = process.wait()
416 if os.WIFSIGNALED(exitCode) or os.WEXITSTATUS(exitCode):
417 raise CommandFailed(exitCode, stdout)
418 return stdout
419
420
421 def buildTeX(self, howtoDir):
422 """
423 Build LaTeX files for lore input files in the given directory.
424
425 Input files ending in .xhtml will be considered. Output will written as
426 .tex files.
427
428 @type howtoDir: L{FilePath}
429 @param howtoDir: A directory containing lore input files.
430
431 @raise ValueError: If C{howtoDir} does not exist.
432 """
433 if not howtoDir.exists():
434 raise ValueError("%r does not exist." % (howtoDir.path,))
435 self.lore(
436 ["--output", "latex",
437 "--config", "section"] +
438 [child.path for child in howtoDir.globChildren("*.xhtml")])
439
440
441 def buildPDF(self, bookPath, inputDirectory, outputPath):
442 """
443 Build a PDF from the given a LaTeX book document.
444
445 @type bookPath: L{FilePath}
446 @param bookPath: The location of a LaTeX document defining a book.
447
448 @type inputDirectory: L{FilePath}
449 @param inputDirectory: The directory which the inputs of the book are
450 relative to.
451
452 @type outputPath: L{FilePath}
453 @param outputPath: The location to which to write the resulting book.
454 """
455 if not bookPath.basename().endswith(".tex"):
456 raise ValueError("Book filename must end with .tex")
457
458 workPath = FilePath(mkdtemp())
459 try:
460 startDir = os.getcwd()
461 try:
462 os.chdir(inputDirectory.path)
463
464 texToDVI = (
465 "latex -interaction=nonstopmode "
466 "-output-directory=%s %s") % (
467 workPath.path, bookPath.path)
468
469 # What I tell you three times is true!
470 # The first two invocations of latex on the book file allows it
471 # correctly create page numbers for in-text references. Why thi s is
472 # the case, I could not tell you. -exarkun
473 for i in range(3):
474 self.run(texToDVI)
475
476 bookBaseWithoutExtension = bookPath.basename()[:-4]
477 dviPath = workPath.child(bookBaseWithoutExtension + ".dvi")
478 psPath = workPath.child(bookBaseWithoutExtension + ".ps")
479 pdfPath = workPath.child(bookBaseWithoutExtension + ".pdf")
480 self.run(
481 "dvips -o %(postscript)s -t letter -Ppdf %(dvi)s" % {
482 'postscript': psPath.path,
483 'dvi': dviPath.path})
484 self.run("ps2pdf13 %(postscript)s %(pdf)s" % {
485 'postscript': psPath.path,
486 'pdf': pdfPath.path})
487 pdfPath.moveTo(outputPath)
488 workPath.remove()
489 finally:
490 os.chdir(startDir)
491 except:
492 workPath.moveTo(bookPath.parent().child(workPath.basename()))
493 raise
494
495
496 def build(self, baseDirectory, inputDirectories, bookPath, outputPath):
497 """
498 Build a PDF book from the given TeX book definition and directories
499 containing lore inputs.
500
501 @type baseDirectory: L{FilePath}
502 @param baseDirectory: The directory which the inputs of the book are
503 relative to.
504
505 @type inputDirectories: C{list} of L{FilePath}
506 @param inputDirectories: The paths which contain lore inputs to be
507 converted to LaTeX.
508
509 @type bookPath: L{FilePath}
510 @param bookPath: The location of a LaTeX document defining a book.
511
512 @type outputPath: L{FilePath}
513 @param outputPath: The location to which to write the resulting book.
514 """
515 for inputDir in inputDirectories:
516 self.buildTeX(inputDir)
517 self.buildPDF(bookPath, baseDirectory, outputPath)
518 for inputDirectory in inputDirectories:
519 for child in inputDirectory.children():
520 if child.splitext()[1] == ".tex" and child != bookPath:
521 child.remove()
522
523
524
525 def filePathDelta(origin, destination):
526 """
527 Return a list of strings that represent C{destination} as a path relative
528 to C{origin}.
529
530 It is assumed that both paths represent directories, not files. That is to
531 say, the delta of L{twisted.python.filepath.FilePath} /foo/bar to
532 L{twisted.python.filepath.FilePath} /foo/baz will be C{../baz},
533 not C{baz}.
534
535 @type origin: L{twisted.python.filepath.FilePath}
536 @param origin: The origin of the relative path.
537
538 @type destination: L{twisted.python.filepath.FilePath}
539 @param destination: The destination of the relative path.
540 """
541 commonItems = 0
542 path1 = origin.path.split(os.sep)
543 path2 = destination.path.split(os.sep)
544 for elem1, elem2 in zip(path1, path2):
545 if elem1 == elem2:
546 commonItems += 1
547 path = [".."] * (len(path1) - commonItems)
548 return path + path2[commonItems:]
549
550
551
552 class DistributionBuilder(object):
553 """
554 A builder of Twisted distributions.
555
556 This knows how to build tarballs for Twisted and all of its subprojects.
557 """
558
559 from twisted.python.dist import twisted_subprojects as subprojects
560 blacklist = ["vfs", "web2"]
561
562 def __init__(self, rootDirectory, outputDirectory, apiBaseURL=None):
563 """
564 Create a distribution builder.
565
566 @param rootDirectory: root of a Twisted export which will populate
567 subsequent tarballs.
568 @type rootDirectory: L{FilePath}.
569
570 @param outputDirectory: The directory in which to create the tarballs.
571 @type outputDirectory: L{FilePath}
572
573 @type apiBaseURL: C{str} or C{NoneType}
574 @param apiBaseURL: A format string which will be interpolated with the
575 fully-qualified Python name for each API link. For example, to
576 generate the Twisted 8.0.0 documentation, pass
577 C{"http://twistedmatrix.com/documents/8.0.0/api/%s.html"}.
578 """
579 self.rootDirectory = rootDirectory
580 self.outputDirectory = outputDirectory
581 self.apiBaseURL = apiBaseURL
582 self.manBuilder = ManBuilder()
583 self.docBuilder = DocBuilder()
584
585
586 def _buildDocInDir(self, path, version, howtoPath):
587 """
588 Generate documentation in the given path, building man pages first if
589 necessary and swallowing errors (so that directories without lore
590 documentation in them are ignored).
591
592 @param path: The path containing documentation to build.
593 @type path: L{FilePath}
594 @param version: The version of the project to include in all generated
595 pages.
596 @type version: C{str}
597 @param howtoPath: The "resource path" as L{DocBuilder} describes it.
598 @type howtoPath: L{FilePath}
599 """
600 templatePath = self.rootDirectory.child("doc").child("core"
601 ).child("howto").child("template.tpl")
602 if path.basename() == "man":
603 self.manBuilder.build(path)
604 if path.isdir():
605 try:
606 self.docBuilder.build(version, howtoPath, path,
607 templatePath, self.apiBaseURL, True)
608 except NoDocumentsFound:
609 pass
610
611
612 def buildTwisted(self, version):
613 """
614 Build the main Twisted distribution in C{Twisted-<version>.tar.bz2}.
615
616 @type version: C{str}
617 @param version: The version of Twisted to build.
618
619 @return: The tarball file.
620 @rtype: L{FilePath}.
621 """
622 releaseName = "Twisted-%s" % (version,)
623 buildPath = lambda *args: '/'.join((releaseName,) + args)
624
625 outputFile = self.outputDirectory.child(releaseName + ".tar.bz2")
626 tarball = tarfile.TarFile.open(outputFile.path, 'w:bz2')
627
628 docPath = self.rootDirectory.child("doc")
629
630 # Generate docs!
631 if docPath.isdir():
632 for subProjectDir in docPath.children():
633 if (subProjectDir.isdir()
634 and subProjectDir.basename() not in self.blacklist):
635 for child in subProjectDir.walk():
636 self._buildDocInDir(child, version,
637 subProjectDir.child("howto"))
638
639 # Now, this part is nasty. We need to exclude blacklisted subprojects
640 # from the main Twisted distribution. This means we need to exclude
641 # their bin directories, their documentation directories, their
642 # plugins, and their python packages. Given that there's no "add all
643 # but exclude these particular paths" functionality in tarfile, we have
644 # to walk through all these directories and add things that *aren't*
645 # part of the blacklisted projects.
646
647 for binthing in self.rootDirectory.child("bin").children():
648 if binthing.basename() not in self.blacklist:
649 tarball.add(binthing.path,
650 buildPath("bin", binthing.basename()))
651
652 bad_plugins = ["twisted_%s.py" % (blacklisted,)
653 for blacklisted in self.blacklist]
654
655 for submodule in self.rootDirectory.child("twisted").children():
656 if submodule.basename() == "plugins":
657 for plugin in submodule.children():
658 if plugin.basename() not in bad_plugins:
659 tarball.add(plugin.path, buildPath("twisted", "plugins",
660 plugin.basename()))
661 elif submodule.basename() not in self.blacklist:
662 tarball.add(submodule.path, buildPath("twisted",
663 submodule.basename()))
664
665 for docDir in self.rootDirectory.child("doc").children():
666 if docDir.basename() not in self.blacklist:
667 tarball.add(docDir.path, buildPath("doc", docDir.basename()))
668
669 for toplevel in self.rootDirectory.children():
670 if not toplevel.isdir():
671 tarball.add(toplevel.path, buildPath(toplevel.basename()))
672
673 tarball.close()
674
675 return outputFile
676
677
678 def buildCore(self, version):
679 """
680 Build a core distribution in C{TwistedCore-<version>.tar.bz2}.
681
682 This is very similar to L{buildSubProject}, but core tarballs and the
683 input are laid out slightly differently.
684
685 - scripts are in the top level of the C{bin} directory.
686 - code is included directly from the C{twisted} directory, excluding
687 subprojects.
688 - all plugins except the subproject plugins are included.
689
690 @type version: C{str}
691 @param version: The version of Twisted to build.
692
693 @return: The tarball file.
694 @rtype: L{FilePath}.
695 """
696 releaseName = "TwistedCore-%s" % (version,)
697 outputFile = self.outputDirectory.child(releaseName + ".tar.bz2")
698 buildPath = lambda *args: '/'.join((releaseName,) + args)
699 tarball = self._createBasicSubprojectTarball(
700 "core", version, outputFile)
701
702 # Include the bin directory for the subproject.
703 for path in self.rootDirectory.child("bin").children():
704 if not path.isdir():
705 tarball.add(path.path, buildPath("bin", path.basename()))
706
707 # Include all files within twisted/ that aren't part of a subproject.
708 for path in self.rootDirectory.child("twisted").children():
709 if path.basename() == "plugins":
710 for plugin in path.children():
711 for subproject in self.subprojects:
712 if plugin.basename() == "twisted_%s.py" % (subproject,):
713 break
714 else:
715 tarball.add(plugin.path,
716 buildPath("twisted", "plugins",
717 plugin.basename()))
718 elif not path.basename() in self.subprojects + ["topfiles"]:
719 tarball.add(path.path, buildPath("twisted", path.basename()))
720
721 tarball.add(self.rootDirectory.child("twisted").child("topfiles").path,
722 releaseName)
723 tarball.close()
724
725 return outputFile
726
727
728 def buildSubProject(self, projectName, version):
729 """
730 Build a subproject distribution in
731 C{Twisted<Projectname>-<version>.tar.bz2}.
732
733 @type projectName: C{str}
734 @param projectName: The lowercase name of the subproject to build.
735 @type version: C{str}
736 @param version: The version of Twisted to build.
737
738 @return: The tarball file.
739 @rtype: L{FilePath}.
740 """
741 releaseName = "Twisted%s-%s" % (projectName.capitalize(), version)
742 outputFile = self.outputDirectory.child(releaseName + ".tar.bz2")
743 buildPath = lambda *args: '/'.join((releaseName,) + args)
744 subProjectDir = self.rootDirectory.child("twisted").child(projectName)
745
746 tarball = self._createBasicSubprojectTarball(projectName, version,
747 outputFile)
748
749 tarball.add(subProjectDir.child("topfiles").path, releaseName)
750
751 # Include all files in the subproject package except for topfiles.
752 for child in subProjectDir.children():
753 name = child.basename()
754 if name != "topfiles":
755 tarball.add(
756 child.path,
757 buildPath("twisted", projectName, name))
758
759 pluginsDir = self.rootDirectory.child("twisted").child("plugins")
760 # Include the plugin for the subproject.
761 pluginFileName = "twisted_%s.py" % (projectName,)
762 pluginFile = pluginsDir.child(pluginFileName)
763 if pluginFile.exists():
764 tarball.add(pluginFile.path,
765 buildPath("twisted", "plugins", pluginFileName))
766
767 # Include the bin directory for the subproject.
768 binPath = self.rootDirectory.child("bin").child(projectName)
769 if binPath.isdir():
770 tarball.add(binPath.path, buildPath("bin"))
771 tarball.close()
772
773 return outputFile
774
775
776 def _createBasicSubprojectTarball(self, projectName, version, outputFile):
777 """
778 Helper method to create and fill a tarball with things common between
779 subprojects and core.
780
781 @param projectName: The subproject's name.
782 @type projectName: C{str}
783 @param version: The version of the release.
784 @type version: C{str}
785 @param outputFile: The location of the tar file to create.
786 @type outputFile: L{FilePath}
787 """
788 releaseName = "Twisted%s-%s" % (projectName.capitalize(), version)
789 buildPath = lambda *args: '/'.join((releaseName,) + args)
790
791 tarball = tarfile.TarFile.open(outputFile.path, 'w:bz2')
792
793 tarball.add(self.rootDirectory.child("LICENSE").path,
794 buildPath("LICENSE"))
795
796 docPath = self.rootDirectory.child("doc").child(projectName)
797
798 if docPath.isdir():
799 for child in docPath.walk():
800 self._buildDocInDir(child, version, docPath.child("howto"))
801 tarball.add(docPath.path, buildPath("doc"))
802
803 return tarball
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/python/_epoll.pyx ('k') | third_party/twisted_8_1/twisted/python/_twisted_zsh_stub » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698