Module pdocs.doc

View Source
import ast

import inspect

import typing

__pdoc__ = {}

def _source(obj):

    """

    Returns the source code of the Python object `obj` as a list of

    lines. This tries to extract the source from the special

    `__wrapped__` attribute if it exists. Otherwise, it falls back

    to `inspect.getsourcelines`.

    If neither works, then the empty list is returned.

    """

    try:

        return inspect.getsourcelines(obj.__wrapped__)[0]

    except BaseException:

        pass

    try:

        return inspect.getsourcelines(obj)[0]

    except Exception:

        return []

def _var_docstrings(tree, module, cls=None, init=False):

    """

    Extracts variable docstrings given `tree` as the abstract syntax,

    `module` as a `pdoc.Module` containing `tree` and an option `cls`

    as a `pdoc.Class` corresponding to the tree. In particular, `cls`

    should be specified when extracting docstrings from a class or an

    `__init__` method. Finally, `init` should be `True` when searching

    the AST of an `__init__` method so that `_var_docstrings` will only

    accept variables starting with `self.` as instance variables.

    A dictionary mapping variable name to a `pdoc.Variable` object is

    returned.

    """

    vs = {}

    children = list(ast.iter_child_nodes(tree))

    for i, child in enumerate(children):

        if isinstance(child, ast.Assign) and len(child.targets) == 1:

            if not init and isinstance(child.targets[0], ast.Name):

                name = child.targets[0].id

            elif (

                isinstance(child.targets[0], ast.Attribute)

                and isinstance(child.targets[0].value, ast.Name)

                and child.targets[0].value.id == "self"

            ):

                name = child.targets[0].attr

            else:

                continue

            if not _is_exported(name) and name not in getattr(module, "__all__", []):

                continue

            docstring = ""

            if (

                i + 1 < len(children)

                and isinstance(children[i + 1], ast.Expr)

                and isinstance(children[i + 1].value, ast.Str)

            ):

                docstring = children[i + 1].value.s

            vs[name] = Variable(name, module, docstring, cls=cls)

    return vs

def _is_exported(ident_name):

    """

    Returns `True` if `ident_name` matches the export criteria for an

    identifier name.

    This should not be used by clients. Instead, use

    `pdoc.Module.is_public`.

    """

    return not ident_name.startswith("_")

def _is_method(cls: typing.Type, method_name: str) -> bool:

    """

    Returns `True` if the given method is a regular method,

    i.e. it's neither annotated with @classmethod nor @staticmethod.

    """

    func = getattr(cls, method_name, None)

    if inspect.ismethod(func):

        # If the function is already bound, it's a classmethod.

        # Regular methods are not bound before initialization.

        return False

    for c in inspect.getmro(cls):

        if method_name in c.__dict__:

            return not isinstance(c.__dict__[method_name], staticmethod)

    else:

        raise ValueError(

            "{method_name} not found in {cls}.".format(method_name=method_name, cls=cls)

        )

def _filter(items, kind, attributes_set=(), attributes_not_set=(), sort=True):

    items = (item for item in items if isinstance(item, kind))

    for attribute_set in attributes_set:

        items = (item for item in items if getattr(item, attribute_set, False))

    for attribute_not_set in attributes_not_set:

        items = (item for item in items if not getattr(item, attribute_not_set, False))

    if sort:

        return sorted(items)

    else:

        return tuple(items)

class Doc(object):

    """

    A base class for all documentation objects.

    A documentation object corresponds to *something* in a Python module

    that has a docstring associated with it. Typically, this only includes

    modules, classes, functions and methods. However, `pdoc` adds support

    for extracting docstrings from the abstract syntax tree, which means

    that variables (module, class or instance) are supported too.

    A special type of documentation object `pdoc.External` is used to

    represent identifiers that are not part of the public interface of

    a module. (The name "External" is a bit of a misnomer, since it can

    also correspond to unexported members of the module, particularly in

    a class's ancestor list.)

    """

    def __init__(self, name, module, docstring):

        """

        Initializes a documentation object, where `name` is the public

        identifier name, `module` is a `pdoc.Module` object, and

        `docstring` is a string containing the docstring for `name`.

        """

        self.module = module

        """

        The module documentation object that this object was defined

        in.

        """

        self.name = name

        """

        The identifier name for this object.

        """

        self.docstring = inspect.cleandoc(docstring or "")

        """

        The docstring for this object. It has already been cleaned

        by `inspect.cleandoc`.

        """

    @property

    def source(self):

        """

        Returns the source code of the Python object `obj` as a list of

        lines. This tries to extract the source from the special

        `__wrapped__` attribute if it exists. Otherwise, it falls back

        to `inspect.getsourcelines`.

        If neither works, then the empty list is returned.

        """

        raise NotImplementedError("source() method should be implemented by sub casses")

    @property

    def refname(self):

        """

        Returns an appropriate reference name for this documentation

        object. Usually this is its fully qualified path. Every

        documentation object must provide this property.

        e.g., The refname for this property is

        <code>pdoc.Doc.refname</code>.

        """

        raise NotImplementedError("refname() method should be implemented by sub casses")

    def __lt__(self, other):

        return self.name < other.name

    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0

