[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