Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 1 | # Build and install an Apple Help Viewer compatible version of the Python |
| 2 | # documentation into the framework. |
| 3 | # Code by Bill Fancher, with some modifications by Jack Jansen. |
| 4 | # |
| 5 | # You must run this as a two-step process |
| 6 | # 1. python setupDocs.py build |
| 7 | # 2. Wait for Apple Help Indexing Tool to finish |
| 8 | # 3. python setupDocs.py install |
| 9 | # |
| 10 | # To do: |
| 11 | # - test whether the docs are available locally before downloading |
| 12 | # - fix buildDocsFromSource |
| 13 | # - Get documentation version from sys.version, fallback to 2.2.1 |
| 14 | # - See if we can somehow detect that Apple Help Indexing Tool is finished |
| 15 | # - data_files to setup() doesn't seem the right way to pass the arguments |
| 16 | # |
| 17 | import sys, os, re |
| 18 | from distutils.cmd import Command |
| 19 | from distutils.command.build import build |
| 20 | from distutils.core import setup |
| 21 | from distutils.file_util import copy_file |
| 22 | from distutils.dir_util import copy_tree |
| 23 | from distutils.log import log |
| 24 | from distutils.spawn import spawn |
| 25 | from distutils import sysconfig, dep_util |
| 26 | |
| 27 | def visit(arg, d,l): |
| 28 | for f in l: |
| 29 | arg.hackFile(d,f) |
| 30 | |
| 31 | class DocBuild(build): |
| 32 | def initialize_options(self): |
| 33 | build.initialize_options(self) |
| 34 | self.doc_dir = None |
| 35 | self.base_dir = None |
| 36 | self.build_dir = None |
| 37 | self.download = 1 |
| 38 | self.doc_version = '2.2.1' |
| 39 | |
| 40 | def finalize_options(self): |
| 41 | build.finalize_options(self) |
| 42 | if self.build_dir is None: |
| 43 | self.build_dir = self.build_temp |
| 44 | if self.doc_dir is None: |
| 45 | self.doc_dir = data_info = self.distribution.data_files[0][1][0] |
| 46 | self.build_dest = os.path.abspath(os.path.join(self.build_dir,self.doc_dir)) |
| 47 | #print 'DocBuild.finalize_options:\n build_dest = %s,\n doc_dir = %s' % (self.build_dest, self.doc_dir) |
| 48 | |
| 49 | def spawn(self, *args): |
| 50 | spawn(args, 1, self.verbose, self.dry_run) |
| 51 | |
| 52 | def downloadDocs(self): |
| 53 | workdir = os.getcwd() |
| 54 | self.spawn('curl','-O', 'http://www.python.org/ftp/python/doc/%s/html-%s.tgz' % (self.doc_version,self.doc_version)) |
| 55 | self.mkpath(self.doc_dir) |
| 56 | os.chdir(self.doc_dir) |
| 57 | self.spawn('tar', '-xzf', '../html-%s.tgz' % self.doc_version) |
| 58 | os.chdir(workdir); |
| 59 | |
| 60 | def buildDocsFromSouce(self): |
| 61 | #Totally untested |
| 62 | spawn(('make','--directory', '../Docs'), 1, self.verbose, self.dry_run) |
| 63 | copy_tree('../Docs/html', self.doc_dir) |
| 64 | |
| 65 | def ensureHtml(self): |
| 66 | if not os.path.exists(self.doc_dir): |
| 67 | if self.download: |
| 68 | self.downloadDocs() |
| 69 | else: |
| 70 | self.buildDocsFromSource() |
| 71 | |
| 72 | def hackIndex(self): |
| 73 | ind_html = 'index.html' |
| 74 | #print 'self.build_dest =', self.build_dest |
| 75 | hackedIndex = file(os.path.join(self.build_dest, ind_html),'w') |
| 76 | origIndex = file(os.path.join(self.doc_dir,ind_html)) |
| 77 | r = re.compile('<style type="text/css">.*</style>', re.DOTALL) |
| 78 | hackedIndex.write(r.sub('<META NAME="AppleTitle" CONTENT="Python Help">',origIndex.read())) |
| 79 | |
| 80 | def hackFile(self,d,f): |
| 81 | origPath = os.path.join(d,f) |
| 82 | outPath = os.path.join(self.build_dir, d, f) |
| 83 | (name, ext) = os.path.splitext(f) |
| 84 | if os.path.isdir(origPath): |
| 85 | self.mkpath(outPath) |
| 86 | elif ext == '.html': |
| 87 | if self.verbose: print 'hacking %s to %s' % (origPath,outPath) |
| 88 | hackedFile = file(outPath, 'w') |
| 89 | origFile = file(origPath,'r') |
| 90 | hackedFile.write(self.r.sub('<dl><dt><dd>', origFile.read())) |
| 91 | else: |
| 92 | copy_file(origPath, outPath) |
| 93 | |
| 94 | def hackHtml(self): |
| 95 | self.r = re.compile('<dl><dd>') |
| 96 | os.path.walk(self.doc_dir, visit, self) |
| 97 | |
| 98 | def makeHelpIndex(self): |
| 99 | app = '/Developer/Applications/Apple Help Indexing Tool.app' |
| 100 | self.spawn('open', '-a', app , self.build_dest) |
| 101 | print "Please wait until Apple Help Indexing Tool finishes before installing" |
| 102 | |
| 103 | def run(self): |
| 104 | self.ensure_finalized() |
| 105 | self.ensureHtml() |
| 106 | data_info = self.distribution.data_files[0][1] |
| 107 | if not os.path.isdir(self.doc_dir): |
| 108 | raise RuntimeError, \ |
| 109 | "Can't find source folder for documentation." |
| 110 | if dep_util.newer(os.path.join(self.doc_dir,'index.html'), os.path.join(self.build_dest,'index.html')): |
| 111 | self.mkpath(self.build_dest) |
| 112 | self.hackHtml() |
| 113 | self.hackIndex() |
| 114 | self.makeHelpIndex() |
| 115 | |
| 116 | class DirInstall(Command): |
| 117 | def initialize_options(self): |
| 118 | self.build_dest = None |
| 119 | self.install_dir = None |
| 120 | |
| 121 | def finalize_options(self): |
| 122 | build_cmd = self.get_finalized_command('build') |
| 123 | if self.build_dest == None: |
| 124 | self.build_dest = build_cmd.build_dest |
| 125 | if self.install_dir == None: |
| 126 | self.install_dir = self.distribution.data_files[0][0] |
| 127 | print self.build_dest, self.install_dir |
| 128 | |
| 129 | def run(self): |
| 130 | self.finalize_options() |
| 131 | self.ensure_finalized() |
| 132 | print "Running Installer" |
| 133 | data_info = self.distribution.data_files[0][1] |
| 134 | # spawn('pax','-r', '-w', base_dir, |
| 135 | print self.__dict__ |
| 136 | self.mkpath(self.install_dir) |
| 137 | # The Python way |
| 138 | copy_tree(self.build_dest, self.install_dir) |
| 139 | # The fast way |
| 140 | #workdir=os.getcwd() |
| 141 | #os.chdir(self.build_dest) |
| 142 | #self.spawn = ('pax', '-r', '-w', '.', self.install_dir) |
| 143 | #selfspawn(cmd, 1, self.verbose, self.dry_run); |
| 144 | #os.chdir(workdir) |
| 145 | print "Installation complete" |
| 146 | |
| 147 | def mungeVersion(infile, outfile): |
| 148 | i = file(infile,'r') |
| 149 | o = file(outfile,'w') |
| 150 | o.write(re.sub('\$\(VERSION\)',sysconfig.get_config_var('VERSION'),i.read())) |
| 151 | i.close() |
| 152 | o.close() |
| 153 | |
| 154 | def main(): |
| 155 | # turn off warnings when deprecated modules are imported |
| 156 | import warnings |
| 157 | warnings.filterwarnings("ignore",category=DeprecationWarning) |
| 158 | setup(name = 'Python Documentation', |
| 159 | version = '%d.%d' % sys.version_info[:2], |
| 160 | cmdclass = {'install_data':DirInstall, 'build':DocBuild}, |
| 161 | # Data to install |
| 162 | data_files = [(sys.prefix+'/Resources/English.lproj/Documentation',['build-html'])] |
| 163 | ) |
| 164 | |
| 165 | if __name__ == '__main__': |
| 166 | main() |