class Module(Doc):

    """

    Representation of a module's documentation.

    """

    __pdoc__["Module.module"] = "The Python module object."

    __pdoc__[

        "Module.name"

    ] = """

        The name of this module with respect to the context in which

        it was imported. It is always an absolute import path.

        """

    def __init__(self, name, module, parent):

        """

        Creates a `Module` documentation object given the actual

        module Python object.

        """

        super().__init__(name, module, inspect.getdoc(module))

        self.parent = parent

        self.doc = {}

        """A mapping from identifier name to a documentation object."""

        self.refdoc = {}

        """

        The same as `pdoc.Module.doc`, but maps fully qualified

        identifier names to documentation objects.

        """

        self.submodules = []

        vardocs = {}

        try:

            tree = ast.parse(inspect.getsource(self.module))

            vardocs = _var_docstrings(tree, self, cls=None)

        except BaseException:

            pass

        self._declared_variables = vardocs.keys()

        public = self.__public_objs()

        for name, obj in public.items():

            # Skip any identifiers that already have doco.

            if name in self.doc and not self.doc[name].is_empty():

                continue

            # Functions and some weird builtins?, plus methods, classes,

            # modules and module level variables.

            if inspect.isroutine(obj):

                self.doc[name] = Function(name, self, obj)

            elif inspect.isclass(obj):

                self.doc[name] = Class(name, self, obj)

            elif name in vardocs:

                self.doc[name] = vardocs[name]

            else:

                # Catch all for variables.

                self.doc[name] = Variable(name, self, "", cls=None)

        # Now see if we can grab inheritance relationships between classes.

        for docobj in self.doc.values():

            if isinstance(docobj, Class):

                docobj._fill_inheritance()

        # Build the reference name dictionary.

        for _basename, docobj in self.doc.items():

            self.refdoc[docobj.refname] = docobj

            if isinstance(docobj, Class):

                for v in docobj.class_variables():

                    self.refdoc[v.refname] = v

                for v in docobj.instance_variables():

                    self.refdoc[v.refname] = v

                for f in docobj.methods():

                    self.refdoc[f.refname] = f

                for f in docobj.functions():

                    self.refdoc[f.refname] = f

        # Finally look for more docstrings in the __pdoc__ override.

        for name, docstring in getattr(self.module, "__pdoc__", {}).items():

            refname = "%s.%s" % (self.refname, name)

            if docstring is None:

                self.doc.pop(name, None)

                self.refdoc.pop(refname, None)

                continue

            dobj = self.find_ident(refname)

            if isinstance(dobj, External):

                continue

            dobj.docstring = inspect.cleandoc(docstring)

    @property

    def source(self):

        return _source(self.module)

    @property

    def refname(self):

        return self.name

    @property

    def is_namespace(self):

        """Returns `True` if this module represents a

           [namespace package](https://packaging.python.org/guides/packaging-namespace-packages/).

        """

        return self.module.__spec__.origin in (None, "namespace")

    def mro(self, cls):

        """

        Returns a method resolution list of ancestor documentation objects

        for `cls`, which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        return [self.find_class(c) for c in inspect.getmro(cls.cls) if c not in (cls.cls, object)]

    def descendents(self, cls):

        """

        Returns a descendent list of documentation objects for `cls`,

        which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        if cls.cls == type or not hasattr(cls.cls, "__subclasses__"):

            # Is this right?

            return []

        downs = cls.cls.__subclasses__()

        return list(map(lambda c: self.find_class(c), downs))

    def is_public(self, name):

        """

        Returns `True` if and only if an identifier with name `name` is

        part of the public interface of this module. While the names

        of sub-modules are included, identifiers only exported by

        sub-modules are not checked.

        `name` should be a fully qualified name, e.g.,

        <code>pdoc.Module.is_public</code>.

        """

        return name in self.refdoc

    def find_class(self, cls):

        """

        Given a Python `cls` object, try to find it in this module

        or in any of the exported identifiers of the submodules.

        """

        for doc_cls in self.classes():

            if cls is doc_cls.cls:

                return doc_cls

        for module in self.submodules:

            doc_cls = module.find_class(cls)

            if not isinstance(doc_cls, External):

                return doc_cls

        return External("%s.%s" % (cls.__module__, cls.__name__))

    def find_ident(self, name, _seen=None):

        """

        Searches this module and **all** of its sub/super-modules for an

        identifier with name `name` in its list of exported

        identifiers according to `pdoc`. Note that unexported

        sub-modules are searched.

        A bare identifier (without `.` separators) will only be checked

        for in this module.

        The documentation object corresponding to the identifier is

        returned. If one cannot be found, then an instance of

        `External` is returned populated with the given identifier.

        """

        _seen = _seen or set()

        if self in _seen:

            return None

        _seen.add(self)

        if name == self.refname:

            return self

        if name in self.refdoc:

            return self.refdoc[name]

        for module in self.submodules:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

        # Traverse also up-level super-modules

        module = self.parent

        while module is not None:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

            module = module.parent

        return External(name)

    def variables(self):

        """

        Returns all documented module level variables in the module

        sorted alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)

    def classes(self):

        """

        Returns all documented module level classes in the module

        sorted alphabetically as a list of `pdoc.Class`.

        """

        return _filter(self.doc.values(), Class)

    def functions(self):

        """

        Returns all documented module level functions in the module

        sorted alphabetically as a list of `pdoc.Function`.

        """

        return _filter(self.doc.values(), Function)

    def __is_exported(self, name, module):

        """

        Returns `True` if and only if `pdoc` considers `name` to be

        a public identifier for this module where `name` was defined

        in the Python module `module`.

        If this module has an `__all__` attribute, then `name` is

        considered to be exported if and only if it is a member of

        this module's `__all__` list.

        If `__all__` is not set, then whether `name` is exported or

        not is heuristically determined. Firstly, if `name` starts

        with an underscore, it will not be considered exported.

        Secondly, if `name` was defined in a module other than this

        one, it will not be considered exported. In all other cases,

        `name` will be considered exported.

        """

        if hasattr(self.module, "__all__"):

            return name in self.module.__all__

        if not _is_exported(name):

            return False

        if module is not None and self.module.__name__ != module.__name__:

            return name in self._declared_variables

        return True

    def __public_objs(self):

        """

        Returns a dictionary mapping a public identifier name to a

        Python object.

        """

        members = dict(inspect.getmembers(self.module))

        return dict(

            [

                (name, obj)

                for name, obj in members.items()

                if self.__is_exported(name, inspect.getmodule(obj))

            ]

        )

    def allmodules(self):

        yield self

        for i in self.submodules:

            yield from i.allmodules()

    def toroot(self):

        n = self

        while n:

            yield n

            n = n.parent

class Class(Doc):

    """

    Representation of a class's documentation.

    """

    def __init__(self, name, module, class_obj):

        """

        Same as `pdocs.Doc.__init__`, except `class_obj` must be a

        Python class object. The docstring is gathered automatically.

        """

        super().__init__(name, module, inspect.getdoc(class_obj))

        self.cls = class_obj

        """The class Python object."""

        self.doc = {}

        """A mapping from identifier name to a `pdoc.Doc` objects."""

        self.doc_init = {}

        """

        A special version of `pdoc.Class.doc` that contains

        documentation for instance variables found in the `__init__`

        method.

        """

        public = self.__public_objs()

        try:

            # First try and find docstrings for class variables.

            # Then move on to finding docstrings for instance variables.

            # This must be optional, since not all modules have source

            # code available.

            cls_ast = ast.parse(inspect.getsource(self.cls)).body[0]

            self.doc = _var_docstrings(cls_ast, self.module, cls=self)

            for n in cls_ast.body if "__init__" in public else []:

                if isinstance(n, ast.FunctionDef) and n.name == "__init__":

                    self.doc_init = _var_docstrings(n, self.module, cls=self, init=True)

                    break

        except BaseException:

            pass

        # Convert the public Python objects to documentation objects.

        for name, obj in public.items():

            # Skip any identifiers that already have doco.

            if name in self.doc and not self.doc[name].is_empty():

                continue

            if name in self.doc_init:

                # Let instance members override class members.

                continue

            if inspect.isroutine(obj):

                self.doc[name] = Function(

                    name, self.module, obj, cls=self, method=_is_method(self.cls, name)

                )

            elif isinstance(obj, property):

                docstring = getattr(obj, "__doc__", "")

                self.doc_init[name] = Variable(name, self.module, docstring, cls=self)

            elif not inspect.isbuiltin(obj) and not inspect.isroutine(obj):

                if name in getattr(self.cls, "__slots__", []):

                    self.doc_init[name] = Variable(name, self.module, "", cls=self)

                else:

                    self.doc[name] = Variable(name, self.module, "", cls=self)

    @property

    def source(self):

        return _source(self.cls)

    @property

    def refname(self):

        return "%s.%s" % (self.module.refname, self.cls.__name__)

    def class_variables(self):

        """

        Returns all documented class variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)

    def instance_variables(self):

        """

        Returns all instance variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`. Instance variables

        are attributes of `self` defined in a class's `__init__`

        method.

        """

        return _filter(self.doc_init.values(), Variable)

    def methods(self):

        """

        Returns all documented methods as `pdoc.Function` objects in

        the class, sorted alphabetically.

        Unfortunately, this also includes class methods.

        """

        return _filter(self.doc.values(), Function, attributes_set=("method",))

    def functions(self):

        """

        Returns all documented static functions as `pdoc.Function`

        objects in the class, sorted alphabetically.

        """

        return _filter(self.doc.values(), Function, attributes_not_set=("method",))

    def params(self):

        """Returns back the parameters for the classes __init__ method"""

        params = Function._params(self.cls.__init__)

        return params[1:] if params[0] == "self" else params

    def _fill_inheritance(self):

        """

        Traverses this class's ancestor list and attempts to fill in

        missing documentation from its ancestor's documentation.

        The first pass connects variables, methods and functions with

        their inherited couterparts. (The templates will decide how to

        display docstrings.) The second pass attempts to add instance

        variables to this class that were only explicitly declared in

        a parent class. This second pass is necessary since instance

        variables are only discoverable by traversing the abstract

        syntax tree.

        """

        mro = [c for c in self.module.mro(self) if c != self and isinstance(c, Class)]

        def search(d, fdoc):

            for c in mro:

                doc = fdoc(c)

                if d.name in doc and isinstance(d, type(doc[d.name])):

                    return doc[d.name]

            return None

        for fdoc in (lambda c: c.doc_init, lambda c: c.doc):

            for d in fdoc(self).values():

                dinherit = search(d, fdoc)

                if dinherit is not None:

                    d.inherits = dinherit

        # Since instance variables aren't part of a class's members,

        # we need to manually deduce inheritance. Oh lawdy.

        for c in mro:

            for name in filter(lambda n: n not in self.doc_init, c.doc_init):

                d = c.doc_init[name]

                self.doc_init[name] = Variable(d.name, d.module, "", cls=self)

                self.doc_init[name].inherits = d

    def mro(self):

        """Returns back the Method Resolution Order (MRO) for this class"""

        return [

            self.module.find_class(cls)

            for cls in inspect.getmro(self.cls)

            if cls not in (self.cls, object, self)

        ]

    def subclasses(self):

        """Returns back all subclasses of this class"""

        return [self.module.find_class(cls) for cls in type.__subclasses__(self.cls)]

    def __public_objs(self):

        """

        Returns a dictionary mapping a public identifier name to a

        Python object. This counts the `__init__` method as being

        public.

        """

        _pdoc = getattr(self.module.module, "__pdoc__", {})

        def forced_out(name):

            return _pdoc.get("%s.%s" % (self.name, name), False) is None

        def exported(name):

            if _is_exported(name) and not forced_out(name):

                return name

        idents = dict(inspect.getmembers(self.cls))

        return dict([(n, o) for n, o in idents.items() if exported(n)])

