What is pydoctor?
masterzope.interface declarations, computing inheritance hierarchies and resolving imports to show which classes implement which interfaces. It was originally developed to replace epydoc for the Twisted project.repository·master·Indexed 42 days ago
https://github.com/twisted/pydoctorA standalone API documentation generator for Python that uses static analysis to create documentation from source code. It is designed to handle complex inheritance and interface implementations, such as zope.interface, and supports docstrings, attribute docstrings, doc-comments, and type annotations.
zope.interface declarations, computing inheritance hierarchies and resolving imports to show which classes implement which interfaces. It was originally developed to replace epydoc for the Twisted project.If you need to modify the state of objects in the Documentable tree (e.g., transforming how certain classes are parsed), use the extension mechanism instead of overriding the System class.
An extension is a Python module containing a setup_pydoctor_extension(registrar) function. This function is called during initialization and receives an ExtRegistrar object.
Extensions can register:
pydoctor.model.Documentable objects.Methods decorated with @property (or any decorator ending in property or Property) are documented as attributes rather than methods.
To ensure custom properties are recognized, follow the naming convention of ending the decorator name with property or Property.
class Knight:
@property
def name(self):
return self._name
@customProperty
def quest(self):
return 'Find the object'napoleon extension to handle Google and NumPy docstring parsing. For detailed technical implementation details, refer to the pydoctor.napoleon module documentation.The generated documentation includes a client-side search system (based on lunr.js).
UX Features:
Ctrl+K or Cmd+K (on Mac) to focus the search box.Enter to open a selection.docstring: (e.g., docstring:<term>) to search specifically within docstrings.? to make a term optional.When choosing between pydoctor and sphinx-autodoc, consider the following differences:
pydoctor is fully automatic and generates documentation directly from Python source files. sphinx-autodoc is semi-automatic and requires accompanying reStructuredText files.pydoctor generates a simple, efficient layout with one page per class, module, and package, often using tables to present information. sphinx-autodoc can produce more complex and potentially overwhelming output.pydoctor output can be seamlessly linked to narrative documentation written in Sphinx.pydoctor is particularly well-suited for libraries with significant internal subclassing and provides native support for zope.interface (recognizing both interfaces and the classes that implement them).Pydoctor recognizes constants based on two criteria:
typing.Final qualifier (available in Python 3.8+).For Python 3.6 and 3.7, use typing_extensions.Final instead.
Constants are rendered with syntax highlighting in the generated documentation.
from typing import Final
X = 3.14
y: Final = ['a', 'b']
# For Python 3.6/3.7
from typing_extensions import Final
z: Final = 'relative/path'Pydoctor uses naming conventions to determine the visibility of modules, classes, and functions:
_Private) are considered private. They are hidden by default in the generated documentation but can be revealed via a button in the UI.__str__, __eq__) are always considered public.Note: Pydoctor supports three levels of privacy: public, private, and hidden. For advanced customization, see the privacy override documentation.
class _Private:
"""This class won't be shown unless explicitly revealed."""
class Public:
"""This class is public, but some of its methods are private."""
def public(self):
"""This is a public method."""
def _private(self):
"""For internal use only."""
def __eq__(self, other):
"""Is this object equal to 'other'?
This method is public.
"""Pydoctor uses a priority system to resolve names when dealing with conditional blocks:
Names defined in the main flow take precedence over definitions in except or else blocks. If a name is defined in the main flow, the version in the except block is ignored.
By default, pydoctor prioritizes the main flow over the TYPE_CHECKING block. If a class or type is defined in both, the runtime version is documented and the TYPE_CHECKING version is ignored.
Tip: Inverting conditions
If you want pydoctor to document the types defined inside a TYPE_CHECKING block (e.g., for Protocols), you should invert the condition so the TYPE_CHECKING block becomes the 'main flow':
if not TYPE_CHECKING:
from ._implementation import Thing
else:
from ._typing import Thing # This will now be the 'main flow' and be documentedfrom typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Protocol
class CapSys(Protocol):
def readouterr() -> Any: ...
else:
class CapSys(object):
...
# In the above, CapSys(object) is documented because it is the 'main flow'.
# To document the Protocol, use:
if not TYPE_CHECKING:
from ._implementation import Thing
else:
from ._typing import ThingIn Python, you can document modules, classes, and functions using docstrings (triple-quoted strings at the top of the definition). For long docstrings, start with a short summary line, followed by an empty line, and then the detailed description. This ensures the summary is used in summary tables while the detail is shown in the full documentation.
To include literal escape sequences like \n in your documentation, either escape them twice (\\n) or use a raw string literal (r"""...""").
"""This docstring describes the purpose of this module."""
class C:
"""This docstring describes the purpose of this class."""
def m(self):
"""This docstring describes the purpose of this method."""
pass
# Long docstring pattern
def f():
r"""This line is used as the summary.
More detail about the workings of this function can be added here.
"""
passIf you want to keep your implementation in private modules but expose a clean public API from a single module, use pydoctor's re-export feature.
To re-export an element, import it into your top-level module (e.g., __init__.py) and include its name in the __all__ special variable. Pydoctor will then move the documentation for that element to the module where it was re-exported.
Example Structure:
my_project/__init__.py (Re-exports MyClass)my_project/core/_impl.py (Defines and documents MyClass)Implementation in my_project/__init__.py:
from .core._impl import MyClass
__all__ = ("MyClass",)from .core._impl import MyClass
__all__ = ("MyClass",)Pydoctor supports attribute docstrings, which are strings placed immediately after an attribute assignment. Note that these are not part of the standard Python language and are not available at runtime.
You can document module-level constants, class variables, or instance variables using this method.
CONST = 123
"""This docstring describes a module level constant."""
class C:
cvar = None
"""This docstring describes a class variable."""
def __init__(self):
self.ivar = [];"""It can also be used inline."""