[Checkins] SVN: Sandbox/ulif/grok-reference-with-rest2/doc/grokref/grokref2html.py Modified publisher, that makes use of simplified roles/directives.

Uli Fouquet uli at gnufix.de
Thu Jan 10 18:47:04 EST 2008


Log message for revision 82789:
  Modified publisher, that makes use of simplified roles/directives.

Changed:
  U   Sandbox/ulif/grok-reference-with-rest2/doc/grokref/grokref2html.py

-=-
Modified: Sandbox/ulif/grok-reference-with-rest2/doc/grokref/grokref2html.py
===================================================================
--- Sandbox/ulif/grok-reference-with-rest2/doc/grokref/grokref2html.py	2008-01-10 23:43:47 UTC (rev 82788)
+++ Sandbox/ulif/grok-reference-with-rest2/doc/grokref/grokref2html.py	2008-01-10 23:47:03 UTC (rev 82789)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -13,116 +13,233 @@
 ##############################################################################
 """Create the grok reference in various output formats."""
 
+import sys
+import re
 import time
+import os
+import os.path
 
-from docutils import nodes
-from docutils.core import publish_cmdline, default_description
+from docutils import nodes, SettingsSpec
+from docutils.core import publish_cmdline, publish_file, default_description
+from docutils.core import default_usage, default_description
+from docutils.frontend import OptionParser
 from docutils.readers.standalone import Reader
 from docutils.transforms import Transform
 from docutils.transforms.universal import FilterMessages
 from docutils.parsers.rst import Parser
-
 from docutils.writers.s5_html import Writer as S5Writer
-from docutils.writers.s5_html import S5HTMLTranslator as S5BaseTranslator
-
 from docutils.writers.latex2e import Writer as LaTeX2eWriter
 
-from extensions import directives, roles
-from extensions.translators import HTMLTranslator
+# Register plain (non-sphinx) directives and roles.
+from extensions import directives_plain, roles_plain
 
 
 class AdditionalSubstitutions(Transform):
+    """Substitute keywords based on the settings `substitutions`
+    dictionary.
+    """
     default_priority = 210
+    
     def apply(self):
-        config = self.document.settings.reference_settings
+        config = self.document.settings
+        substitutions = config.substitutions
         for ref in self.document.traverse(nodes.substitution_reference):
             refname = ref['refname']
-            text = config.get(refname, None)
+            text = substitutions.get(refname, None)
             ref.replace_self(nodes.Text(text, text))
         return
 
 class ReferenceReader(Reader):
+    """A reader that performs additional substitutions.
+    """
     def get_transforms(self):
         tf = Reader.get_transforms(self)
         return tf + [AdditionalSubstitutions, FilterMessages]
 
 
 class ReferenceParser(Parser):
+    """A marker class."""
     pass
 
-class ReferenceTranslatorS5(S5BaseTranslator, HTMLTranslator):
-    def __init__(self, *args, **kwds):
-        S5BaseTranslator.__init__(self, *args, **kwds)
-        self.highlightlang = 'python'
 
-    def unknown_visit(self, node):
-        print "UNKNOWN: ", node
-    def unknown_departure(self, node):
-        pass
-
 class ReferenceS5Writer(S5Writer):
-    def __init__(self, *args, **kw):
-        S5Writer.__init__(self)
-        self.translator_class = ReferenceTranslatorS5
+    """A marker class."""
+    pass
 
 
 class ReferenceLaTeX2eWriter(LaTeX2eWriter):
+    """A marker class."""
     pass
 
 
-class ReferenceProducer(object):
+class ReferencePublisher(object):
+    """A publisher for reference docs in ReST format.
+
+    Renders the ReST files of a directory into HTML.
     """
