InstallDocs.py :  » XML » 4Suite » 4Suite-XML-1.0.2 » Ft » Lib » DistExt » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » XML » 4Suite 
4Suite » 4Suite XML 1.0.2 » Ft » Lib » DistExt » InstallDocs.py
import os, copy, rfc822, time, cStringIO
from distutils import util
from distutils.core import Command,DEBUG
from distutils.errors import *

from Ft import GetConfigVar
from Ft.Lib import Uri,ImportUtil
from Ft.Lib.DistExt import Structures
from Ft.Lib.DistExt.BuildDocs import ProcessIncludes

class Stylesheet:
    """Class used to hold various attributes of an XSLT stylesheet."""
    def __init__(self, uri, extra_outputs=None, mtime=None):
        self.uri = uri
        self.extra_outputs = extra_outputs
        self.mtime = mtime
        return

class InstallDocs(Command):
    """
    Base class for install sub-commands which install documentation.
    """

    user_options = [
        ('install-dir=', 'd', "directory to install documentation to"),
        ('build-dir=','b', "build directory (where to install from)"),
        ('force', 'f', "force installation (overwrite existing files)"),
        ('skip-build', None, "skip the build steps"),
        ]

    boolean_options = ['force', 'skip-build']

    def initialize_options(self):
        self.install_dir = None
        self.force = None
        self.build_dir = None
        self.skip_build = None

        # Stylesheets used for rendering the document files.
        self.docbook_xslt = None
        self.sdocbook_xslt = None
        self.modules_xslt = None
        self.extensions_xslt = None
        self.commandline_xslt = None
        self.docbook_html_xslt = None
        return

    def finalize_options(self):
        self.set_undefined_options('build_docs',
                                   ('build_dir', 'build_dir'))
        self.set_undefined_options('install',
                                   ('install_docs', 'install_dir'),
                                   ('skip_build', 'skip_build'),
                                   ('force', 'force'))
        self.documents = self.get_documents()

        resourcebundle = GetConfigVar('RESOURCEBUNDLE')
        if resourcebundle is None:
            # building 4Suite itself; use different (hard-wired) directories
            base_uri = Uri.OsPathToUri(os.path.join('Ft', 'Data'))
        else:
            datadir = GetConfigVar('DATADIR')
            datadir = os.path.join(datadir, 'Data', 'Stylesheets')
            if resourcebundle:
                resource = ImportUtil.OsPathToResource(datadir)
                base_uri = Uri.ResourceToUri('Ft.Lib', resource)
            else:
                base_uri = Uri.OsPathToUri(datadir)

        defaults = self.get_default_stylesheets()
        for name in defaults:
            attr = name + '_xslt'
            value = getattr(self, attr)
            if value is None:
                value = base_uri + '/' + defaults[name]
            else:
                pathname = util.convert_path(value)
                value = Uri.OsPathToUri(pathname)
            setattr(self, attr, value)

        self._xslt_processor = None
        self._stylesheets = {}
        return

    def get_documents(self):
        documents = []

        def new_document(category, name):
            """Returns a Document instance for the category/name pair."""
            xmlfile = os.path.join(self.build_dir, category, name + '.xml')
            return Structures.Document(xmlfile, category, category=category)

        for document in self.distribution.doc_files:
            if isinstance(document, Structures.Document):
                document = copy.copy(document)
                document.source = util.convert_path(document.source)
                documents.append(document)
            elif isinstance(document, Structures.ExtensionsDocument):
                documents.append(new_document('extensions', document.name))

        # Add Documents for the installed Python modules.
        if self.distribution.has_pure_modules():
            build_py = self.get_finalized_command('build_py')
            for package, module, filename in build_py.find_all_modules():
                if module == '__init__':
                    module = package
                elif package:
                    module = package + '.' + module
                documents.append(new_document('modules', module))
        if self.distribution.has_ext_modules():
            build_ext = self.get_finalized_command('build_ext')
            for extension in build_ext.extensions:
                name = build_ext.get_ext_fullname(extension.name)
                documents.append(new_document('modules', name))

        # Add the CommandLineApp-based scripts
        for script in self.distribution.scripts:
            if script.application is not None:
                documents.append(new_document('commandline', script.name))
        return documents

    def run(self):
        if not self.skip_build:
            self.run_command('build_docs')

        self.render_documents()
        return

    # -- Top-level worker functions ------------------------------------
    # (called from 'run()')

    def render_documents(self):
        extras = {}
        for document in self.documents:
            # Find the stylesheet to render this document
            stylesheet = self.get_stylesheet_obj(document.stylesheet)

            filename = self.get_output_filename(document)
            destdir = os.path.dirname(filename)
            self.mkpath(destdir)
            try:
                target_mtime = os.path.getmtime(filename)
            except OSError:
                target_mtime = -1
            document.uri = Uri.OsPathToUri(document.source)
            document_mtime = self.get_modification_time(document.uri)
            source_mtime = max(document_mtime, stylesheet.mtime)
            if document_mtime is None:
                self.announce('skipping %s (not documented)' % filename, 3)
            elif self.force or source_mtime > target_mtime:
                self.announce("rendering %s -> %s" % (document.source,
                                                      filename), 2)
                try:
                    self.render_document(document, stylesheet, filename)
                except (KeyboardInterrupt, SystemExit):
                    # Let "exitting" exceptions propagate through.
                    raise
                except Exception, exc:
                    if DEBUG: raise
                    raise DistutilsFileError(
                        "could not render %s (%s)" % (document.source, exc))
            else:
                self.announce('not rendering %s (up-to-date)' % filename, 1)

            # Copy any extra files for the stylesheet to destdir.
            # 'extra_outputs' is a list of URIs.
            for uri in stylesheet.extra_outputs:
                pathname = Uri.Relativize(uri, stylesheet.uri)
                target = os.path.join(destdir, *pathname.split('/'))
                if target not in extras:
                    extras[target] = True
                    self.copy_uri(uri, target)
        return

    def render_document(self, document, stylesheet, outfile):
        """
        This method is responsible for using 'stylesheet' to transform
        'document' to the file 'outfile'.

        Override this method to use a different XSLT rendering engine.
        """
        from Ft.Xml.InputSource import DefaultFactory
        from Ft.Xml.Xslt import Processor

        # Get a "clean" processor object
        if self._xslt_processor is None:
            self._xslt_processor = Processor.Processor()
        else:
            self._xslt_processor.reset()

        # Add the stylesheet to the processor object.
        isrc = DefaultFactory.fromUri(stylesheet.uri)
        try:
            self._xslt_processor.appendStylesheet(isrc)
        finally:
            isrc.close()

        params = {'name' : self.distribution.get_name(),
                  'version' : self.distribution.version,
                  'fullname' : self.distribution.get_fullname(),
                  'author' : self.distribution.author,
                  'author-email' : self.distribution.author_email,
                  }
        params.update(document.params)

        # Render the document
        isrc = DefaultFactory.fromUri(document.uri)
        try:
            if self.dry_run:
                stream = cStringIO.StringIO()
            else:
                self.mkpath(os.path.dirname(outfile))
                stream = open(outfile, 'w')
            try:
                try:
                    self._xslt_processor.run(isrc, topLevelParams=params,
                                             outputStream=stream)
                    stream.write('\n')
                finally:
                    stream.close()
            except:
                if not self.dry_run:
                    os.remove(outfile)
                raise
        finally:
            isrc.close()
        return

    # -- Utility methods ---------------------------------------------

    def get_stylesheet_obj(self, stylesheet):
        if stylesheet in self._stylesheets:
            return self._stylesheets[stylesheet]

        uri = getattr(self, stylesheet + '_xslt', None)
        if uri is None:
            raise DistutilsFileError("no stylesheet file defined for '%s'"
                                     % stylesheet)
        extras = self.get_stylesheet_extras(stylesheet, uri)
        mtime = self.get_modification_time(uri, True)
        obj = self._stylesheets[stylesheet] = Stylesheet(uri, extras, mtime)
        return obj

    def get_stylesheet_extras(self, stylesheet):
        return []

    def get_modification_time(self, uri, xslt=False, _mtimes=None):
        if _mtimes is None:
            _mtimes = {}
        def gather_mtimes(fullurl):
            if fullurl not in _mtimes:
                _mtimes[fullurl] = -1
                self.get_modification_time(fullurl, xslt, _mtimes)
            return
        try:
            source = Uri.UrlOpen(uri)
        except EnvironmentError:
            mtime = None
        else:
            mtime = source.headers.getdate_tz('last-modified')
            mtime = rfc822.mktime_tz(mtime)
            ProcessIncludes(source, gather_mtimes, xslt)
        _mtimes[uri] = mtime
        return max(_mtimes.values())

    def copy_uri(self, uri, filename):
        """
        Copies the contents of the resource given by 'uri' to 'filename'.
        """
        source = Uri.UrlOpen(uri)
        try:
            source_mtime = source.headers.getdate_tz('last-modified')
            source_mtime = rfc822.mktime_tz(source_mtime)
            try:
                target_mtime = os.path.getmtime(filename)
            except OSError:
                target_mtime = -1
            if not (self.force or source_mtime > target_mtime):
                self.announce("not copying %s (output up-to-date)" % uri, 1)
                return filename, False

            self.announce("copying %s -> %s" % (uri, filename), 2)
            if not self.dry_run:
                f = open(filename, 'wb')
                try:
                    f.write(source.read())
                finally:
                    f.close()
        finally:
            source.close()
        return filename, True

    # -- Reporting methods ---------------------------------------------

    def get_source_files(self):
        # The sources are assumed to be reported by 'build_docs'
        return []

    def get_inputs(self):
        build_docs = self.get_finalized_command('build_docs')
        return build_docs.get_outputs()

    def get_outputs(self):
        outputs = []
        extras = {}
        for document in self.documents:
            filename = self.get_output_filename(document)
            outputs.append(filename)
            destdir = os.path.dirname(filename)
            stylesheet = self.get_stylesheet_obj(document.stylesheet)
            for source in stylesheet.extra_outputs:
                target = os.path.join(destdir, os.path.basename(source))
                if target not in extras:
                    extras[target] = True
                    outputs.append(target)
        return outputs
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.