diff -r be27ed110b50 -r d8ac696cc51f buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/directives/desc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/directives/desc.py Wed Dec 23 19:29:07 2009 +0200 @@ -0,0 +1,592 @@ +# -*- coding: utf-8 -*- +""" + sphinx.directives.desc + ~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: 2007-2008 by Georg Brandl. + :license: BSD. +""" + +import re +import string + +from docutils import nodes +from docutils.parsers.rst import directives + +from sphinx import addnodes +from sphinx.util import ws_re + + +# ------ information units --------------------------------------------------------- + +def desc_index_text(desctype, module, name, add_modules): + if desctype == 'function': + if not module: + return _('%s() (built-in function)') % name + return _('%s() (in module %s)') % (name, module) + elif desctype == 'data': + if not module: + return _('%s (built-in variable)') % name + return _('%s (in module %s)') % (name, module) + elif desctype == 'class': + if not module: + return _('%s (built-in class)') % name + return _('%s (class in %s)') % (name, module) + elif desctype == 'exception': + return name + elif desctype == 'method': + try: + clsname, methname = name.rsplit('.', 1) + except ValueError: + if module: + return _('%s() (in module %s)') % (name, module) + else: + return '%s()' % name + if module and add_modules: + return _('%s() (%s.%s method)') % (methname, module, clsname) + else: + return _('%s() (%s method)') % (methname, clsname) + elif desctype == 'staticmethod': + try: + clsname, methname = name.rsplit('.', 1) + except ValueError: + if module: + return _('%s() (in module %s)') % (name, module) + else: + return '%s()' % name + if module and add_modules: + return _('%s() (%s.%s static method)') % (methname, module, clsname) + else: + return _('%s() (%s static method)') % (methname, clsname) + elif desctype == 'attribute': + try: + clsname, attrname = name.rsplit('.', 1) + except ValueError: + if module: + return _('%s (in module %s)') % (name, module) + else: + return name + if module and add_modules: + return _('%s (%s.%s attribute)') % (attrname, module, clsname) + else: + return _('%s (%s attribute)') % (attrname, clsname) + elif desctype == 'cfunction': + return _('%s (C function)') % name + elif desctype == 'cmember': + return _('%s (C member)') % name + elif desctype == 'cmacro': + return _('%s (C macro)') % name + elif desctype == 'ctype': + return _('%s (C type)') % name + elif desctype == 'cvar': + return _('%s (C variable)') % name + else: + raise ValueError('unhandled descenv: %s' % desctype) + + +# ------ make field lists (like :param foo:) in desc bodies prettier + +_ = 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'), +} + +del _ + + +def _is_only_paragraph(node): + # determine 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 + + +def handle_doc_fields(node, env): + # 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 = 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 = _(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: + pfield = nodes.field() + pfield += nodes.field_name('', _('Parameters')) + pfield += nodes.field_body() + params = nodes.bullet_list() + pfield[1] += params + 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 += 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 doc_fields_with_linked_arg: + node = addnodes.pending_xref(obj, reftype='obj', + refcaption=False, + reftarget=obj, + modname=env.currmodule, + classname=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 = _(doc_fields_without_arg[fnametext]) + except KeyError: + # at least capitalize the field name + typ = fnametext.capitalize() + fname[0] = nodes.Text(typ) + new_list += field + for param, type in param_types.iteritems(): + if param in param_nodes: + param_nodes[param][1:1] = type + child.replace_self(new_list) + + +# ------ functions to parse a Python or C signature and create desc_* nodes. + +py_sig_re = re.compile( + r'''^ ([\w.]*\.)? # class name(s) + (\w+) \s* # thing name + (?: \((.*)\) # optional arguments + (\s* -> \s* .*)? )? $ # optional return annotation + ''', re.VERBOSE) + +py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ',' + +def parse_py_signature(signode, sig, desctype, module, env): + """ + Transform a python signature into RST nodes. + Return (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 retann: + retann = u' \N{RIGHTWARDS ARROW} ' + retann.strip()[2:] + + if env.currclass: + add_module = False + if classname and classname.startswith(env.currclass): + fullname = classname + name + # class name is given again in the signature + classname = classname[len(env.currclass):].lstrip('.') + elif classname: + # class name is given in the signature, but different + # (shouldn't happen) + fullname = env.currclass + '.' + classname + name + else: + # class name is not given in the signature + fullname = env.currclass + '.' + name + else: + add_module = True + fullname = classname and classname + name or name + + if desctype == 'staticmethod': + signode += addnodes.desc_annotation('static ', 'static ') + + 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 env.config.add_module_names and \ + module and module != 'exceptions': + nodetext = module + '.' + signode += addnodes.desc_addname(nodetext, nodetext) + + signode += addnodes.desc_name(name, name) + if not arglist: + if desctype in ('function', 'method', 'staticmethod'): + # for callables, add an empty parameter list + signode += addnodes.desc_parameterlist() + if retann: + signode += addnodes.desc_type(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_type(retann, retann) + return fullname, classname + + +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 to split at word boundaries +wsplit_re = re.compile(r'(\W+)') + +# These C types aren't described in the reference, so don't try to create +# a cross-reference to them +stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct')) + +def parse_c_type(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.letters+'_' and part not in stopwords: + pnode = addnodes.pending_xref( + '', reftype='ctype', reftarget=part, modname=None, classname=None) + pnode += tnode + node += pnode + else: + node += tnode + +def parse_c_signature(signode, sig, desctype): + """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('', '') + parse_c_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 desctype == 'cfunction': + # for functions, add an empty parameter list + signode += addnodes.desc_parameterlist() + 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 + parse_c_type(param, arg) + else: + parse_c_type(param, ctype) + param += nodes.emphasis(' '+argname, ' '+argname) + paramlist += param + signode += paramlist + if const: + signode += addnodes.desc_addname(const, const) + return name + + +option_desc_re = re.compile( + r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)') + +def parse_option_desc(signode, sig): + """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 + + +strip_backslash_re = re.compile(r'\\(?=[^\\])') + +def desc_directive(desctype, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + env = state.document.settings.env + inode = addnodes.index(entries=[]) + node = addnodes.desc() + node['desctype'] = desctype + + noindex = ('noindex' in options) + node['noindex'] = noindex + # remove backslashes to support (dummy) escapes; helps Vim's highlighting + signatures = map(lambda s: strip_backslash_re.sub('', s.strip()), + arguments[0].split('\n')) + names = [] + clsname = None + module = options.get('module', env.currmodule) + for i, sig in enumerate(signatures): + # add a signature node for each signature in the current unit + # and add a reference target for it + sig = sig.strip() + signode = addnodes.desc_signature(sig, '') + signode['first'] = False + node.append(signode) + try: + if desctype in ('function', 'data', 'class', 'exception', + 'method', 'staticmethod', 'attribute'): + name, clsname = parse_py_signature(signode, sig, desctype, module, env) + elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'): + name = parse_c_signature(signode, sig, desctype) + elif desctype == 'cmdoption': + optname = parse_option_desc(signode, sig) + if not noindex: + targetname = optname.replace('/', '-') + if env.currprogram: + targetname = '-' + env.currprogram + targetname + targetname = 'cmdoption' + targetname + signode['ids'].append(targetname) + state.document.note_explicit_target(signode) + inode['entries'].append( + ('pair', _('%scommand line option; %s') % + ((env.currprogram and env.currprogram + ' ' or ''), sig), + targetname, targetname)) + env.note_progoption(optname, targetname) + continue + elif desctype == 'describe': + signode.clear() + signode += addnodes.desc_name(sig, sig) + continue + else: + # another registered generic x-ref directive + rolename, indextemplate, parse_node = additional_xref_types[desctype] + if parse_node: + fullname = parse_node(env, sig, signode) + else: + signode.clear() + signode += addnodes.desc_name(sig, sig) + # normalize whitespace like xfileref_role does + fullname = ws_re.sub('', sig) + if not noindex: + targetname = '%s-%s' % (rolename, fullname) + signode['ids'].append(targetname) + state.document.note_explicit_target(signode) + if indextemplate: + indexentry = _(indextemplate) % (fullname,) + indextype = 'single' + colon = indexentry.find(':') + if colon != -1: + indextype = indexentry[:colon].strip() + indexentry = indexentry[colon+1:].strip() + inode['entries'].append((indextype, indexentry, + targetname, targetname)) + env.note_reftarget(rolename, fullname, targetname) + # don't use object indexing below + continue + except ValueError, err: + # signature parsing failed + signode.clear() + signode += addnodes.desc_name(sig, sig) + continue # we don't want an index entry here + # only add target and index entry if this is the first description of the + # function name in this desc block + if not noindex and name not in names: + fullname = (module and module + '.' or '') + name + # note target + if fullname not in state.document.ids: + signode['names'].append(fullname) + signode['ids'].append(fullname) + signode['first'] = (not names) + state.document.note_explicit_target(signode) + env.note_descref(fullname, desctype, lineno) + names.append(name) + + indextext = desc_index_text(desctype, module, name, + env.config.add_module_names) + inode['entries'].append(('single', indextext, fullname, fullname)) + + subnode = addnodes.desc_content() + # needed for automatic qualification of members + clsname_set = False + if desctype in ('class', 'exception') and names: + env.currclass = names[0] + clsname_set = True + elif desctype in ('method', 'staticmethod', 'attribute') and \ + clsname and not env.currclass: + env.currclass = clsname.strip('.') + clsname_set = True + # needed for association of version{added,changed} directives + if names: + env.currdesc = names[0] + state.nested_parse(content, content_offset, subnode) + handle_doc_fields(subnode, env) + if clsname_set: + env.currclass = None + env.currdesc = None + node.append(subnode) + return [inode, node] + +desc_directive.content = 1 +desc_directive.arguments = (1, 0, 1) +desc_directive.options = {'noindex': directives.flag, + 'module': directives.unchanged} + +desctypes = [ + # the Python ones + 'function', + 'data', + 'class', + 'method', + 'staticmethod', + 'attribute', + 'exception', + # the C ones + 'cfunction', + 'cmember', + 'cmacro', + 'ctype', + 'cvar', + # for command line options + 'cmdoption', + # the generic one + 'describe', + 'envvar', +] + +for _name in desctypes: + directives.register_directive(_name, desc_directive) + +_ = 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 _ + + +# ------ target -------------------------------------------------------------------- + +def target_directive(targettype, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + """Generic target for user-defined cross-reference types.""" + env = state.document.settings.env + rolename, indextemplate, foo = additional_xref_types[targettype] + # normalize whitespace in fullname like xfileref_role does + fullname = ws_re.sub('', arguments[0].strip()) + targetname = '%s-%s' % (rolename, fullname) + node = nodes.target('', '', ids=[targetname]) + 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 + +target_directive.content = 0 +target_directive.arguments = (1, 0, 1) + +# note, the target directive is not registered here, it is used by the application +# when registering additional xref types