def process_usecase_nodes(app, doctree, fromdocname):
    if not app.config.usecases_include_usecases:
        for node in doctree.traverse(usecase):
            node.parent.remove(node)

    # Replace all usecaselist nodes with a list of the collected usecases.
    # Argument each usecase with a backlink to the original location.
    env = app.builder.env

    if not hasattr(env, "usecase_all_usecases"):
        return

    for node in doctree.traverse(usecaselist):
        if not app.config.usecases_include_usecases:
            node.replace_self([])
            continue

        content = []

        for usecase_info in env.usecase_all_usecases:
            para = nodes.paragraph()
            # Create a reference

            if app.config.usecases_simple_usecaseslist:
                para += nodes.strong("UseCase: ", "UseCase: ")
                # description = (
                #    _('%s ') %
                #    (usecase_info['usecase-name']))
                # para += nodes.Text(description, description)
                newnode = nodes.reference("", "")
                innernode = nodes.emphasis(_(usecase_info["usecase-name"]), _(usecase_info["usecase-name"]))
                newnode["refdocname"] = usecase_info["docname"]
                newnode["refuri"] = app.builder.get_relative_uri(fromdocname, usecase_info["docname"])
                newnode["refuri"] += "#" + usecase_info["target"]["refid"]
                newnode.append(innernode)
                para += newnode
                content.append(para)

            else:
                filename = env.doc2path(usecase_info["docname"], base=None)
                description = _("(The original entry is located in %s, line %d and can be found ") % (
                    filename,
                    usecase_info["lineno"],
                )
                para += nodes.Text(description, description)
                newnode = nodes.reference("", "")
                innernode = nodes.emphasis(_("here"), _("here"))
                newnode["refdocname"] = usecase_info["docname"]
                newnode["refuri"] = app.builder.get_relative_uri(fromdocname, usecase_info["docname"])
                # newnode['refuri'] += '#' + usecase_info['target']['refid']
                newnode.append(innernode)

                para += newnode
                para += nodes.Text(".)", ".)")

                # Insert into the usecaselist
                content.append(usecase_info["usecase"])
                content.append(para)

        node.replace_self(content)
示例#2
0
 def get_index_text(self, name):
     if self.objtype == 'option':
         return _('%s (option)') % name
     elif self.objtype == 'variable':
         return _('%s (variable)') % name
     else:
         return ''
示例#3
0
文件: conf.py 项目: i386x/doit
        def depart_caption(self, node):
            self.body.append('</span>')

            # append permalink if available
            if isinstance(node.parent, nodes.container) \
            and node.parent.get('literal_block'):
                self.add_permalink_ref(
                    node.parent, _('Permalink to this code')
                )
            elif isinstance(node.parent, nodes.figure):
                image_nodes = node.parent.traverse(nodes.image)
                target_node = image_nodes and image_nodes[0] or node.parent
                self.add_permalink_ref(
                    target_node, _('Permalink to this image')
                )
            elif node.parent.get('toctree'):
                self.add_permalink_ref(
                    node.parent.parent, _('Permalink to this toctree')
                )

            if isinstance(node.parent, nodes.container) \
            and node.parent.get('literal_block'):
                self.body.append('</div>\n')
            else:
                SmartyPantsHTMLTranslator.__bases__[0].__bases__[0] \
                    .depart_caption(self, node)