-    """
 
-    settings = {
-        'filename': None,
-        'today': '01/01/1970',
-        'version': 'None',
-        'release': 'unknown'
-        }
-
+    settings = {}
+    usage = '%prog [options] <source-dir> [<destination-dir>]'
     description = ('Generates reference documents from standalone '
-                   'reStructuredText sources.  ' + default_description)        
+                   'reStructuredText sources. '
+                   ' '
+                   'If no destination directory is given, everything '
+                   'will be rendered into the source directory. '
+                   )
 
-    def __init__(self, filename=None):
+    def __init__(self):
         self.reader = ReferenceReader()
         self.parser = ReferenceParser()
         self.writer = ReferenceS5Writer()
-        # Values from the `settings` directory can be used as
-        # substituted values in documents.  For example it is possible
-        # to use |foo| and this term will be substituted by a value
-        # defined in self.settings, called `foo`.  If such a key does
-        # not exist, a warning will be generated.  This requires a
-        # reader of type 'ReferenceReader'.
-        self.settings = {
-            'filename': filename,
+        
+        # Substitutions, that should be replaced during rendering...
+        self.subs = {
             'today': time.strftime('%B %d, %Y'),
-            'version': 'foo',
-            'release': 'bar'
-            }
+            'version': 'unknown',
+            'release': 'unknown'
+        }
 
-    def publish(self):
-        """Generate the reference."""
-        settings_overrides = {
+        # Default settings for reading, parsing, writing...
+        self.settings = {
             'halt_level': 6,
             'input_encoding': 'utf8',
             'output_encoding': 'utf8',
             'initial_header_level': 2,
             # don't try to include the stylesheet (docutils gets hiccups)
             'stylesheet_path': '',
-            'reference_settings' : self.settings,
+            'substitutions': self.subs,
         }
-        publish_cmdline(
-            reader=self.reader,
-            writer=self.writer,
-            parser=self.parser,
-            description=self.description,
-            settings_overrides=settings_overrides
-            )
-        
 
+        # Read settings with commandline options set...
+        self.processCommandLine(usage=self.usage,
+                                description=self.description,
+                                **self.settings)
+
+        self.subs['version'] = self.getVersionInfo()
+        self.subs['release'] = self.subs['version']
+        # The source directory...
+        self.dirname = os.path.normpath(os.path.abspath(
+            self.settings['_source']))
+        self.filelist = self.getFileList(self.dirname, '*.rst')
+        return
+
+
+    def getFileList(self, dirname, pattern):
+        """Get the list of files we will parse.
+        """
+        import fnmatch
+        try:
+            if os.path.isfile(dirname):
+                return [dirname]
+        except OSError:
+            return []
+        try:
+            result = [filename for filename in os.listdir(dirname)
+                      if fnmatch.fnmatch(filename, pattern) and
+                      os.path.isfile(os.path.join(dirname, filename))]
+        except OSError:
+            return []
+        result.sort()
+        return result
+
+    def setupOptionParser(self, usage=None, description=None,
+                            settings_spec=None, config_section=None,
+                            **defaults):
+        """Setup options for commandline.
+        """
+        if config_section:
+            if not settings_spec:
+                settings_spec = SettingsSpec()
+            settings_spec.config_section = config_section
+            parts = config_section.split()
+            if len(parts) > 1 and parts[-1] == 'application':
+                settings_spec.config_section_dependencies = ['applications']
+        option_parser = OptionParser(
+            components=(self.parser, self.reader, self.writer, settings_spec),
+            defaults=defaults, read_config_files=1,
+            usage=usage, description=description)
+        return option_parser
+
+
+          
+    def processCommandLine(self, argv=None, usage=None, description=None,
+                             settings_spec=None, config_section=None,
+                             **defaults):
+        """
+        Pass an empty list to `argv` to avoid reading `sys.argv` (the
+        default).
+        """
+        option_parser = self.setupOptionParser(
+            usage, description, settings_spec, config_section, **defaults)
+        if argv is None:
+            argv = sys.argv[1:]
+        settings = option_parser.parse_args(argv)
+        # Turn the `optparse` values instance in `settings` into a
+        # real dictionary, so that is can be handled by docutils
+        # publishers.
+        self.settings = {}
+        for key, val in settings.__dict__.items():
+            self.settings[key] = val
+        return
+
+
+    def getVersionInfo(self):
+        """Determine the release number.
+
+        We read the version info from the setup.py file two
+        directories above.
+        """
+        selfdir = os.path.dirname(__file__)
+        setup_file = os.path.join(selfdir, '..', '..', 'setup.py')
+        setup_file = os.path.abspath(setup_file)
+        try:
+            fp = open(setup_file, 'r')
+        except OSError:
+            return 'unknown'
+        reg_exp = re.compile("^\s*version\s*=\s*('|\")(.+)('|\")\s*")
+        for line in fp:
+            m = reg_exp.match(line)
+            if not m:
+                continue
+            return m.groups()[1]
+        return 'unknown'
+
+
+    def getInOutFilenames(self, filename):
+        """Compute the absolute filenames of input and output based on
+        commandline parameters.
+        """
+        src_path = os.path.abspath(os.path.join(self.dirname, filename))
+        if self.settings['_destination'] is not None:
+            dest_path = os.path.join(self.settings['_destination'], filename)
+        else:
+            dest_path = src_path
+        dest_path = os.path.splitext(dest_path)[0] + '.html'
+        return (src_path, dest_path)
+
+
+    def publish(self):
+        """Generate the reference.
+
+        Read a bunch of files, render and output it. TOCtrees and
+        references are not resolved in this plain version.
+        """
+        print "Reading sources from %s." % (self.dirname,)
+        for filename in self.filelist:
+            src_path, dest_path = self.getInOutFilenames(filename)
+            print "Writing %s..." %  dest_path
+            publish_file(
+                source_path=src_path,
+                destination_path=dest_path,
+                reader=self.reader,
+                writer=self.writer,
+                parser=self.parser,
+                settings_overrides=self.settings
+                )
+        return
+
 def main():
-    reference = ReferenceProducer().publish()
+    reference = ReferencePublisher().publish()
 
 if __name__ == '__main__':
     main()



More information about the Checkins mailing list