Beispiel #1
0
def reportErrors(obj: model.Documentable, errs: Sequence[ParseError]) -> None:
    if errs and obj.fullName() not in obj.system.docstring_syntax_errors:
        obj.system.docstring_syntax_errors.add(obj.fullName())
        for err in errs:
            obj.report('bad docstring: ' + err.descr(),
                       lineno_offset=(err.linenum() or 1) - 1,
                       section='docstring')
Beispiel #2
0
def extract_fields(obj: model.Documentable) -> None:
    """Populate Attributes for module/class variables using fields from
    that module/class's docstring.
    Must only be called for objects that have a docstring.
    """

    doc = obj.docstring
    assert doc is not None, obj
    pdoc = parse_docstring(obj, doc, obj)
    obj.parsed_docstring = pdoc

    for field in pdoc.fields:
        tag = field.tag()
        if tag in ['ivar', 'cvar', 'var', 'type']:
            arg = field.arg()
            if arg is None:
                obj.report("Missing field name in @%s" % (tag, ), 'docstring',
                           field.lineno)
                continue
            attrobj: Optional[model.Documentable] = obj.contents.get(arg)
            if attrobj is None:
                attrobj = obj.system.Attribute(obj.system, arg, obj)
                attrobj.kind = None
                attrobj.parentMod = obj.parentMod
                obj.system.addObject(attrobj)
            attrobj.setLineNumber(obj.docstring_lineno + field.lineno)
            if tag == 'type':
                attrobj.parsed_type = field.body()
            else:
                attrobj.parsed_docstring = field.body()
                attrobj.kind = field_name_to_human_name[tag]
Beispiel #3
0
def taglink(o: model.Documentable, label: Optional[str] = None) -> Tag:
    if not o.isVisible:
        o.system.msg("html", "don't link to %s" % o.fullName())
    if label is None:
        label = o.fullName()
    # Create a link to the object, with a "data-type" attribute which says what
    # kind of object it is (class, etc). This helps doc2dash figure out what it
    # is.
    ret: Tag = tags.a(href=o.url, class_="code", **{"data-type":
                                                    o.kind})(label)
    return ret
Beispiel #4
0
 def push(self, obj: model.Documentable, lineno: int) -> None:
     self._stack.append(self.current)
     self.current = obj
     if isinstance(obj, model.Module):
         assert self.currentMod is None
         obj.parentMod = self.currentMod = obj
     elif self.currentMod is not None:
         if obj.parentMod is not None:
             assert obj.parentMod is self.currentMod
         else:
             obj.parentMod = self.currentMod
     else:
         assert obj.parentMod is None
     if lineno:
         obj.setLineNumber(lineno)
Beispiel #5
0
 def privacyClass(self, documentable: Documentable) -> PrivacyClass:
     """Report the privacy level for an object. Hide the module
     'docstring_parser.tests'.
     """
     if documentable.fullName().startswith("docstring_parser.tests"):
         return PrivacyClass.HIDDEN
     return super().privacyClass(documentable)
Beispiel #6
0
def taglink(o: model.Documentable,
            page_url: str,
            label: Optional[str] = None) -> Tag:
    if not o.isVisible:
        o.system.msg("html", "don't link to %s" % o.fullName())

    if label is None:
        label = o.fullName()

    url = o.url
    if url.startswith(page_url + '#'):
        # When linking to an item on the same page, omit the path.
        # Besides shortening the HTML, this also avoids the page being reloaded
        # if the query string is non-empty.
        url = url[len(page_url):]

    ret: Tag = tags.a(label, href=url)
    return ret
Beispiel #7
0
def node2fullname(expr: Optional[ast.expr],
                  ctx: model.Documentable) -> Optional[str]:
    dottedname = node2dottedname(expr)
    if dottedname is None:
        return None
    base = ctx.expandName(dottedname[0])
    if base:
        return '.'.join([base] + dottedname[1:])
    else:
        return None
Beispiel #8
0
def get_docstring(
    obj: model.Documentable
) -> Tuple[Optional[str], Optional[model.Documentable]]:
    for source in obj.docsources():
        doc = source.docstring
        if doc:
            return doc, source
        if doc is not None:
            # Treat empty docstring as undocumented.
            return None, source
    return None, None
