mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add static method support.
This commit is contained in:
parent
1cafce9101
commit
8b0f48a38b
3
CHANGES
3
CHANGES
@ -13,6 +13,9 @@ New features added
|
|||||||
* Sphinx now interprets field lists with fields like ``:param foo:``
|
* Sphinx now interprets field lists with fields like ``:param foo:``
|
||||||
in description units.
|
in description units.
|
||||||
|
|
||||||
|
* The new `staticmethod` directive can be used to mark methods as
|
||||||
|
static methods.
|
||||||
|
|
||||||
* HTML output:
|
* HTML output:
|
||||||
|
|
||||||
- The "previous" and "next" links have a more logical structure, so
|
- The "previous" and "next" links have a more logical structure, so
|
||||||
|
@ -199,6 +199,12 @@ The directives are:
|
|||||||
parameter. The description should include similar information to that
|
parameter. The description should include similar information to that
|
||||||
described for ``function``. See also :ref:`signatures`.
|
described for ``function``. See also :ref:`signatures`.
|
||||||
|
|
||||||
|
.. directive:: .. staticmethod:: name(signature)
|
||||||
|
|
||||||
|
Like :dir:`method`, but indicates that the method is a static method.
|
||||||
|
|
||||||
|
.. versionadded:: 0.4
|
||||||
|
|
||||||
.. directive:: .. opcode:: name
|
.. directive:: .. opcode:: name
|
||||||
|
|
||||||
Describes a Python bytecode instruction (this is not very useful for projects
|
Describes a Python bytecode instruction (this is not very useful for projects
|
||||||
|
@ -23,7 +23,7 @@ class desc(nodes.Admonition, nodes.Element): pass
|
|||||||
class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
||||||
# compatibility alias
|
# compatibility alias
|
||||||
desc_classname = desc_addname
|
desc_classname = desc_addname
|
||||||
# return type (C), object type (Python)
|
# return type (C); object type, e.g. -> annotation (Python)
|
||||||
class desc_type(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
class desc_type(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
||||||
# main name of object
|
# main name of object
|
||||||
class desc_name(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
class desc_name(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
||||||
@ -36,6 +36,8 @@ class desc_optional(nodes.Part, nodes.Inline, nodes.TextElement):
|
|||||||
child_text_separator = ', '
|
child_text_separator = ', '
|
||||||
def astext(self):
|
def astext(self):
|
||||||
return '[' + nodes.TextElement.astext(self) + ']'
|
return '[' + nodes.TextElement.astext(self) + ']'
|
||||||
|
# annotation (not Python 3-style annotations)
|
||||||
|
class desc_annotation(nodes.Part, nodes.Inline, nodes.TextElement): pass
|
||||||
|
|
||||||
# node for content
|
# node for content
|
||||||
class desc_content(nodes.General, nodes.Element): pass
|
class desc_content(nodes.General, nodes.Element): pass
|
||||||
|
@ -45,6 +45,18 @@ def desc_index_text(desctype, module, name):
|
|||||||
return '%s() (%s.%s method)' % (methname, module, clsname)
|
return '%s() (%s.%s method)' % (methname, module, clsname)
|
||||||
else:
|
else:
|
||||||
return '%s() (%s method)' % (methname, clsname)
|
return '%s() (%s method)' % (methname, clsname)
|
||||||
|
elif desctype == 'staticmethod':
|
||||||
|
try:
|
||||||
|
clsname, methname = name.rsplit('.', 1)
|
||||||
|
except ValueError:
|
||||||
|
if module:
|
||||||
|
return '%s() (in module %s)' % (name, module)
|
||||||
|
else:
|
||||||
|
return '%s()' % name
|
||||||
|
if module:
|
||||||
|
return '%s() (%s.%s static method)' % (methname, module, clsname)
|
||||||
|
else:
|
||||||
|
return '%s() (%s static method)' % (methname, clsname)
|
||||||
elif desctype == 'attribute':
|
elif desctype == 'attribute':
|
||||||
try:
|
try:
|
||||||
clsname, attrname = name.rsplit('.', 1)
|
clsname, attrname = name.rsplit('.', 1)
|
||||||
@ -91,6 +103,8 @@ doc_fields_with_arg = {
|
|||||||
'var': 'Variable',
|
'var': 'Variable',
|
||||||
'ivar': 'Variable',
|
'ivar': 'Variable',
|
||||||
'cvar': 'Variable',
|
'cvar': 'Variable',
|
||||||
|
'returns': 'Returns',
|
||||||
|
'return': 'Returns',
|
||||||
}
|
}
|
||||||
|
|
||||||
doc_fields_without_arg = {
|
doc_fields_without_arg = {
|
||||||
@ -140,7 +154,7 @@ def handle_doc_fields(node):
|
|||||||
nfield = nodes.field()
|
nfield = nodes.field()
|
||||||
nfield += nodes.field_name(typ, typ)
|
nfield += nodes.field_name(typ, typ)
|
||||||
nfield += nodes.field_body()
|
nfield += nodes.field_body()
|
||||||
nfield[1] += children
|
nfield[1] += fbody.children
|
||||||
new_list += nfield
|
new_list += nfield
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
fnametext = fname.astext()
|
fnametext = fname.astext()
|
||||||
@ -199,6 +213,9 @@ def parse_py_signature(signode, sig, desctype, module, env):
|
|||||||
add_module = True
|
add_module = True
|
||||||
fullname = classname and classname + name or name
|
fullname = classname and classname + name or name
|
||||||
|
|
||||||
|
if desctype == 'staticmethod':
|
||||||
|
signode += addnodes.desc_annotation('static ', 'static ')
|
||||||
|
|
||||||
if classname:
|
if classname:
|
||||||
signode += addnodes.desc_addname(classname, classname)
|
signode += addnodes.desc_addname(classname, classname)
|
||||||
# exceptions are a special case, since they are documented in the
|
# exceptions are a special case, since they are documented in the
|
||||||
@ -210,7 +227,7 @@ def parse_py_signature(signode, sig, desctype, module, env):
|
|||||||
|
|
||||||
signode += addnodes.desc_name(name, name)
|
signode += addnodes.desc_name(name, name)
|
||||||
if not arglist:
|
if not arglist:
|
||||||
if desctype in ('function', 'method'):
|
if desctype in ('function', 'method', 'staticmethod'):
|
||||||
# for callables, add an empty parameter list
|
# for callables, add an empty parameter list
|
||||||
signode += addnodes.desc_parameterlist()
|
signode += addnodes.desc_parameterlist()
|
||||||
return fullname, classname
|
return fullname, classname
|
||||||
@ -383,7 +400,7 @@ def desc_directive(desctype, arguments, options, content, lineno,
|
|||||||
node.append(signode)
|
node.append(signode)
|
||||||
try:
|
try:
|
||||||
if desctype in ('function', 'data', 'class', 'exception',
|
if desctype in ('function', 'data', 'class', 'exception',
|
||||||
'method', 'attribute'):
|
'method', 'staticmethod', 'attribute'):
|
||||||
name, clsname = parse_py_signature(signode, sig, desctype, module, env)
|
name, clsname = parse_py_signature(signode, sig, desctype, module, env)
|
||||||
elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
|
elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
|
||||||
name = parse_c_signature(signode, sig, desctype)
|
name = parse_c_signature(signode, sig, desctype)
|
||||||
@ -457,7 +474,8 @@ def desc_directive(desctype, arguments, options, content, lineno,
|
|||||||
if desctype in ('class', 'exception') and names:
|
if desctype in ('class', 'exception') and names:
|
||||||
env.currclass = names[0]
|
env.currclass = names[0]
|
||||||
clsname_set = True
|
clsname_set = True
|
||||||
elif desctype in ('method', 'attribute') and clsname and not env.currclass:
|
elif desctype in ('method', 'staticmethod', 'attribute') and \
|
||||||
|
clsname and not env.currclass:
|
||||||
env.currclass = clsname.strip('.')
|
env.currclass = clsname.strip('.')
|
||||||
clsname_set = True
|
clsname_set = True
|
||||||
# needed for association of version{added,changed} directives
|
# needed for association of version{added,changed} directives
|
||||||
@ -482,6 +500,7 @@ desctypes = [
|
|||||||
'data',
|
'data',
|
||||||
'class',
|
'class',
|
||||||
'method',
|
'method',
|
||||||
|
'staticmethod',
|
||||||
'attribute',
|
'attribute',
|
||||||
'exception',
|
'exception',
|
||||||
# the C ones
|
# the C ones
|
||||||
|
@ -254,7 +254,6 @@ def format_signature(what, obj):
|
|||||||
def generate_rst(what, name, members, options, add_content, document, lineno,
|
def generate_rst(what, name, members, options, add_content, document, lineno,
|
||||||
indent=u'', filename_set=None, check_module=False):
|
indent=u'', filename_set=None, check_module=False):
|
||||||
env = document.settings.env
|
env = document.settings.env
|
||||||
is_static = False
|
|
||||||
|
|
||||||
result = None
|
result = None
|
||||||
|
|
||||||
|
@ -113,6 +113,11 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
def depart_desc_optional(self, node):
|
def depart_desc_optional(self, node):
|
||||||
self.body.append('<span class="optional">]</span>')
|
self.body.append('<span class="optional">]</span>')
|
||||||
|
|
||||||
|
def visit_desc_annotation(self, node):
|
||||||
|
self.body.append(self.starttag(node, 'em', CLASS='property'))
|
||||||
|
def depart_desc_annotation(self, node):
|
||||||
|
self.body.append('</em>')
|
||||||
|
|
||||||
def visit_desc_content(self, node):
|
def visit_desc_content(self, node):
|
||||||
self.body.append(self.starttag(node, 'dd', ''))
|
self.body.append(self.starttag(node, 'dd', ''))
|
||||||
def depart_desc_content(self, node):
|
def depart_desc_content(self, node):
|
||||||
|
@ -86,7 +86,7 @@ class Desc(object):
|
|||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
self.env = LaTeXTranslator.desc_map.get(node['desctype'], 'describe')
|
self.env = LaTeXTranslator.desc_map.get(node['desctype'], 'describe')
|
||||||
self.ni = node['noindex']
|
self.ni = node['noindex']
|
||||||
self.type = self.cls = self.name = self.params = ''
|
self.type = self.cls = self.name = self.params = self.annotation = ''
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
|
|
||||||
@ -284,6 +284,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
'function' : 'funcdesc',
|
'function' : 'funcdesc',
|
||||||
'class': 'classdesc',
|
'class': 'classdesc',
|
||||||
'method': 'methoddesc',
|
'method': 'methoddesc',
|
||||||
|
'staticmethod': 'staticmethoddesc',
|
||||||
'exception': 'excdesc',
|
'exception': 'excdesc',
|
||||||
'data': 'datadesc',
|
'data': 'datadesc',
|
||||||
'attribute': 'memberdesc',
|
'attribute': 'memberdesc',
|
||||||
@ -325,7 +326,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
t2 = "{%s}{%s}" % (d.name, d.params)
|
t2 = "{%s}{%s}" % (d.name, d.params)
|
||||||
elif d.env in ('datadesc', 'classdesc*', 'excdesc', 'csimplemacrodesc'):
|
elif d.env in ('datadesc', 'classdesc*', 'excdesc', 'csimplemacrodesc'):
|
||||||
t2 = "{%s}" % (d.name)
|
t2 = "{%s}" % (d.name)
|
||||||
elif d.env == 'methoddesc':
|
elif d.env in ('methoddesc', 'staticmethoddesc'):
|
||||||
if d.cls:
|
if d.cls:
|
||||||
t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params)
|
t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params)
|
||||||
else:
|
else:
|
||||||
@ -390,6 +391,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.descstack[-1].params = self.encode(node.astext().strip())
|
self.descstack[-1].params = self.encode(node.astext().strip())
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
def visit_desc_annotation(self, node):
|
||||||
|
d = self.descstack[-1]
|
||||||
|
if d.env == 'describe':
|
||||||
|
d.name += self.encode(node.astext())
|
||||||
|
else:
|
||||||
|
self.descstack[-1].annotation = self.encode(node.astext().strip())
|
||||||
|
raise nodes.SkipNode
|
||||||
|
|
||||||
def visit_refcount(self, node):
|
def visit_refcount(self, node):
|
||||||
self.body.append("\\emph{")
|
self.body.append("\\emph{")
|
||||||
def depart_refcount(self, node):
|
def depart_refcount(self, node):
|
||||||
|
@ -572,6 +572,35 @@
|
|||||||
\methodlineni{#2}{#3}
|
\methodlineni{#2}{#3}
|
||||||
}{\end{fulllineitems}}
|
}{\end{fulllineitems}}
|
||||||
|
|
||||||
|
% static method ----------------------------------------------------------
|
||||||
|
% \begin{staticmethoddesc}[classname]{methodname}{args}
|
||||||
|
\newcommand{\staticmethodline}[3][\@undefined]{
|
||||||
|
\staticmethodlineni{#2}{#3}
|
||||||
|
\ifx\@undefined#1\relax
|
||||||
|
\index{#2@{\py@idxcode{#2()}} (\py@thisclass\ static method)}
|
||||||
|
\else
|
||||||
|
\index{#2@{\py@idxcode{#2()}} (#1 static method)}
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\newenvironment{staticmethoddesc}[3][\@undefined]{
|
||||||
|
\begin{fulllineitems}
|
||||||
|
\ifx\@undefined#1\relax
|
||||||
|
\staticmethodline{#2}{#3}
|
||||||
|
\else
|
||||||
|
\def\py@thisclass{#1}
|
||||||
|
\staticmethodline{#2}{#3}
|
||||||
|
\fi
|
||||||
|
}{\end{fulllineitems}}
|
||||||
|
|
||||||
|
% similar to {staticmethoddesc}, but doesn't add to the index
|
||||||
|
% (never actually uses the optional argument)
|
||||||
|
\newcommand{\staticmethodlineni}[3][\py@classbadkey]{%
|
||||||
|
\py@sigline{static \bfcode{#2}}{#3}}
|
||||||
|
\newenvironment{staticmethoddescni}[3][\py@classbadkey]{
|
||||||
|
\begin{fulllineitems}
|
||||||
|
\staticmethodlineni{#2}{#3}
|
||||||
|
}{\end{fulllineitems}}
|
||||||
|
|
||||||
% object data attribute --------------------------------------------------
|
% object data attribute --------------------------------------------------
|
||||||
% \begin{memberdesc}[classname]{membername}
|
% \begin{memberdesc}[classname]{membername}
|
||||||
\newcommand{\memberline}[2][\py@classbadkey]{%
|
\newcommand{\memberline}[2][\py@classbadkey]{%
|
||||||
|
Loading…
Reference in New Issue
Block a user