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 |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 26 | from distutils.util import change_root |
Jack Jansen | f7c8220 | 2003-05-27 22:47:55 +0000 | [diff] [blame] | 27 | import HelpIndexingTool |
| 28 | import Carbon.File |
| 29 | import time |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 30 | |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 31 | class DocBuild(build): |
| 32 | def initialize_options(self): |
| 33 | build.initialize_options(self) |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 34 | self.build_html = None |
| 35 | self.build_dest = None |
Jack Jansen | 006ebeb | 2003-06-28 23:38:04 +0000 | [diff] [blame] | 36 | self.download = 0 |
| 37 | self.doc_version = '2.3b1' # Only needed if download is true |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 38 | |
| 39 | def finalize_options(self): |
| 40 | build.finalize_options(self) |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 41 | if self.build_html is None: |
| 42 | self.build_html = os.path.join(self.build_base, 'html') |
| 43 | if self.build_dest is None: |
Jack Jansen | 006ebeb | 2003-06-28 23:38:04 +0000 | [diff] [blame] | 44 | self.build_dest = os.path.join(self.build_base, 'PythonDocumentation') |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 45 | |
| 46 | def spawn(self, *args): |
| 47 | spawn(args, 1, self.verbose, self.dry_run) |
| 48 | |
| 49 | def downloadDocs(self): |
| 50 | workdir = os.getcwd() |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 51 | url = 'http://www.python.org/ftp/python/doc/%s/html-%s.tgz' % \ |
| 52 | (self.doc_version,self.doc_version) |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 53 | os.chdir(self.build_base) |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 54 | self.spawn('curl','-O', url) |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 55 | os.chdir(workdir) |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 56 | tarfile = 'html-%s.tgz' % self.doc_version |
| 57 | ## This no longer works due to name changes |
| 58 | ## self.mkpath(self.build_html) |
| 59 | ## os.chdir(self.build_html) |
| 60 | ## self.spawn('tar', '-xzf', '../' + tarfile) |
| 61 | ## os.chdir(workdir) |
| 62 | print "** Please unpack %s" % os.path.join(self.build_base, tarfile) |
| 63 | print "** Unpack the files into %s" % self.build_html |
| 64 | raise RuntimeError, "You need to unpack the docs manually" |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 65 | |
Jack Jansen | f68043c | 2003-02-14 12:47:14 +0000 | [diff] [blame] | 66 | def buildDocsFromSource(self): |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 67 | srcdir = '../../..' |
| 68 | docdir = os.path.join(srcdir, 'Doc') |
| 69 | htmldir = os.path.join(docdir, 'html') |
| 70 | spawn(('make','--directory', docdir, 'html'), 1, self.verbose, self.dry_run) |
| 71 | self.mkpath(self.build_html) |
| 72 | copy_tree(htmldir, self.build_html) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 73 | |
| 74 | def ensureHtml(self): |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 75 | if not os.path.exists(self.build_html): |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 76 | if self.download: |
| 77 | self.downloadDocs() |
| 78 | else: |
| 79 | self.buildDocsFromSource() |
| 80 | |
| 81 | def hackIndex(self): |
| 82 | ind_html = 'index.html' |
| 83 | #print 'self.build_dest =', self.build_dest |
| 84 | hackedIndex = file(os.path.join(self.build_dest, ind_html),'w') |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 85 | origIndex = file(os.path.join(self.build_html,ind_html)) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 86 | r = re.compile('<style type="text/css">.*</style>', re.DOTALL) |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 87 | hackedIndex.write(r.sub('<META NAME="AppleTitle" CONTENT="Python Documentation">',origIndex.read())) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 88 | |
| 89 | def hackFile(self,d,f): |
| 90 | origPath = os.path.join(d,f) |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 91 | assert(origPath[:len(self.build_html)] == self.build_html) |
| 92 | outPath = os.path.join(self.build_dest, d[len(self.build_html)+1:], f) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 93 | (name, ext) = os.path.splitext(f) |
| 94 | if os.path.isdir(origPath): |
| 95 | self.mkpath(outPath) |
| 96 | elif ext == '.html': |
| 97 | if self.verbose: print 'hacking %s to %s' % (origPath,outPath) |
| 98 | hackedFile = file(outPath, 'w') |
| 99 | origFile = file(origPath,'r') |
| 100 | hackedFile.write(self.r.sub('<dl><dt><dd>', origFile.read())) |
| 101 | else: |
| 102 | copy_file(origPath, outPath) |
| 103 | |
| 104 | def hackHtml(self): |
| 105 | self.r = re.compile('<dl><dd>') |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 106 | os.path.walk(self.build_html, self.visit, None) |
| 107 | |
| 108 | def visit(self, dummy, dirname, filenames): |
| 109 | for f in filenames: |
| 110 | self.hackFile(dirname, f) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 111 | |
| 112 | def makeHelpIndex(self): |
| 113 | app = '/Developer/Applications/Apple Help Indexing Tool.app' |
| 114 | self.spawn('open', '-a', app , self.build_dest) |
| 115 | print "Please wait until Apple Help Indexing Tool finishes before installing" |
| 116 | |
Jack Jansen | f7c8220 | 2003-05-27 22:47:55 +0000 | [diff] [blame] | 117 | def makeHelpIndex(self): |
| 118 | app = HelpIndexingTool.HelpIndexingTool(start=1) |
| 119 | app.open(Carbon.File.FSSpec(self.build_dest)) |
| 120 | sys.stderr.write("Waiting for Help Indexing Tool to start...") |
| 121 | while 1: |
| 122 | # This is bad design in the suite generation code! |
| 123 | idle = app._get(HelpIndexingTool.Help_Indexing_Tool_Suite._Prop_idleStatus()) |
| 124 | time.sleep(10) |
| 125 | if not idle: break |
| 126 | sys.stderr.write(".") |
| 127 | sys.stderr.write("\n") |
| 128 | sys.stderr.write("Waiting for Help Indexing Tool to finish...") |
| 129 | while 1: |
| 130 | # This is bad design in the suite generation code! |
| 131 | idle = app._get(HelpIndexingTool.Help_Indexing_Tool_Suite._Prop_idleStatus()) |
| 132 | time.sleep(10) |
| 133 | if idle: break |
| 134 | sys.stderr.write(".") |
| 135 | sys.stderr.write("\n") |
| 136 | |
| 137 | |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 138 | def run(self): |
| 139 | self.ensure_finalized() |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 140 | self.mkpath(self.build_base) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 141 | self.ensureHtml() |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 142 | if not os.path.isdir(self.build_html): |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 143 | raise RuntimeError, \ |
| 144 | "Can't find source folder for documentation." |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 145 | self.mkpath(self.build_dest) |
| 146 | if dep_util.newer(os.path.join(self.build_html,'index.html'), os.path.join(self.build_dest,'index.html')): |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 147 | self.mkpath(self.build_dest) |
| 148 | self.hackHtml() |
| 149 | self.hackIndex() |
| 150 | self.makeHelpIndex() |
| 151 | |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 152 | class AHVDocInstall(Command): |
| 153 | description = "install Apple Help Viewer html files" |
| 154 | user_options = [('install-doc=', 'd', |
| 155 | 'directory to install HTML tree'), |
| 156 | ('root=', None, |
| 157 | "install everything relative to this alternate root directory"), |
| 158 | ] |
| 159 | |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 160 | def initialize_options(self): |
| 161 | self.build_dest = None |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 162 | self.install_doc = None |
| 163 | self.prefix = None |
| 164 | self.root = None |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 165 | |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 166 | def finalize_options(self): |
| 167 | self.set_undefined_options('install', |
| 168 | ('prefix', 'prefix'), |
| 169 | ('root', 'root')) |
| 170 | # import pdb ; pdb.set_trace() |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 171 | build_cmd = self.get_finalized_command('build') |
| 172 | if self.build_dest == None: |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 173 | build_cmd = self.get_finalized_command('build') |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 174 | self.build_dest = build_cmd.build_dest |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 175 | if self.install_doc == None: |
Jack Jansen | 08801db | 2003-03-16 22:09:22 +0000 | [diff] [blame] | 176 | self.install_doc = os.path.join(self.prefix, 'Resources/Python.app/Contents/Resources/English.lproj/PythonDocumentation') |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 177 | print 'INSTALL', self.build_dest, '->', self.install_doc |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 178 | |
| 179 | def run(self): |
| 180 | self.finalize_options() |
| 181 | self.ensure_finalized() |
| 182 | print "Running Installer" |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 183 | instloc = self.install_doc |
| 184 | if self.root: |
| 185 | instloc = change_root(self.root, instloc) |
| 186 | self.mkpath(instloc) |
| 187 | copy_tree(self.build_dest, instloc) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 188 | print "Installation complete" |
| 189 | |
| 190 | def mungeVersion(infile, outfile): |
| 191 | i = file(infile,'r') |
| 192 | o = file(outfile,'w') |
| 193 | o.write(re.sub('\$\(VERSION\)',sysconfig.get_config_var('VERSION'),i.read())) |
| 194 | i.close() |
| 195 | o.close() |
| 196 | |
| 197 | def main(): |
| 198 | # turn off warnings when deprecated modules are imported |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 199 | ## import warnings |
| 200 | ## warnings.filterwarnings("ignore",category=DeprecationWarning) |
| 201 | setup(name = 'Documentation', |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 202 | version = '%d.%d' % sys.version_info[:2], |
Jack Jansen | d2c684f | 2003-02-14 23:46:22 +0000 | [diff] [blame] | 203 | cmdclass = {'install_data':AHVDocInstall, 'build':DocBuild}, |
| 204 | data_files = ['dummy'], |
| 205 | ) |
Jack Jansen | 278a3a2 | 2002-08-28 22:22:10 +0000 | [diff] [blame] | 206 | |
| 207 | if __name__ == '__main__': |
| 208 | main() |