示例#4
0
 def run(self):
     env = self.state.document.settings.env
     modname = self.arguments[0].strip()
     noindex = "noindex" in self.options
     env.temp_data["py:module"] = modname
     env.domaindata["py"]["modules"][modname] = (
         env.docname,
         self.options.get("synopsis", ""),
         self.options.get("platform", ""),
         "deprecated" in self.options,
     )
     # make a duplicate entry in 'objects' to facilitate searching for the
     # module in PythonDomain.find_obj()
     env.domaindata["py"]["objects"][modname] = (env.docname, "module")
     targetnode = nodes.target("", "", ids=["module-" + modname], ismod=True)
     self.state.document.note_explicit_target(targetnode)
     ret = [targetnode]
     # XXX this behavior of the module directive is a mess...
     if "platform" in self.options:
         platform = self.options["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.append(inode)
     return ret
示例#5
0
def text_visit_graphviz(self, node):
    # type: (nodes.NodeVisitor, graphviz) -> None
    if 'alt' in node.attributes:
        self.add_text(_('[graph: %s]') % node['alt'])
    else:
        self.add_text(_('[graph]'))
    raise nodes.SkipNode
示例#6
0
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type(
        'confval',
        'confval',
        objname='configuration value',
        indextemplate='pair: %s; configuration value',
        doc_field_types=[
            PyField(
                'type',
                label=_('Type'),
                has_arg=False,
                names=('type',),
                bodyrolename='class'
            ),
            Field(
                'default',
                label=_('Default'),
                has_arg=False,
                names=('default',),
            ),
        ]
    )
示例#7
0
文件: application.py 项目: nwf/sphinx
    def build(self, force_all=False, filenames=None):
        # type: (bool, List[unicode]) -> None
        try:
            if force_all:
                self.builder.compile_all_catalogs()
                self.builder.build_all()
            elif filenames:
                self.builder.compile_specific_catalogs(filenames)
                self.builder.build_specific(filenames)
            else:
                self.builder.compile_update_catalogs()
                self.builder.build_update()

            status = (self.statuscode == 0 and
                      _('succeeded') or _('finished with problems'))
            if self._warncount:
                logger.info(bold(_('build %s, %s warning%s.') %
                                 (status, self._warncount,
                                  self._warncount != 1 and 's' or '')))
            else:
                logger.info(bold(_('build %s.') % status))
        except Exception as err:
            # delete the saved env to force a fresh build next time
            envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
            if path.isfile(envfile):
                os.unlink(envfile)
            self.emit('build-finished', err)
            raise
        else:
            self.emit('build-finished', None)
        self.builder.cleanup()
示例#8
0
def depart_title(self, node):

    # XXX Because we want to inject our link into the title, this is
    # largely copy-pasta'd from sphinx.html.writers.HtmlTranslator.

    close_tag = self.context[-1]

    if (self.permalink_text and self.builder.add_permalinks and
        node.parent.hasattr('ids') and node.parent['ids']):
        aname = node.parent['ids'][0]

        if close_tag.startswith('</a></h'):
            self.body.append('</a>')

        self.body.append(u'<a class="headerlink" href="#%s" ' % aname +
                         u'title="%s">%s</a>' % (
                         _('Permalink to this headline'),
                         self.permalink_text))

        self.body.append(u'<a class="headerlink" href="%s#%s" ' % (
                                html.slide_path(self.builder), aname,) +
                         u'title="%s">%s' % (
                         _('Slides'),
                         self.builder.app.config.slide_html_slide_link_symbol))

        if not close_tag.startswith('</a></h'):
            self.body.append('</a>')

    BaseTranslator.depart_title(self, node)
示例#9
0
def generic_visit_altair_plot(self, node):
    # TODO: generate PNGs and insert them here
    if 'alt' in node.attributes:
        self.body.append(_('[ graph: %s ]') % node['alt'])
    else:
        self.body.append(_('[ graph ]'))
    raise nodes.SkipNode
示例#10
0
 def run(self):
     env = self.state.document.settings.env
     modname = self.arguments[0].strip()
     noindex = 'noindex' in self.options
     env.temp_data['tcpip:module'] = modname
     env.domaindata['tcpip']['modules'][modname] = \
         (env.docname, self.options.get('synopsis', ''),
          self.options.get('platform', ''), 'deprecated' in self.options)
     targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
     self.state.document.note_explicit_target(targetnode)
     ret = [targetnode]
     # XXX this behavior of the module directive is a mess...
     if 'platform' in self.options:
         platform = self.options['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.append(inode)
     return ret
示例#11
0
文件: config.py 项目: atodorov/sphinx
 def convert_overrides(self, name, value):
     # type: (unicode, Any) -> Any
     if not isinstance(value, string_types):
         return value
     else:
         defvalue = self.values[name][0]
         if isinstance(defvalue, dict):
             raise ValueError(_('cannot override dictionary config setting %r, '
                                'ignoring (use %r to set individual elements)') %
                              (name, name + '.key=value'))
         elif isinstance(defvalue, list):
             return value.split(',')
         elif isinstance(defvalue, integer_types):
             try:
                 return int(value)
             except ValueError:
                 raise ValueError(_('invalid number %r for config value %r, ignoring') %
                                  (value, name))
         elif hasattr(defvalue, '__call__'):
             return value
         elif defvalue is not None and not isinstance(defvalue, string_types):
             raise ValueError(_('cannot override config setting %r with unsupported '
                                'type, ignoring') % name)
         else:
             return value
示例#12
0
文件: bro.py 项目: fabaff/bro
def process_see_nodes(app, doctree, fromdocname):
    for node in doctree.traverse(see):
        content = []
        para = nodes.paragraph()
        para += nodes.Text("See also:", "See also:")
        for name in node.refs:
            join_str = " "
            if name != node.refs[0]:
                join_str  = ", "
            link_txt = join_str + name;

            if name not in app.env.domaindata['bro']['idtypes']:
                # Just create the text and issue warning
                app.env.warn(fromdocname,
                             'unknown target for ".. bro:see:: %s"' % (name))
                para += nodes.Text(link_txt, link_txt)
            else:
                # Create a reference
                typ = app.env.domaindata['bro']['idtypes'][name]
                todocname = app.env.domaindata['bro']['objects'][(typ, name)]

                newnode = nodes.reference('', '')
                innernode = nodes.literal(_(name), _(name))
                newnode['refdocname'] = todocname
                newnode['refuri'] = app.builder.get_relative_uri(
                    fromdocname, todocname)
                newnode['refuri'] += '#' + typ + '-' + name
                newnode.append(innernode)
                para += nodes.Text(join_str, join_str)
                para += newnode

        content.append(para)
        node.replace_self(content)
示例#13
0
文件: rst.py 项目: lmregus/Portfolio
 def get_index_text(self, objectname, name):
     # type: (str, str) -> str
     if self.objtype == 'directive':
         return _('%s (directive)') % name
     elif self.objtype == 'role':
         return _('%s (role)') % name
     return ''
示例#14
0
 def assemble_doctree(self, indexfile):
     docnames = set([indexfile])
     self.info(darkgreen(indexfile) + " ", nonl=1)
     tree = self.env.get_doctree(indexfile)
     tree['docname'] = indexfile
     # extract toctree nodes from the tree and put them in a fresh document
     new_tree = docutils.utils.new_document('<rinoh output>')
     for node in tree.traverse(addnodes.toctree):
         new_tree += node
     largetree = inline_all_toctrees(self, docnames, indexfile, new_tree,
                                     darkgreen)
     largetree['docname'] = indexfile
     self.info()
     self.info("resolving references...")
     self.env.resolve_references(largetree, indexfile, self)
     # resolve :ref:s to distant tex files -- we can't add a cross-reference,
     # but append the document name
     for pendingnode in largetree.traverse(addnodes.pending_xref):
         docname = pendingnode['refdocname']
         sectname = pendingnode['refsectname']
         newnodes = [nodes.emphasis(sectname, sectname)]
         for subdir, title in self.titles:
             if docname.startswith(subdir):
                 newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
                 newnodes.append(nodes.emphasis(title, title))
                 newnodes.append(nodes.Text(')', ')'))
                 break
         else:
             pass
         pendingnode.replace_self(newnodes)
     return largetree
示例#15
0
def man_visit_graphviz(self, node):
    warn_for_deprecated_option(self, node)
    if 'alt' in node.attributes:
        self.body.append(_('[graph: %s]') % node['alt'])
    else:
        self.body.append(_('[graph]'))
    raise nodes.SkipNode
示例#16
0
 def get_index_text(self, objectname, name_obj):
     name = name_obj[0].split('->')[-1]
     if objectname or name_obj[1]:
         objectname = name_obj[0].split('->')[0]
         return _('%s() (%s member)') % (name, objectname)
     else:
         return _('%s() (method)') % name
示例#17
0
def text_visit_graphviz(self, node):
    warn_for_deprecated_option(self, node)
    if 'alt' in node.attributes:
        self.add_text(_('[graph: %s]') % node['alt'])
    else:
        self.add_text(_('[graph]'))
    raise nodes.SkipNode
示例#18
0
 def get_index_text(self, modname, name_cls):
     if self.objtype == 'function':
         if not modname:
             return _('%s() (global function)') % name_cls[0]
         return _('%s() (module function in %s)') % (name_cls[0], modname)
     else:
         return ''
示例#19
0
	def run(self):

		env = self.state.document.settings.env

		targetid = "question-%d" % env.new_serialno('question')
		targetnode = nodes.target('', '', ids=[targetid])
 

		ad = Question('\n'.join(self.content))
		ad += nodes.title(_('Question'), _('Question'))
		#ad += nodes.class(_('Question'), _('Question'))
		self.state.nested_parse(self.content, self.content_offset, ad)
		ad.attributes["classes"] =  ["question"]
		#ad.options["class"] = "question"

		#ad = Question()
		#ad.name = self.name 
		#ad.content_offset = self.content_offset 
		#ad.options = self.options 
		#ad.content = self.content 
		#ad.block_text = self.block_text
		#ad.state = self.state
		#ad.state_machine = self.state_machine

		#ad = make_admonition(Question, self.name, [_('Question')], self.options,
		#					self.content, self.lineno, self.content_offset,
		#					self.block_text, self.state, self.state_machine)

		return [targetnode,ad]
示例#20
0
文件: rst.py 项目: JelteF/sphinx
 def get_index_text(self, objectname, name):
     # type: (unicode, unicode) -> unicode
     if self.objtype == 'directive':
         return _('%s (directive)') % name
     elif self.objtype == 'role':
         return _('%s (role)') % name
     return ''
示例#21
0
    def __init__(self, name, theme_path, factory):
        # type: (unicode, unicode, HTMLThemeFactory) -> None
        self.name = name
        self.base = None
        self.rootdir = None

        if path.isdir(theme_path):
            # already a directory, do nothing
            self.rootdir = None
            self.themedir = theme_path
        else:
            # extract the theme to a temp directory
            self.rootdir = tempfile.mkdtemp('sxt')
            self.themedir = path.join(self.rootdir, name)
            extract_zip(theme_path, self.themedir)

        self.config = configparser.RawConfigParser()
        self.config.read(path.join(self.themedir, THEMECONF))  # type: ignore

        try:
            inherit = self.config.get('theme', 'inherit')
        except configparser.NoSectionError:
            raise ThemeError(_('theme %r doesn\'t have "theme" setting') % name)
        except configparser.NoOptionError:
            raise ThemeError(_('theme %r doesn\'t have "inherit" setting') % name)

        if inherit != 'none':
            try:
                self.base = factory.create(inherit)
            except ThemeError:
                raise ThemeError(_('no theme named %r found, inherited by %r') %
                                 (inherit, name))
示例#22
0
    def run(self):
        pkgname = self.arguments[0].strip()
        env = self.state.document.settings.env
        env.ref_context['qbs:package'] = pkgname

        if 'noindex' in self.options:
            return []

        sdkname = self.options.get('sdk', env.ref_context.get('qbs:sdk', None))

        if sdkname:
            pkgname = sdkname + '.' + pkgname

        env.domaindata['qbs']['packages'][pkgname] = (env.docname, self.options.get('synopsis', ''))
        env.domaindata['qbs']['objects'][pkgname] = (env.docname, 'package')

        # target
        targetname = 'package-' + pkgname
        targetnode = nodes.target('', '', ids=[targetname], ismod=True)
        self.state.document.note_explicit_target(targetnode)

        # index
        if sdkname:
            itext = _('%s (Qbs Package in %s)') % (pkgname[len(sdkname) + 1:], sdkname)
        else:
            itext = _('%s (Qbs Package') % (pkgname[len(sdkname) + 1:])
        inode = addnodes.index(entries=[('single', itext, targetname, '', None)])

        return [targetnode, inode]
示例#23
0
    def convert(self, _from, _to):
        # type: (unicode, unicode) -> bool
        """Converts the image to expected one."""
        try:
            args = ([self.config.image_converter] +
                    self.config.image_converter_args +
                    [_from, _to])
            logger.debug('Invoking %r ...', args)
            p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            logger.warning(_('convert command %r cannot be run.'
                             'check the image_converter setting'),
                           self.config.image_converter)
            return False

        try:
            stdout, stderr = p.communicate()
        except (OSError, IOError) as err:
            if err.errno not in (EPIPE, EINVAL):
                raise
            stdout, stderr = p.stdout.read(), p.stderr.read()
            p.wait()
        if p.returncode != 0:
            raise ExtensionError(_('convert exited with error:\n'
                                   '[stderr]\n%s\n[stdout]\n%s') %
                                 (stderr, stdout))

        return True
示例#24
0
def man_visit_graphviz(self, node):
    # type: (nodes.NodeVisitor, graphviz) -> None
    if 'alt' in node.attributes:
        self.body.append(_('[graph: %s]') % node['alt'])
    else:
        self.body.append(_('[graph]'))
    raise nodes.SkipNode
示例#25
0
    def run(self):

        if not self.content:
            self.content = docutils.statemachine.StringList(['This driver supports :ref:`virtual I/O operations (/vsimem/, etc.) <virtual_file_systems>`'])
        node = supports_virtualio('\n'.join(self.content))
        node += nodes.title(_('Supports VirtualIO'), _('Supports VirtualIO'))

        return finish_directive(self, 'supports_virtualio', node)
示例#26
0
 def get_index_text(self, modname, name):
     """Return the text for the index entry of the object."""
     if self.objtype == 'function':
         return _('%s()') % name[0]
     elif self.objtype == 'data':
         return _('%s') % name[0]
     else:
         return ''
示例#27
0
    def run(self):

        if not self.content:
            self.content = docutils.statemachine.StringList(['This driver supports the :cpp:func:`GDALDriver::CreateCopy` operation'])
        node = supports_createcopy('\n'.join(self.content))
        node += nodes.title(_('Supports CreateCopy()'), _('Supports CreateCopy()'))

        return finish_directive(self, 'supports_createcopy', node)
示例#28
0
    def run(self):

        if not self.content:
            self.content = docutils.statemachine.StringList(['This driver supports georeferencing'])
        node = supports_georeferencing('\n'.join(self.content))
        node += nodes.title(_('Supports Georeferencing'), _('Supports Georeferencing'))

        return finish_directive(self, 'supports_georeferencing', node)
示例#29
0
 def add_builder(self, builder):
     # type: (Type[Builder]) -> None
     if not hasattr(builder, 'name'):
         raise ExtensionError(_('Builder class %s has no "name" attribute') % builder)
     if builder.name in self.builders:
         raise ExtensionError(_('Builder %r already exists (in module %s)') %
                              (builder.name, self.builders[builder.name].__module__))
     self.builders[builder.name] = builder
示例#30
0
 def override_domain(self, domain):
     # type: (Type[Domain]) -> None
     if domain.name not in self.domains:
         raise ExtensionError(_('domain %s not yet registered') % domain.name)
     if not issubclass(domain, self.domains[domain.name]):
         raise ExtensionError(_('new domain not a subclass of registered %s '
                                'domain') % domain.name)
     self.domains[domain.name] = domain
示例#31
0
    def __init__(self,
                 srcdir,
                 confdir,
                 outdir,
                 doctreedir,
                 buildername,
                 confoverrides=None,
                 status=sys.stdout,
                 warning=sys.stderr,
                 freshenv=False,
                 warningiserror=False,
                 tags=None,
                 verbosity=0,
                 parallel=0):
        # type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, List[unicode], int, int) -> None  # NOQA
        self.verbosity = verbosity
        self.extensions = {}  # type: Dict[unicode, Extension]
        self._setting_up_extension = ['?']  # type: List[unicode]
        self.builder = None  # type: Builder
        self.env = None  # type: BuildEnvironment
        self.registry = SphinxComponentRegistry()
        self.enumerable_nodes = {
        }  # type: Dict[nodes.Node, Tuple[unicode, Callable]]  # NOQA
        self.post_transforms = []  # type: List[Transform]
        self.html_themes = {}  # type: Dict[unicode, unicode]

        self.srcdir = srcdir
        self.confdir = confdir
        self.outdir = outdir
        self.doctreedir = doctreedir

        self.parallel = parallel

        if status is None:
            self._status = cStringIO()  # type: IO
            self.quiet = True
        else:
            self._status = status
            self.quiet = False

        if warning is None:
            self._warning = cStringIO()  # type: IO
        else:
            self._warning = warning
        self._warncount = 0
        self.warningiserror = warningiserror
        logging.setup(self, self._status, self._warning)

        self.events = EventManager()

        # keep last few messages for traceback
        # This will be filled by sphinx.util.logging.LastMessagesWriter
        self.messagelog = deque(maxlen=10)  # type: deque

        # say hello to the world
        logger.info(bold('Running Sphinx v%s' % sphinx.__display_version__))

        # status code for command-line application
        self.statuscode = 0

        if not path.isdir(outdir):
            logger.info('making output directory...')
            os.makedirs(outdir)

        # read config
        self.tags = Tags(tags)
        self.config = Config(confdir, CONFIG_FILENAME, confoverrides or {},
                             self.tags)
        self.config.check_unicode()
        # defer checking types until i18n has been initialized

        # initialize some limited config variables before initialize i18n and loading
        # extensions
        self.config.pre_init_values()

        # set up translation infrastructure
        self._init_i18n()

        # check the Sphinx version if requested
        if self.config.needs_sphinx and self.config.needs_sphinx > sphinx.__display_version__:
            raise VersionRequirementError(
                _('This project needs at least Sphinx v%s and therefore cannot '
                  'be built with this version.') % self.config.needs_sphinx)

        # set confdir to srcdir if -C given (!= no confdir); a few pieces
        # of code expect a confdir to be set
        if self.confdir is None:
            self.confdir = self.srcdir

        # load all built-in extension modules
        for extension in builtin_extensions:
            self.setup_extension(extension)

        # load all user-given extension modules
        for extension in self.config.extensions:
            self.setup_extension(extension)

        # preload builder module (before init config values)
        self.preload_builder(buildername)

        # the config file itself can be an extension
        if self.config.setup:
            self._setting_up_extension = ['conf.py']
            # py31 doesn't have 'callable' function for below check
            if hasattr(self.config.setup, '__call__'):
                self.config.setup(self)
            else:
                raise ConfigError(
                    _("'setup' as currently defined in conf.py isn't a Python callable. "
                      "Please modify its definition to make it a callable function. This is "
                      "needed for conf.py to behave as a Sphinx extension."))

        # now that we know all config values, collect them from conf.py
        self.config.init_values()

        # check extension versions if requested
        verify_required_extensions(self, self.config.needs_extensions)

        # check primary_domain if requested
        primary_domain = self.config.primary_domain
        if primary_domain and not self.registry.has_domain(primary_domain):
            logger.warning(_('primary_domain %r not found, ignored.'),
                           primary_domain)

        # create the builder
        self.builder = self.create_builder(buildername)
        # check all configuration values for permissible types
        self.config.check_types()
        # set up source_parsers
        self._init_source_parsers()
        # set up the build environment
        self._init_env(freshenv)
        # set up the builder
        self._init_builder()
        # set up the enumerable nodes
        self._init_enumerable_nodes()
示例#32
0
    def run(self) -> List[Node]:
        node = addnodes.glossary()
        node.document = self.state.document

        # This directive implements a custom format of the reST definition list
        # that allows multiple lines of terms before the definition.  This is
        # easy to parse since we know that the contents of the glossary *must
        # be* a definition list.

        # first, collect single entries
        entries = []  # type: List[Tuple[List[Tuple[str, str, int]], StringList]]
        in_definition = True
        in_comment = False
        was_empty = True
        messages = []  # type: List[Node]
        for line, (source, lineno) in zip(self.content, self.content.items):
            # empty line -> add to last definition
            if not line:
                if in_definition and entries:
                    entries[-1][1].append('', source, lineno)
                was_empty = True
                continue
            # unindented line -> a term
            if line and not line[0].isspace():
                # enable comments
                if line.startswith('.. '):
                    in_comment = True
                    continue
                else:
                    in_comment = False

                # first term of definition
                if in_definition:
                    if not was_empty:
                        messages.append(self.state.reporter.warning(
                            _('glossary term must be preceded by empty line'),
                            source=source, line=lineno))
                    entries.append(([(line, source, lineno)], StringList()))
                    in_definition = False
                # second term and following
                else:
                    if was_empty:
                        messages.append(self.state.reporter.warning(
                            _('glossary terms must not be separated by empty lines'),
                            source=source, line=lineno))
                    if entries:
                        entries[-1][0].append((line, source, lineno))
                    else:
                        messages.append(self.state.reporter.warning(
                            _('glossary seems to be misformatted, check indentation'),
                            source=source, line=lineno))
            elif in_comment:
                pass
            else:
                if not in_definition:
                    # first line of definition, determines indentation
                    in_definition = True
                    indent_len = len(line) - len(line.lstrip())
                if entries:
                    entries[-1][1].append(line[indent_len:], source, lineno)
                else:
                    messages.append(self.state.reporter.warning(
                        _('glossary seems to be misformatted, check indentation'),
                        source=source, line=lineno))
            was_empty = False

        # now, parse all the entries into a big definition list
        items = []
        for terms, definition in entries:
            termtexts = []          # type: List[str]
            termnodes = []          # type: List[Node]
            system_messages = []    # type: List[Node]
            for line, source, lineno in terms:
                parts = split_term_classifiers(line)
                # parse the term with inline markup
                # classifiers (parts[1:]) will not be shown on doctree
                textnodes, sysmsg = self.state.inline_text(parts[0], lineno)

                # use first classifier as a index key
                term = make_glossary_term(self.env, textnodes, parts[1], source, lineno,
                                          document=self.state.document)
                term.rawsource = line
                system_messages.extend(sysmsg)
                termtexts.append(term.astext())
                termnodes.append(term)

            termnodes.extend(system_messages)

            defnode = nodes.definition()
            if definition:
                self.state.nested_parse(definition, definition.items[0][1],
                                        defnode)
            termnodes.append(defnode)
            items.append((termtexts,
                          nodes.definition_list_item('', *termnodes)))

        if 'sorted' in self.options:
            items.sort(key=lambda x:
                       unicodedata.normalize('NFD', x[0][0].lower()))

        dlist = nodes.definition_list()
        dlist['classes'].append('glossary')
        dlist.extend(item[1] for item in items)
        node += dlist
        return messages + [node]
示例#33
0
class EnvVar(GenericObject):
    indextemplate = _('environment variable; %s')
示例#34
0
文件: graphviz.py 项目: th0/test2
def text_visit_graphviz(self, node):
    if 'alt' in node.attributes:
        self.add_text(_('[graph: %s]') % node['alt'])
    else:
        self.add_text(_('[graph]'))
    raise nodes.SkipNode
示例#35
0
 def get_type_name(self, type, primary=False):
     # type: (ObjType, bool) -> unicode
     """Return full name for given ObjType."""
     if primary:
         return type.lname
     return _('%s %s') % (self.label, type.lname)
示例#36
0
# 3rd party
import sphinx.domains.changeset
from docutils import nodes
from docutils.nodes import Node
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.locale import _

# this package
from sphinx_toolbox.utils import SphinxExtMetadata, metadata_add_version

__all__ = ["VersionChange", "setup"]

versionlabels = {
    "versionremoved": _("Removed in version %s"),
    **sphinx.domains.changeset.versionlabels,
}

versionlabel_classes = {
    "versionremoved": "removed",
    **sphinx.domains.changeset.versionlabel_classes,
}


class VersionChange(sphinx.domains.changeset.VersionChange):
    """
	Directive to describe a addition/change/deprecation/removal in a specific version.
	"""
    def run(self) -> List[Node]:
        """
示例#37
0
 def get_index_text(self, modname, name_cls):
     # type: (str, str) -> str
     name, cls = name_cls
     add_modules = self.env.config.add_module_names
     if self.objtype == '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.objtype == '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.objtype == '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.objtype == '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 ''
示例#38
0
    def generate(self, docnames=None):
        # type: (Iterable[str]) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]
        content = {}  # type: Dict[str, List[IndexEntry]]
        # list of prefixes to ignore
        ignores = None  # type: List[str]
        ignores = self.domain.env.config[
            'modindex_common_prefix']  # type: ignore
        ignores = sorted(ignores, key=len, reverse=True)
        # list of all modules, sorted by module name
        modules = sorted(self.domain.data['modules'].items(),
                         key=lambda x: x[0].lower())
        # sort out collapsable modules
        prev_modname = ''
        num_toplevels = 0
        for modname, (docname, synopsis, platforms, deprecated) in modules:
            if docnames and docname not in docnames:
                continue

            for ignore in ignores:
                if modname.startswith(ignore):
                    modname = modname[len(ignore):]
                    stripped = ignore
                    break
            else:
                stripped = ''

            # we stripped the whole module name?
            if not modname:
                modname, stripped = stripped, ''

            entries = content.setdefault(modname[0].lower(), [])

            package = modname.split('.')[0]
            if package != modname:
                # it's a submodule
                if prev_modname == package:
                    # first submodule - make parent a group head
                    if entries:
                        last = entries[-1]
                        entries[-1] = IndexEntry(last[0], 1, last[2], last[3],
                                                 last[4], last[5], last[6])
                    entries.append(
                        IndexEntry(stripped + package, 1, '', '', '', '', ''))
                elif not prev_modname.startswith(package):
                    # submodule without parent in list, add dummy entry
                    entries.append(
                        IndexEntry(stripped + package, 1, '', '', '', '', ''))
                subtype = 2
            else:
                num_toplevels += 1
                subtype = 0

            qualifier = deprecated and _('Deprecated') or ''
            entries.append(
                IndexEntry(stripped + modname, subtype, docname,
                           'module-' + stripped + modname, platforms,
                           qualifier, synopsis))
            prev_modname = modname

        # apply heuristics when to collapse modindex at page load:
        # only collapse if number of toplevel modules is larger than
        # number of submodules
        collapse = len(modules) - num_toplevels < num_toplevels

        # sort by first letter
        sorted_content = sorted(content.items())

        return sorted_content, collapse
示例#39
0
class PythonDomain(Domain):
    """Python language domain."""
    name = 'py'
    label = 'Python'
    object_types = {
        'function': ObjType(_('function'), 'func', 'obj'),
        'data': ObjType(_('data'), 'data', 'obj'),
        'class': ObjType(_('class'), 'class', 'exc', 'obj'),
        'exception': ObjType(_('exception'), 'exc', 'class', 'obj'),
        'method': ObjType(_('method'), 'meth', 'obj'),
        'classmethod': ObjType(_('class method'), 'meth', 'obj'),
        'staticmethod': ObjType(_('static method'), 'meth', 'obj'),
        'attribute': ObjType(_('attribute'), 'attr', 'obj'),
        'module': ObjType(_('module'), 'mod', 'obj'),
    }  # type: Dict[str, ObjType]

    directives = {
        'function': PyModulelevel,
        'data': PyModulelevel,
        'class': PyClasslike,
        'exception': PyClasslike,
        'method': PyClassmember,
        'classmethod': PyClassmember,
        'staticmethod': PyClassmember,
        'attribute': PyClassmember,
        'module': PyModule,
        'currentmodule': PyCurrentModule,
        'decorator': PyDecoratorFunction,
        'decoratormethod': PyDecoratorMethod,
    }
    roles = {
        'data': PyXRefRole(),
        'exc': PyXRefRole(),
        'func': PyXRefRole(fix_parens=True),
        'class': PyXRefRole(),
        'const': PyXRefRole(),
        'attr': PyXRefRole(),
        'meth': PyXRefRole(fix_parens=True),
        'mod': PyXRefRole(),
        'obj': PyXRefRole(),
    }
    initial_data = {
        'objects': {},  # fullname -> docname, objtype
        'modules': {},  # modname -> docname, synopsis, platform, deprecated
    }  # type: Dict[str, Dict[str, Tuple[Any]]]
    indices = [
        PythonModuleIndex,
    ]

    def clear_doc(self, docname):
        # type: (str) -> None
        for fullname, (fn, _l) in list(self.data['objects'].items()):
            if fn == docname:
                del self.data['objects'][fullname]
        for modname, (fn, _x, _x, _x) in list(self.data['modules'].items()):
            if fn == docname:
                del self.data['modules'][modname]

    def merge_domaindata(self, docnames, otherdata):
        # type: (List[str], Dict) -> None
        # XXX check duplicates?
        for fullname, (fn, objtype) in otherdata['objects'].items():
            if fn in docnames:
                self.data['objects'][fullname] = (fn, objtype)
        for modname, data in otherdata['modules'].items():
            if data[0] in docnames:
                self.data['modules'][modname] = data

    def find_obj(self, env, modname, classname, name, type, searchmode=0):
        # type: (BuildEnvironment, str, str, str, str, int) -> List[Tuple[str, Any]]
        """Find a Python object for "name", perhaps using the given module
        and/or classname.  Returns a list of (name, object entry) tuples.
        """
        # skip parens
        if name[-2:] == '()':
            name = name[:-2]

        if not name:
            return []

        objects = self.data['objects']
        matches = []  # type: List[Tuple[str, Any]]

        newname = None
        if searchmode == 1:
            if type is None:
                objtypes = list(self.object_types)
            else:
                objtypes = self.objtypes_for_role(type)
            if objtypes is not None:
                if modname and classname:
                    fullname = modname + '.' + classname + '.' + name
                    if fullname in objects and objects[fullname][1] in objtypes:
                        newname = fullname
                if not newname:
                    if modname and modname + '.' + name in objects and \
                       objects[modname + '.' + name][1] in objtypes:
                        newname = modname + '.' + name
                    elif name in objects and objects[name][1] in objtypes:
                        newname = name
                    else:
                        # "fuzzy" searching mode
                        searchname = '.' + name
                        matches = [(oname, objects[oname]) for oname in objects
                                   if oname.endswith(searchname)
                                   and objects[oname][1] in objtypes]
        else:
            # NOTE: searching for exact match, object type is not considered
            if name in objects:
                newname = name
            elif type == 'mod':
                # only exact matches allowed for modules
                return []
            elif classname and classname + '.' + name in objects:
                newname = classname + '.' + name
            elif modname and modname + '.' + name in objects:
                newname = modname + '.' + name
            elif modname and classname and \
                    modname + '.' + classname + '.' + name in objects:
                newname = modname + '.' + classname + '.' + name
            # special case: builtin exceptions have module "exceptions" set
            elif type == 'exc' and '.' not in name and \
                    'exceptions.' + name in objects:
                newname = 'exceptions.' + name
            # special case: object methods
            elif type in ('func', 'meth') and '.' not in name and \
                    'object.' + name in objects:
                newname = 'object.' + name
        if newname is not None:
            matches.append((newname, objects[newname]))
        return matches

    def resolve_xref(self, env, fromdocname, builder, type, target, node,
                     contnode):
        # type: (BuildEnvironment, str, Builder, str, str, addnodes.pending_xref, nodes.Element) -> nodes.Element  # NOQA
        modname = node.get('py:module')
        clsname = node.get('py:class')
        searchmode = node.hasattr('refspecific') and 1 or 0
        matches = self.find_obj(env, modname, clsname, target, type,
                                searchmode)
        if not matches:
            return None
        elif len(matches) > 1:
            logger.warning(
                __('more than one target found for cross-reference %r: %s'),
                target,
                ', '.join(match[0] for match in matches),
                type='ref',
                subtype='python',
                location=node)
        name, obj = matches[0]

        if obj[1] == 'module':
            return self._make_module_refnode(builder, fromdocname, name,
                                             contnode)
        else:
            return make_refnode(builder, fromdocname, obj[0], name, contnode,
                                name)

    def resolve_any_xref(self, env, fromdocname, builder, target, node,
                         contnode):
        # type: (BuildEnvironment, str, Builder, str, addnodes.pending_xref, nodes.Element) -> List[Tuple[str, nodes.Element]]  # NOQA
        modname = node.get('py:module')
        clsname = node.get('py:class')
        results = []  # type: List[Tuple[str, nodes.Element]]

        # always search in "refspecific" mode with the :any: role
        matches = self.find_obj(env, modname, clsname, target, None, 1)
        for name, obj in matches:
            if obj[1] == 'module':
                results.append(
                    ('py:mod',
                     self._make_module_refnode(builder, fromdocname, name,
                                               contnode)))
            else:
                results.append(('py:' + self.role_for_objtype(obj[1]),
                                make_refnode(builder, fromdocname, obj[0],
                                             name, contnode, name)))
        return results

    def _make_module_refnode(self, builder, fromdocname, name, contnode):
        # type: (Builder, str, str, nodes.Node) -> nodes.Element
        # get additional info for modules
        docname, synopsis, platform, deprecated = self.data['modules'][name]
        title = name
        if synopsis:
            title += ': ' + synopsis
        if deprecated:
            title += _(' (deprecated)')
        if platform:
            title += ' (' + platform + ')'
        return make_refnode(builder, fromdocname, docname, 'module-' + name,
                            contnode, title)

    def get_objects(self):
        # type: () -> Iterator[Tuple[str, str, str, str, str, int]]
        for modname, info in self.data['modules'].items():
            yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
        for refname, (docname, type) in self.data['objects'].items():
            if type != 'module':  # modules are already handled
                yield (refname, refname, type, docname, refname, 1)

    def get_full_qualified_name(self, node):
        # type: (nodes.Element) -> str
        modname = node.get('py:module')
        clsname = node.get('py:class')
        target = node.get('reftarget')
        if target is None:
            return None
        else:
            return '.'.join(filter(None, [modname, clsname, target]))
示例#40
0
 def get_index_text(self, name, type):
     return _('%s (Lisp %s)') % (name, type)
示例#41
0
文件: html.py 项目: xiaogh98/sphinx
 def depart_desc_signature_line(self, node):
     if node.get('add_permalink'):
         # the permalink info is on the parent desc_signature node
         self.add_permalink_ref(node.parent,
                                _('Permalink to this definition'))
     self.body.append('<br />')
示例#42
0
def collect_pages(app):
    # type: (Sphinx) -> Iterator[Tuple[unicode, Dict[unicode, Any], unicode]]
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        return
    highlighter = app.builder.highlighter  # type: ignore
    urito = app.builder.get_relative_uri

    modnames = set(env._viewcode_modules)  # type: ignore

    #    app.builder.info(' (%d module code pages)' %
    #                     len(env._viewcode_modules), nonl=1)

    for modname, entry in status_iterator(
            iteritems(env._viewcode_modules),  # type: ignore
            'highlighting module code... ',
            "blue",
            len(env._viewcode_modules),  # type: ignore
            app.verbosity,
            lambda x: x[0]):
        if not entry:
            continue
        code, tags, used, refname = entry
        # construct a page name for the highlighted source
        pagename = '_modules/' + modname.replace('.', '/')
        # highlight the source using the builder's highlighter
        if env.config.highlight_language in ('python3', 'default', 'none'):
            lexer = env.config.highlight_language
        else:
            lexer = 'python'
        highlighted = highlighter.highlight_block(code, lexer, linenos=False)
        # split the code into lines
        lines = highlighted.splitlines()
        # split off wrap markup from the first line of the actual code
        before, after = lines[0].split('<pre>')
        lines[0:1] = [before + '<pre>', after]
        # nothing to do for the last line; it always starts with </pre> anyway
        # now that we have code lines (starting at index 1), insert anchors for
        # the collected tags (HACK: this only works if the tag boundaries are
        # properly nested!)
        maxindex = len(lines) - 1
        for name, docname in iteritems(used):
            type, start, end = tags[name]
            backlink = urito(pagename, docname) + '#' + refname + '.' + name
            lines[start] = (
                '<div class="viewcode-block" id="%s"><a class="viewcode-back" '
                'href="%s">%s</a>' % (name, backlink, _('[docs]')) +
                lines[start])
            lines[min(end - 1, maxindex)] += '</div>'
        # try to find parents (for submodules)
        parents = []
        parent = modname
        while '.' in parent:
            parent = parent.rsplit('.', 1)[0]
            if parent in modnames:
                parents.append({
                    'link':
                    urito(pagename, '_modules/' + parent.replace('.', '/')),
                    'title':
                    parent
                })
        parents.append({
            'link': urito(pagename, '_modules/index'),
            'title': _('Module code')
        })
        parents.reverse()
        # putting it all together
        context = {
            'parents':
            parents,
            'title':
            modname,
            'body':
            (_('<h1>Source code for %s</h1>') % modname + '\n'.join(lines)),
        }  # type: Dict[unicode, Any]
        yield (pagename, context, 'page.html')

    if not modnames:
        return

    html = ['\n']
    # the stack logic is needed for using nested lists for submodules
    stack = ['']
    for modname in sorted(modnames):
        if modname.startswith(stack[-1]):
            stack.append(modname + '.')
            html.append('<ul>')
        else:
            stack.pop()
            while not modname.startswith(stack[-1]):
                stack.pop()
                html.append('</ul>')
            stack.append(modname + '.')
        html.append('<li><a href="%s">%s</a></li>\n' %
                    (urito('_modules/index',
                           '_modules/' + modname.replace('.', '/')), modname))
    html.append('</ul>' * (len(stack) - 1))
    context = {
        'title':
        _('Overview: module code'),
        'body': (_('<h1>All modules for which code is available</h1>') +
                 ''.join(html)),
    }

    yield ('_modules/index', context, 'page.html')
示例#43
0
class PyObject(ObjectDescription):
    """
    Description of a general Python object.

    :cvar allow_nesting: Class is an object that allows for nested namespaces
    :vartype allow_nesting: bool
    """
    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
        'annotation': directives.unchanged,
    }

    doc_field_types = [
        PyTypedField('parameter',
                     label=_('Parameters'),
                     names=('param', 'parameter', 'arg', 'argument', 'keyword',
                            'kwarg', 'kwparam'),
                     typerolename='class',
                     typenames=('paramtype', 'type'),
                     can_collapse=True),
        PyTypedField('variable',
                     label=_('Variables'),
                     rolename='obj',
                     names=('var', 'ivar', 'cvar'),
                     typerolename='class',
                     typenames=('vartype', ),
                     can_collapse=True),
        PyGroupedField('exceptions',
                       label=_('Raises'),
                       rolename='exc',
                       names=('raises', 'raise', 'exception', 'except'),
                       can_collapse=True),
        Field('returnvalue',
              label=_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        PyField('returntype',
                label=_('Return type'),
                has_arg=False,
                names=('rtype', ),
                bodyrolename='class'),
    ]

    allow_nesting = False

    def get_signature_prefix(self, sig):
        # type: (str) -> str
        """May return a prefix to put before the object name in the
        signature.
        """
        return ''

    def needs_arglist(self):
        # type: () -> bool
        """May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig, signode):
        # type: (str, addnodes.desc_signature) -> Tuple[str, str]
        """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
        name_prefix, name, arglist, retann = m.groups()

        # determine module and class name (if applicable), as well as full name
        modname = self.options.get('module',
                                   self.env.ref_context.get('py:module'))
        classname = self.env.ref_context.get('py:class')
        if classname:
            add_module = False
            if name_prefix and (name_prefix == classname
                                or name_prefix.startswith(classname + ".")):
                fullname = name_prefix + name
                # class name is given again in the signature
                name_prefix = name_prefix[len(classname):].lstrip('.')
            elif name_prefix:
                # class name is given in the signature, but different
                # (shouldn't happen)
                fullname = classname + '.' + name_prefix + name
            else:
                # class name is not given in the signature
                fullname = classname + '.' + name
        else:
            add_module = True
            if name_prefix:
                classname = name_prefix.rstrip('.')
                fullname = name_prefix + name
            else:
                classname = ''
                fullname = name

        signode['module'] = modname
        signode['class'] = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if name_prefix:
            signode += addnodes.desc_addname(name_prefix, name_prefix)
        # 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.ref_context.get('py:module'))
            if modname and modname != 'exceptions':
                nodetext = modname + '.'
                signode += addnodes.desc_addname(nodetext, nodetext)

        anno = self.options.get('annotation')

        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)
            if anno:
                signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
            return fullname, name_prefix

        _pseudo_parse_arglist(signode, arglist)
        if retann:
            signode += addnodes.desc_returns(retann, retann)
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        # type: (str, str) -> str
        """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):
        # type: (str, str, addnodes.desc_signature) -> None
        modname = self.options.get('module',
                                   self.env.ref_context.get('py:module'))
        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)
            objects = self.env.domaindata['py']['objects']
            if fullname in objects:
                self.state_machine.reporter.warning(
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]) +
                    ', use :noindex: for one of them',
                    line=self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, fullname, '', None))

    def before_content(self):
        # type: () -> None
        """Handle object nesting before content

        :py:class:`PyObject` represents Python language constructs. For
        constructs that are nestable, such as a Python classes, this method will
        build up a stack of the nesting heirarchy so that it can be later
        de-nested correctly, in :py:meth:`after_content`.

        For constructs that aren't nestable, the stack is bypassed, and instead
        only the most recent object is tracked. This object prefix name will be
        removed with :py:meth:`after_content`.
        """
        prefix = None
        if self.names:
            # fullname and name_prefix come from the `handle_signature` method.
            # fullname represents the full object name that is constructed using
            # object nesting and explicit prefixes. `name_prefix` is the
            # explicit prefix given in a signature
            (fullname, name_prefix) = self.names[-1]
            if self.allow_nesting:
                prefix = fullname
            elif name_prefix:
                prefix = name_prefix.strip('.')
        if prefix:
            self.env.ref_context['py:class'] = prefix
            if self.allow_nesting:
                classes = self.env.ref_context.setdefault('py:classes', [])
                classes.append(prefix)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            modules.append(self.env.ref_context.get('py:module'))
            self.env.ref_context['py:module'] = self.options['module']

    def after_content(self):
        # type: () -> None
        """Handle object de-nesting after content

        If this class is a nestable object, removing the last nested class prefix
        ends further nesting in the object.

        If this class is not a nestable object, the list of classes should not
        be altered as we didn't affect the nesting levels in
        :py:meth:`before_content`.
        """
        classes = self.env.ref_context.setdefault('py:classes', [])
        if self.allow_nesting:
            try:
                classes.pop()
            except IndexError:
                pass
        self.env.ref_context['py:class'] = (classes[-1]
                                            if len(classes) > 0 else None)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            if modules:
                self.env.ref_context['py:module'] = modules.pop()
            else:
                self.env.ref_context.pop('py:module')