class Function(Doc):

    """

    Representation of documentation for a Python function or method.

    """

    def __init__(self, name, module, func_obj, cls=None, method=False):

        """

        Same as `pdoc.Doc.__init__`, except `func_obj` must be a

        Python function object. The docstring is gathered automatically.

        `cls` should be set when this is a method or a static function

        beloing to a class. `cls` should be a `pdoc.Class` object.

        `method` should be `True` when the function is a method. In

        all other cases, it should be `False`.

        """

        super().__init__(name, module, inspect.getdoc(func_obj))

        self.func = func_obj

        """The Python function object."""

        self.cls = cls

        """

        The `pdoc.Class` documentation object if this is a method. If

        not, this is None.

        """

        self.method = method

        """

        Whether this function is a method or not.

        In particular, static class methods have this set to False.

        """

    @property

    def source(self):

        return _source(self.func)

    @property

    def refname(self):

        if self.cls is None:

            return "%s.%s" % (self.module.refname, self.name)

        else:

            return "%s.%s" % (self.cls.refname, self.name)

    def funcdef(self):

        """

        Generates the string of keywords used to define the function, for

        example `def` or `async def`.

        """

        keywords = []

        if self._is_async():

            keywords.append("async")

        keywords.append("def")

        return " ".join(keywords)

    def _is_async(self):

        """

        Returns whether is function is asynchronous, either as a coroutine or an

        async generator.

        """

        try:

            # Both of these are required because coroutines aren't classified as

            # async generators and vice versa.

            return inspect.iscoroutinefunction(self.func) or inspect.isasyncgenfunction(self.func)

        except AttributeError:

            return False

    def spec(self):

        """

        Returns a nicely formatted spec of the function's parameter

        list as a string. This includes argument lists, keyword

        arguments and default values.

        """

        return ", ".join(self.params())

    @staticmethod

    def _signature(function):

        try:

            return inspect.signature(function)

        except (TypeError, ValueError):  # We can't get a Python signature (likely C function)

            return False

    def return_annotation(self):

        """Returns back return type annotation if a valid one is found"""

        signature = self._signature(self.func)

        if not signature or signature.return_annotation == inspect._empty:

            return ""

        return inspect.formatannotation(signature.return_annotation)

    def params(self):

        """

        Returns a list where each element is a nicely formatted

        parameter of this function. This includes argument lists,

        keyword arguments and default values.

        """

        return self._params(self.func)

    @classmethod

    def _params(cls, function):

        """

        Returns a list where each element is a nicely formatted

        parameter of this function. This includes argument lists,

        keyword arguments and default values.

        """

        signature = cls._signature(function)

        if not signature:

            return ["..."]

        # The following is taken almost verbatim from the Python stdlib

        # https://github.com/python/cpython/blob/3.6/Lib/inspect.py#L3017

        #

        # This is done simply because it is hard to unstringify the result since commas could

        # be present beyond just between parameters.

        params = []

        render_pos_only_separator = False

        render_kw_only_separator = True

        for param in signature.parameters.values():

            kind = param.kind

            if kind == inspect._POSITIONAL_ONLY:

                render_pos_only_separator = True

            elif render_pos_only_separator:

                params.append('/')

                render_pos_only_separator = False

            if kind == inspect._VAR_POSITIONAL:

                render_kw_only_separator = False

            elif kind == inspect._KEYWORD_ONLY and render_kw_only_separator:

                params.append('*')

                render_kw_only_separator = False

            params.append(str(param))

        if render_pos_only_separator:

            params.append('/')

        return params

    def __lt__(self, other):

        # Push __init__ to the top.

        if "__init__" in (self.name, other.name):

            return self.name != other.name and self.name == "__init__"

        else:

            return self.name < other.name

