docs.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. from fabric.tasks import WrappedCallableTask
  2. def unwrap_tasks(module, hide_nontasks=False):
  3. """
  4. Replace task objects on ``module`` with their wrapped functions instead.
  5. Specifically, look for instances of `~fabric.tasks.WrappedCallableTask` and
  6. replace them with their ``.wrapped`` attribute (the original decorated
  7. function.)
  8. This is intended for use with the Sphinx autodoc tool, to be run near the
  9. bottom of a project's ``conf.py``. It ensures that the autodoc extension
  10. will have full access to the "real" function, in terms of function
  11. signature and so forth. Without use of ``unwrap_tasks``, autodoc is unable
  12. to access the function signature (though it is able to see e.g.
  13. ``__doc__``.)
  14. For example, at the bottom of your ``conf.py``::
  15. from fabric.docs import unwrap_tasks
  16. import my_package.my_fabfile
  17. unwrap_tasks(my_package.my_fabfile)
  18. You can go above and beyond, and explicitly **hide** all non-task
  19. functions, by saying ``hide_nontasks=True``. This renames all objects
  20. failing the "is it a task?" check so they appear to be private, which will
  21. then cause autodoc to skip over them.
  22. ``hide_nontasks`` is thus useful when you have a fabfile mixing in
  23. subroutines with real tasks and want to document *just* the real tasks.
  24. If you run this within an actual Fabric-code-using session (instead of
  25. within a Sphinx ``conf.py``), please seek immediate medical attention.
  26. .. versionadded: 1.5
  27. .. seealso:: `~fabric.tasks.WrappedCallableTask`, `~fabric.decorators.task`
  28. """
  29. set_tasks = []
  30. for name, obj in vars(module).items():
  31. if isinstance(obj, WrappedCallableTask):
  32. setattr(module, obj.name, obj.wrapped)
  33. # Handle situation where a task's real name shadows a builtin.
  34. # If the builtin comes after the task in vars().items(), the object
  35. # we just setattr'd above will get re-hidden :(
  36. set_tasks.append(obj.name)
  37. # In the same vein, "privately" named wrapped functions whose task
  38. # name is public, needs to get renamed so autodoc picks it up.
  39. obj.wrapped.func_name = obj.name
  40. else:
  41. if name in set_tasks:
  42. continue
  43. has_docstring = getattr(obj, '__doc__', False)
  44. if hide_nontasks and has_docstring and not name.startswith('_'):
  45. setattr(module, '_%s' % name, obj)
  46. delattr(module, name)