Commits

georg.brandl  committed 76dfdd9

#3422: allow changing the signature of functions via a new hook.

  • Participants
  • Parent commits d2e65aa

Comments (0)

Files changed (4)

   to disable the anchor-link creation after headlines and definition
   links.  EXPERIMENTAL
 
+* sphinx.doc.autodoc has a new event ``autodoc-process-signature`` that
+  allows tuning function signature introspection.
+
 
 Release 0.4.2 (Jul 29, 2008)
 ============================

File doc/ext/autodoc.rst

 Docstring preprocessing
 -----------------------
 
-.. versionadded:: 0.4
-
-autodoc provides the following additional event:
+autodoc provides the following additional events:
 
 .. event:: autodoc-process-docstring (app, what, name, obj, options, lines)
 
+   .. versionadded:: 0.4
+
    Emitted when autodoc has read and processed a docstring.  *lines* is a list
    of strings -- the lines of the processed docstring -- that the event handler
    can modify **in place** to change what Sphinx puts into the output.
       auto directive
    :param lines: the lines of the docstring, see above
 
+.. event:: autodoc-process-signature (app, what, name, obj, options, signature, return_annotation)
+
+   .. versionadded:: 0.5
+
+   Emitted when autodoc has formatted a signature for an object. The event
+   handler can return a new tuple ``(signature, return_annotation)`` to change
+   what Sphinx puts into the output.
+
+   :param app: the Sphinx application object
+   :param what: the type of the object which the docstring belongs to (one of
+      ``"module"``, ``"class"``, ``"exception"``, ``"function"``, ``"method"``,
+      ``"attribute"``)
+   :param name: the fully qualified name of the object
+   :param obj: the object itself
+   :param options: the options given to the directive: an object with attributes
+      ``inherited_members``, ``undoc_members``, ``show_inheritance`` and
+      ``noindex`` that are true if the flag option of same name was given to the
+      auto directive
+   :param signature: function signature, as a string of the form
+      ``"(parameter_1, parameter_2)"``, or ``None`` if introspection didn't succeed
+      and signature wasn't specified in the directive.
+   :param return_annotation: function return annotation as a string of the form
+      ``" -> annotation"``, or ``None`` if there is no return annotation
 
 The :mod:`sphinx.ext.autodoc` module provides factory functions for commonly
-needed docstring processing:
+needed docstring processing in event :event:`autodoc-process-docstring`:
 
 .. autofunction:: cut_lines
 .. autofunction:: between
 ez_setup.use_setuptools()
 
 import sys
-from setuptools import setup, Feature
+from setuptools import setup
 
 import sphinx
 

File sphinx/ext/autodoc.py

                 mod = self.env.currmodule
             return fullname, mod, [cls, base], args, retann
 
-    def format_signature(self, what, obj, args, retann):
+    def format_signature(self, what, name, obj, args, retann):
         """
         Return the signature of the object, formatted for display.
         """
         if what not in ('class', 'method', 'function'):
             return ''
+
+        err = None
         if args is not None:
             # signature given explicitly
-            return '(%s)%s' % (args, retann or '')
-        if what == 'class':
-            # for classes, the relevant signature is the __init__ method's
-            obj = getattr(obj, '__init__', None)
-            # classes without __init__ method?
-            if obj is None or obj is object.__init__ or not \
-               (inspect.ismethod(obj) or inspect.isfunction(obj)):
-                return ''
-        argspec = inspect.getargspec(obj)
-        if what in ('class', 'method') and argspec[0] and \
-           argspec[0][0] in ('cls', 'self'):
-            del argspec[0][0]
-        return inspect.formatargspec(*argspec)
+            args = "(%s)" % args
+        else:
+            # try to introspect the signature
+            try:
+                if what == 'class':
+                    # for classes, the relevant signature is the __init__ method's
+                    obj = getattr(obj, '__init__', None)
+                    # classes without __init__ method?
+                    if obj is None or obj is object.__init__ or not \
+                       (inspect.ismethod(obj) or inspect.isfunction(obj)):
+                        return ''
+                argspec = inspect.getargspec(obj)
+                if what in ('class', 'method') and argspec[0] and \
+                   argspec[0][0] in ('cls', 'self'):
+                    del argspec[0][0]
+                args = inspect.formatargspec(*argspec)
+            except Exception, e:
+                args = None
+                err = e
+
+        results = self.env.app.emit('autodoc-process-signature',
+                                    what, name, obj, self.options, args, retann)
+        for result in results:
+            if result:
+                args, retann = result
+
+        if args is not None:
+            return '%s%s' % (args, retann or '')
+        elif err:
+            # re-raise the error for perusal of the handler in generate()
+            raise RuntimeError(err)
+        else:
+            return ''
 
     def generate(self, what, name, members, add_content, indent=u'', check_module=False):
         """
 
         # format the object's signature, if any
         try:
-            sig = self.format_signature(what, todoc, args, retann)
+            sig = self.format_signature(what, name, todoc, args, retann)
         except Exception, err:
             self.warn('error while formatting signature for %s: %s' %
                       (fullname, err))
     app.add_config_value('automodule_skip_lines', 0, True)
     app.add_config_value('autoclass_content', 'class', True)
     app.add_event('autodoc-process-docstring')
+    app.add_event('autodoc-process-signature')