class Variable(Doc):

    """

    Representation of a variable's documentation. This includes

    module, class and instance variables.

    """

    def __init__(self, name, module, docstring, cls=None):

        """

        Same as `pdoc.Doc.__init__`, except `cls` should be provided

        as a `pdoc.Class` object when this is a class or instance

        variable.

        """

        super().__init__(name, module, docstring)

        self.cls = cls

        """

        The `podc.Class` object if this is a class or instance

        variable. If not, this is None.

        """

    @property

    def source(self):

        return []

    @property

    def refname(self):

        if self.cls is None:

            return "%s.%s" % (self.module.refname, self.name)

        else:

            return "%s.%s" % (self.cls.refname, self.name)

class External(Doc):

    """

    A representation of an external identifier. The textual

    representation is the same as an internal identifier, but without

    any context. (Usually this makes linking more difficult.)

    External identifiers are also used to represent something that is

    not exported but appears somewhere in the public interface (like

    the ancestor list of a class).

    """

    __pdoc__[

        "External.docstring"

    ] = """

        An empty string. External identifiers do not have

        docstrings.

        """

    __pdoc__[

        "External.module"

    ] = """

        Always `None`. External identifiers have no associated

        `pdoc.Module`.

        """

    __pdoc__[

        "External.name"

    ] = """

        Always equivalent to `pdoc.External.refname` since external

        identifiers are always expressed in their fully qualified

        form.

        """

    def __init__(self, name):

        """

        Initializes an external identifier with `name`, where `name`

        should be a fully qualified name.

        """

        super().__init__(name, None, "")

    @property

    def source(self):

        return []

    @property

    def refname(self):

        return self.name

Classes

Class
class (
    name,
    module,
    class_obj
)

Representation of a class's documentation.

