summaryrefslogtreecommitdiff
path: root/sphinx/directives
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-01-08 18:55:35 +0100
committerGeorg Brandl <georg@python.org>2010-01-08 18:55:35 +0100
commit3529fca3c92b6f6d4e736c9d09a1162ef65a9a8c (patch)
treea3c3d445bcfc9b200da74038ae22737f6410f650 /sphinx/directives
parent7df7eeb1918272ce1c395032baca55671b941bfe (diff)
parent25d1dff2d40ebee23e4e00956e621f13208adf1d (diff)
downloadsphinx-3529fca3c92b6f6d4e736c9d09a1162ef65a9a8c.tar.gz
merge with trunk
Diffstat (limited to 'sphinx/directives')
-rw-r--r--sphinx/directives/__init__.py271
-rw-r--r--sphinx/directives/code.py13
-rw-r--r--sphinx/directives/desc.py771
-rw-r--r--sphinx/directives/other.py261
4 files changed, 299 insertions, 1017 deletions
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 00bb55ec..5ffce16b 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -9,11 +9,16 @@
:license: BSD, see LICENSE for details.
"""
-from docutils.parsers.rst import directives
+import re
+
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives import images
+from sphinx import addnodes
+from sphinx.locale import l_
+
# import and register directives
-from sphinx.directives.desc import *
from sphinx.directives.code import *
from sphinx.directives.other import *
@@ -25,3 +30,265 @@ try:
except AttributeError:
images.figure.options['figwidth'] = \
directives.length_or_percentage_or_unitless
+
+
+def _is_only_paragraph(node):
+ """True if the node only contains one paragraph (and system messages)."""
+ if len(node) == 0:
+ return False
+ elif len(node) > 1:
+ for subnode in node[1:]:
+ if not isinstance(subnode, nodes.system_message):
+ return False
+ if isinstance(node[0], nodes.paragraph):
+ return True
+ return False
+
+
+# RE to strip backslash escapes
+strip_backslash_re = re.compile(r'\\(?=[^\\])')
+
+
+class ObjectDescription(Directive):
+ """
+ Directive to describe a class, function or similar object. Not used
+ directly, but subclassed to add custom behavior.
+ """
+
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {
+ 'noindex': directives.flag,
+ 'module': directives.unchanged,
+ }
+
+ # XXX make this more domain specific
+
+ doc_fields_with_arg = {
+ 'param': '%param',
+ 'parameter': '%param',
+ 'arg': '%param',
+ 'argument': '%param',
+ 'keyword': '%param',
+ 'kwarg': '%param',
+ 'kwparam': '%param',
+ 'type': '%type',
+ 'raises': l_('Raises'),
+ 'raise': l_('Raises'),
+ 'exception': l_('Raises'),
+ 'except': l_('Raises'),
+ 'var': l_('Variable'),
+ 'ivar': l_('Variable'),
+ 'cvar': l_('Variable'),
+ 'returns': l_('Returns'),
+ 'return': l_('Returns'),
+ }
+
+ doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except')
+
+ doc_fields_without_arg = {
+ 'returns': l_('Returns'),
+ 'return': l_('Returns'),
+ 'rtype': l_('Return type'),
+ }
+
+ # XXX refactor this
+
+ def handle_doc_fields(self, node):
+ """
+ Convert field lists with known keys inside the description content into
+ better-looking equivalents.
+ """
+ # don't traverse, only handle field lists that are immediate children
+ for child in node.children:
+ if not isinstance(child, nodes.field_list):
+ continue
+ params = []
+ pfield = None
+ param_nodes = {}
+ param_types = {}
+ new_list = nodes.field_list()
+ for field in child:
+ fname, fbody = field
+ try:
+ typ, obj = fname.astext().split(None, 1)
+ typdesc = self.doc_fields_with_arg[typ]
+ if _is_only_paragraph(fbody):
+ children = fbody.children[0].children
+ else:
+ children = fbody.children
+ if typdesc == '%param':
+ if not params:
+ # add the field that later gets all the parameters
+ pfield = nodes.field()
+ new_list += pfield
+ dlitem = nodes.list_item()
+ dlpar = nodes.paragraph()
+ dlpar += nodes.emphasis(obj, obj)
+ dlpar += nodes.Text(' -- ', ' -- ')
+ dlpar += children
+ param_nodes[obj] = dlpar
+ dlitem += dlpar
+ params.append(dlitem)
+ elif typdesc == '%type':
+ typenodes = fbody.children
+ if _is_only_paragraph(fbody):
+ typenodes = ([nodes.Text(' (')] +
+ typenodes[0].children +
+ [nodes.Text(')')])
+ param_types[obj] = typenodes
+ else:
+ fieldname = typdesc + ' '
+ nfield = nodes.field()
+ nfieldname = nodes.field_name(fieldname, fieldname)
+ nfield += nfieldname
+ node = nfieldname
+ if typ in self.doc_fields_with_linked_arg:
+ # XXX currmodule/currclass
+ node = addnodes.pending_xref(
+ obj, reftype='obj', refexplicit=False,
+ reftarget=obj)
+ #, modname=self.env.currmodule
+ #, classname=self.env.currclass
+ nfieldname += node
+ node += nodes.Text(obj, obj)
+ nfield += nodes.field_body()
+ nfield[1] += fbody.children
+ new_list += nfield
+ except (KeyError, ValueError):
+ fnametext = fname.astext()
+ try:
+ typ = self.doc_fields_without_arg[fnametext]
+ except KeyError:
+ # at least capitalize the field name
+ typ = fnametext.capitalize()
+ fname[0] = nodes.Text(typ)
+ new_list += field
+ if params:
+ if len(params) == 1:
+ pfield += nodes.field_name('', _('Parameter'))
+ pfield += nodes.field_body()
+ pfield[1] += params[0][0]
+ else:
+ pfield += nodes.field_name('', _('Parameters'))
+ pfield += nodes.field_body()
+ pfield[1] += nodes.bullet_list()
+ pfield[1][0].extend(params)
+
+ for param, type in param_types.iteritems():
+ if param in param_nodes:
+ param_nodes[param][1:1] = type
+ child.replace_self(new_list)
+
+ def get_signatures(self):
+ """
+ Retrieve the signatures to document from the directive arguments.
+ """
+ # remove backslashes to support (dummy) escapes; helps Vim highlighting
+ return [strip_backslash_re.sub('', sig.strip())
+ for sig in self.arguments[0].split('\n')]
+
+ def parse_signature(self, sig, signode):
+ """
+ Parse the signature *sig* into individual nodes and append them to
+ *signode*. If ValueError is raised, parsing is aborted and the whole
+ *sig* is put into a single desc_name node.
+ """
+ raise ValueError
+
+ def add_target_and_index(self, name, sig, signode):
+ """
+ Add cross-reference IDs and entries to self.indexnode, if applicable.
+ """
+ return # do nothing by default
+
+ def before_content(self):
+ """
+ Called before parsing content. Used to set information about the current
+ directive context on the build environment.
+ """
+ pass
+
+ def after_content(self):
+ """
+ Called after parsing content. Used to reset information about the
+ current directive context on the build environment.
+ """
+ pass
+
+ def run(self):
+ if ':' in self.name:
+ self.domain, self.objtype = self.name.split(':', 1)
+ else:
+ self.domain, self.objtype = '', self.name
+ self.env = self.state.document.settings.env
+ self.indexnode = addnodes.index(entries=[])
+
+ node = addnodes.desc()
+ node.document = self.state.document
+ node['domain'] = self.domain
+ # 'desctype' is a backwards compatible attribute
+ node['objtype'] = node['desctype'] = self.objtype
+ node['noindex'] = noindex = ('noindex' in self.options)
+
+ self.names = []
+ signatures = self.get_signatures()
+ for i, sig in enumerate(signatures):
+ # add a signature node for each signature in the current unit
+ # and add a reference target for it
+ signode = addnodes.desc_signature(sig, '')
+ signode['first'] = False
+ node.append(signode)
+ try:
+ # name can also be a tuple, e.g. (classname, objname)
+ name = self.parse_signature(sig, signode)
+ except ValueError, err:
+ # signature parsing failed
+ signode.clear()
+ signode += addnodes.desc_name(sig, sig)
+ continue # we don't want an index entry here
+ if not noindex and name not in self.names:
+ # only add target and index entry if this is the first
+ # description of the object with this name in this desc block
+ self.names.append(name)
+ self.add_target_and_index(name, sig, signode)
+
+ contentnode = addnodes.desc_content()
+ node.append(contentnode)
+ if self.names:
+ # needed for association of version{added,changed} directives
+ self.env.doc_read_data['object'] = self.names[0]
+ self.before_content()
+ self.state.nested_parse(self.content, self.content_offset, contentnode)
+ self.handle_doc_fields(contentnode)
+ self.env.doc_read_data['object'] = None
+ self.after_content()
+ return [self.indexnode, node]
+
+# backwards compatible old name
+DescDirective = ObjectDescription
+
+
+class DefaultDomain(Directive):
+ """
+ Directive to (re-)set the default domain for this source file.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ domain_name = arguments[0]
+ env.doc_read_data['default_domain'] = env.domains.get(domain_name)
+
+
+directives.register_directive('default-domain', DefaultDomain)
+directives.register_directive('describe', ObjectDescription)
+# new, more consistent, name
+directives.register_directive('object', ObjectDescription)
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index 6535bdf5..4136bcec 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -13,11 +13,10 @@ import codecs
from os import path
from docutils import nodes
-from docutils.parsers.rst import directives
+from docutils.parsers.rst import Directive, directives
from sphinx import addnodes
from sphinx.util import parselinenos
-from sphinx.util.compat import Directive, directive_dwim
class Highlight(Directive):
@@ -187,8 +186,8 @@ class LiteralInclude(Directive):
return [retnode]
-directives.register_directive('highlight', directive_dwim(Highlight))
-directives.register_directive('highlightlang', directive_dwim(Highlight)) # old
-directives.register_directive('code-block', directive_dwim(CodeBlock))
-directives.register_directive('sourcecode', directive_dwim(CodeBlock))
-directives.register_directive('literalinclude', directive_dwim(LiteralInclude))
+directives.register_directive('highlight', Highlight)
+directives.register_directive('highlightlang', Highlight) # old
+directives.register_directive('code-block', CodeBlock)
+directives.register_directive('sourcecode', CodeBlock)
+directives.register_directive('literalinclude', LiteralInclude)
diff --git a/sphinx/directives/desc.py b/sphinx/directives/desc.py
deleted file mode 100644
index 5a8ed791..00000000
--- a/sphinx/directives/desc.py
+++ /dev/null
@@ -1,771 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- sphinx.directives.desc
- ~~~~~~~~~~~~~~~~~~~~~~
-
- :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-
-import re
-import string
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-
-from sphinx import addnodes
-from sphinx.util import ws_re
-from sphinx.util.compat import Directive, directive_dwim
-
-
-def _is_only_paragraph(node):
- """True if the node only contains one paragraph (and system messages)."""
- if len(node) == 0:
- return False
- elif len(node) > 1:
- for subnode in node[1:]:
- if not isinstance(subnode, nodes.system_message):
- return False
- if isinstance(node[0], nodes.paragraph):
- return True
- return False
-
-
-# REs for Python signatures
-py_sig_re = re.compile(
- r'''^ ([\w.]*\.)? # class name(s)
- (\w+) \s* # thing name
- (?: \((.*)\) # optional: arguments
- (?:\s* -> \s* (.*))? # return annotation
- )? $ # and nothing more
- ''', re.VERBOSE)
-
-py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
-
-# REs for C signatures
-c_sig_re = re.compile(
- r'''^([^(]*?) # return type
- ([\w:]+) \s* # thing name (colon allowed for C++ class names)
- (?: \((.*)\) )? # optionally arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
-c_funcptr_sig_re = re.compile(
- r'''^([^(]+?) # return type
- (\( [^()]+ \)) \s* # name in parentheses
- \( (.*) \) # arguments
- (\s+const)? $ # const specifier
- ''', re.VERBOSE)
-c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
-
-# RE for option descriptions
-option_desc_re = re.compile(
- r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
-
-# RE to split at word boundaries
-wsplit_re = re.compile(r'(\W+)')
-
-# RE to strip backslash escapes
-strip_backslash_re = re.compile(r'\\(?=[^\\])')
-
-
-class DescDirective(Directive):
- """
- Directive to describe a class, function or similar object. Not used
- directly, but subclassed to add custom behavior.
- """
-
- has_content = True
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {
- 'noindex': directives.flag,
- 'module': directives.unchanged,
- }
-
- _ = lambda x: x # make gettext extraction in constants possible
-
- doc_fields_with_arg = {
- 'param': '%param',
- 'parameter': '%param',
- 'arg': '%param',
- 'argument': '%param',
- 'keyword': '%param',
- 'kwarg': '%param',
- 'kwparam': '%param',
- 'type': '%type',
- 'raises': _('Raises'),
- 'raise': 'Raises',
- 'exception': 'Raises',
- 'except': 'Raises',
- 'var': _('Variable'),
- 'ivar': 'Variable',
- 'cvar': 'Variable',
- 'returns': _('Returns'),
- 'return': 'Returns',
- }
-
- doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except')
-
- doc_fields_without_arg = {
- 'returns': 'Returns',
- 'return': 'Returns',
- 'rtype': _('Return type'),
- }
-
- def handle_doc_fields(self, node):
- """
- Convert field lists with known keys inside the description content into
- better-looking equivalents.
- """
- # don't traverse, only handle field lists that are immediate children
- for child in node.children:
- if not isinstance(child, nodes.field_list):
- continue
- params = []
- pfield = None
- param_nodes = {}
- param_types = {}
- new_list = nodes.field_list()
- for field in child:
- fname, fbody = field
- try:
- typ, obj = fname.astext().split(None, 1)
- typdesc = _(self.doc_fields_with_arg[typ])
- if _is_only_paragraph(fbody):
- children = fbody.children[0].children
- else:
- children = fbody.children
- if typdesc == '%param':
- if not params:
- # add the field that later gets all the parameters
- pfield = nodes.field()
- new_list += pfield
- dlitem = nodes.list_item()
- dlpar = nodes.paragraph()
- dlpar += nodes.emphasis(obj, obj)
- dlpar += nodes.Text(' -- ', ' -- ')
- dlpar += children
- param_nodes[obj] = dlpar
- dlitem += dlpar
- params.append(dlitem)
- elif typdesc == '%type':
- typenodes = fbody.children
- if _is_only_paragraph(fbody):
- typenodes = ([nodes.Text(' (')] +
- typenodes[0].children +
- [nodes.Text(')')])
- param_types[obj] = typenodes
- else:
- fieldname = typdesc + ' '
- nfield = nodes.field()
- nfieldname = nodes.field_name(fieldname, fieldname)
- nfield += nfieldname
- node = nfieldname
- if typ in self.doc_fields_with_linked_arg:
- node = addnodes.pending_xref(
- obj, reftype='obj', refcaption=False,
- reftarget=obj, modname=self.env.currmodule,
- classname=self.env.currclass)
- nfieldname += node
- node += nodes.Text(obj, obj)
- nfield += nodes.field_body()
- nfield[1] += fbody.children
- new_list += nfield
- except (KeyError, ValueError):
- fnametext = fname.astext()
- try:
- typ = _(self.doc_fields_without_arg[fnametext])
- except KeyError:
- # at least capitalize the field name
- typ = fnametext.capitalize()
- fname[0] = nodes.Text(typ)
- new_list += field
- if params:
- if len(params) == 1:
- pfield += nodes.field_name('', _('Parameter'))
- pfield += nodes.field_body()
- pfield[1] += params[0][0]
- else:
- pfield += nodes.field_name('', _('Parameters'))
- pfield += nodes.field_body()
- pfield[1] += nodes.bullet_list()
- pfield[1][0].extend(params)
-
- for param, type in param_types.iteritems():
- if param in param_nodes:
- param_nodes[param][1:1] = type
- child.replace_self(new_list)
-
- def get_signatures(self):
- """
- Retrieve the signatures to document from the directive arguments.
- """
- # remove backslashes to support (dummy) escapes; helps Vim highlighting
- return [strip_backslash_re.sub('', sig.strip())
- for sig in self.arguments[0].split('\n')]
-
- def parse_signature(self, sig, signode):
- """
- Parse the signature *sig* into individual nodes and append them to
- *signode*. If ValueError is raised, parsing is aborted and the whole
- *sig* is put into a single desc_name node.
- """
- raise ValueError
-
- def add_target_and_index(self, name, sig, signode):
- """
- Add cross-reference IDs and entries to self.indexnode, if applicable.
- """
- return # do nothing by default
-
- def before_content(self):
- """
- Called before parsing content. Used to set information about the current
- directive context on the build environment.
- """
- pass
-
- def after_content(self):
- """
- Called after parsing content. Used to reset information about the
- current directive context on the build environment.
- """
- pass
-
- def run(self):
- self.desctype = self.name
- self.env = self.state.document.settings.env
- self.indexnode = addnodes.index(entries=[])
-
- node = addnodes.desc()
- node.document = self.state.document
- node['desctype'] = self.desctype
- node['noindex'] = noindex = ('noindex' in self.options)
-
- self.names = []
- signatures = self.get_signatures()
- for i, sig in enumerate(signatures):
- # add a signature node for each signature in the current unit
- # and add a reference target for it
- signode = addnodes.desc_signature(sig, '')
- signode['first'] = False
- node.append(signode)
- try:
- # name can also be a tuple, e.g. (classname, objname)
- name = self.parse_signature(sig, signode)
- except ValueError, err:
- # signature parsing failed
- signode.clear()
- signode += addnodes.desc_name(sig, sig)
- continue # we don't want an index entry here
- if not noindex and name not in self.names:
- # only add target and index entry if this is the first
- # description of the object with this name in this desc block
- self.names.append(name)
- self.add_target_and_index(name, sig, signode)
-
- contentnode = addnodes.desc_content()
- node.append(contentnode)
- if self.names:
- # needed for association of version{added,changed} directives
- self.env.currdesc = self.names[0]
- self.before_content()
- self.state.nested_parse(self.content, self.content_offset, contentnode)
- self.handle_doc_fields(contentnode)
- self.env.currdesc = None
- self.after_content()
- return [self.indexnode, node]
-
-
-class PythonDesc(DescDirective):
- """
- Description of a general Python object.
- """
-
- def get_signature_prefix(self, sig):
- """
- May return a prefix to put before the object name in the signature.
- """
- return ''
-
- def needs_arglist(self):
- """
- May return true if an empty argument list is to be generated even if
- the document contains none.
- """
- return False
-
- def parse_signature(self, sig, signode):
- """
- Transform a Python signature into RST nodes.
- Returns (fully qualified name of the thing, classname if any).
-
- If inside a class, the current class name is handled intelligently:
- * it is stripped from the displayed name if present
- * it is added to the full name (return value) if not present
- """
- m = py_sig_re.match(sig)
- if m is None:
- raise ValueError
- classname, name, arglist, retann = m.groups()
-
- if self.env.currclass:
- add_module = False
- if classname and classname.startswith(self.env.currclass):
- fullname = classname + name
- # class name is given again in the signature
- classname = classname[len(self.env.currclass):].lstrip('.')
- elif classname:
- # class name is given in the signature, but different
- # (shouldn't happen)
- fullname = self.env.currclass + '.' + classname + name
- else:
- # class name is not given in the signature
- fullname = self.env.currclass + '.' + name
- else:
- add_module = True
- fullname = classname and classname + name or name
-
- prefix = self.get_signature_prefix(sig)
- if prefix:
- signode += addnodes.desc_annotation(prefix, prefix)
-
- if classname:
- signode += addnodes.desc_addname(classname, classname)
- # exceptions are a special case, since they are documented in the
- # 'exceptions' module.
- elif add_module and self.env.config.add_module_names:
- modname = self.options.get('module', self.env.currmodule)
- if modname and modname != 'exceptions':
- nodetext = modname + '.'
- signode += addnodes.desc_addname(nodetext, nodetext)
-
- signode += addnodes.desc_name(name, name)
- if not arglist:
- if self.needs_arglist():
- # for callables, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, classname
- signode += addnodes.desc_parameterlist()
-
- stack = [signode[-1]]
- for token in py_paramlist_re.split(arglist):
- if token == '[':
- opt = addnodes.desc_optional()
- stack[-1] += opt
- stack.append(opt)
- elif token == ']':
- try:
- stack.pop()
- except IndexError:
- raise ValueError
- elif not token or token == ',' or token.isspace():
- pass
- else:
- token = token.strip()
- stack[-1] += addnodes.desc_parameter(token, token)
- if len(stack) != 1:
- raise ValueError
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, classname
-
- def get_index_text(self, modname, name):
- """
- Return the text for the index entry of the object.
- """
- raise NotImplementedError('must be implemented in subclasses')
-
- def add_target_and_index(self, name_cls, sig, signode):
- modname = self.options.get('module', self.env.currmodule)
- fullname = (modname and modname + '.' or '') + name_cls[0]
- # note target
- if fullname not in self.state.document.ids:
- signode['names'].append(fullname)
- signode['ids'].append(fullname)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- self.env.note_descref(fullname, self.desctype, self.lineno)
-
- indextext = self.get_index_text(modname, name_cls)
- if indextext:
- self.indexnode['entries'].append(('single', indextext,
- fullname, fullname))
-
- def before_content(self):
- # needed for automatic qualification of members (reset in subclasses)
- self.clsname_set = False
-
- def after_content(self):
- if self.clsname_set:
- self.env.currclass = None
-
-
-class ModulelevelDesc(PythonDesc):
- """
- Description of an object on module level (functions, data).
- """
-
- def needs_arglist(self):
- return self.desctype == 'function'
-
- def get_index_text(self, modname, name_cls):
- if self.desctype == 'function':
- if not modname:
- return _('%s() (built-in function)') % name_cls[0]
- return _('%s() (in module %s)') % (name_cls[0], modname)
- elif self.desctype == 'data':
- if not modname:
- return _('%s (built-in variable)') % name_cls[0]
- return _('%s (in module %s)') % (name_cls[0], modname)
- else:
- return ''
-
-
-class ClasslikeDesc(PythonDesc):
- """
- Description of a class-like object (classes, interfaces, exceptions).
- """
-
- def get_signature_prefix(self, sig):
- return self.desctype + ' '
-
- def get_index_text(self, modname, name_cls):
- if self.desctype == 'class':
- if not modname:
- return _('%s (built-in class)') % name_cls[0]
- return _('%s (class in %s)') % (name_cls[0], modname)
- elif self.desctype == 'exception':
- return name_cls[0]
- else:
- return ''
-
- def before_content(self):
- PythonDesc.before_content(self)
- if self.names:
- self.env.currclass = self.names[0][0]
- self.clsname_set = True
-
-
-class ClassmemberDesc(PythonDesc):
- """
- Description of a class member (methods, attributes).
- """
-
- def needs_arglist(self):
- return self.desctype.endswith('method')
-
- def get_signature_prefix(self, sig):
- if self.desctype == 'staticmethod':
- return 'static '
- elif self.desctype == 'classmethod':
- return 'classmethod '
- return ''
-
- def get_index_text(self, modname, name_cls):
- name, cls = name_cls
- add_modules = self.env.config.add_module_names
- if self.desctype == 'method':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s() (in module %s)') % (name, modname)
- else:
- return '%s()' % name
- if modname and add_modules:
- return _('%s() (%s.%s method)') % (methname, modname, clsname)
- else:
- return _('%s() (%s method)') % (methname, clsname)
- elif self.desctype == 'staticmethod':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s() (in module %s)') % (name, modname)
- else:
- return '%s()' % name
- if modname and add_modules:
- return _('%s() (%s.%s static method)') % (methname, modname,
- clsname)
- else:
- return _('%s() (%s static method)') % (methname, clsname)
- elif self.desctype == 'classmethod':
- try:
- clsname, methname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return '%s() (in module %s)' % (name, modname)
- else:
- return '%s()' % name
- if modname:
- return '%s() (%s.%s class method)' % (methname, modname,
- clsname)
- else:
- return '%s() (%s class method)' % (methname, clsname)
- elif self.desctype == 'attribute':
- try:
- clsname, attrname = name.rsplit('.', 1)
- except ValueError:
- if modname:
- return _('%s (in module %s)') % (name, modname)
- else:
- return name
- if modname and add_modules:
- return _('%s (%s.%s attribute)') % (attrname, modname, clsname)
- else:
- return _('%s (%s attribute)') % (attrname, clsname)
- else:
- return ''
-
- def before_content(self):
- PythonDesc.before_content(self)
- if self.names and self.names[-1][1] and not self.env.currclass:
- self.env.currclass = self.names[-1][1].strip('.')
- self.clsname_set = True
-
-
-class CDesc(DescDirective):
- """
- Description of a C language object.
- """
-
- # These C types aren't described anywhere, so don't try to create
- # a cross-reference to them
- stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
-
- def _parse_type(self, node, ctype):
- # add cross-ref nodes for all words
- for part in filter(None, wsplit_re.split(ctype)):
- tnode = nodes.Text(part, part)
- if part[0] in string.ascii_letters+'_' and \
- part not in self.stopwords:
- pnode = addnodes.pending_xref(
- '', reftype='ctype', reftarget=part,
- modname=None, classname=None)
- pnode += tnode
- node += pnode
- else:
- node += tnode
-
- def parse_signature(self, sig, signode):
- """Transform a C (or C++) signature into RST nodes."""
- # first try the function pointer signature regex, it's more specific
- m = c_funcptr_sig_re.match(sig)
- if m is None:
- m = c_sig_re.match(sig)
- if m is None:
- raise ValueError('no match')
- rettype, name, arglist, const = m.groups()
-
- signode += addnodes.desc_type('', '')
- self._parse_type(signode[-1], rettype)
- try:
- classname, funcname = name.split('::', 1)
- classname += '::'
- signode += addnodes.desc_addname(classname, classname)
- signode += addnodes.desc_name(funcname, funcname)
- # name (the full name) is still both parts
- except ValueError:
- signode += addnodes.desc_name(name, name)
- # clean up parentheses from canonical name
- m = c_funcptr_name_re.match(name)
- if m:
- name = m.group(1)
- if not arglist:
- if self.desctype == 'cfunction':
- # for functions, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if const:
- signode += addnodes.desc_addname(const, const)
- return name
-
- paramlist = addnodes.desc_parameterlist()
- arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
- # this messes up function pointer types, but not too badly ;)
- args = arglist.split(',')
- for arg in args:
- arg = arg.strip()
- param = addnodes.desc_parameter('', '', noemph=True)
- try:
- ctype, argname = arg.rsplit(' ', 1)
- except ValueError:
- # no argument name given, only the type
- self._parse_type(param, arg)
- else:
- self._parse_type(param, ctype)
- param += nodes.emphasis(' '+argname, ' '+argname)
- paramlist += param
- signode += paramlist
- if const:
- signode += addnodes.desc_addname(const, const)
- return name
-
- def get_index_text(self, name):
- if self.desctype == 'cfunction':
- return _('%s (C function)') % name
- elif self.desctype == 'cmember':
- return _('%s (C member)') % name
- elif self.desctype == 'cmacro':
- return _('%s (C macro)') % name
- elif self.desctype == 'ctype':
- return _('%s (C type)') % name
- elif self.desctype == 'cvar':
- return _('%s (C variable)') % name
- else:
- return ''
-
- def add_target_and_index(self, name, sig, signode):
- # note target
- if name not in self.state.document.ids:
- signode['names'].append(name)
- signode['ids'].append(name)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- self.env.note_descref(name, self.desctype, self.lineno)
-
- indextext = self.get_index_text(name)
- if indextext:
- self.indexnode['entries'].append(('single', indextext, name, name))
-
-
-class CmdoptionDesc(DescDirective):
- """
- Description of a command-line option (.. cmdoption).
- """
-
- def parse_signature(self, sig, signode):
- """Transform an option description into RST nodes."""
- count = 0
- firstname = ''
- for m in option_desc_re.finditer(sig):
- optname, args = m.groups()
- if count:
- signode += addnodes.desc_addname(', ', ', ')
- signode += addnodes.desc_name(optname, optname)
- signode += addnodes.desc_addname(args, args)
- if not count:
- firstname = optname
- count += 1
- if not firstname:
- raise ValueError
- return firstname
-
- def add_target_and_index(self, name, sig, signode):
- targetname = name.replace('/', '-')
- if self.env.currprogram:
- targetname = '-' + self.env.currprogram + targetname
- targetname = 'cmdoption' + targetname
- signode['ids'].append(targetname)
- self.state.document.note_explicit_target(signode)
- self.indexnode['entries'].append(
- ('pair', _('%scommand line option; %s') %
- ((self.env.currprogram and
- self.env.currprogram + ' ' or ''), sig),
- targetname, targetname))
- self.env.note_progoption(name, targetname)
-
-
-class GenericDesc(DescDirective):
- """
- A generic x-ref directive registered with Sphinx.add_description_unit().
- """
-
- def parse_signature(self, sig, signode):
- parse_node = additional_xref_types[self.desctype][2]
- if parse_node:
- name = parse_node(self.env, sig, signode)
- else:
- signode.clear()
- signode += addnodes.desc_name(sig, sig)
- # normalize whitespace like xfileref_role does
- name = ws_re.sub('', sig)
- return name
-
- def add_target_and_index(self, name, sig, signode):
- rolename, indextemplate = additional_xref_types[self.desctype][:2]
- targetname = '%s-%s' % (rolename, name)
- signode['ids'].append(targetname)
- self.state.document.note_explicit_target(signode)
- if indextemplate:
- indexentry = _(indextemplate) % (name,)
- indextype = 'single'
- colon = indexentry.find(':')
- if colon != -1:
- indextype = indexentry[:colon].strip()
- indexentry = indexentry[colon+1:].strip()
- self.indexnode['entries'].append((indextype, indexentry,
- targetname, targetname))
- self.env.note_reftarget(rolename, name, targetname)
-
-
-class Target(Directive):
- """
- Generic target for user-defined cross-reference types.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- rolename, indextemplate, foo = additional_xref_types[self.name]
- # normalize whitespace in fullname like xfileref_role does
- fullname = ws_re.sub('', self.arguments[0].strip())
- targetname = '%s-%s' % (rolename, fullname)
- node = nodes.target('', '', ids=[targetname])
- self.state.document.note_explicit_target(node)
- ret = [node]
- if indextemplate:
- indexentry = indextemplate % (fullname,)
- indextype = 'single'
- colon = indexentry.find(':')
- if colon != -1:
- indextype = indexentry[:colon].strip()
- indexentry = indexentry[colon+1:].strip()
- inode = addnodes.index(entries=[(indextype, indexentry,
- targetname, targetname)])
- ret.insert(0, inode)
- env.note_reftarget(rolename, fullname, targetname)
- return ret
-
-# Note: the target directive is not registered here, it is used by the
-# application when registering additional xref types.
-
-_ = lambda x: x
-
-# Generic cross-reference types; they can be registered in the application;
-# the directives are either desc_directive or target_directive.
-additional_xref_types = {
- # directive name: (role name, index text, function to parse the desc node)
- 'envvar': ('envvar', _('environment variable; %s'), None),
-}
-
-del _
-
-
-directives.register_directive('describe', directive_dwim(DescDirective))
-
-directives.register_directive('function', directive_dwim(ModulelevelDesc))
-directives.register_directive('data', directive_dwim(ModulelevelDesc))
-directives.register_directive('class', directive_dwim(ClasslikeDesc))
-directives.register_directive('exception', directive_dwim(ClasslikeDesc))
-directives.register_directive('method', directive_dwim(ClassmemberDesc))
-directives.register_directive('classmethod', directive_dwim(ClassmemberDesc))
-directives.register_directive('staticmethod', directive_dwim(ClassmemberDesc))
-directives.register_directive('attribute', directive_dwim(ClassmemberDesc))
-
-directives.register_directive('cfunction', directive_dwim(CDesc))
-directives.register_directive('cmember', directive_dwim(CDesc))
-directives.register_directive('cmacro', directive_dwim(CDesc))
-directives.register_directive('ctype', directive_dwim(CDesc))
-directives.register_directive('cvar', directive_dwim(CDesc))
-
-directives.register_directive('cmdoption', directive_dwim(CmdoptionDesc))
-directives.register_directive('envvar', directive_dwim(GenericDesc))
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index d746ea62..a347970c 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -10,13 +10,13 @@
import re
from docutils import nodes
-from docutils.parsers.rst import directives
+from docutils.parsers.rst import Directive, directives
from sphinx import addnodes
from sphinx.locale import pairindextypes
from sphinx.util import patfilter, ws_re, url_re, docname_join, \
explicit_title_re
-from sphinx.util.compat import Directive, directive_dwim, make_admonition
+from sphinx.util.compat import make_admonition
class TocTree(Directive):
@@ -106,75 +106,6 @@ class TocTree(Directive):
return ret
-class Module(Directive):
- """
- Directive to mark description of a new module.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {
- 'platform': lambda x: x,
- 'synopsis': lambda x: x,
- 'noindex': directives.flag,
- 'deprecated': directives.flag,
- }
-
- def run(self):
- env = self.state.document.settings.env
- modname = self.arguments[0].strip()
- noindex = 'noindex' in self.options
- env.currmodule = modname
- env.note_module(modname, self.options.get('synopsis', ''),
- self.options.get('platform', ''),
- 'deprecated' in self.options)
- modulenode = addnodes.module()
- modulenode['modname'] = modname
- modulenode['synopsis'] = self.options.get('synopsis', '')
- targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
- self.state.document.note_explicit_target(targetnode)
- ret = [modulenode, targetnode]
- if 'platform' in self.options:
- platform = self.options['platform']
- modulenode['platform'] = platform
- node = nodes.paragraph()
- node += nodes.emphasis('', _('Platforms: '))
- node += nodes.Text(platform, platform)
- ret.append(node)
- # the synopsis isn't printed; in fact, it is only used in the
- # modindex currently
- if not noindex:
- indextext = _('%s (module)') % modname
- inode = addnodes.index(entries=[('single', indextext,
- 'module-' + modname, modname)])
- ret.insert(0, inode)
- return ret
-
-
-class CurrentModule(Directive):
- """
- This directive is just to tell Sphinx that we're documenting
- stuff in module foo, but links to module foo won't lead here.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- modname = self.arguments[0].strip()
- if modname == 'None':
- env.currmodule = None
- else:
- env.currmodule = modname
- return []
-
-
class Author(Directive):
"""
Directive to give the name of the author of the current document
@@ -207,27 +138,6 @@ class Author(Directive):
return [para] + messages
-class Program(Directive):
- """
- Directive to name the program for which options are documented.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- program = ws_re.sub('-', self.arguments[0].strip())
- if program == 'None':
- env.currprogram = None
- else:
- env.currprogram = program
- return []
-
-
class Index(Directive):
"""
Directive to add entries to the index.
@@ -246,8 +156,7 @@ class Index(Directive):
def run(self):
arguments = self.arguments[0].split('\n')
env = self.state.document.settings.env
- targetid = 'index-%s' % env.index_num
- env.index_num += 1
+ targetid = 'index-%s' % env.new_serialno('index')
targetnode = nodes.target('', '', ids=[targetid])
self.state.document.note_explicit_target(targetnode)
indexnode = addnodes.index()
@@ -304,7 +213,11 @@ class VersionChange(Directive):
else:
ret = [node]
env = self.state.document.settings.env
- env.note_versionchange(node['type'], node['version'], node, self.lineno)
+ env.versionchanges.setdefault(node['version'], []).append(
+ (node['type'], env.doc_read_data['docname'], self.lineno,
+ env.doc_read_data.get('py_module'),
+ env.doc_read_data.get('object'),
+ node.astext()))
return ret
@@ -334,66 +247,6 @@ class SeeAlso(Directive):
return ret
-token_re = re.compile('`([a-z_]+)`')
-
-def token_xrefs(text, env):
- retnodes = []
- pos = 0
- for m in token_re.finditer(text):
- if m.start() > pos:
- txt = text[pos:m.start()]
- retnodes.append(nodes.Text(txt, txt))
- refnode = addnodes.pending_xref(m.group(1))
- refnode['reftype'] = 'token'
- refnode['reftarget'] = m.group(1)
- refnode['modname'] = env.currmodule
- refnode['classname'] = env.currclass
- refnode += nodes.literal(m.group(1), m.group(1), classes=['xref'])
- retnodes.append(refnode)
- pos = m.end()
- if pos < len(text):
- retnodes.append(nodes.Text(text[pos:], text[pos:]))
- return retnodes
-
-class ProductionList(Directive):
- """
- Directive to list grammar productions.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- node = addnodes.productionlist()
- messages = []
- i = 0
-
- for rule in self.arguments[0].split('\n'):
- if i == 0 and ':' not in rule:
- # production group
- continue
- i += 1
- try:
- name, tokens = rule.split(':', 1)
- except ValueError:
- break
- subnode = addnodes.production()
- subnode['tokenname'] = name.strip()
- if subnode['tokenname']:
- idname = 'grammar-token-%s' % subnode['tokenname']
- if idname not in self.state.document.ids:
- subnode['ids'].append(idname)
- self.state.document.note_implicit_target(subnode, subnode)
- env.note_reftarget('token', subnode['tokenname'], idname)
- subnode.extend(token_xrefs(tokens, env))
- node.append(subnode)
- return [node] + messages
-
-
class TabularColumns(Directive):
"""
Directive to give an explicit tabulary column definition to LaTeX.
@@ -411,57 +264,6 @@ class TabularColumns(Directive):
return [node]
-class Glossary(Directive):
- """
- Directive to create a glossary with cross-reference targets
- for :term: roles.
- """
-
- has_content = True
- required_arguments = 0
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {
- 'sorted': directives.flag,
- }
-
- def run(self):
- env = self.state.document.settings.env
- node = addnodes.glossary()
- node.document = self.state.document
- self.state.nested_parse(self.content, self.content_offset, node)
-
- # the content should be definition lists
- dls = [child for child in node
- if isinstance(child, nodes.definition_list)]
- # now, extract definition terms to enable cross-reference creation
- new_dl = nodes.definition_list()
- new_dl['classes'].append('glossary')
- items = []
- for dl in dls:
- for li in dl.children:
- if not li.children or not isinstance(li[0], nodes.term):
- continue
- termtext = li.children[0].astext()
- new_id = 'term-' + nodes.make_id(termtext)
- if new_id in env.gloss_entries:
- new_id = 'term-' + str(len(env.gloss_entries))
- env.gloss_entries.add(new_id)
- li[0]['names'].append(new_id)
- li[0]['ids'].append(new_id)
- env.note_reftarget('term', termtext.lower(), new_id)
- # add an index entry too
- indexnode = addnodes.index()
- indexnode['entries'] = [('single', termtext, new_id, termtext)]
- li.insert(0, indexnode)
- items.append((termtext, li))
- if 'sorted' in self.options:
- items.sort(key=lambda x: x[0].lower())
- new_dl.extend(item[1] for item in items)
- node.children = [new_dl]
- return [node]
-
-
class Centered(Directive):
"""
Directive to create a centered line of bold text.
@@ -564,36 +366,21 @@ class Only(Directive):
return [node]
-directives.register_directive('toctree', directive_dwim(TocTree))
-directives.register_directive('module', directive_dwim(Module))
-directives.register_directive('currentmodule', directive_dwim(CurrentModule))
-directives.register_directive('sectionauthor', directive_dwim(Author))
-directives.register_directive('moduleauthor', directive_dwim(Author))
-directives.register_directive('program', directive_dwim(Program))
-directives.register_directive('index', directive_dwim(Index))
-directives.register_directive('deprecated', directive_dwim(VersionChange))
-directives.register_directive('versionadded', directive_dwim(VersionChange))
-directives.register_directive('versionchanged', directive_dwim(VersionChange))
-directives.register_directive('seealso', directive_dwim(SeeAlso))
-directives.register_directive('productionlist', directive_dwim(ProductionList))
-directives.register_directive('tabularcolumns', directive_dwim(TabularColumns))
-directives.register_directive('glossary', directive_dwim(Glossary))
-directives.register_directive('centered', directive_dwim(Centered))
-directives.register_directive('acks', directive_dwim(Acks))
-directives.register_directive('hlist', directive_dwim(HList))
-directives.register_directive('only', directive_dwim(Only))
+directives.register_directive('toctree', TocTree)
+directives.register_directive('sectionauthor', Author)
+directives.register_directive('moduleauthor', Author)
+directives.register_directive('index', Index)
+directives.register_directive('deprecated', VersionChange)
+directives.register_directive('versionadded', VersionChange)
+directives.register_directive('versionchanged', VersionChange)
+directives.register_directive('seealso', SeeAlso)
+directives.register_directive('tabularcolumns', TabularColumns)
+directives.register_directive('centered', Centered)
+directives.register_directive('acks', Acks)
+directives.register_directive('hlist', HList)
+directives.register_directive('only', Only)
# register the standard rst class directive under a different name
-
-try:
- # docutils 0.4
- from docutils.parsers.rst.directives.misc import class_directive
- directives.register_directive('cssclass', class_directive)
-except ImportError:
- try:
- # docutils 0.5
- from docutils.parsers.rst.directives.misc import Class
- directives.register_directive('cssclass', Class)
- except ImportError:
- # whatever :)
- pass
+# only for backwards compatibility now
+from docutils.parsers.rst.directives.misc import Class
+directives.register_directive('cssclass', Class)