mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
663 lines
25 KiB
Python
663 lines
25 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
sphinx.domains.std
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
The standard domain.
|
|
|
|
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
:license: BSD, see LICENSE for details.
|
|
"""
|
|
|
|
import re
|
|
import unicodedata
|
|
|
|
from six import iteritems
|
|
from docutils import nodes
|
|
from docutils.parsers.rst import directives
|
|
from docutils.statemachine import ViewList
|
|
|
|
from sphinx import addnodes
|
|
from sphinx.roles import XRefRole
|
|
from sphinx.locale import l_, _
|
|
from sphinx.domains import Domain, ObjType
|
|
from sphinx.directives import ObjectDescription
|
|
from sphinx.util import ws_re
|
|
from sphinx.util.nodes import clean_astext, make_refnode
|
|
from sphinx.util.compat import Directive
|
|
|
|
|
|
# RE for option descriptions
|
|
option_desc_re = re.compile(r'((?:/|--|-|\+)?[-?@#_a-zA-Z0-9]+)(=?\s*.*)')
|
|
# RE for grammar tokens
|
|
token_re = re.compile('`(\w+)`', re.U)
|
|
|
|
|
|
class GenericObject(ObjectDescription):
|
|
"""
|
|
A generic x-ref directive registered with Sphinx.add_object_type().
|
|
"""
|
|
indextemplate = ''
|
|
parse_node = None
|
|
|
|
def handle_signature(self, sig, signode):
|
|
if self.parse_node:
|
|
name = self.parse_node(self.env, sig, signode)
|
|
else:
|
|
signode.clear()
|
|
signode += addnodes.desc_name(sig, sig)
|
|
# normalize whitespace like XRefRole does
|
|
name = ws_re.sub('', sig)
|
|
return name
|
|
|
|
def add_target_and_index(self, name, sig, signode):
|
|
targetname = '%s-%s' % (self.objtype, name)
|
|
signode['ids'].append(targetname)
|
|
self.state.document.note_explicit_target(signode)
|
|
if self.indextemplate:
|
|
colon = self.indextemplate.find(':')
|
|
if colon != -1:
|
|
indextype = self.indextemplate[:colon].strip()
|
|
indexentry = self.indextemplate[colon+1:].strip() % (name,)
|
|
else:
|
|
indextype = 'single'
|
|
indexentry = self.indextemplate % (name,)
|
|
self.indexnode['entries'].append((indextype, indexentry,
|
|
targetname, ''))
|
|
self.env.domaindata['std']['objects'][self.objtype, name] = \
|
|
self.env.docname, targetname
|
|
|
|
|
|
class EnvVar(GenericObject):
|
|
indextemplate = l_('environment variable; %s')
|
|
|
|
|
|
class EnvVarXRefRole(XRefRole):
|
|
"""
|
|
Cross-referencing role for environment variables (adds an index entry).
|
|
"""
|
|
|
|
def result_nodes(self, document, env, node, is_ref):
|
|
if not is_ref:
|
|
return [node], []
|
|
varname = node['reftarget']
|
|
tgtid = 'index-%s' % env.new_serialno('index')
|
|
indexnode = addnodes.index()
|
|
indexnode['entries'] = [
|
|
('single', varname, tgtid, ''),
|
|
('single', _('environment variable; %s') % varname, tgtid, '')
|
|
]
|
|
targetnode = nodes.target('', '', ids=[tgtid])
|
|
document.note_explicit_target(targetnode)
|
|
return [indexnode, targetnode, node], []
|
|
|
|
|
|
class Target(Directive):
|
|
"""
|
|
Generic target for user-defined cross-reference types.
|
|
"""
|
|
indextemplate = ''
|
|
|
|
has_content = False
|
|
required_arguments = 1
|
|
optional_arguments = 0
|
|
final_argument_whitespace = True
|
|
option_spec = {}
|
|
|
|
def run(self):
|
|
env = self.state.document.settings.env
|
|
# normalize whitespace in fullname like XRefRole does
|
|
fullname = ws_re.sub(' ', self.arguments[0].strip())
|
|
targetname = '%s-%s' % (self.name, fullname)
|
|
node = nodes.target('', '', ids=[targetname])
|
|
self.state.document.note_explicit_target(node)
|
|
ret = [node]
|
|
if self.indextemplate:
|
|
indexentry = self.indextemplate % (fullname,)
|
|
indextype = 'single'
|
|
colon = indexentry.find(':')
|
|
if colon != -1:
|
|
indextype = indexentry[:colon].strip()
|
|
indexentry = indexentry[colon+1:].strip()
|
|
inode = addnodes.index(entries=[(indextype, indexentry,
|
|
targetname, '')])
|
|
ret.insert(0, inode)
|
|
name = self.name
|
|
if ':' in self.name:
|
|
_, name = self.name.split(':', 1)
|
|
env.domaindata['std']['objects'][name, fullname] = \
|
|
env.docname, targetname
|
|
return ret
|
|
|
|
|
|
class Cmdoption(ObjectDescription):
|
|
"""
|
|
Description of a command-line option (.. option).
|
|
"""
|
|
|
|
def handle_signature(self, sig, signode):
|
|
"""Transform an option description into RST nodes."""
|
|
count = 0
|
|
firstname = ''
|
|
for potential_option in sig.split(', '):
|
|
potential_option = potential_option.strip()
|
|
m = option_desc_re.match(potential_option)
|
|
if not m:
|
|
self.env.warn(
|
|
self.env.docname,
|
|
'Malformed option description %r, should '
|
|
'look like "opt", "-opt args", "--opt args", '
|
|
'"/opt args" or "+opt args"' % potential_option,
|
|
self.lineno)
|
|
continue
|
|
optname, args = m.groups()
|
|
if count:
|
|
signode += addnodes.desc_addname(', ', ', ')
|
|
signode += addnodes.desc_name(optname, optname)
|
|
signode += addnodes.desc_addname(args, args)
|
|
if not count:
|
|
firstname = optname
|
|
signode['allnames'] = [optname]
|
|
else:
|
|
signode['allnames'].append(optname)
|
|
count += 1
|
|
if not firstname:
|
|
raise ValueError
|
|
return firstname
|
|
|
|
def add_target_and_index(self, firstname, sig, signode):
|
|
currprogram = self.env.ref_context.get('std:program')
|
|
for optname in signode.get('allnames', []):
|
|
targetname = optname.replace('/', '-')
|
|
if not targetname.startswith('-'):
|
|
targetname = '-arg-' + targetname
|
|
if currprogram:
|
|
targetname = '-' + currprogram + targetname
|
|
targetname = 'cmdoption' + targetname
|
|
signode['ids'].append(targetname)
|
|
self.state.document.note_explicit_target(signode)
|
|
self.env.domaindata['std']['progoptions'][currprogram, optname] = \
|
|
self.env.docname, targetname
|
|
# create only one index entry for the whole option
|
|
if optname == firstname:
|
|
self.indexnode['entries'].append(
|
|
('pair', _('%scommand line option; %s') %
|
|
((currprogram and currprogram + ' ' or ''), sig),
|
|
targetname, ''))
|
|
|
|
|
|
class Program(Directive):
|
|
"""
|
|
Directive to name the program for which options are documented.
|
|
"""
|
|
|
|
has_content = False
|
|
required_arguments = 1
|
|
optional_arguments = 0
|
|
final_argument_whitespace = True
|
|
option_spec = {}
|
|
|
|
def run(self):
|
|
env = self.state.document.settings.env
|
|
program = ws_re.sub('-', self.arguments[0].strip())
|
|
if program == 'None':
|
|
env.ref_context.pop('std:program', None)
|
|
else:
|
|
env.ref_context['std:program'] = program
|
|
return []
|
|
|
|
|
|
class OptionXRefRole(XRefRole):
|
|
def process_link(self, env, refnode, has_explicit_title, title, target):
|
|
# validate content
|
|
if not re.match('(.+ )?[-/+]', target):
|
|
env.warn_node('Malformed :option: %r, does not contain option '
|
|
'marker - or -- or / or +' % target, refnode)
|
|
refnode['std:program'] = env.ref_context.get('std:program')
|
|
return title, target
|
|
|
|
|
|
def make_termnodes_from_paragraph_node(env, node, new_id=None):
|
|
gloss_entries = env.temp_data.setdefault('gloss_entries', set())
|
|
objects = env.domaindata['std']['objects']
|
|
|
|
termtext = node.astext()
|
|
if new_id is None:
|
|
new_id = 'term-' + nodes.make_id(termtext)
|
|
if new_id in gloss_entries:
|
|
new_id = 'term-' + str(len(gloss_entries))
|
|
gloss_entries.add(new_id)
|
|
objects['term', termtext.lower()] = env.docname, new_id
|
|
|
|
# add an index entry too
|
|
indexnode = addnodes.index()
|
|
indexnode['entries'] = [('single', termtext, new_id, 'main')]
|
|
new_termnodes = []
|
|
new_termnodes.append(indexnode)
|
|
new_termnodes.extend(node.children)
|
|
new_termnodes.append(addnodes.termsep())
|
|
for termnode in new_termnodes:
|
|
termnode.source, termnode.line = node.source, node.line
|
|
|
|
return new_id, termtext, new_termnodes
|
|
|
|
|
|
def make_term_from_paragraph_node(termnodes, ids):
|
|
# make a single "term" node with all the terms, separated by termsep
|
|
# nodes (remove the dangling trailing separator)
|
|
term = nodes.term('', '', *termnodes[:-1])
|
|
term.source, term.line = termnodes[0].source, termnodes[0].line
|
|
term.rawsource = term.astext()
|
|
term['ids'].extend(ids)
|
|
term['names'].extend(ids)
|
|
return term
|
|
|
|
|
|
class Glossary(Directive):
|
|
"""
|
|
Directive to create a glossary with cross-reference targets for :term:
|
|
roles.
|
|
"""
|
|
|
|
has_content = True
|
|
required_arguments = 0
|
|
optional_arguments = 0
|
|
final_argument_whitespace = False
|
|
option_spec = {
|
|
'sorted': directives.flag,
|
|
}
|
|
|
|
def run(self):
|
|
env = self.state.document.settings.env
|
|
node = addnodes.glossary()
|
|
node.document = self.state.document
|
|
|
|
# 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 = []
|
|
in_definition = True
|
|
was_empty = True
|
|
messages = []
|
|
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('.. '):
|
|
continue
|
|
# first term of definition
|
|
if in_definition:
|
|
if not was_empty:
|
|
messages.append(self.state.reporter.system_message(
|
|
2, 'glossary term must be preceded by empty line',
|
|
source=source, line=lineno))
|
|
entries.append(([(line, source, lineno)], ViewList()))
|
|
in_definition = False
|
|
# second term and following
|
|
else:
|
|
if was_empty:
|
|
messages.append(self.state.reporter.system_message(
|
|
2, '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.system_message(
|
|
2, 'glossary seems to be misformatted, check '
|
|
'indentation', source=source, line=lineno))
|
|
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.system_message(
|
|
2, '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 = []
|
|
termnodes = []
|
|
system_messages = []
|
|
ids = []
|
|
for line, source, lineno in terms:
|
|
# parse the term with inline markup
|
|
res = self.state.inline_text(line, lineno)
|
|
system_messages.extend(res[1])
|
|
|
|
# get a text-only representation of the term and register it
|
|
# as a cross-reference target
|
|
tmp = nodes.paragraph('', '', *res[0])
|
|
tmp.source = source
|
|
tmp.line = lineno
|
|
new_id, termtext, new_termnodes = \
|
|
make_termnodes_from_paragraph_node(env, tmp)
|
|
ids.append(new_id)
|
|
termtexts.append(termtext)
|
|
termnodes.extend(new_termnodes)
|
|
|
|
term = make_term_from_paragraph_node(termnodes, ids)
|
|
term += system_messages
|
|
|
|
defnode = nodes.definition()
|
|
if definition:
|
|
self.state.nested_parse(definition, definition.items[0][1],
|
|
defnode)
|
|
|
|
items.append((termtexts,
|
|
nodes.definition_list_item('', term, defnode)))
|
|
|
|
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]
|
|
|
|
|
|
def token_xrefs(text):
|
|
retnodes = []
|
|
pos = 0
|
|
for m in token_re.finditer(text):
|
|
if m.start() > pos:
|
|
txt = text[pos:m.start()]
|
|
retnodes.append(nodes.Text(txt, txt))
|
|
refnode = addnodes.pending_xref(
|
|
m.group(1), reftype='token', refdomain='std', reftarget=m.group(1))
|
|
refnode += nodes.literal(m.group(1), m.group(1), classes=['xref'])
|
|
retnodes.append(refnode)
|
|
pos = m.end()
|
|
if pos < len(text):
|
|
retnodes.append(nodes.Text(text[pos:], text[pos:]))
|
|
return retnodes
|
|
|
|
|
|
class ProductionList(Directive):
|
|
"""
|
|
Directive to list grammar productions.
|
|
"""
|
|
|
|
has_content = False
|
|
required_arguments = 1
|
|
optional_arguments = 0
|
|
final_argument_whitespace = True
|
|
option_spec = {}
|
|
|
|
def run(self):
|
|
env = self.state.document.settings.env
|
|
objects = env.domaindata['std']['objects']
|
|
node = addnodes.productionlist()
|
|
messages = []
|
|
i = 0
|
|
|
|
for rule in self.arguments[0].split('\n'):
|
|
if i == 0 and ':' not in rule:
|
|
# production group
|
|
continue
|
|
i += 1
|
|
try:
|
|
name, tokens = rule.split(':', 1)
|
|
except ValueError:
|
|
break
|
|
subnode = addnodes.production()
|
|
subnode['tokenname'] = name.strip()
|
|
if subnode['tokenname']:
|
|
idname = 'grammar-token-%s' % subnode['tokenname']
|
|
if idname not in self.state.document.ids:
|
|
subnode['ids'].append(idname)
|
|
self.state.document.note_implicit_target(subnode, subnode)
|
|
objects['token', subnode['tokenname']] = env.docname, idname
|
|
subnode.extend(token_xrefs(tokens))
|
|
node.append(subnode)
|
|
return [node] + messages
|
|
|
|
|
|
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(l_('glossary term'), 'term', searchprio=-1),
|
|
'token': ObjType(l_('grammar token'), 'token', searchprio=-1),
|
|
'label': ObjType(l_('reference label'), 'ref', 'keyword',
|
|
searchprio=-1),
|
|
'envvar': ObjType(l_('environment variable'), 'envvar'),
|
|
'cmdoption': ObjType(l_('program option'), 'option'),
|
|
}
|
|
|
|
directives = {
|
|
'program': Program,
|
|
'cmdoption': Cmdoption, # old name for backwards compatibility
|
|
'option': Cmdoption,
|
|
'envvar': EnvVar,
|
|
'glossary': Glossary,
|
|
'productionlist': ProductionList,
|
|
}
|
|
roles = {
|
|
'option': OptionXRefRole(),
|
|
'envvar': EnvVarXRefRole(),
|
|
# links to tokens in grammar productions
|
|
'token': XRefRole(),
|
|
# links to terms in glossary
|
|
'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
|
|
warn_dangling=True),
|
|
# links to headings or arbitrary labels
|
|
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
|
|
warn_dangling=True),
|
|
# links to labels, without a different title
|
|
'keyword': XRefRole(warn_dangling=True),
|
|
}
|
|
|
|
initial_data = {
|
|
'progoptions': {}, # (program, name) -> docname, labelid
|
|
'objects': {}, # (type, name) -> docname, labelid
|
|
'labels': { # labelname -> docname, labelid, sectionname
|
|
'genindex': ('genindex', '', l_('Index')),
|
|
'modindex': ('py-modindex', '', l_('Module Index')),
|
|
'search': ('search', '', l_('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)',
|
|
'keyword': 'unknown keyword: %(target)s',
|
|
}
|
|
|
|
def clear_doc(self, docname):
|
|
for key, (fn, _) in list(self.data['progoptions'].items()):
|
|
if fn == docname:
|
|
del self.data['progoptions'][key]
|
|
for key, (fn, _) in list(self.data['objects'].items()):
|
|
if fn == docname:
|
|
del self.data['objects'][key]
|
|
for key, (fn, _, _) in list(self.data['labels'].items()):
|
|
if fn == docname:
|
|
del self.data['labels'][key]
|
|
for key, (fn, _) in list(self.data['anonlabels'].items()):
|
|
if fn == docname:
|
|
del self.data['anonlabels'][key]
|
|
|
|
def process_doc(self, env, docname, document):
|
|
labels, anonlabels = self.data['labels'], self.data['anonlabels']
|
|
for name, explicit in iteritems(document.nametypes):
|
|
if not explicit:
|
|
continue
|
|
labelid = document.nameids[name]
|
|
if labelid is None:
|
|
continue
|
|
node = document.ids[labelid]
|
|
if name.isdigit() 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 labels:
|
|
env.warn_node('duplicate label %s, ' % name + 'other instance '
|
|
'in ' + env.doc2path(labels[name][0]), node)
|
|
anonlabels[name] = docname, labelid
|
|
if node.tagname == 'section':
|
|
sectname = clean_astext(node[0]) # node[0] == title node
|
|
elif node.tagname == 'figure':
|
|
for n in node:
|
|
if n.tagname == 'caption':
|
|
sectname = clean_astext(n)
|
|
break
|
|
else:
|
|
continue
|
|
elif node.tagname == 'image' and node.parent.tagname == 'figure':
|
|
for n in node.parent:
|
|
if n.tagname == 'caption':
|
|
sectname = clean_astext(n)
|
|
break
|
|
else:
|
|
continue
|
|
elif node.tagname == 'table':
|
|
for n in node:
|
|
if n.tagname == 'title':
|
|
sectname = clean_astext(n)
|
|
break
|
|
else:
|
|
continue
|
|
else:
|
|
# anonymous-only labels
|
|
continue
|
|
labels[name] = docname, labelid, sectname
|
|
|
|
def resolve_xref(self, env, fromdocname, builder,
|
|
typ, target, node, contnode):
|
|
if typ == 'ref':
|
|
if node['refexplicit']:
|
|
# reference to anonymous label; the reference uses
|
|
# the supplied link caption
|
|
docname, labelid = self.data['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.data['labels'].get(target,
|
|
('', '', ''))
|
|
if not docname:
|
|
return None
|
|
newnode = nodes.reference('', '', internal=True)
|
|
innernode = nodes.emphasis(sectname, sectname)
|
|
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 = addnodes.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
|
|
elif typ == 'keyword':
|
|
# keywords are oddballs: they are referenced by named labels
|
|
docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
|
|
if not docname:
|
|
return None
|
|
return make_refnode(builder, fromdocname, docname,
|
|
labelid, contnode)
|
|
elif typ == 'option':
|
|
target = target.strip()
|
|
# most obvious thing: we are a flag option without program
|
|
if target.startswith(('-', '/', '+')):
|
|
progname = node.get('std:program')
|
|
else:
|
|
try:
|
|
progname, target = re.split(r' (?=-|--|/|\+)', target, 1)
|
|
except ValueError:
|
|
return None
|
|
progname = ws_re.sub('-', progname.strip())
|
|
docname, labelid = self.data['progoptions'].get((progname, target),
|
|
('', ''))
|
|
if not docname:
|
|
return None
|
|
return make_refnode(builder, fromdocname, docname,
|
|
labelid, contnode)
|
|
else:
|
|
objtypes = self.objtypes_for_role(typ) or []
|
|
for objtype in objtypes:
|
|
if (objtype, target) in self.data['objects']:
|
|
docname, labelid = self.data['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, fromdocname, builder, target,
|
|
node, contnode):
|
|
results = []
|
|
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.data['objects']:
|
|
docname, labelid = self.data['objects'][key]
|
|
results.append(('std:' + self.role_for_objtype(objtype),
|
|
make_refnode(builder, fromdocname, docname,
|
|
labelid, contnode)))
|
|
return results
|
|
|
|
def get_objects(self):
|
|
for (prog, option), info in iteritems(self.data['progoptions']):
|
|
yield (option, option, 'option', info[0], info[1], 1)
|
|
for (type, name), info in iteritems(self.data['objects']):
|
|
yield (name, name, type, info[0], info[1],
|
|
self.object_types[type].attrs['searchprio'])
|
|
for name, info in iteritems(self.data['labels']):
|
|
yield (name, info[2], 'label', info[0], info[1], -1)
|
|
# add anonymous-only labels as well
|
|
non_anon_labels = set(self.data['labels'])
|
|
for name, info in iteritems(self.data['anonlabels']):
|
|
if name not in non_anon_labels:
|
|
yield (name, name, 'label', info[0], info[1], -1)
|
|
|
|
def get_type_name(self, type, primary=False):
|
|
# never prepend "Default"
|
|
return type.lname
|