Beispiel #9
0
def objects_order(o: model.Documentable) -> Tuple[int, int, str]:
    """
    Function to use as the value of standard library's L{sorted} function C{key} argument
    such that the objects are sorted by: Privacy, Kind and Name.

    Example::

        children = sorted((o for o in ob.contents.values() if o.isVisible),
                      key=objects_order)
    """
    return (-o.privacyClass.value, -o.kind.value if o.kind else 0,
            o.fullName().lower())
Beispiel #10
0
    def _generateLine(self, obj: Documentable) -> str:
        """
        Return inventory line for object.

        name domain_name:type priority URL display_name

        Domain name is always: py
        Priority is always: -1
        Display name is always: -
        """
        # Avoid circular import.
        from pydoctor import model

        full_name = obj.fullName()

        if obj.documentation_location is model.DocLocation.OWN_PAGE:
            url = obj.fullName() + '.html'
        else:
            url = obj.parent.fullName() + '.html#' + obj.name

        display = '-'
        if isinstance(obj, (model.Package, model.Module)):
            domainname = 'module'
        elif isinstance(obj, model.Class):
            domainname = 'class'
        elif isinstance(obj, model.Function):
            if obj.kind == 'Function':
                domainname = 'function'
            else:
                domainname = 'method'
        elif isinstance(obj, model.Attribute):
            domainname = 'attribute'
        else:
            domainname = 'obj'
            self.error('sphinx', "Unknown type %r for %s." % (
                type(obj),
                full_name,
            ))

        return f'{full_name} py:{domainname} -1 {url} {display}\n'
Beispiel #11
0
def format_docstring(obj: model.Documentable) -> Tag:
    """Generate an HTML representation of a docstring"""

    doc, source = get_docstring(obj)

    # Use cached or split version if possible.
    pdoc = obj.parsed_docstring

    if source is None:
        if pdoc is None:
            # We don't use 'source' if pdoc is None, but mypy is not that
            # sophisticated, so we fool it by assigning a dummy object.
            source = obj
        else:
            # A split field is documented by its parent.
            source = obj.parent
            assert source is not None

    if pdoc is None and doc is not None:
        pdoc = parse_docstring(obj, doc, source)
        obj.parsed_docstring = pdoc

    ret: Tag = tags.div
    if pdoc is None:
        ret(tags.p(class_='undocumented')("Undocumented"))
    else:
        try:
            stan = pdoc.to_stan(_EpydocLinker(source))
        except Exception as e:
            errs = [ParseError(f'{e.__class__.__name__}: {e}', 1)]
            if doc is None:
                stan = tags.p(class_="undocumented")('Broken description')
            else:
                pdoc_plain = pydoctor.epydoc.markup.plaintext.parse_docstring(
                    doc, errs)
                stan = pdoc_plain.to_stan(_EpydocLinker(source))
            reportErrors(source, errs)
        if stan.tagName:
            ret(stan)
        else:
            ret(*stan.children)

    fh = FieldHandler(obj)
    if isinstance(obj, model.Function):
        fh.set_param_types_from_annotations(obj.annotations)
    if pdoc is not None:
        for field in pdoc.fields:
            fh.handle(Field.from_epydoc(field, source))
    if isinstance(obj, model.Function):
        fh.resolve_types()
    ret(fh.format())
    return ret
Beispiel #12
0
def _lckey(x: model.Documentable) -> Tuple[str, str]:
    return (x.fullName().lower(), x.fullName())
Beispiel #13
0
 def fullName(obj: model.Documentable) -> str:
     return obj.fullName()
Beispiel #14
0
def hasdocstring(ob: model.Documentable) -> bool:
    for source in ob.docsources():
        if source.docstring is not None:
            return True
    return False
Beispiel #15
0
def node2fullname(expr: Optional[ast.expr],
                  ctx: model.Documentable) -> Optional[str]:
    dottedname = node2dottedname(expr)
    if dottedname is None:
        return None
    return ctx.expandName('.'.join(dottedname))