1. Georg Brandl
  2. sphinx

Commits

Georg Brandl  committed 5af68b9

Close #23: Added a ``classmethod`` directive along with ``method``
and ``staticmethod``.

  • Participants
  • Parent commits 3c36362
  • Branches default

Comments (0)

Files changed (6)

File CHANGES

View file
   - #6: Don't generate redundant ``<ul>`` for top-level TOC tree
     items, which leads to a visual separation of TOC entries.
 
+  - #23: Added a ``classmethod`` directive along with ``method``
+    and ``staticmethod``.
+
 * Configuration:
 
   - The new ``html_add_permalinks`` config value can be used to

File doc/markup/desc.rst

View file
 
    .. versionadded:: 0.4
 
+.. directive:: .. classmethod:: name(signature)
+
+   Like :dir:`method`, but indicates that the method is a class method.
+
+   .. versionadded:: 0.6
+
 
 .. _signatures:
 

File sphinx/directives/desc.py

View file
             return _('%s() (%s.%s static method)') % (methname, module, clsname)
         else:
             return _('%s() (%s static method)') % (methname, clsname)
+    elif desctype == 'classmethod':
+        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 class method)' % (methname, module, clsname)
+        else:
+            return '%s() (%s class method)' % (methname, clsname)
     elif desctype == 'attribute':
         try:
             clsname, attrname = name.rsplit('.', 1)
 
     if desctype == 'staticmethod':
         signode += addnodes.desc_annotation('static ', 'static ')
+    elif desctype == 'classmethod':
+        signode += addnodes.desc_annotation('classmethod ', 'classmethod ')
 
     if classname:
         signode += addnodes.desc_addname(classname, classname)
 
     signode += addnodes.desc_name(name, name)
     if not arglist:
-        if desctype in ('function', 'method', 'staticmethod'):
+        if desctype in ('function', 'method', 'staticmethod', 'classmethod'):
             # for callables, add an empty parameter list
             signode += addnodes.desc_parameterlist()
         if retann:
         node.append(signode)
         try:
             if desctype in ('function', 'data', 'class', 'exception',
-                            'method', 'staticmethod', 'attribute'):
+                            'method', 'staticmethod', 'classmethod',
+                            'attribute'):
                 name, clsname = parse_py_signature(signode, sig, desctype, module, env)
             elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
                 name = parse_c_signature(signode, sig, desctype)
     if desctype in ('class', 'exception') and names:
         env.currclass = names[0]
         clsname_set = True
-    elif desctype in ('method', 'staticmethod', 'attribute') and \
-             clsname and not env.currclass:
+    elif desctype in ('method', 'staticmethod', 'classmethod',
+                      'attribute') and clsname and not env.currclass:
         env.currclass = clsname.strip('.')
         clsname_set = True
     # needed for association of version{added,changed} directives
     'data',
     'class',
     'method',
+    'classmethod',
     'staticmethod',
     'attribute',
     'exception',

File sphinx/ext/autodoc.py

View file
     pass
 
 
-def is_static_method(obj):
-    """Check if the object given is a static method."""
-    if isinstance(obj, (FunctionType, classmethod)):
-        return True
-    elif isinstance(obj, BuiltinFunctionType):
-        return obj.__self__ is not None
-    elif isinstance(obj, MethodType):
-        return obj.im_self is not None
-    return False
+def get_method_type(obj):
+    """
+    Return the method type for an object: method, staticmethod or classmethod.
+    """
+    if isinstance(obj, classmethod) or \
+           (isinstance(obj, MethodType) and obj.im_self is not None):
+        return 'classmethod'
+    elif isinstance(obj, FunctionType) or \
+             (isinstance(obj, BuiltinFunctionType) and obj.__self__ is not None):
+        return 'staticmethod'
+    else:
+        return 'method'
 
 
 class AutodocReporter(object):
         """
         Return the signature of the object, formatted for display.
         """
-        if what not in ('class', 'method', 'function'):
+        if what not in ('class', 'method', 'staticmethod', 'classmethod',
+                        'function'):
             return ''
 
         err = None
                     getargs = False
                 if getargs:
                     argspec = inspect.getargspec(obj)
-                    if what in ('class', 'method') and argspec[0] and \
+                    if what in ('class', 'method', 'staticmethod',
+                                'classmethod') and argspec[0] and \
                            argspec[0][0] in ('cls', 'self'):
                         del argspec[0][0]
                     args = inspect.formatargspec(*argspec)
         self.result.append(u'', '')
 
         # now, create the directive header
-        directive = (what == 'method' and is_static_method(todoc)) \
-                    and 'staticmethod' or what
+        if what == 'method':
+            directive = get_method_type(todoc)
+        else:
+            directive = what
         self.result.append(indent + u'.. %s:: %s%s' %
                            (directive, name_in_directive, sig), '<autodoc>')
         if what == 'module':
                 self.result.append(indent + line, src[0], src[1])
 
         # document members?
-        if not members or what in ('function', 'method', 'data', 'attribute'):
+        if not members or what in ('function', 'method', 'staticmethod',
+                                   'classmethod', 'data', 'attribute'):
             return
 
         # set current namespace for finding members
                                            source='')
                     else:
                         memberwhat = 'class'
-                elif callable(member):
+                elif inspect.isroutine(member):
                     memberwhat = 'method'
                 elif isdescriptor(member):
                     memberwhat = 'attribute'

File sphinx/texinputs/sphinx.sty

View file
     \fi
 }{\end{fulllineitems}}
 
+% class method ----------------------------------------------------------
+% \begin{classmethoddesc}[classname]{methodname}{args}
+\newcommand{\classmethodline}[3][\@undefined]{
+  \classmethodlineni{#2}{#3}
+  \ifx\@undefined#1\relax
+    \index{#2@{\py@idxcode{#2()}} (\py@thisclass\ class method)}
+  \else
+    \index{#2@{\py@idxcode{#2()}} (#1 class method)}
+  \fi
+}
+\newenvironment{classmethoddesc}[3][\@undefined]{
+  \begin{fulllineitems}
+    \ifx\@undefined#1\relax
+      \classmethodline{#2}{#3}
+    \else
+      \def\py@thisclass{#1}
+      \classmethodline{#2}{#3}
+    \fi
+}{\end{fulllineitems}}
+
+% similar to {classmethoddesc}, but doesn't add to the index
+% (never actually uses the optional argument)
+\newcommand{\classmethodlineni}[3][\py@classbadkey]{%
+  \py@sigline{class \bfcode{#2}}{#3}}
+\newenvironment{classmethoddescni}[3][\py@classbadkey]{
+  \begin{fulllineitems}
+    \classmethodlineni{#2}{#3}
+}{\end{fulllineitems}}
+
 % object data attribute --------------------------------------------------
 % \begin{memberdesc}[classname]{membername}
 \newcommand{\memberline}[2][\py@classbadkey]{%

File sphinx/writers/latex.py

View file
         'function' : 'funcdesc',
         'class': 'classdesc',
         'method': 'methoddesc',
+        'classmethod': 'classmethoddesc',
         'staticmethod': 'staticmethoddesc',
         'exception': 'excdesc',
         'data': 'datadesc',
             t2 = "{%s}{%s}" % (d.name, d.params)
         elif d.env in ('datadesc', 'excdesc', 'csimplemacrodesc'):
             t2 = "{%s}" % (d.name)
-        elif d.env in ('methoddesc', 'staticmethoddesc'):
+        elif d.env in ('methoddesc', 'classmethoddesc', 'staticmethoddesc'):
             if d.cls:
                 t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params)
             else: