Commits

Georg Brandl committed 043b32f

#478: Added :rst:dir:`py:decorator` directive to describe decorators.

Comments (0)

Files changed (3)

 * #259: HTML table rows now have even/odd CSS classes to enable
   "Zebra styling".
 
+* #478: Added :rst:dir:`py:decorator` directive to describe decorators.
+
 * #367: Added automatic exclusion of hidden members in inheritance
   diagrams, and an option to selectively enable it.
 
 
    .. versionadded:: 0.6
 
+.. rst:directive:: .. py:decorator:: name
+                   .. py:decorator:: name(signature)
+
+   Describes a decorator function.  The signature should *not* represent the
+   signature of the actual function, but the usage as a decorator.  For example,
+   given the functions
+
+   .. code-block:: python
+
+      def removename(func):
+          func.__name__ = ''
+          return func
+
+      def setnewname(name):
+          def decorator(func):
+              func.__name__ = name
+              return func
+          return decorator
+
+   the descriptions should look like this::
+
+      .. py:decorator:: removename
+
+         Remove name of the decorated function.
+
+      .. py:decorator:: setnewname(name)
+
+         Set name of the decorated function to *name*.
+
+   There is no ``py:deco`` role to link to a decorator that is marked up with
+   this directive; rather, use the :rst:role:`py:func` role.
+
+.. rst:directive:: .. py:decoratormethod:: name
+                   .. py:decoratormethod:: name(signature)
+
+   Same as :rst:dir:`py:decorator`, but for decorators that are methods.
+
+   Refer to a decorator method using the :rst:role:`py:meth` role.
+
 
 .. _signatures:
 

sphinx/domains/python.py

             self.clsname_set = True
 
 
+class PyDecoratorMixin(object):
+    """
+    Mixin for decorator directives.
+    """
+    def handle_signature(self, sig, signode):
+        ret = super(PyDecoratorMixin, self).handle_signature(sig, signode)
+        signode.insert(0, addnodes.desc_addname('@', '@'))
+        return ret
+
+    def needs_arglist(self):
+        return False
+
+
+class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
+    """
+    Directive to mark functions meant to be used as decorators.
+    """
+    def run(self):
+        # a decorator function is a function after all
+        self.name = 'py:function'
+        return PyModulelevel.run(self)
+
+
+class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
+    """
+    Directive to mark methods meant to be used as decorators.
+    """
+    def run(self):
+        self.name = 'py:method'
+        return PyClassmember.run(self)
+
+
 class PyModule(Directive):
     """
     Directive to mark description of a new module.
     }
 
     directives = {
-        'function':      PyModulelevel,
-        'data':          PyModulelevel,
-        'class':         PyClasslike,
-        'exception':     PyClasslike,
-        'method':        PyClassmember,
-        'classmethod':   PyClassmember,
-        'staticmethod':  PyClassmember,
-        'attribute':     PyClassmember,
-        'module':        PyModule,
-        'currentmodule': PyCurrentModule,
+        '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(),