formatter_html.py

#

Generate HTML documentation

[[Page

[[Document

]] ]]

Formatter class for HTML documentation.

import logging
import os
import re
import sys
import sysconfig
from typing import Any, Callable, Dict, Sequence, Tuple, Union

from pydoc_fork import inline_styles
from pydoc_fork.utils import resolve
from pydoc_fork.all_found import MENTIONED_MODULES
from pydoc_fork.html_repr_class import HTMLRepr
from pydoc_fork.jinja_code import JINJA_ENV
from pydoc_fork.string_utils import replace

LOGGER = logging.getLogger(__name__)
STDLIB_BASEDIR = sysconfig.get_path("stdlib")

DOCUMENT_INTERNALS = False
OUTPUT_FOLDER = ""

PYTHONDOCS = os.environ.get(
    "PYTHONDOCS", "https://docs.python.org/%d.%d/library" % sys.version_info[:2]
)
#
#

monkey patching was messing with mypy– is this now a redeclare? Turn method into function

def html_repr(value: Any) -> str:  # noqa - unhiding could break code?
#
    _repr_instance = HTMLRepr()
    return _repr_instance.repr(value)
#

HTML safe repr and escape

def escape(value: Any) -> str:
#
    _repr_instance = HTMLRepr()
    result = _repr_instance.escape(value)
    if ">" in result:
        print("possible double escape")
    return result
#

Format a page heading.

def heading(title: str, fgcol: str, bgcol: str, extras: str = "") -> str:
#
    template = JINJA_ENV.get_template("heading.jinja2")
    return template.render(title=title, fgcol=fgcol, bgcol=bgcol, extras=extras)


#     return f"""
#
 
 
{title}
{extras or ' '}
# """
#

Format a section with a heading.

def section(
    title: str,
    fgcol: str,
    bgcol: str,
    contents: str,
    width: int = 6,  # used by marginalia?
    prelude: str = "",
    marginalia: str = "",  # not used
    gap: str = " ",  # not used
) -> str:
#
    if marginalia is None:
        marginalia = "<tt>" + "&nbsp;" * width + "</tt>"
    template = JINJA_ENV.get_template("section.jinja2")
    return template.render(
        title=title,
        fgcol=fgcol,
        bgcol=bgcol,
        marginalia=marginalia,
        prelude=prelude,
        contents=contents,
        gap=gap,
    )
#

This is only used by docclass

#
if marginalia is None:
    marginalia = "<tt>" + "&nbsp;" * width + "</tt>"
result = f"""<p>
# """
#
if prelude:
    result = (
        result
#             + f"""
#
# <tr><td>{gap}</td>"""
#
    )
else:
    result = (
        result
#             + f"""
# <tr><td bgcolor="{bgcol}">{marginalia}</td><td>{gap}</td>"""
#
    )

return result + f'\n<td width="100%%">{contents}</td></tr></table>'
#
def bigsection(
    title: str,
    fgcol: str,
    bgcol: str,
    contents: str,
    width: int = 6,  # used by marginalia?
    prelude: str = "",
    marginalia: str = "",  # not used
    gap: str = "&nbsp;",  # not used
) -> str:
    """Format a section with a big heading."""
    title = f"<big><strong>{title}</strong></big>"
#

prefer explicit interfaces over secret hidden ones

    return section(title, fgcol, bgcol, contents, width, prelude, marginalia, gap)
#

Format literal preformatted text.

def preformat(text: str) -> str:
#
    text = escape(text.expandtabs())
    return replace(
        text, "\n\n", "\n \n", "\n\n", "\n \n", " ", "&nbsp;", "\n", "<br>\n"
    )
#

Format a list of items into a multi-column list.

def multicolumn(
    the_list: Union[Sequence[Tuple[Any, str, Any, int]], Sequence[Tuple[str, Any]]],
    the_format: Callable[[Any], str],
    cols: int = 4,
) -> str:
#
    result = ""
    rows = (len(the_list) + cols - 1) // cols
    for col in range(cols):
        result = result + '<td width="%d%%" valign=top>' % (100 // cols)
        for i in range(rows * col, rows * col + rows):
            if i < len(the_list):
                result = result + the_format(the_list[i]) + "<br>\n"
        result = result + "</td>"
    return f'<table width="100%%" summary="list"><tr>{result}</tr></table>'
#

Wrap in grey

def disabled_text(text: str) -> str:
#
    return f'<span style="color:{inline_styles.DISABLED_TEXT}">{text}</span>'
#

Make a link for an identifier, given name-to-URL mappings.

def namelink(name: str, *dicts: Dict[str, str]) -> str:
#
    for the_dict in dicts:
        if name in the_dict:
            return f'<a href="{the_dict[name]}">{name}</a>'
#

LOGGER.warning(f”Failed to find link for {name}”)

    return name
#

Make a link for a module or package to display in an index.

def modpkglink(modpkginfo: Tuple[str, str, str, str]) -> str:
#
    name, path, ispackage, shadowed = modpkginfo
    MENTIONED_MODULES.add((resolve(path + "." + name)[0], name))
    if shadowed:
        return disabled_text(name)
    if path:
        url = f"{path}.{name}.html"
    else:
        url = f"{name}.html"
    if ispackage:
        text = f"<strong>{name}</strong>&nbsp;(package)"
    else:
        text = name
    return f'<a href="{url}">{text}</a>'
#

Make a link to source file.

def filelink(url: str, path: str) -> str:
#
    return f'<a href="file:{url}">{path}</a>'
#

Mark up some plain text, given a context of symbols to look for.

def markup(
    text: str,
    funcs: Dict[str, str] = {},  # noqa - clean up later
    classes: Dict[str, str] = {},  # noqa - clean up later
    methods: Dict[str, str] = {},  # noqa - clean up later
) -> str:
#
    Each context dictionary maps object names to anchor names."""

    results = []
    here = 0
    pattern = re.compile(
        r"\b((http|https|ftp)://\S+[\w/]|"
        r"RFC[- ]?(\d+)|"
        r"PEP[- ]?(\d+)|"
        r"(self\.)?(\w+))"
    )
    while True:
        match = pattern.search(text, here)
        if not match:
            break
        start, end = match.span()
        results.append(preformat(text[here:start]))

        the_all, scheme, rfc, pep, selfdot, name = match.groups()
        if scheme:
            url = preformat(the_all).replace('"', "&quot;")
            results.append(f'<a href="{url}">{url}</a>')
        elif rfc:
            url = "http://www.rfc-editor.org/rfc/rfc%d.txt" % int(rfc)
            results.append(f'<a href="{url}">{preformat(the_all)}</a>')
        elif pep:
            url = "https://www.python.org/dev/peps/pep-%04d/" % int(pep)
            results.append(f'<a href="{url}">{preformat(the_all)}</a>')
        elif selfdot:
#DIVIDER
            if text[end : end + 1] == "(":
                results.append("self." + namelink(name, methods))
            else:
                results.append(f"self.<strong>{name}</strong>")
        elif text[end : end + 1] == "(":
            results.append(namelink(name, methods, funcs, classes))
        else:
#DIVIDER
            results.append(namelink(name, classes))
        here = end
    results.append(preformat(text[here:]))
    return "".join(results)
#DIVIDER
#     """Format an argument default value as text."""
#DIVIDER

#

Create a link for methods like ‘self.method(…)’ and use for attributes like ‘self.attr’

#

This assumes everything else is a class!!

#

dead code def formatvalue(the_object: Any) -> str:

#
return grey("=" + html_repr(the_object))
 
{title}
{marginalia} {prelude}