Commit 8a1caa23 authored by Georg Brandl's avatar Georg Brandl

#6522: add a "decorator" directive to explicitly document decorators, and use it in a few places.

parent b0a4e3c1
...@@ -177,6 +177,34 @@ The directives are: ...@@ -177,6 +177,34 @@ The directives are:
are modified), side effects, and possible exceptions. A small example may be are modified), side effects, and possible exceptions. A small example may be
provided. provided.
.. describe:: decorator
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::
.. decorator:: removename
Remove name of the decorated function.
.. decorator:: setnewname(name)
Set name of the decorated function to *name*.
.. describe:: class .. describe:: class
Describes a class. The signature can include parentheses with parameters Describes a class. The signature can include parentheses with parameters
...@@ -194,6 +222,10 @@ The directives are: ...@@ -194,6 +222,10 @@ The directives are:
parameter. The description should include similar information to that parameter. The description should include similar information to that
described for ``function``. described for ``function``.
.. describe:: decoratormethod
Same as ``decorator``, but for decorators that are methods.
.. describe:: opcode .. describe:: opcode
Describes a Python :term:`bytecode` instruction. Describes a Python :term:`bytecode` instruction.
......
...@@ -122,7 +122,7 @@ This module provides the following class: ...@@ -122,7 +122,7 @@ This module provides the following class:
It also provides the following decorators: It also provides the following decorators:
.. function:: abstractmethod(function) .. decorator:: abstractmethod(function)
A decorator indicating abstract methods. A decorator indicating abstract methods.
......
...@@ -12,7 +12,7 @@ statement. For more information see also :ref:`typecontextmanager` and ...@@ -12,7 +12,7 @@ statement. For more information see also :ref:`typecontextmanager` and
Functions provided: Functions provided:
.. function:: contextmanager(func) .. decorator:: contextmanager
This function is a :term:`decorator` that can be used to define a factory This function is a :term:`decorator` that can be used to define a factory
function for :keyword:`with` statement context managers, without needing to function for :keyword:`with` statement context managers, without needing to
......
...@@ -37,7 +37,7 @@ The :mod:`functools` module defines the following functions: ...@@ -37,7 +37,7 @@ The :mod:`functools` module defines the following functions:
.. versionadded:: 3.2 .. versionadded:: 3.2
.. function:: total_ordering(cls) .. decorator:: total_ordering
Given a class defining one or more rich comparison ordering methods, this Given a class defining one or more rich comparison ordering methods, this
class decorator supplies the rest. This simplifies the effort involved class decorator supplies the rest. This simplifies the effort involved
...@@ -122,7 +122,7 @@ The :mod:`functools` module defines the following functions: ...@@ -122,7 +122,7 @@ The :mod:`functools` module defines the following functions:
than helpful. than helpful.
.. function:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) .. decorator:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
This is a convenience function for invoking ``partial(update_wrapper, This is a convenience function for invoking ``partial(update_wrapper,
wrapped=wrapped, assigned=assigned, updated=updated)`` as a function decorator wrapped=wrapped, assigned=assigned, updated=updated)`` as a function decorator
......
...@@ -469,7 +469,7 @@ find and load modules. ...@@ -469,7 +469,7 @@ find and load modules.
This module contains the various objects that help in the construction of This module contains the various objects that help in the construction of
an :term:`importer`. an :term:`importer`.
.. function:: module_for_loader(method) .. decorator:: module_for_loader
A :term:`decorator` for a :term:`loader` method, A :term:`decorator` for a :term:`loader` method,
to handle selecting the proper to handle selecting the proper
...@@ -494,7 +494,7 @@ an :term:`importer`. ...@@ -494,7 +494,7 @@ an :term:`importer`.
Use of this decorator handles all the details of which module object a Use of this decorator handles all the details of which module object a
loader should initialize as specified by :pep:`302`. loader should initialize as specified by :pep:`302`.
.. function:: set_loader(fxn) .. decorator:: set_loader
A :term:`decorator` for a :term:`loader` method, A :term:`decorator` for a :term:`loader` method,
to set the :attr:`__loader__` to set the :attr:`__loader__`
...@@ -502,7 +502,7 @@ an :term:`importer`. ...@@ -502,7 +502,7 @@ an :term:`importer`.
does nothing. It is assumed that the first positional argument to the does nothing. It is assumed that the first positional argument to the
wrapped method is what :attr:`__loader__` should be set to. wrapped method is what :attr:`__loader__` should be set to.
.. function:: set_package(fxn) .. decorator:: set_package
A :term:`decorator` for a :term:`loader` to set the :attr:`__package__` A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
attribute on the module returned by the loader. If :attr:`__package__` is attribute on the module returned by the loader. If :attr:`__package__` is
......
...@@ -621,20 +621,20 @@ the test unless the passed object has a certain attribute: :: ...@@ -621,20 +621,20 @@ the test unless the passed object has a certain attribute: ::
The following decorators implement test skipping and expected failures: The following decorators implement test skipping and expected failures:
.. function:: skip(reason) .. decorator:: skip(reason)
Unconditionally skip the decorated test. *reason* should describe why the Unconditionally skip the decorated test. *reason* should describe why the
test is being skipped. test is being skipped.
.. function:: skipIf(condition, reason) .. decorator:: skipIf(condition, reason)
Skip the decorated test if *condition* is true. Skip the decorated test if *condition* is true.
.. function:: skipUnless(condition, reason) .. decorator:: skipUnless(condition, reason)
Skip the decoratored test unless *condition* is true. Skip the decoratored test unless *condition* is true.
.. function:: expectedFailure .. decorator:: expectedFailure
Mark the test as an expected failure. If the test fails when run, the test Mark the test as an expected failure. If the test fails when run, the test
is not counted as a failure. is not counted as a failure.
...@@ -1048,11 +1048,11 @@ Test cases ...@@ -1048,11 +1048,11 @@ Test cases
:attr:`exception` attribute. This can be useful if the intention :attr:`exception` attribute. This can be useful if the intention
is to perform additional checks on the exception raised:: is to perform additional checks on the exception raised::
with self.assertRaises(SomeException) as cm: with self.assertRaises(SomeException) as cm:
do_something() do_something()
the_exception = cm.exception the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3) self.assertEqual(the_exception.error_code, 3)
.. versionchanged:: 3.1 .. versionchanged:: 3.1
Added the ability to use :meth:`assertRaises` as a context manager. Added the ability to use :meth:`assertRaises` as a context manager.
......
...@@ -72,6 +72,32 @@ class ImplementationDetail(Directive): ...@@ -72,6 +72,32 @@ class ImplementationDetail(Directive):
return [pnode] return [pnode]
# Support for documenting decorators
from sphinx import addnodes
from sphinx.domains.python import PyModulelevel, PyClassmember
class PyDecoratorMixin(object):
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):
def run(self):
# a decorator function is a function after all
self.name = 'py:function'
return PyModulelevel.run(self)
class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
def run(self):
self.name = 'py:method'
return PyClassmember.run(self)
# Support for building "topic help" for pydoc # Support for building "topic help" for pydoc
pydoc_topic_labels = [ pydoc_topic_labels = [
...@@ -147,7 +173,6 @@ import suspicious ...@@ -147,7 +173,6 @@ import suspicious
# Support for documenting Opcodes # Support for documenting Opcodes
import re import re
from sphinx import addnodes
opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)(?:\s*\((.*)\))?') opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)(?:\s*\((.*)\))?')
...@@ -197,3 +222,5 @@ def setup(app): ...@@ -197,3 +222,5 @@ def setup(app):
app.add_description_unit('pdbcommand', 'pdbcmd', '%s (pdb command)', app.add_description_unit('pdbcommand', 'pdbcmd', '%s (pdb command)',
parse_pdb_command) parse_pdb_command)
app.add_description_unit('2to3fixer', '2to3fixer', '%s (2to3 fixer)') app.add_description_unit('2to3fixer', '2to3fixer', '%s (2to3 fixer)')
app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction)
app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment