| # Build and install an Apple Help Viewer compatible version of the Python | 
 | # documentation into the framework. | 
 | # Code by Bill Fancher, with some modifications by Jack Jansen. | 
 | # | 
 | # You must run this as a two-step process | 
 | # 1. python setupDocs.py build | 
 | # 2. Wait for Apple Help Indexing Tool to finish | 
 | # 3. python setupDocs.py install | 
 | # | 
 | # To do: | 
 | # - test whether the docs are available locally before downloading | 
 | # - fix buildDocsFromSource | 
 | # - Get documentation version from sys.version, fallback to 2.2.1 | 
 | # - See if we can somehow detect that Apple Help Indexing Tool is finished | 
 | # - data_files to setup() doesn't seem the right way to pass the arguments | 
 | # | 
 | import sys, os, re | 
 | from distutils.cmd import Command | 
 | from distutils.command.build import build | 
 | from distutils.core import setup | 
 | from distutils.file_util import copy_file | 
 | from distutils.dir_util import copy_tree | 
 | from distutils.log import log | 
 | from distutils.spawn import spawn | 
 | from distutils import sysconfig, dep_util | 
 | from distutils.util import change_root | 
 | import HelpIndexingTool | 
 | import Carbon.File | 
 | import time | 
 |  | 
 | MAJOR_VERSION='2.4' | 
 | MINOR_VERSION='2.4.1' | 
 | DESTDIR='/Applications/MacPython-%s/PythonIDE.app/Contents/Resources/English.lproj/PythonDocumentation' % MAJOR_VERSION | 
 |  | 
 | class DocBuild(build): | 
 |     def initialize_options(self): | 
 |         build.initialize_options(self) | 
 |         self.build_html = None | 
 |         self.build_dest = None | 
 |         self.download = 1 | 
 |         self.doc_version = MINOR_VERSION # Only needed if download is true | 
 |  | 
 |     def finalize_options(self): | 
 |         build.finalize_options(self) | 
 |         if self.build_html is None: | 
 |             self.build_html = os.path.join(self.build_base, 'html') | 
 |         if self.build_dest is None: | 
 |             self.build_dest = os.path.join(self.build_base, 'PythonDocumentation') | 
 |  | 
 |     def spawn(self, *args): | 
 |         spawn(args, 1,  self.verbose, self.dry_run) | 
 |  | 
 |     def downloadDocs(self): | 
 |         workdir = os.getcwd() | 
 |         # XXX Note: the next strings may change from version to version | 
 |         url = 'http://www.python.org/ftp/python/doc/%s/html-%s.tar.bz2' % \ | 
 |                 (self.doc_version,self.doc_version) | 
 |         tarfile = 'html-%s.tar.bz2' % self.doc_version | 
 |         dirname = 'Python-Docs-%s' % self.doc_version | 
 |  | 
 |         if os.path.exists(self.build_html): | 
 |             raise RuntimeError('%s: already exists, please remove and try again' % self.build_html) | 
 |         os.chdir(self.build_base) | 
 |         self.spawn('curl','-O', url) | 
 |         self.spawn('tar', '-xjf', tarfile) | 
 |         os.rename(dirname, 'html') | 
 |         os.chdir(workdir) | 
 | ##        print "** Please unpack %s" % os.path.join(self.build_base, tarfile) | 
 | ##        print "** Unpack the files into %s" % self.build_html | 
 | ##        raise RuntimeError, "You need to unpack the docs manually" | 
 |  | 
 |     def buildDocsFromSource(self): | 
 |         srcdir = '../../..' | 
 |         docdir = os.path.join(srcdir, 'Doc') | 
 |         htmldir = os.path.join(docdir, 'html') | 
 |         spawn(('make','--directory', docdir, 'html'), 1, self.verbose, self.dry_run) | 
 |         self.mkpath(self.build_html) | 
 |         copy_tree(htmldir, self.build_html) | 
 |  | 
 |     def ensureHtml(self): | 
 |         if not os.path.exists(self.build_html): | 
 |             if self.download: | 
 |                 self.downloadDocs() | 
 |             else: | 
 |                 self.buildDocsFromSource() | 
 |  | 
 |     def hackIndex(self): | 
 |         ind_html = 'index.html' | 
 |         #print 'self.build_dest =', self.build_dest | 
 |         hackedIndex = file(os.path.join(self.build_dest, ind_html),'w') | 
 |         origIndex = file(os.path.join(self.build_html,ind_html)) | 
 |         r = re.compile('<style type="text/css">.*</style>', re.DOTALL) | 
 |         hackedIndex.write(r.sub('<META NAME="AppleTitle" CONTENT="Python Documentation">',origIndex.read())) | 
 |  | 
 |     def hackFile(self,d,f): | 
 |         origPath = os.path.join(d,f) | 
 |         assert(origPath[:len(self.build_html)] == self.build_html) | 
 |         outPath = os.path.join(self.build_dest, d[len(self.build_html)+1:], f) | 
 |         (name, ext) = os.path.splitext(f) | 
 |         if os.path.isdir(origPath): | 
 |             self.mkpath(outPath) | 
 |         elif ext == '.html': | 
 |             if self.verbose: print('hacking %s to %s' % (origPath,outPath)) | 
 |             hackedFile = file(outPath, 'w') | 
 |             origFile = file(origPath,'r') | 
 |             hackedFile.write(self.r.sub('<dl><dt><dd>', origFile.read())) | 
 |         else: | 
 |             copy_file(origPath, outPath) | 
 |  | 
 |     def hackHtml(self): | 
 |         self.r = re.compile('<dl><dd>') | 
 |         os.walk(self.build_html, self.visit, None) | 
 |  | 
 |     def visit(self, dummy, dirname, filenames): | 
 |         for f in filenames: | 
 |             self.hackFile(dirname, f) | 
 |  | 
 |     def makeHelpIndex(self): | 
 |         app = '/Developer/Applications/Apple Help Indexing Tool.app' | 
 |         self.spawn('open', '-a', app , self.build_dest) | 
 |         print("Please wait until Apple Help Indexing Tool finishes before installing") | 
 |  | 
 |     def makeHelpIndex(self): | 
 |         app = HelpIndexingTool.HelpIndexingTool(start=1) | 
 |         app.open(Carbon.File.FSSpec(self.build_dest)) | 
 |         sys.stderr.write("Waiting for Help Indexing Tool to start...") | 
 |         while 1: | 
 |             # This is bad design in the suite generation code! | 
 |             idle = app._get(HelpIndexingTool.Help_Indexing_Tool_Suite._Prop_idleStatus()) | 
 |             time.sleep(10) | 
 |             if not idle: break | 
 |             sys.stderr.write(".") | 
 |         sys.stderr.write("\n") | 
 |         sys.stderr.write("Waiting for Help Indexing Tool to finish...") | 
 |         while 1: | 
 |             # This is bad design in the suite generation code! | 
 |             idle = app._get(HelpIndexingTool.Help_Indexing_Tool_Suite._Prop_idleStatus()) | 
 |             time.sleep(10) | 
 |             if idle: break | 
 |             sys.stderr.write(".") | 
 |         sys.stderr.write("\n") | 
 |  | 
 |  | 
 |     def run(self): | 
 |         self.ensure_finalized() | 
 |         self.mkpath(self.build_base) | 
 |         self.ensureHtml() | 
 |         if not os.path.isdir(self.build_html): | 
 |             raise RuntimeError("Can't find source folder for documentation.") | 
 |         self.mkpath(self.build_dest) | 
 |         if dep_util.newer(os.path.join(self.build_html,'index.html'), os.path.join(self.build_dest,'index.html')): | 
 |             self.mkpath(self.build_dest) | 
 |             self.hackHtml() | 
 |             self.hackIndex() | 
 |             self.makeHelpIndex() | 
 |  | 
 | class AHVDocInstall(Command): | 
 |     description = "install Apple Help Viewer html files" | 
 |     user_options = [('install-doc=', 'd', | 
 |             'directory to install HTML tree'), | 
 |              ('root=', None, | 
 |              "install everything relative to this alternate root directory"), | 
 |             ] | 
 |  | 
 |     def initialize_options(self): | 
 |         self.build_dest = None | 
 |         self.install_doc = None | 
 |         self.prefix = None | 
 |         self.root = None | 
 |  | 
 |     def finalize_options(self): | 
 |         self.set_undefined_options('install', | 
 |                 ('prefix', 'prefix'), | 
 |                 ('root', 'root')) | 
 | #               import pdb ; pdb.set_trace() | 
 |         build_cmd = self.get_finalized_command('build') | 
 |         if self.build_dest is None: | 
 |             build_cmd = self.get_finalized_command('build') | 
 |             self.build_dest = build_cmd.build_dest | 
 |         if self.install_doc is None: | 
 |             self.install_doc = os.path.join(self.prefix, DESTDIR) | 
 |         print('INSTALL', self.build_dest, '->', self.install_doc) | 
 |  | 
 |     def run(self): | 
 |         self.finalize_options() | 
 |         self.ensure_finalized() | 
 |         print("Running Installer") | 
 |         instloc = self.install_doc | 
 |         if self.root: | 
 |             instloc = change_root(self.root, instloc) | 
 |         self.mkpath(instloc) | 
 |         copy_tree(self.build_dest, instloc) | 
 |         print("Installation complete") | 
 |  | 
 | def mungeVersion(infile, outfile): | 
 |     i = file(infile,'r') | 
 |     o = file(outfile,'w') | 
 |     o.write(re.sub('\$\(VERSION\)',sysconfig.get_config_var('VERSION'),i.read())) | 
 |     i.close() | 
 |     o.close() | 
 |  | 
 | def main(): | 
 |     # turn off warnings when deprecated modules are imported | 
 | ##      import warnings | 
 | ##      warnings.filterwarnings("ignore",category=DeprecationWarning) | 
 |     setup(name = 'Documentation', | 
 |             version = '%d.%d' % sys.version_info[:2], | 
 |             cmdclass = {'install_data':AHVDocInstall, 'build':DocBuild}, | 
 |             data_files = ['dummy'], | 
 |             ) | 
 |  | 
 | if __name__ == '__main__': | 
 |     main() |