示例#44
0
class CObject(ObjectDescription):
    """
    Description of a C language object.
    """

    doc_field_types = [
        TypedField('parameter',
                   label=_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    # These C types aren't described anywhere, so don't try to create
    # a cross-reference to them
    stopwords = set((
        'const',
        'void',
        'char',
        'wchar_t',
        'int',
        'short',
        'long',
        'float',
        'double',
        'unsigned',
        'signed',
        'FILE',
        'clock_t',
        'time_t',
        'ptrdiff_t',
        'size_t',
        'ssize_t',
        'struct',
        '_Bool',
    ))

    def _parse_type(self, node, ctype):
        # type: (nodes.Element, str) -> None
        # add cross-ref nodes for all words
        for part in [_f for _f in wsplit_re.split(ctype) if _f]:
            tnode = nodes.Text(part, part)
            if part[0] in string.ascii_letters + '_' and \
               part not in self.stopwords:
                pnode = addnodes.pending_xref('',
                                              refdomain='c',
                                              reftype='type',
                                              reftarget=part,
                                              modname=None,
                                              classname=None)
                pnode += tnode
                node += pnode
            else:
                node += tnode

    def _parse_arglist(self, arglist):
        # type: (str) -> Iterator[str]
        while True:
            m = c_funcptr_arg_sig_re.match(arglist)
            if m:
                yield m.group()
                arglist = c_funcptr_arg_sig_re.sub('', arglist)
                if ',' in arglist:
                    _, arglist = arglist.split(',', 1)
                else:
                    break
            else:
                if ',' in arglist:
                    arg, arglist = arglist.split(',', 1)
                    yield arg
                else:
                    yield arglist
                    break

    def handle_signature(self, sig, signode):
        # type: (str, addnodes.desc_signature) -> str
        """Transform a 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()

        desc_type = addnodes.desc_type('', '')
        signode += desc_type
        self._parse_type(desc_type, 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)

        typename = self.env.ref_context.get('c:type')
        if self.name == 'c:member' and typename:
            fullname = typename + '.' + name
        else:
            fullname = name

        if not arglist:
            if self.objtype == 'function' or \
                    self.objtype == 'macro' and sig.rstrip().endswith('()'):
                # for functions, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if const:
                signode += addnodes.desc_addname(const, const)
            return fullname

        paramlist = addnodes.desc_parameterlist()
        arglist = arglist.replace('`', '').replace('\\ ', '')  # remove markup
        # this messes up function pointer types, but not too badly ;)
        for arg in self._parse_arglist(arglist):
            arg = arg.strip()
            param = addnodes.desc_parameter('', '', noemph=True)
            try:
                m = c_funcptr_arg_sig_re.match(arg)
                if m:
                    self._parse_type(param, m.group(1) + '(')
                    param += nodes.emphasis(m.group(2), m.group(2))
                    self._parse_type(param, ')(' + m.group(3) + ')')
                    if m.group(4):
                        param += addnodes.desc_addname(m.group(4), m.group(4))
                else:
                    ctype, argname = arg.rsplit(' ', 1)
                    self._parse_type(param, ctype)
                    # separate by non-breaking space in the output
                    param += nodes.emphasis(' ' + argname, u'\xa0' + argname)
            except ValueError:
                # no argument name given, only the type
                self._parse_type(param, arg)
            paramlist += param
        signode += paramlist
        if const:
            signode += addnodes.desc_addname(const, const)
        return fullname

    def get_index_text(self, name):
        # type: (str) -> str
        if self.objtype == 'function':
            return _('%s (C function)') % name
        elif self.objtype == 'member':
            return _('%s (C member)') % name
        elif self.objtype == 'macro':
            return _('%s (C macro)') % name
        elif self.objtype == 'type':
            return _('%s (C type)') % name
        elif self.objtype == 'var':
            return _('%s (C variable)') % name
        else:
            return ''

    def add_target_and_index(self, name, sig, signode):
        # type: (str, str, addnodes.desc_signature) -> None
        # for C API items we add a prefix since names are usually not qualified
        # by a module name and so easily clash with e.g. section titles
        targetname = 'c.' + name
        if targetname not in self.state.document.ids:
            signode['names'].append(targetname)
            signode['ids'].append(targetname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            inv = self.env.domaindata['c']['objects']
            if name in inv:
                self.state_machine.reporter.warning(
                    'duplicate C object description of %s, ' % name +
                    'other instance in ' + self.env.doc2path(inv[name][0]),
                    line=self.lineno)
            inv[name] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, targetname, '', None))

    def before_content(self):
        # type: () -> None
        self.typename_set = False
        if self.name == 'c:type':
            if self.names:
                self.env.ref_context['c:type'] = self.names[0]
                self.typename_set = True

    def after_content(self):
        # type: () -> None
        if self.typename_set:
            self.env.ref_context.pop('c:type', None)
示例#45
0
def config_initiated(app, config):
    theme_options = config.html_theme_options or {}
    if theme_options.get("canonical_url"):
        logger.warning(
            _("The canonical_url option is deprecated, use the html_baseurl option from Sphinx instead.")
        )
示例#46
0
文件: html5.py 项目: yassu/sphinx
 def depart_desc_signature(self, node):
     # type: (addnodes.desc_signature) -> None
     if not node.get('is_multiline'):
         self.add_permalink_ref(node, _('Permalink to this definition'))
     self.body.append('</dt>\n')
示例#47
0
 def get_index_text(self, objectname, name):
     if self.objtype == 'directive':
         return _('%s (directive)') % name
     elif self.objtype == 'role':
         return _('%s (role)') % name
     return ''
示例#48
0
 def set_translator(self, name, translator_class):
     # type: (unicode, Type[nodes.NodeVisitor]) -> None
     logger.info(bold(_('Change of translator for the %s builder.') % name))
     self.registry.add_translator(name, translator_class)
示例#49
0
class CDomain(Domain):
    """C language domain."""
    name = 'c'
    label = 'C'
    object_types = {
        'function': ObjType(_('function'), 'func'),
        'member': ObjType(_('member'), 'member'),
        'macro': ObjType(_('macro'), 'macro'),
        'type': ObjType(_('type'), 'type'),
        'var': ObjType(_('variable'), 'data'),
    }

    directives = {
        'function': CObject,
        'member': CObject,
        'macro': CObject,
        'type': CObject,
        'var': CObject,
    }
    roles = {
        'func': CXRefRole(fix_parens=True),
        'member': CXRefRole(),
        'macro': CXRefRole(),
        'data': CXRefRole(),
        'type': CXRefRole(),
    }
    initial_data = {
        'objects': {},  # fullname -> docname, objtype
    }  # type: Dict[str, Dict[str, Tuple[str, Any]]]

    def clear_doc(self, docname):
        # type: (str) -> None
        for fullname, (fn, _l) in list(self.data['objects'].items()):
            if fn == docname:
                del self.data['objects'][fullname]

    def merge_domaindata(self, docnames, otherdata):
        # type: (List[str], Dict) -> None
        # XXX check duplicates
        for fullname, (fn, objtype) in otherdata['objects'].items():
            if fn in docnames:
                self.data['objects'][fullname] = (fn, objtype)

    def resolve_xref(self, env, fromdocname, builder, typ, target, node,
                     contnode):
        # type: (BuildEnvironment, str, Builder, str, str, addnodes.pending_xref, nodes.Element) -> nodes.Element  # NOQA
        # strip pointer asterisk
        target = target.rstrip(' *')
        # becase TypedField can generate xrefs
        if target in CObject.stopwords:
            return contnode
        if target not in self.data['objects']:
            return None
        obj = self.data['objects'][target]
        return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
                            contnode, target)

    def resolve_any_xref(self, env, fromdocname, builder, target, node,
                         contnode):
        # type: (BuildEnvironment, str, Builder, str, addnodes.pending_xref, nodes.Element) -> List[Tuple[str, nodes.Element]]  # NOQA
        # strip pointer asterisk
        target = target.rstrip(' *')
        if target not in self.data['objects']:
            return []
        obj = self.data['objects'][target]
        return [('c:' + self.role_for_objtype(obj[1]),
                 make_refnode(builder, fromdocname, obj[0], 'c.' + target,
                              contnode, target))]

    def get_objects(self):
        # type: () -> Iterator[Tuple[str, str, str, str, str, int]]
        for refname, (docname, type) in list(self.data['objects'].items()):
            yield (refname, refname, type, docname, 'c.' + refname, 1)
示例#50
0
    from sphinx.environment import BuildEnvironment  # NOQA
    from sphinx.util.typing import TextlikeNode  # NOQA

logger = logging.getLogger(__name__)

# REs for Python signatures
py_sig_re = re.compile(
    r'''^ ([\w.]*\.)?            # class name(s)
          (\w+)  \s*             # thing name
          (?: \(\s*(.*)\s*\)     # optional: arguments
           (?:\s* -> \s* (.*))?  #           return annotation
          )? $                   # and nothing more
          ''', re.VERBOSE)

pairindextypes = {
    'module': _('module'),
    'keyword': _('keyword'),
    'operator': _('operator'),
    'object': _('object'),
    'exception': _('exception'),
    'statement': _('statement'),
    'builtin': _('built-in function'),
}

locale.pairindextypes = DeprecatedDict(
    pairindextypes, 'sphinx.locale.pairindextypes is deprecated. '
    'Please use sphinx.domains.python.pairindextypes instead.',
    RemovedInSphinx30Warning)


def _pseudo_parse_arglist(signode, arglist):
示例#51
0
def indexmarkup_role(typ,
                     rawtext,
                     etext,
                     lineno,
                     inliner,
                     options={},
                     content=[]):
    """Role for PEP/RFC references that generate an index entry."""
    env = inliner.document.settings.env
    if not typ:
        typ = env.config.default_role
    else:
        typ = typ.lower()
    text = utils.unescape(etext)
    targetid = 'index-%s' % env.new_serialno('index')
    indexnode = addnodes.index()
    targetnode = nodes.target('', '', ids=[targetid])
    inliner.document.note_explicit_target(targetnode)
    if typ == 'pep':
        indexnode['entries'] = [
            ('single', _('Python Enhancement Proposals; PEP %s') % text,
             targetid, '')
        ]
        anchor = ''
        anchorindex = text.find('#')
        if anchorindex > 0:
            text, anchor = text[:anchorindex], text[anchorindex:]
        try:
            pepnum = int(text)
        except ValueError:
            msg = inliner.reporter.error('invalid PEP number %s' % text,
                                         line=lineno)
            prb = inliner.problematic(rawtext, rawtext, msg)
            return [prb], [msg]
        ref = inliner.document.settings.pep_base_url + 'pep-%04d' % pepnum
        sn = nodes.strong('PEP ' + text, 'PEP ' + text)
        rn = nodes.reference('',
                             '',
                             internal=False,
                             refuri=ref + anchor,
                             classes=[typ])
        rn += sn
        return [indexnode, targetnode, rn], []
    elif typ == 'rfc':
        indexnode['entries'] = [('single', 'RFC; RFC %s' % text, targetid, '')]
        anchor = ''
        anchorindex = text.find('#')
        if anchorindex > 0:
            text, anchor = text[:anchorindex], text[anchorindex:]
        try:
            rfcnum = int(text)
        except ValueError:
            msg = inliner.reporter.error('invalid RFC number %s' % text,
                                         line=lineno)
            prb = inliner.problematic(rawtext, rawtext, msg)
            return [prb], [msg]
        ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
        sn = nodes.strong('RFC ' + text, 'RFC ' + text)
        rn = nodes.reference('',
                             '',
                             internal=False,
                             refuri=ref + anchor,
                             classes=[typ])
        rn += sn
        return [indexnode, targetnode, rn], []
示例#52
0
文件: todo.py 项目: daleevans/sphinx
def process_todo_nodes(app, doctree, fromdocname):
    # type: (Sphinx, nodes.document, str) -> None
    node = None  # type: nodes.Element
    if not app.config['todo_include_todos']:
        for node in doctree.traverse(todo_node):
            node.parent.remove(node)

    # Replace all todolist nodes with a list of the collected todos.
    # Augment each todo with a backlink to the original location.
    env = app.builder.env

    if not hasattr(env, 'todo_all_todos'):
        env.todo_all_todos = []  # type: ignore

    for node in doctree.traverse(todolist):
        if node.get('ids'):
            content = [nodes.target()]  # type: List[nodes.Element]
        else:
            content = []

        if not app.config['todo_include_todos']:
            node.replace_self(content)
            continue

        for todo_info in env.todo_all_todos:  # type: ignore
            para = nodes.paragraph(classes=['todo-source'])
            if app.config['todo_link_only']:
                description = _('<<original entry>>')
            else:
                description = (
                    _('(The <<original entry>> is located in %s, line %d.)') %
                    (todo_info['source'], todo_info['lineno']))
            desc1 = description[:description.find('<<')]
            desc2 = description[description.find('>>') + 2:]
            para += nodes.Text(desc1, desc1)

            # Create a reference
            newnode = nodes.reference('', '', internal=True)
            innernode = nodes.emphasis(_('original entry'),
                                       _('original entry'))
            try:
                newnode['refuri'] = app.builder.get_relative_uri(
                    fromdocname, todo_info['docname'])
                try:
                    newnode['refuri'] += '#' + todo_info['target']['refid']
                except KeyError:
                    # presently, there's no refid for a todo that appears
                    # inside a param, possibly other places.  avoid crashing
                    # and leave a warning so we can track it down.
                    logger.warning(__("TODO target missing refid: %s"),
                                   todo_info['source'],
                                   location=node)
            except NoUri:
                # ignore if no URI can be determined, e.g. for LaTeX output
                pass
            newnode.append(innernode)
            para += newnode
            para += nodes.Text(desc2, desc2)

            todo_entry = todo_info['todo']
            # Remove targetref from the (copied) node to avoid emitting a
            # duplicate label of the original entry when we walk this node.
            if 'targetref' in todo_entry:
                del todo_entry['targetref']

            # (Recursively) resolve references in the todo content
            env.resolve_references(todo_entry, todo_info['docname'],
                                   app.builder)

            # Insert into the todolist
            content.append(todo_entry)
            content.append(para)

        node.replace_self(content)
示例#53
0
class StandardDomain(Domain):
    """
    Domain for all objects that don't fit into another domain or are added
    via the application interface.
    """

    name = 'std'
    label = 'Default'

    object_types = {
        'term': ObjType(_('glossary term'), 'term', searchprio=-1),
        'token': ObjType(_('grammar token'), 'token', searchprio=-1),
        'label': ObjType(_('reference label'), 'ref', 'keyword',
                         searchprio=-1),
        'envvar': ObjType(_('environment variable'), 'envvar'),
        'cmdoption': ObjType(_('program option'), 'option'),
        'doc': ObjType(_('document'), 'doc', searchprio=-1)
    }  # type: Dict[str, ObjType]

    directives = {
        'program': Program,
        'cmdoption': Cmdoption,  # old name for backwards compatibility
        'option': Cmdoption,
        'envvar': EnvVar,
        'glossary': Glossary,
        'productionlist': ProductionList,
    }  # type: Dict[str, Type[Directive]]
    roles = {
        'option':  OptionXRefRole(warn_dangling=True),
        'envvar':  EnvVarXRefRole(),
        # links to tokens in grammar productions
        'token':   TokenXRefRole(),
        # links to terms in glossary
        'term':    XRefRole(lowercase=True, innernodeclass=nodes.inline,
                            warn_dangling=True),
        # links to headings or arbitrary labels
        'ref':     XRefRole(lowercase=True, innernodeclass=nodes.inline,
                            warn_dangling=True),
        # links to labels of numbered figures, tables and code-blocks
        'numref':  XRefRole(lowercase=True,
                            warn_dangling=True),
        # links to labels, without a different title
        'keyword': XRefRole(warn_dangling=True),
        # links to documents
        'doc':     XRefRole(warn_dangling=True, innernodeclass=nodes.inline),
    }  # type: Dict[str, Union[RoleFunction, XRefRole]]

    initial_data = {
        'progoptions': {},      # (program, name) -> docname, labelid
        'objects': {},          # (type, name) -> docname, labelid
        'labels': {             # labelname -> docname, labelid, sectionname
            'genindex': ('genindex', '', _('Index')),
            'modindex': ('py-modindex', '', _('Module Index')),
            'search':   ('search', '', _('Search Page')),
        },
        'anonlabels': {         # labelname -> docname, labelid
            'genindex': ('genindex', ''),
            'modindex': ('py-modindex', ''),
            'search':   ('search', ''),
        },
    }

    dangling_warnings = {
        'term': 'term not in glossary: %(target)s',
        'ref':  'undefined label: %(target)s (if the link has no caption '
                'the label must precede a section header)',
        'numref':  'undefined label: %(target)s',
        'keyword': 'unknown keyword: %(target)s',
        'doc': 'unknown document: %(target)s',
        'option': 'unknown option: %(target)s',
    }

    enumerable_nodes = {  # node_class -> (figtype, title_getter)
        nodes.figure: ('figure', None),
        nodes.table: ('table', None),
        nodes.container: ('code-block', None),
    }  # type: Dict[Type[Node], Tuple[str, Callable]]

    def __init__(self, env: "BuildEnvironment") -> None:
        super().__init__(env)

        # set up enumerable nodes
        self.enumerable_nodes = copy(self.enumerable_nodes)  # create a copy for this instance
        for node, settings in env.app.registry.enumerable_nodes.items():
            self.enumerable_nodes[node] = settings

    def note_hyperlink_target(self, name: str, docname: str, node_id: str,
                              title: str = '') -> None:
        """Add a hyperlink target for cross reference.

        .. warning::

           This is only for internal use.  Please don't use this from your extension.
           ``document.note_explicit_target()`` or ``note_implicit_target()`` are recommended to
           add a hyperlink target to the document.

           This only adds a hyperlink target to the StandardDomain.  And this does not add a
           node_id to node.  Therefore, it is very fragile to calling this without
           understanding hyperlink target framework in both docutils and Sphinx.

        .. versionadded:: 3.0
        """
        if name in self.anonlabels and self.anonlabels[name] != (docname, node_id):
            logger.warning(__('duplicate label %s, other instance in %s'),
                           name, self.env.doc2path(self.anonlabels[name][0]))

        self.anonlabels[name] = (docname, node_id)
        if title:
            self.labels[name] = (docname, node_id, title)

    @property
    def objects(self) -> Dict[Tuple[str, str], Tuple[str, str]]:
        return self.data.setdefault('objects', {})  # (objtype, name) -> docname, labelid

    def note_object(self, objtype: str, name: str, labelid: str, location: Any = None
                    ) -> None:
        """Note a generic object for cross reference.

        .. versionadded:: 3.0
        """
        if (objtype, name) in self.objects:
            docname = self.objects[objtype, name][0]
            logger.warning(__('duplicate %s description of %s, other instance in %s'),
                           objtype, name, docname, location=location)
        self.objects[objtype, name] = (self.env.docname, labelid)

    def add_object(self, objtype: str, name: str, docname: str, labelid: str) -> None:
        warnings.warn('StandardDomain.add_object() is deprecated.',
                      RemovedInSphinx50Warning)
        self.objects[objtype, name] = (docname, labelid)

    @property
    def progoptions(self) -> Dict[Tuple[str, str], Tuple[str, str]]:
        return self.data.setdefault('progoptions', {})  # (program, name) -> docname, labelid

    @property
    def labels(self) -> Dict[str, Tuple[str, str, str]]:
        return self.data.setdefault('labels', {})  # labelname -> docname, labelid, sectionname

    @property
    def anonlabels(self) -> Dict[str, Tuple[str, str]]:
        return self.data.setdefault('anonlabels', {})  # labelname -> docname, labelid

    def clear_doc(self, docname: str) -> None:
        key = None  # type: Any
        for key, (fn, _l) in list(self.progoptions.items()):
            if fn == docname:
                del self.progoptions[key]
        for key, (fn, _l) in list(self.objects.items()):
            if fn == docname:
                del self.objects[key]
        for key, (fn, _l, _l) in list(self.labels.items()):
            if fn == docname:
                del self.labels[key]
        for key, (fn, _l) in list(self.anonlabels.items()):
            if fn == docname:
                del self.anonlabels[key]

    def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
        # XXX duplicates?
        for key, data in otherdata['progoptions'].items():
            if data[0] in docnames:
                self.progoptions[key] = data
        for key, data in otherdata['objects'].items():
            if data[0] in docnames:
                self.objects[key] = data
        for key, data in otherdata['labels'].items():
            if data[0] in docnames:
                self.labels[key] = data
        for key, data in otherdata['anonlabels'].items():
            if data[0] in docnames:
                self.anonlabels[key] = data

    def process_doc(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None:  # NOQA
        for name, explicit in document.nametypes.items():
            if not explicit:
                continue
            labelid = document.nameids[name]
            if labelid is None:
                continue
            node = document.ids[labelid]
            if isinstance(node, nodes.target) and 'refid' in node:
                # indirect hyperlink targets
                node = document.ids.get(node['refid'])
                labelid = node['names'][0]
            if (node.tagname == 'footnote' or
                    'refuri' in node or
                    node.tagname.startswith('desc_')):
                # ignore footnote labels, labels automatically generated from a
                # link and object descriptions
                continue
            if name in self.labels:
                logger.warning(__('duplicate label %s, other instance in %s'),
                               name, env.doc2path(self.labels[name][0]),
                               location=node)
            self.anonlabels[name] = docname, labelid
            if node.tagname in ('section', 'rubric'):
                title = cast(nodes.title, node[0])
                sectname = clean_astext(title)
            elif self.is_enumerable_node(node):
                sectname = self.get_numfig_title(node)
                if not sectname:
                    continue
            else:
                toctree = next(iter(node.traverse(addnodes.toctree)), None)
                if toctree and toctree.get('caption'):
                    sectname = toctree.get('caption')
                else:
                    # anonymous-only labels
                    continue
            self.labels[name] = docname, labelid, sectname

    def add_program_option(self, program: str, name: str, docname: str, labelid: str) -> None:
        self.progoptions[program, name] = (docname, labelid)

    def build_reference_node(self, fromdocname: str, builder: "Builder", docname: str,
                             labelid: str, sectname: str, rolename: str, **options: Any
                             ) -> Element:
        nodeclass = options.pop('nodeclass', nodes.reference)
        newnode = nodeclass('', '', internal=True, **options)
        innernode = nodes.inline(sectname, sectname)
        if innernode.get('classes') is not None:
            innernode['classes'].append('std')
            innernode['classes'].append('std-' + rolename)
        if docname == fromdocname:
            newnode['refid'] = labelid
        else:
            # set more info in contnode; in case the
            # get_relative_uri call raises NoUri,
            # the builder will then have to resolve these
            contnode = pending_xref('')
            contnode['refdocname'] = docname
            contnode['refsectname'] = sectname
            newnode['refuri'] = builder.get_relative_uri(
                fromdocname, docname)
            if labelid:
                newnode['refuri'] += '#' + labelid
        newnode.append(innernode)
        return newnode

    def resolve_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder",
                     typ: str, target: str, node: pending_xref, contnode: Element) -> Element:
        if typ == 'ref':
            resolver = self._resolve_ref_xref
        elif typ == 'numref':
            resolver = self._resolve_numref_xref
        elif typ == 'keyword':
            resolver = self._resolve_keyword_xref
        elif typ == 'doc':
            resolver = self._resolve_doc_xref
        elif typ == 'option':
            resolver = self._resolve_option_xref
        elif typ == 'citation':
            warnings.warn('pending_xref(domain=std, type=citation) is deprecated: %r' % node,
                          RemovedInSphinx40Warning)
            domain = env.get_domain('citation')
            return domain.resolve_xref(env, fromdocname, builder, typ, target, node, contnode)
        else:
            resolver = self._resolve_obj_xref

        return resolver(env, fromdocname, builder, typ, target, node, contnode)

    def _resolve_ref_xref(self, env: "BuildEnvironment", fromdocname: str,
                          builder: "Builder", typ: str, target: str, node: pending_xref,
                          contnode: Element) -> Element:
        if node['refexplicit']:
            # reference to anonymous label; the reference uses
            # the supplied link caption
            docname, labelid = self.anonlabels.get(target, ('', ''))
            sectname = node.astext()
        else:
            # reference to named label; the final node will
            # contain the section name after the label
            docname, labelid, sectname = self.labels.get(target, ('', '', ''))
        if not docname:
            return None

        return self.build_reference_node(fromdocname, builder,
                                         docname, labelid, sectname, 'ref')

    def _resolve_numref_xref(self, env: "BuildEnvironment", fromdocname: str,
                             builder: "Builder", typ: str, target: str,
                             node: pending_xref, contnode: Element) -> Element:
        if target in self.labels:
            docname, labelid, figname = self.labels.get(target, ('', '', ''))
        else:
            docname, labelid = self.anonlabels.get(target, ('', ''))
            figname = None

        if not docname:
            return None

        target_node = env.get_doctree(docname).ids.get(labelid)
        figtype = self.get_enumerable_node_type(target_node)
        if figtype is None:
            return None

        if figtype != 'section' and env.config.numfig is False:
            logger.warning(__('numfig is disabled. :numref: is ignored.'), location=node)
            return contnode

        try:
            fignumber = self.get_fignumber(env, builder, figtype, docname, target_node)
            if fignumber is None:
                return contnode
        except ValueError:
            logger.warning(__("no number is assigned for %s: %s"), figtype, labelid,
                           location=node)
            return contnode

        try:
            if node['refexplicit']:
                title = contnode.astext()
            else:
                title = env.config.numfig_format.get(figtype, '')

            if figname is None and '{name}' in title:
                logger.warning(__('the link has no caption: %s'), title, location=node)
                return contnode
            else:
                fignum = '.'.join(map(str, fignumber))
                if '{name}' in title or 'number' in title:
                    # new style format (cf. "Fig.{number}")
                    if figname:
                        newtitle = title.format(name=figname, number=fignum)
                    else:
                        newtitle = title.format(number=fignum)
                else:
                    # old style format (cf. "Fig.%s")
                    newtitle = title % fignum
        except KeyError as exc:
            logger.warning(__('invalid numfig_format: %s (%r)'), title, exc, location=node)
            return contnode
        except TypeError:
            logger.warning(__('invalid numfig_format: %s'), title, location=node)
            return contnode

        return self.build_reference_node(fromdocname, builder,
                                         docname, labelid, newtitle, 'numref',
                                         nodeclass=addnodes.number_reference,
                                         title=title)

    def _resolve_keyword_xref(self, env: "BuildEnvironment", fromdocname: str,
                              builder: "Builder", typ: str, target: str,
                              node: pending_xref, contnode: Element) -> Element:
        # keywords are oddballs: they are referenced by named labels
        docname, labelid, _ = self.labels.get(target, ('', '', ''))
        if not docname:
            return None
        return make_refnode(builder, fromdocname, docname,
                            labelid, contnode)

    def _resolve_doc_xref(self, env: "BuildEnvironment", fromdocname: str,
                          builder: "Builder", typ: str, target: str,
                          node: pending_xref, contnode: Element) -> Element:
        # directly reference to document by source name; can be absolute or relative
        refdoc = node.get('refdoc', fromdocname)
        docname = docname_join(refdoc, node['reftarget'])
        if docname not in env.all_docs:
            return None
        else:
            if node['refexplicit']:
                # reference with explicit title
                caption = node.astext()
            else:
                caption = clean_astext(env.titles[docname])
            innernode = nodes.inline(caption, caption, classes=['doc'])
            return make_refnode(builder, fromdocname, docname, None, innernode)

    def _resolve_option_xref(self, env: "BuildEnvironment", fromdocname: str,
                             builder: "Builder", typ: str, target: str,
                             node: pending_xref, contnode: Element) -> Element:
        progname = node.get('std:program')
        target = target.strip()
        docname, labelid = self.progoptions.get((progname, target), ('', ''))
        if not docname:
            commands = []
            while ws_re.search(target):
                subcommand, target = ws_re.split(target, 1)
                commands.append(subcommand)
                progname = "-".join(commands)

                docname, labelid = self.progoptions.get((progname, target), ('', ''))
                if docname:
                    break
            else:
                return None

        return make_refnode(builder, fromdocname, docname,
                            labelid, contnode)

    def _resolve_obj_xref(self, env: "BuildEnvironment", fromdocname: str,
                          builder: "Builder", typ: str, target: str,
                          node: pending_xref, contnode: Element) -> Element:
        objtypes = self.objtypes_for_role(typ) or []
        for objtype in objtypes:
            if (objtype, target) in self.objects:
                docname, labelid = self.objects[objtype, target]
                break
        else:
            docname, labelid = '', ''
        if not docname:
            return None
        return make_refnode(builder, fromdocname, docname,
                            labelid, contnode)

    def resolve_any_xref(self, env: "BuildEnvironment", fromdocname: str,
                         builder: "Builder", target: str, node: pending_xref,
                         contnode: Element) -> List[Tuple[str, Element]]:
        results = []  # type: List[Tuple[str, Element]]
        ltarget = target.lower()  # :ref: lowercases its target automatically
        for role in ('ref', 'option'):  # do not try "keyword"
            res = self.resolve_xref(env, fromdocname, builder, role,
                                    ltarget if role == 'ref' else target,
                                    node, contnode)
            if res:
                results.append(('std:' + role, res))
        # all others
        for objtype in self.object_types:
            key = (objtype, target)
            if objtype == 'term':
                key = (objtype, ltarget)
            if key in self.objects:
                docname, labelid = self.objects[key]
                results.append(('std:' + self.role_for_objtype(objtype),
                                make_refnode(builder, fromdocname, docname,
                                             labelid, contnode)))
        return results

    def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
        # handle the special 'doc' reference here
        for doc in self.env.all_docs:
            yield (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
        for (prog, option), info in self.progoptions.items():
            if prog:
                fullname = ".".join([prog, option])
                yield (fullname, fullname, 'cmdoption', info[0], info[1], 1)
            else:
                yield (option, option, 'cmdoption', info[0], info[1], 1)
        for (type, name), info in self.objects.items():
            yield (name, name, type, info[0], info[1],
                   self.object_types[type].attrs['searchprio'])
        for name, (docname, labelid, sectionname) in self.labels.items():
            yield (name, sectionname, 'label', docname, labelid, -1)
        # add anonymous-only labels as well
        non_anon_labels = set(self.labels)
        for name, (docname, labelid) in self.anonlabels.items():
            if name not in non_anon_labels:
                yield (name, name, 'label', docname, labelid, -1)

    def get_type_name(self, type: ObjType, primary: bool = False) -> str:
        # never prepend "Default"
        return type.lname

    def is_enumerable_node(self, node: Node) -> bool:
        return node.__class__ in self.enumerable_nodes

    def get_numfig_title(self, node: Node) -> str:
        """Get the title of enumerable nodes to refer them using its title"""
        if self.is_enumerable_node(node):
            elem = cast(Element, node)
            _, title_getter = self.enumerable_nodes.get(elem.__class__, (None, None))
            if title_getter:
                return title_getter(elem)
            else:
                for subnode in elem:
                    if isinstance(subnode, (nodes.caption, nodes.title)):
                        return clean_astext(subnode)

        return None

    def get_enumerable_node_type(self, node: Node) -> str:
        """Get type of enumerable nodes."""
        def has_child(node: Element, cls: "Type") -> bool:
            return any(isinstance(child, cls) for child in node)

        if isinstance(node, nodes.section):
            return 'section'
        elif (isinstance(node, nodes.container) and
              'literal_block' in node and
              has_child(node, nodes.literal_block)):
            # given node is a code-block having caption
            return 'code-block'
        else:
            figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
            return figtype

    def get_fignumber(self, env: "BuildEnvironment", builder: "Builder",
                      figtype: str, docname: str, target_node: Element) -> Tuple[int, ...]:
        if figtype == 'section':
            if builder.name == 'latex':
                return tuple()
            elif docname not in env.toc_secnumbers:
                raise ValueError  # no number assigned
            else:
                anchorname = '#' + target_node['ids'][0]
                if anchorname not in env.toc_secnumbers[docname]:
                    # try first heading which has no anchor
                    return env.toc_secnumbers[docname].get('')
                else:
                    return env.toc_secnumbers[docname].get(anchorname)
        else:
            try:
                figure_id = target_node['ids'][0]
                return env.toc_fignumbers[docname][figtype][figure_id]
            except (KeyError, IndexError):
                # target_node is found, but fignumber is not assigned.
                # Maybe it is defined in orphaned document.
                raise ValueError

    def get_full_qualified_name(self, node: Element) -> str:
        if node.get('reftype') == 'option':
            progname = node.get('std:program')
            command = ws_re.split(node.get('reftarget'))
            if progname:
                command.insert(0, progname)
            option = command.pop()
            if command:
                return '.'.join(['-'.join(command), option])
            else:
                return None
        else:
            return None

    def note_citations(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None:  # NOQA
        warnings.warn('StandardDomain.note_citations() is deprecated.',
                      RemovedInSphinx40Warning)

    def note_citation_refs(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None:  # NOQA
        warnings.warn('StandardDomain.note_citation_refs() is deprecated.',
                      RemovedInSphinx40Warning)

    def note_labels(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None:  # NOQA
        warnings.warn('StandardDomain.note_labels() is deprecated.',
                      RemovedInSphinx40Warning)
示例#54
0
    def write(self, *ignored):
        # type: (Any) -> None
        version = self.config.version
        domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
        libchanges = {}  # type: Dict[str, List[Tuple[str, str, int]]]
        apichanges = []  # type: List[Tuple[str, str, int]]
        otherchanges = {
        }  # type: Dict[Tuple[str, str], List[Tuple[str, str, int]]]
        if version not in self.env.versionchanges:
            logger.info(bold(__('no changes in version %s.') % version))
            return
        logger.info(bold('writing summary file...'))
        for changeset in domain.get_changesets_for(version):
            if isinstance(changeset.descname, tuple):
                descname = changeset.descname[0]
            else:
                descname = changeset.descname
            ttext = self.typemap[changeset.type]
            context = changeset.content.replace('\n', ' ')
            if descname and changeset.docname.startswith('c-api'):
                if context:
                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext,
                                                          context)
                else:
                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
                apichanges.append((entry, changeset.docname, changeset.lineno))
            elif descname or changeset.module:
                if not changeset.module:
                    module = _('Builtins')
                if not descname:
                    descname = _('Module level')
                if context:
                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext,
                                                          context)
                else:
                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
                libchanges.setdefault(module, []).append(
                    (entry, changeset.docname, changeset.lineno))
            else:
                if not context:
                    continue
                entry = '<i>%s:</i> %s' % (ttext.capitalize(), context)
                title = self.env.titles[changeset.docname].astext()
                otherchanges.setdefault((changeset.docname, title), []).append(
                    (entry, changeset.docname, changeset.lineno))

        ctx = {
            'project': self.config.project,
            'version': version,
            'docstitle': self.config.html_title,
            'shorttitle': self.config.html_short_title,
            'libchanges': sorted(libchanges.items()),
            'apichanges': sorted(apichanges),
            'otherchanges': sorted(otherchanges.items()),
            'show_copyright': self.config.html_show_copyright,
            'show_sphinx': self.config.html_show_sphinx,
        }
        with open(path.join(self.outdir, 'index.html'), 'w',
                  encoding='utf8') as f:
            f.write(self.templates.render('changes/frameset.html', ctx))
        with open(path.join(self.outdir, 'changes.html'), 'w',
                  encoding='utf8') as f:
            f.write(self.templates.render('changes/versionchanges.html', ctx))

        hltext = [
            '.. versionadded:: %s' % version,
            '.. versionchanged:: %s' % version,
            '.. deprecated:: %s' % version
        ]

        def hl(no, line):
            # type: (int, str) -> str
            line = '<a name="L%s"> </a>' % no + html.escape(line)
            for x in hltext:
                if x in line:
                    line = '<span class="hl">%s</span>' % line
                    break
            return line

        logger.info(bold(__('copying source files...')))
        for docname in self.env.all_docs:
            with open(self.env.doc2path(docname),
                      encoding=self.env.config.source_encoding) as f:
                try:
                    lines = f.readlines()
                except UnicodeDecodeError:
                    logger.warning(
                        __('could not read %r for changelog creation'),
                        docname)
                    continue
            targetfn = path.join(self.outdir, 'rst',
                                 os_path(docname)) + '.html'
            ensuredir(path.dirname(targetfn))
            with open(targetfn, 'w', encoding='utf-8') as f:
                text = ''.join(
                    hl(i + 1, line) for (i, line) in enumerate(lines))
                ctx = {
                    'filename': self.env.doc2path(docname, None),
                    'text': text
                }
                f.write(self.templates.render('changes/rstsource.html', ctx))
        themectx = dict(('theme_' + key, val)
                        for (key, val) in self.theme.get_options({}).items())
        copy_asset_file(path.join(package_dir, 'themes', 'default', 'static',
                                  'default.css_t'),
                        self.outdir,
                        context=themectx,
                        renderer=self.templates)
        copy_asset_file(
            path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
            self.outdir)
示例#55
0
文件: mermaid.py 项目: syslaila/mamba
def man_visit_mermaid(self, node):
    if "alt" in node.attributes:
        self.body.append(_("[graph: %s]") % node["alt"])
    else:
        self.body.append(_("[graph]"))
    raise nodes.SkipNode
示例#56
0
文件: mermaid.py 项目: syslaila/mamba
def text_visit_mermaid(self, node):
    if "alt" in node.attributes:
        self.add_text(_("[graph: %s]") % node["alt"])
    else:
        self.add_text(_("[graph]"))
    raise nodes.SkipNode
示例#57
0
文件: graphviz.py 项目: th0/test2
def man_visit_graphviz(self, node):
    if 'alt' in node.attributes:
        self.body.append(_('[graph: %s]') % node['alt'])
    else:
        self.body.append(_('[graph]'))
    raise nodes.SkipNode
示例#58
0
def doctree_read(app, doctree):
    # type: (Sphinx, nodes.Node) -> None
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}  # type: ignore
    if app.builder.name == "singlehtml":
        return
    if app.builder.name.startswith(
            "epub") and not env.config.viewcode_enable_epub:
        return

    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False  # type: ignore
            return
        if not isinstance(analyzer.code, text_type):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        if entry is None or entry[0] != code:
            analyzer.find_tags()
            entry = code, analyzer.tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        elif entry is False:
            return
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()  # type: Set[unicode]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = _get_full_modname(app, modname, fullname)
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('',
                                              reftype='viewcode',
                                              refdomain='std',
                                              refexplicit=False,
                                              reftarget=pagename,
                                              refid=fullname,
                                              refdoc=env.docname)
            onlynode[0] += nodes.inline('',
                                        _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
示例#59
0
def missing_reference(app, env, node, contnode):
    # type: (Sphinx, BuildEnvironment, nodes.Element, nodes.TextElement) -> None
    """Attempt to resolve a missing reference via intersphinx references."""
    target = node['reftarget']
    inventories = InventoryAdapter(env)
    objtypes = None  # type: List[unicode]
    if node['reftype'] == 'any':
        # we search anything!
        objtypes = [
            '%s:%s' % (domain.name, objtype)
            for domain in env.domains.values()
            for objtype in domain.object_types
        ]
        domain = None
    else:
        domain = node.get('refdomain')
        if not domain:
            # only objects in domains are in the inventory
            return
        objtypes = env.get_domain(domain).objtypes_for_role(node['reftype'])
        if not objtypes:
            return
        objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
    if 'std:cmdoption' in objtypes:
        # until Sphinx-1.6, cmdoptions are stored as std:option
        objtypes.append('std:option')
    to_try = [(inventories.main_inventory, target)]
    if domain:
        full_qualified_name = env.get_domain(domain).get_full_qualified_name(
            node)
        if full_qualified_name:
            to_try.append((inventories.main_inventory, full_qualified_name))
    in_set = None
    if ':' in target:
        # first part may be the foreign doc set name
        setname, newtarget = target.split(':', 1)
        if setname in inventories.named_inventory:
            in_set = setname
            to_try.append((inventories.named_inventory[setname], newtarget))
            if domain:
                node['reftarget'] = newtarget
                full_qualified_name = env.get_domain(
                    domain).get_full_qualified_name(node)
                if full_qualified_name:
                    to_try.append((inventories.named_inventory[setname],
                                   full_qualified_name))
    for inventory, target in to_try:
        for objtype in objtypes:
            if objtype not in inventory or target not in inventory[objtype]:
                continue
            proj, version, uri, dispname = inventory[objtype][target]
            if '://' not in uri and node.get('refdoc'):
                # get correct path in case of subdirectories
                uri = path.join(relative_path(node['refdoc'], '.'), uri)
            if version:
                reftitle = _('(in %s v%s)') % (proj, version)
            else:
                reftitle = _('(in %s)') % (proj, )
            newnode = nodes.reference('',
                                      '',
                                      internal=False,
                                      refuri=uri,
                                      reftitle=reftitle)
            if node.get('refexplicit'):
                # use whatever title was given
                newnode.append(contnode)
            elif dispname == '-' or \
                    (domain == 'std' and node['reftype'] == 'keyword'):
                # use whatever title was given, but strip prefix
                title = contnode.astext()
                if in_set and title.startswith(in_set + ':'):
                    newnode.append(
                        contnode.__class__(title[len(in_set) + 1:],
                                           title[len(in_set) + 1:]))
                else:
                    newnode.append(contnode)
            else:
                # else use the given display name (used for :ref:)
                newnode.append(contnode.__class__(dispname, dispname))
            return newnode
    # at least get rid of the ':' in the target if no explicit title given
    if in_set is not None and not node.get('refexplicit', True):
        if len(contnode) and isinstance(contnode[0], nodes.Text):
            contnode[0] = nodes.Text(newtarget, contnode[0].rawsource)
示例#60
0
def missing_reference(app, env, node, contnode):
    """Attempt to resolve a missing reference via intersphinx references."""
    target = node['reftarget']
    if node['reftype'] == 'any':
        # we search anything!
        objtypes = [
            '%s:%s' % (domain.name, objtype)
            for domain in env.domains.values()
            for objtype in domain.object_types
        ]
        domain = None
    elif node['reftype'] == 'doc':
        domain = 'std'  # special case
        objtypes = ['std:doc']
    else:
        domain = node.get('refdomain')
        if not domain:
            # only objects in domains are in the inventory
            return
        objtypes = env.domains[domain].objtypes_for_role(node['reftype'])
        if not objtypes:
            return
        objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
    to_try = [(env.intersphinx_inventory, target)]
    in_set = None
    if ':' in target:
        # first part may be the foreign doc set name
        setname, newtarget = target.split(':', 1)
        if setname in env.intersphinx_named_inventory:
            in_set = setname
            to_try.append(
                (env.intersphinx_named_inventory[setname], newtarget))
    for inventory, target in to_try:
        for objtype in objtypes:
            if objtype not in inventory or target not in inventory[objtype]:
                continue
            proj, version, uri, dispname = inventory[objtype][target]
            if '://' not in uri and node.get('refdoc'):
                # get correct path in case of subdirectories
                uri = path.join(relative_path(node['refdoc'], '.'), uri)
            newnode = nodes.reference('',
                                      '',
                                      internal=False,
                                      refuri=uri,
                                      reftitle=_('(in %s v%s)') %
                                      (proj, version))
            if node.get('refexplicit'):
                # use whatever title was given
                newnode.append(contnode)
            elif dispname == '-' or \
                    (domain == 'std' and node['reftype'] == 'keyword'):
                # use whatever title was given, but strip prefix
                title = contnode.astext()
                if in_set and title.startswith(in_set + ':'):
                    newnode.append(
                        contnode.__class__(title[len(in_set) + 1:],
                                           title[len(in_set) + 1:]))
                else:
                    newnode.append(contnode)
            else:
                # else use the given display name (used for :ref:)
                newnode.append(contnode.__class__(dispname, dispname))
            return newnode
    # at least get rid of the ':' in the target if no explicit title given
    if in_set is not None and not node.get('refexplicit', True):
        if len(contnode) and isinstance(contnode[0], nodes.Text):
            contnode[0] = nodes.Text(newtarget, contnode[0].rawsource)