View Source
class Class(Doc):

    """

    Representation of a class's documentation.

    """

    def __init__(self, name, module, class_obj):

        """

        Same as `pdocs.Doc.__init__`, except `class_obj` must be a

        Python class object. The docstring is gathered automatically.

        """

        super().__init__(name, module, inspect.getdoc(class_obj))

        self.cls = class_obj

        """The class Python object."""

        self.doc = {}

        """A mapping from identifier name to a `pdoc.Doc` objects."""

        self.doc_init = {}

        """

        A special version of `pdoc.Class.doc` that contains

        documentation for instance variables found in the `__init__`

        method.

        """

        public = self.__public_objs()

        try:

            # First try and find docstrings for class variables.

            # Then move on to finding docstrings for instance variables.

            # This must be optional, since not all modules have source

            # code available.

            cls_ast = ast.parse(inspect.getsource(self.cls)).body[0]

            self.doc = _var_docstrings(cls_ast, self.module, cls=self)

            for n in cls_ast.body if "__init__" in public else []:

                if isinstance(n, ast.FunctionDef) and n.name == "__init__":

                    self.doc_init = _var_docstrings(n, self.module, cls=self, init=True)

                    break

        except BaseException:

            pass

        # Convert the public Python objects to documentation objects.

        for name, obj in public.items():

            # Skip any identifiers that already have doco.

            if name in self.doc and not self.doc[name].is_empty():

                continue

            if name in self.doc_init:

                # Let instance members override class members.

                continue

            if inspect.isroutine(obj):

                self.doc[name] = Function(

                    name, self.module, obj, cls=self, method=_is_method(self.cls, name)

                )

            elif isinstance(obj, property):

                docstring = getattr(obj, "__doc__", "")

                self.doc_init[name] = Variable(name, self.module, docstring, cls=self)

            elif not inspect.isbuiltin(obj) and not inspect.isroutine(obj):

                if name in getattr(self.cls, "__slots__", []):

                    self.doc_init[name] = Variable(name, self.module, "", cls=self)

                else:

                    self.doc[name] = Variable(name, self.module, "", cls=self)

    @property

    def source(self):

        return _source(self.cls)

    @property

    def refname(self):

        return "%s.%s" % (self.module.refname, self.cls.__name__)

    def class_variables(self):

        """

        Returns all documented class variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)

    def instance_variables(self):

        """

        Returns all instance variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`. Instance variables

        are attributes of `self` defined in a class's `__init__`

        method.

        """

        return _filter(self.doc_init.values(), Variable)

    def methods(self):

        """

        Returns all documented methods as `pdoc.Function` objects in

        the class, sorted alphabetically.

        Unfortunately, this also includes class methods.

        """

        return _filter(self.doc.values(), Function, attributes_set=("method",))

    def functions(self):

        """

        Returns all documented static functions as `pdoc.Function`

        objects in the class, sorted alphabetically.

        """

        return _filter(self.doc.values(), Function, attributes_not_set=("method",))

    def params(self):

        """Returns back the parameters for the classes __init__ method"""

        params = Function._params(self.cls.__init__)

        return params[1:] if params[0] == "self" else params

    def _fill_inheritance(self):

        """

        Traverses this class's ancestor list and attempts to fill in

        missing documentation from its ancestor's documentation.

        The first pass connects variables, methods and functions with

        their inherited couterparts. (The templates will decide how to

        display docstrings.) The second pass attempts to add instance

        variables to this class that were only explicitly declared in

        a parent class. This second pass is necessary since instance

        variables are only discoverable by traversing the abstract

        syntax tree.

        """

        mro = [c for c in self.module.mro(self) if c != self and isinstance(c, Class)]

        def search(d, fdoc):

            for c in mro:

                doc = fdoc(c)

                if d.name in doc and isinstance(d, type(doc[d.name])):

                    return doc[d.name]

            return None

        for fdoc in (lambda c: c.doc_init, lambda c: c.doc):

            for d in fdoc(self).values():

                dinherit = search(d, fdoc)

                if dinherit is not None:

                    d.inherits = dinherit

        # Since instance variables aren't part of a class's members,

        # we need to manually deduce inheritance. Oh lawdy.

        for c in mro:

            for name in filter(lambda n: n not in self.doc_init, c.doc_init):

                d = c.doc_init[name]

                self.doc_init[name] = Variable(d.name, d.module, "", cls=self)

                self.doc_init[name].inherits = d

    def mro(self):

        """Returns back the Method Resolution Order (MRO) for this class"""

        return [

            self.module.find_class(cls)

            for cls in inspect.getmro(self.cls)

            if cls not in (self.cls, object, self)

        ]

    def subclasses(self):

        """Returns back all subclasses of this class"""

        return [self.module.find_class(cls) for cls in type.__subclasses__(self.cls)]

    def __public_objs(self):

        """

        Returns a dictionary mapping a public identifier name to a

        Python object. This counts the `__init__` method as being

        public.

        """

        _pdoc = getattr(self.module.module, "__pdoc__", {})

        def forced_out(name):

            return _pdoc.get("%s.%s" % (self.name, name), False) is None

        def exported(name):

            if _is_exported(name) and not forced_out(name):

                return name

        idents = dict(inspect.getmembers(self.cls))

        return dict([(n, o) for n, o in idents.items() if exported(n)])

Ancestors (in MRO)

  • pdocs.doc.Doc

Instance variables

refname
source

Methods

class_variables
def (
    self
)

Returns all documented class variables in the class, sorted alphabetically as a list of pdoc.Variable.

View Source
    def class_variables(self):

        """

        Returns all documented class variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)
functions
def (
    self
)

Returns all documented static functions as pdoc.Function objects in the class, sorted alphabetically.

View Source
    def functions(self):

        """

        Returns all documented static functions as `pdoc.Function`

        objects in the class, sorted alphabetically.

        """

        return _filter(self.doc.values(), Function, attributes_not_set=("method",))
instance_variables
def (
    self
)

Returns all instance variables in the class, sorted alphabetically as a list of pdoc.Variable. Instance variables are attributes of self defined in a class's __init__ method.

View Source
    def instance_variables(self):

        """

        Returns all instance variables in the class, sorted

        alphabetically as a list of `pdoc.Variable`. Instance variables

        are attributes of `self` defined in a class's `__init__`

        method.

        """

        return _filter(self.doc_init.values(), Variable)
is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0
methods
def (
    self
)

Returns all documented methods as pdoc.Function objects in the class, sorted alphabetically.

Unfortunately, this also includes class methods.

View Source
    def methods(self):

        """

        Returns all documented methods as `pdoc.Function` objects in

        the class, sorted alphabetically.

        Unfortunately, this also includes class methods.

        """

        return _filter(self.doc.values(), Function, attributes_set=("method",))
mro
def (
    self
)

Returns back the Method Resolution Order (MRO) for this class

View Source
    def mro(self):

        """Returns back the Method Resolution Order (MRO) for this class"""

        return [

            self.module.find_class(cls)

            for cls in inspect.getmro(self.cls)

            if cls not in (self.cls, object, self)

        ]
params
def (
    self
)

Returns back the parameters for the classes init method

View Source
    def params(self):

        """Returns back the parameters for the classes __init__ method"""

        params = Function._params(self.cls.__init__)

        return params[1:] if params[0] == "self" else params
subclasses
def (
    self
)

Returns back all subclasses of this class

View Source
    def subclasses(self):

        """Returns back all subclasses of this class"""

        return [self.module.find_class(cls) for cls in type.__subclasses__(self.cls)]
Doc
class (
    name,
    module,
    docstring
)

A base class for all documentation objects.

A documentation object corresponds to something in a Python module that has a docstring associated with it. Typically, this only includes modules, classes, functions and methods. However, pdoc adds support for extracting docstrings from the abstract syntax tree, which means that variables (module, class or instance) are supported too.

A special type of documentation object pdoc.External is used to represent identifiers that are not part of the public interface of a module. (The name "External" is a bit of a misnomer, since it can also correspond to unexported members of the module, particularly in a class's ancestor list.)

View Source
class Doc(object):

    """

    A base class for all documentation objects.

    A documentation object corresponds to *something* in a Python module

    that has a docstring associated with it. Typically, this only includes

    modules, classes, functions and methods. However, `pdoc` adds support

    for extracting docstrings from the abstract syntax tree, which means

    that variables (module, class or instance) are supported too.

    A special type of documentation object `pdoc.External` is used to

    represent identifiers that are not part of the public interface of

    a module. (The name "External" is a bit of a misnomer, since it can

    also correspond to unexported members of the module, particularly in

    a class's ancestor list.)

    """

    def __init__(self, name, module, docstring):

        """

        Initializes a documentation object, where `name` is the public

        identifier name, `module` is a `pdoc.Module` object, and

        `docstring` is a string containing the docstring for `name`.

        """

        self.module = module

        """

        The module documentation object that this object was defined

        in.

        """

        self.name = name

        """

        The identifier name for this object.

        """

        self.docstring = inspect.cleandoc(docstring or "")

        """

        The docstring for this object. It has already been cleaned

        by `inspect.cleandoc`.

        """

    @property

    def source(self):

        """

        Returns the source code of the Python object `obj` as a list of

        lines. This tries to extract the source from the special

        `__wrapped__` attribute if it exists. Otherwise, it falls back

        to `inspect.getsourcelines`.

        If neither works, then the empty list is returned.

        """

        raise NotImplementedError("source() method should be implemented by sub casses")

    @property

    def refname(self):

        """

        Returns an appropriate reference name for this documentation

        object. Usually this is its fully qualified path. Every

        documentation object must provide this property.

        e.g., The refname for this property is

        <code>pdoc.Doc.refname</code>.

        """

        raise NotImplementedError("refname() method should be implemented by sub casses")

    def __lt__(self, other):

        return self.name < other.name

    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0

Descendants

  • pdocs.doc.Module
  • pdocs.doc.Class
  • pdocs.doc.Function
  • pdocs.doc.Variable
  • pdocs.doc.External

Instance variables

refname

Returns an appropriate reference name for this documentation object. Usually this is its fully qualified path. Every documentation object must provide this property.

e.g., The refname for this property is pdoc.Doc.refname.

source

Returns the source code of the Python object obj as a list of lines. This tries to extract the source from the special __wrapped__ attribute if it exists. Otherwise, it falls back to inspect.getsourcelines.

If neither works, then the empty list is returned.

Methods

is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0
External
class (
    name
)

A representation of an external identifier. The textual representation is the same as an internal identifier, but without any context. (Usually this makes linking more difficult.)

External identifiers are also used to represent something that is not exported but appears somewhere in the public interface (like the ancestor list of a class).

View Source
class External(Doc):

    """

    A representation of an external identifier. The textual

    representation is the same as an internal identifier, but without

    any context. (Usually this makes linking more difficult.)

    External identifiers are also used to represent something that is

    not exported but appears somewhere in the public interface (like

    the ancestor list of a class).

    """

    __pdoc__[

        "External.docstring"

    ] = """

        An empty string. External identifiers do not have

        docstrings.

        """

    __pdoc__[

        "External.module"

    ] = """

        Always `None`. External identifiers have no associated

        `pdoc.Module`.

        """

    __pdoc__[

        "External.name"

    ] = """

        Always equivalent to `pdoc.External.refname` since external

        identifiers are always expressed in their fully qualified

        form.

        """

    def __init__(self, name):

        """

        Initializes an external identifier with `name`, where `name`

        should be a fully qualified name.

        """

        super().__init__(name, None, "")

    @property

    def source(self):

        return []

    @property

    def refname(self):

        return self.name

Ancestors (in MRO)

  • pdocs.doc.Doc

Instance variables

refname
source

Methods

is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0
Function
class (
    name,
    module,
    func_obj,
    cls=None,
    method=False
)

Representation of documentation for a Python function or method.

View Source
class Function(Doc):

    """

    Representation of documentation for a Python function or method.

    """

    def __init__(self, name, module, func_obj, cls=None, method=False):

        """

        Same as `pdoc.Doc.__init__`, except `func_obj` must be a

        Python function object. The docstring is gathered automatically.

        `cls` should be set when this is a method or a static function

        beloing to a class. `cls` should be a `pdoc.Class` object.

        `method` should be `True` when the function is a method. In

        all other cases, it should be `False`.

        """

        super().__init__(name, module, inspect.getdoc(func_obj))

        self.func = func_obj

        """The Python function object."""

        self.cls = cls

        """

        The `pdoc.Class` documentation object if this is a method. If

        not, this is None.

        """

        self.method = method

        """

        Whether this function is a method or not.

        In particular, static class methods have this set to False.

        """

    @property

    def source(self):

        return _source(self.func)

    @property

    def refname(self):

        if self.cls is None:

            return "%s.%s" % (self.module.refname, self.name)

        else:

            return "%s.%s" % (self.cls.refname, self.name)

    def funcdef(self):

        """

        Generates the string of keywords used to define the function, for

        example `def` or `async def`.

        """

        keywords = []

        if self._is_async():

            keywords.append("async")

        keywords.append("def")

        return " ".join(keywords)

    def _is_async(self):

        """

        Returns whether is function is asynchronous, either as a coroutine or an

        async generator.

        """

        try:

            # Both of these are required because coroutines aren't classified as

            # async generators and vice versa.

            return inspect.iscoroutinefunction(self.func) or inspect.isasyncgenfunction(self.func)

        except AttributeError:

            return False

    def spec(self):

        """

        Returns a nicely formatted spec of the function's parameter

        list as a string. This includes argument lists, keyword

        arguments and default values.

        """

        return ", ".join(self.params())

    @staticmethod

    def _signature(function):

        try:

            return inspect.signature(function)

        except (TypeError, ValueError):  # We can't get a Python signature (likely C function)

            return False

    def return_annotation(self):

        """Returns back return type annotation if a valid one is found"""

        signature = self._signature(self.func)

        if not signature or signature.return_annotation == inspect._empty:

            return ""

        return inspect.formatannotation(signature.return_annotation)

    def params(self):

        """

        Returns a list where each element is a nicely formatted

        parameter of this function. This includes argument lists,

        keyword arguments and default values.

        """

        return self._params(self.func)

    @classmethod

    def _params(cls, function):

        """

        Returns a list where each element is a nicely formatted

        parameter of this function. This includes argument lists,

        keyword arguments and default values.

        """

        signature = cls._signature(function)

        if not signature:

            return ["..."]

        # The following is taken almost verbatim from the Python stdlib

        # https://github.com/python/cpython/blob/3.6/Lib/inspect.py#L3017

        #

        # This is done simply because it is hard to unstringify the result since commas could

        # be present beyond just between parameters.

        params = []

        render_pos_only_separator = False

        render_kw_only_separator = True

        for param in signature.parameters.values():

            kind = param.kind

            if kind == inspect._POSITIONAL_ONLY:

                render_pos_only_separator = True

            elif render_pos_only_separator:

                params.append('/')

                render_pos_only_separator = False

            if kind == inspect._VAR_POSITIONAL:

                render_kw_only_separator = False

            elif kind == inspect._KEYWORD_ONLY and render_kw_only_separator:

                params.append('*')

                render_kw_only_separator = False

            params.append(str(param))

        if render_pos_only_separator:

            params.append('/')

        return params

    def __lt__(self, other):

        # Push __init__ to the top.

        if "__init__" in (self.name, other.name):

            return self.name != other.name and self.name == "__init__"

        else:

            return self.name < other.name

Ancestors (in MRO)

  • pdocs.doc.Doc

Instance variables

refname
source

Methods

funcdef
def (
    self
)

Generates the string of keywords used to define the function, for example def or async def.

View Source
    def funcdef(self):

        """

        Generates the string of keywords used to define the function, for

        example `def` or `async def`.

        """

        keywords = []

        if self._is_async():

            keywords.append("async")

        keywords.append("def")

        return " ".join(keywords)
is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0
params
def (
    self
)

Returns a list where each element is a nicely formatted parameter of this function. This includes argument lists, keyword arguments and default values.

View Source
    def params(self):

        """

        Returns a list where each element is a nicely formatted

        parameter of this function. This includes argument lists,

        keyword arguments and default values.

        """

        return self._params(self.func)
return_annotation
def (
    self
)

Returns back return type annotation if a valid one is found

View Source
    def return_annotation(self):

        """Returns back return type annotation if a valid one is found"""

        signature = self._signature(self.func)

        if not signature or signature.return_annotation == inspect._empty:

            return ""

        return inspect.formatannotation(signature.return_annotation)
spec
def (
    self
)

Returns a nicely formatted spec of the function's parameter list as a string. This includes argument lists, keyword arguments and default values.

View Source
    def spec(self):

        """

        Returns a nicely formatted spec of the function's parameter

        list as a string. This includes argument lists, keyword

        arguments and default values.

        """

        return ", ".join(self.params())
Module
class (
    name,
    module,
    parent
)

Representation of a module's documentation.

View Source
class Module(Doc):

    """

    Representation of a module's documentation.

    """

    __pdoc__["Module.module"] = "The Python module object."

    __pdoc__[

        "Module.name"

    ] = """

        The name of this module with respect to the context in which

        it was imported. It is always an absolute import path.

        """

    def __init__(self, name, module, parent):

        """

        Creates a `Module` documentation object given the actual

        module Python object.

        """

        super().__init__(name, module, inspect.getdoc(module))

        self.parent = parent

        self.doc = {}

        """A mapping from identifier name to a documentation object."""

        self.refdoc = {}

        """

        The same as `pdoc.Module.doc`, but maps fully qualified

        identifier names to documentation objects.

        """

        self.submodules = []

        vardocs = {}

        try:

            tree = ast.parse(inspect.getsource(self.module))

            vardocs = _var_docstrings(tree, self, cls=None)

        except BaseException:

            pass

        self._declared_variables = vardocs.keys()

        public = self.__public_objs()

        for name, obj in public.items():

            # Skip any identifiers that already have doco.

            if name in self.doc and not self.doc[name].is_empty():

                continue

            # Functions and some weird builtins?, plus methods, classes,

            # modules and module level variables.

            if inspect.isroutine(obj):

                self.doc[name] = Function(name, self, obj)

            elif inspect.isclass(obj):

                self.doc[name] = Class(name, self, obj)

            elif name in vardocs:

                self.doc[name] = vardocs[name]

            else:

                # Catch all for variables.

                self.doc[name] = Variable(name, self, "", cls=None)

        # Now see if we can grab inheritance relationships between classes.

        for docobj in self.doc.values():

            if isinstance(docobj, Class):

                docobj._fill_inheritance()

        # Build the reference name dictionary.

        for _basename, docobj in self.doc.items():

            self.refdoc[docobj.refname] = docobj

            if isinstance(docobj, Class):

                for v in docobj.class_variables():

                    self.refdoc[v.refname] = v

                for v in docobj.instance_variables():

                    self.refdoc[v.refname] = v

                for f in docobj.methods():

                    self.refdoc[f.refname] = f

                for f in docobj.functions():

                    self.refdoc[f.refname] = f

        # Finally look for more docstrings in the __pdoc__ override.

        for name, docstring in getattr(self.module, "__pdoc__", {}).items():

            refname = "%s.%s" % (self.refname, name)

            if docstring is None:

                self.doc.pop(name, None)

                self.refdoc.pop(refname, None)

                continue

            dobj = self.find_ident(refname)

            if isinstance(dobj, External):

                continue

            dobj.docstring = inspect.cleandoc(docstring)

    @property

    def source(self):

        return _source(self.module)

    @property

    def refname(self):

        return self.name

    @property

    def is_namespace(self):

        """Returns `True` if this module represents a

           [namespace package](https://packaging.python.org/guides/packaging-namespace-packages/).

        """

        return self.module.__spec__.origin in (None, "namespace")

    def mro(self, cls):

        """

        Returns a method resolution list of ancestor documentation objects

        for `cls`, which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        return [self.find_class(c) for c in inspect.getmro(cls.cls) if c not in (cls.cls, object)]

    def descendents(self, cls):

        """

        Returns a descendent list of documentation objects for `cls`,

        which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        if cls.cls == type or not hasattr(cls.cls, "__subclasses__"):

            # Is this right?

            return []

        downs = cls.cls.__subclasses__()

        return list(map(lambda c: self.find_class(c), downs))

    def is_public(self, name):

        """

        Returns `True` if and only if an identifier with name `name` is

        part of the public interface of this module. While the names

        of sub-modules are included, identifiers only exported by

        sub-modules are not checked.

        `name` should be a fully qualified name, e.g.,

        <code>pdoc.Module.is_public</code>.

        """

        return name in self.refdoc

    def find_class(self, cls):

        """

        Given a Python `cls` object, try to find it in this module

        or in any of the exported identifiers of the submodules.

        """

        for doc_cls in self.classes():

            if cls is doc_cls.cls:

                return doc_cls

        for module in self.submodules:

            doc_cls = module.find_class(cls)

            if not isinstance(doc_cls, External):

                return doc_cls

        return External("%s.%s" % (cls.__module__, cls.__name__))

    def find_ident(self, name, _seen=None):

        """

        Searches this module and **all** of its sub/super-modules for an

        identifier with name `name` in its list of exported

        identifiers according to `pdoc`. Note that unexported

        sub-modules are searched.

        A bare identifier (without `.` separators) will only be checked

        for in this module.

        The documentation object corresponding to the identifier is

        returned. If one cannot be found, then an instance of

        `External` is returned populated with the given identifier.

        """

        _seen = _seen or set()

        if self in _seen:

            return None

        _seen.add(self)

        if name == self.refname:

            return self

        if name in self.refdoc:

            return self.refdoc[name]

        for module in self.submodules:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

        # Traverse also up-level super-modules

        module = self.parent

        while module is not None:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

            module = module.parent

        return External(name)

    def variables(self):

        """

        Returns all documented module level variables in the module

        sorted alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)

    def classes(self):

        """

        Returns all documented module level classes in the module

        sorted alphabetically as a list of `pdoc.Class`.

        """

        return _filter(self.doc.values(), Class)

    def functions(self):

        """

        Returns all documented module level functions in the module

        sorted alphabetically as a list of `pdoc.Function`.

        """

        return _filter(self.doc.values(), Function)

    def __is_exported(self, name, module):

        """

        Returns `True` if and only if `pdoc` considers `name` to be

        a public identifier for this module where `name` was defined

        in the Python module `module`.

        If this module has an `__all__` attribute, then `name` is

        considered to be exported if and only if it is a member of

        this module's `__all__` list.

        If `__all__` is not set, then whether `name` is exported or

        not is heuristically determined. Firstly, if `name` starts

        with an underscore, it will not be considered exported.

        Secondly, if `name` was defined in a module other than this

        one, it will not be considered exported. In all other cases,

        `name` will be considered exported.

        """

        if hasattr(self.module, "__all__"):

            return name in self.module.__all__

        if not _is_exported(name):

            return False

        if module is not None and self.module.__name__ != module.__name__:

            return name in self._declared_variables

        return True

    def __public_objs(self):

        """

        Returns a dictionary mapping a public identifier name to a

        Python object.

        """

        members = dict(inspect.getmembers(self.module))

        return dict(

            [

                (name, obj)

                for name, obj in members.items()

                if self.__is_exported(name, inspect.getmodule(obj))

            ]

        )

    def allmodules(self):

        yield self

        for i in self.submodules:

            yield from i.allmodules()

    def toroot(self):

        n = self

        while n:

            yield n

            n = n.parent

Ancestors (in MRO)

  • pdocs.doc.Doc

Instance variables

is_namespace

Returns True if this module represents a namespace package.

refname
source

Methods

allmodules
def (
    self
)
View Source
    def allmodules(self):

        yield self

        for i in self.submodules:

            yield from i.allmodules()
classes
def (
    self
)

Returns all documented module level classes in the module sorted alphabetically as a list of pdoc.Class.

View Source
    def classes(self):

        """

        Returns all documented module level classes in the module

        sorted alphabetically as a list of `pdoc.Class`.

        """

        return _filter(self.doc.values(), Class)
descendents
def (
    self,
    cls
)

Returns a descendent list of documentation objects for cls, which must be a documentation object.

The list will contain objects belonging to pdoc.Class or pdoc.External. Objects belonging to the former are exported classes either in this module or in one of its sub-modules.

View Source
    def descendents(self, cls):

        """

        Returns a descendent list of documentation objects for `cls`,

        which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        if cls.cls == type or not hasattr(cls.cls, "__subclasses__"):

            # Is this right?

            return []

        downs = cls.cls.__subclasses__()

        return list(map(lambda c: self.find_class(c), downs))
find_class
def (
    self,
    cls
)

Given a Python cls object, try to find it in this module or in any of the exported identifiers of the submodules.

View Source
    def find_class(self, cls):

        """

        Given a Python `cls` object, try to find it in this module

        or in any of the exported identifiers of the submodules.

        """

        for doc_cls in self.classes():

            if cls is doc_cls.cls:

                return doc_cls

        for module in self.submodules:

            doc_cls = module.find_class(cls)

            if not isinstance(doc_cls, External):

                return doc_cls

        return External("%s.%s" % (cls.__module__, cls.__name__))
find_ident
def (
    self,
    name,
    _seen=None
)

Searches this module and all of its sub/super-modules for an identifier with name name in its list of exported identifiers according to pdoc. Note that unexported sub-modules are searched.

A bare identifier (without . separators) will only be checked for in this module.

The documentation object corresponding to the identifier is returned. If one cannot be found, then an instance of External is returned populated with the given identifier.

View Source
    def find_ident(self, name, _seen=None):

        """

        Searches this module and **all** of its sub/super-modules for an

        identifier with name `name` in its list of exported

        identifiers according to `pdoc`. Note that unexported

        sub-modules are searched.

        A bare identifier (without `.` separators) will only be checked

        for in this module.

        The documentation object corresponding to the identifier is

        returned. If one cannot be found, then an instance of

        `External` is returned populated with the given identifier.

        """

        _seen = _seen or set()

        if self in _seen:

            return None

        _seen.add(self)

        if name == self.refname:

            return self

        if name in self.refdoc:

            return self.refdoc[name]

        for module in self.submodules:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

        # Traverse also up-level super-modules

        module = self.parent

        while module is not None:

            o = module.find_ident(name, _seen=_seen)

            if not isinstance(o, (External, type(None))):

                return o

            module = module.parent

        return External(name)
functions
def (
    self
)

Returns all documented module level functions in the module sorted alphabetically as a list of pdoc.Function.

View Source
    def functions(self):

        """

        Returns all documented module level functions in the module

        sorted alphabetically as a list of `pdoc.Function`.

        """

        return _filter(self.doc.values(), Function)
is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0
is_public
def (
    self,
    name
)

Returns True if and only if an identifier with name name is part of the public interface of this module. While the names of sub-modules are included, identifiers only exported by sub-modules are not checked.

name should be a fully qualified name, e.g., pdoc.Module.is_public.

View Source
    def is_public(self, name):

        """

        Returns `True` if and only if an identifier with name `name` is

        part of the public interface of this module. While the names

        of sub-modules are included, identifiers only exported by

        sub-modules are not checked.

        `name` should be a fully qualified name, e.g.,

        <code>pdoc.Module.is_public</code>.

        """

        return name in self.refdoc
mro
def (
    self,
    cls
)

Returns a method resolution list of ancestor documentation objects for cls, which must be a documentation object.

The list will contain objects belonging to pdoc.Class or pdoc.External. Objects belonging to the former are exported classes either in this module or in one of its sub-modules.

View Source
    def mro(self, cls):

        """

        Returns a method resolution list of ancestor documentation objects

        for `cls`, which must be a documentation object.

        The list will contain objects belonging to `pdoc.Class` or

        `pdoc.External`. Objects belonging to the former are exported

        classes either in this module or in one of its sub-modules.

        """

        return [self.find_class(c) for c in inspect.getmro(cls.cls) if c not in (cls.cls, object)]
toroot
def (
    self
)
View Source
    def toroot(self):

        n = self

        while n:

            yield n

            n = n.parent
variables
def (
    self
)

Returns all documented module level variables in the module sorted alphabetically as a list of pdoc.Variable.

View Source
    def variables(self):

        """

        Returns all documented module level variables in the module

        sorted alphabetically as a list of `pdoc.Variable`.

        """

        return _filter(self.doc.values(), Variable)
Variable
class (
    name,
    module,
    docstring,
    cls=None
)

Representation of a variable's documentation. This includes module, class and instance variables.

View Source
class Variable(Doc):

    """

    Representation of a variable's documentation. This includes

    module, class and instance variables.

    """

    def __init__(self, name, module, docstring, cls=None):

        """

        Same as `pdoc.Doc.__init__`, except `cls` should be provided

        as a `pdoc.Class` object when this is a class or instance

        variable.

        """

        super().__init__(name, module, docstring)

        self.cls = cls

        """

        The `podc.Class` object if this is a class or instance

        variable. If not, this is None.

        """

    @property

    def source(self):

        return []

    @property

    def refname(self):

        if self.cls is None:

            return "%s.%s" % (self.module.refname, self.name)

        else:

            return "%s.%s" % (self.cls.refname, self.name)

Ancestors (in MRO)

  • pdocs.doc.Doc

Instance variables

refname
source

Methods

is_empty
def (
    self
)

Returns true if the docstring for this object is empty.

View Source
    def is_empty(self):

        """

        Returns true if the docstring for this object is empty.

        """

        return len(self.docstring.strip()) == 0