[Checkins] SVN: Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/ Added 'plain' directives/roles, that do not require additional node types to improve docutils compatibility.

Uli Fouquet uli at gnufix.de
Thu Jan 10 18:43:48 EST 2008


Log message for revision 82788:
  Added 'plain' directives/roles, that do not require additional node types to improve docutils compatibility.

Changed:
  A   Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/directives_plain.py
  A   Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/roles_plain.py

-=-
Added: Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/directives_plain.py
===================================================================
--- Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/directives_plain.py	                        (rev 0)
+++ Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/directives_plain.py	2008-01-10 23:43:47 UTC (rev 82788)
@@ -0,0 +1,217 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+Additional directives for reference documentation.
+"""
+from os import path
+import re
+from docutils.parsers.rst import directives, roles
+from docutils.parsers.rst.directives import admonitions
+
+# ------ functions to parse a Python or C signature and create desc_* nodes.
+# ------ also used for parameters like '*args', '**kw'.
+
+py_sig_re = re.compile(r'''^([\w.]*\.)?        # class names
+                           (\w+)  \s*          # thing name
+                           (?: \((.*)\) )? $   # optionally arguments
+                        ''', re.VERBOSE)
+py_paramlist_re = re.compile(r'([\[\],])')  # split at '[', ']' and ','
+
+
+def parse_py_signature(signode, sig, desctype):
+    """
+    Transform a python signature into RST nodes.
+
+    Return (fully qualified name of the thing, classname if any).
+    """
+    m = py_sig_re.match(sig)
+    if m is None: raise ValueError
+    classname, name, arglist = m.groups()
+    
+    fullname = classname and classname + name or name
+    if classname is not None:
+        signode += nodes.strong(classname, classname)
+    signode += nodes.strong(name, name)
+    if not arglist:
+        if desctype in ('function', 'method'):
+            # for callables, add an empty parameter list
+            signode += nodes.inline(u'()', u'()')
+        return fullname, classname
+    signode += nodes.inline()
+
+    paramlist = py_paramlist_re.split(arglist)
+    if len(paramlist):
+        signode += nodes.inline('(', '(')
+    stack = [signode[-1]]
+    for token in paramlist:
+        if token == '[':
+            opt = nodes.inline('[', '[')
+            stack[-1] += opt
+            stack.append(opt)
+        elif token == ']':
+            stack[-1] += nodes.inline(token, token)
+            try: stack.pop()
+            except IndexError: raise ValueError
+        elif not token or token == ',' or token.isspace():
+            if token:
+                if token == ',':
+                    stack[-1] += nodes.inline(', ', ', ')
+                else:
+                    stack[-1] += nodes.inline(token, token)
+            pass
+        else:
+            token = token.strip()
+            paramnode = nodes.emphasis(token, token)
+            stack[-1] += paramnode
+    if len(stack) != 1: raise ValueError
+    if len(paramlist):
+        signode += nodes.inline(')', ')')
+    return fullname, classname
+
+
+# ------ toctree directive ----------------------------------------------------
+from docutils import nodes
+def toctree_directive(name, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+    # We currently ignore toctrees, i.e. we set them up as comment nodes.
+    settings = state.document.settings
+    filename = settings._source
+    dirname = path.dirname(filename)
+
+    subnode = nodes.comment()
+    includefiles = filter(None, content)
+    # normalize filenames
+    includefiles = map(lambda x: path.normpath(path.join(dirname, x)),
+                       includefiles)
+    subnode['includefiles'] = includefiles
+    subnode['maxdepth'] = options.get('maxdepth', -1)
+    return [subnode]
+
+
+toctree_directive.content = 1
+toctree_directive.options = {'maxdepth': int}
+directives.register_directive('toctree', toctree_directive)
+
+
+# ------ desc directive ----------------------------------------------------
+
+def desc_directive(desctype, arguments, options, content, lineno,
+                   content_offset, block_text, state, state_machine):
+    node = nodes.admonition()
+    node['classes'] += ['desc-' + str(desctype)]
+    signatures = map(lambda s: s.strip(), arguments[0].split('\n'))
+    node['desctype'] = desctype
+    names = []
+    for i, sig in enumerate(signatures):
+        sig = sig.strip()
+        signode = nodes.inline(sig, '')
+        signode['first'] = False
+        node.append(signode)
+        try:
+            if desctype in ('function', 'data', 'class', 'exception',
+                            'method', 'attribute'):
+                name, clsname = parse_py_signature(signode, sig, desctype)
+        except ValueError, err:
+            signode.clear()
+            signode += nodes.inline(sig, sig)
+            continue
+    subnode = nodes.container()
+    # needed for automatic qualification of members
+    state.nested_parse(content, content_offset, subnode)
+    node.append(subnode)
+    return [node]
+
+desc_directive.content = 1
+desc_directive.arguments = (1, 0, 1)
+desc_directive.options = {'noindex': directives.flag}
+
+desctypes = [
+    # the Python ones
+    'function',
+    'data',
+    'class',
+    'method',
+    'attribute',
+    'exception',
+    # the generic ones
+    'cmdoption', # for command line options
+    'envvar', # for environment variables
+    'describe',
+]
+
+for name in desctypes:
+    directives.register_directive(name, desc_directive)
+
+
+# ------ see also -------------------------------------------------------------
+
+def seealso_directive(name, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+    """A directive to indicate, that other things are of interest as
+    well.
+    """
+    # Add a marker, which type of versioninfo we build.  This way, in
+    # HTML output there will be a class='seealso' attribution.
+    options['class'] = [str(name)]
+
+    rv = admonitions.make_admonition(
+        nodes.admonition, name, ['See also'], options, content,
+        lineno, content_offset, block_text, state, state_machine)
+    return rv
+
+seealso_directive.content = 1
+seealso_directive.arguments = (0, 0, 0)
+directives.register_directive('seealso', seealso_directive)
+
+
+
+# ------ versionadded/versionchanged ------------------------------------------
+
+def version_directive(name, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+    """A directive to indicate version related modifications.
+    """
+    node = nodes.admonition()
+
+    # sphinx stuff. Do we really need it?
+    node['type'] = name
+    node['version'] = arguments[0]
+
+    # Construct a message...
+    if name == 'versionchanged':
+        text = u'Changed in version %s: ' % (node['version'])
+    elif name == 'versionadded':
+        text = u'Added in version %s: ' % (node['version'])
+    elif name == 'deprecated':
+        text = u'Deprecated from version %s: '% (node['version'])
+    else:
+        text = u'%s %s: ' % (name, arguments[0])
+    arguments[0] = text
+    
+    # Add a marker, which type of versioninfo we build.  This way, in
+    # HTML output there will be a class='versionchanged' attribution.
+    options['class'] = [str(name)]
+
+    # Create a admonition node...
+    rv = admonitions.make_admonition(
+        nodes.admonition, name, arguments, options, content,
+        lineno, content_offset, block_text, state, state_machine)
+    return rv
+
+version_directive.arguments = (1, 1, 1)
+version_directive.content = 1
+
+directives.register_directive('deprecated', version_directive)
+directives.register_directive('versionadded', version_directive)
+directives.register_directive('versionchanged', version_directive)

Added: Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/roles_plain.py
===================================================================
--- Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/roles_plain.py	                        (rev 0)
+++ Sandbox/ulif/grok-reference-with-rest2/doc/grokref/extensions/roles_plain.py	2008-01-10 23:43:47 UTC (rev 82788)
@@ -0,0 +1,97 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Additional roles for reference documentation.
+"""
+
+import re
+from docutils import nodes, utils
+from docutils.parsers.rst import roles
+
+#import addnodes
+
+# default is `literal`
+innernodetypes = {
+    'ref': nodes.emphasis,
+    'term': nodes.emphasis,
+    'token': nodes.strong,
+}
+
+ws_re = re.compile(r'\s+')
+_litvar_re = re.compile('{([^}]+)}')
+
+def deprecated_xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+    text = utils.unescape(text)
+    if text[0:1] == '!':
+        text = text[1:]
+        return [innernodetypes.get(typ, nodes.literal)(
+            rawtext, text, classes=['xref'])], []
+    pnode = addnodes.pending_xref(rawtext)
+    pnode['reftype'] = typ
+    # if the first character is a dot, search more specific namespaces first
+    # else search builtins first
+    if text[0:1] == '.' and \
+       typ in ('data', 'exc', 'func', 'class', 'const', 'attr', 'meth'):
+        text = text[1:]
+        pnode['refspecific'] = True
+    pnode['reftarget'] = ws_re.sub((typ == 'term' and ' ' or ''), text)
+    pnode += innernodetypes.get(typ, nodes.literal)(rawtext, text,
+                                                    classes=['xref'])
+    return [pnode], []
+
+
+
+def emph_literal_role(typ, rawtext, text, lineno, inliner, options={},
+                      content=[]):
+    text = utils.unescape(text)
+    retnodes = []
+    pos = 0
+    for m in _litvar_re.finditer(text):
+        if m.start() > pos:
+            txt = text[pos:m.start()]
+            retnodes.append(nodes.literal(txt, txt))
+        retnodes.append(nodes.emphasis('', '', nodes.literal(m.group(1),
+                                                             m.group(1))))
+        pos = m.end()
+    if pos < len(text):
+        retnodes.append(nodes.literal(text[pos:], text[pos:]))
+    return retnodes, []
+
+
+specific_docroles = {
+    'data': emph_literal_role,
+    'exc': emph_literal_role,
+    'func': emph_literal_role,
+    'class': emph_literal_role,
+    'const': emph_literal_role,
+    'attr': emph_literal_role,
+    'meth': emph_literal_role,
+
+    'cfunc' : emph_literal_role,
+    'cdata' : emph_literal_role,
+    'ctype' : emph_literal_role,
+    'cmacro' : emph_literal_role,
+
+    'mod' : emph_literal_role,
+    'keyword' : emph_literal_role,
+
+    'ref': emph_literal_role,
+    'token' : emph_literal_role,
+    'term': emph_literal_role,
+
+    'file' : emph_literal_role,
+    'samp' : emph_literal_role,
+}
+
+for rolename, func in specific_docroles.iteritems():
+    roles.register_canonical_role(rolename, func)



More information about the Checkins mailing list