diff --git a/Lib/pydoc.py b/Lib/pydoc.py index daa7205bd7..98d0ba0a3f 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -473,13 +473,31 @@ class HTMLDoc(Doc): def page(self, title, contents): """Format an HTML page.""" - return '''\ - -Python: %s - - -%s -''' % (title, contents) + + values = dict(title=title, + css_path="pydoc_data/_pydoc.css", + header=html_header(), + content=contents, + ) + template = \ +''' + + + PyDoc: {title} + + + + + +
+ {header} + {content} +
+ + +''' + return template.format(**values) def heading(self, title, fgcol, bgcol, extras=''): """Format a page heading.""" @@ -2344,66 +2362,148 @@ def _url_handler(url, content_type="text/html"): Pydoc: %s + %s%s
%s
''' % (title, css_link, html_navbar(), contents) def filelink(self, url, path): return '%s' % (url, path) + def _index_section(self, title, items, css_class): + """Make an index sub-section""" + items = '\n
  • '.join(items) + values = dict(title = title, + items = items, + css_class=css_class, + ) + template = ('
    {title}
    ' + '
    ' + ' ' + '
    ' + ) + return template.format(**values) + + def index_columns(self, title, items, css_class): + """Create a index section with columns.""" + section = html._index_section(title, items, + css_class="index-columns") + template = ('
    ' + ' {section}' + '
    ' + ) + return template.format(css_class=css_class, section=section) + + def index_lines(self, title, items, css_class): + """Create an index section with line.""" + section = html._index_section(title, items, + css_class="index-lines") + template = ('
    ' + ' {section}' + '
    ' + ) + return template.format(css_class=css_class, section=section) html = _HTMLDoc() + def html_header(): + values = dict(version=platform.python_version(), + build=platform.python_build()[0], + compiler=platform.python_compiler(), + platform=platform.platform(terse=True), + ) + template = \ +""" + +""" + return template.format(**values) + + def html_modules(): + """Module Index page.""" + link_list = ['%s' % (name, name) + for name in sys.builtin_module_names + if name != '__main__'] + contents = [html.index_columns('Built-in modules', link_list, + css_class='section modules')] + shadowed = set() + for dir in sys.path: + modules = [] + for importer, name, ispkg in pkgutil.iter_modules([dir]): + if name not in shadowed: + modules.append((name, ispkg)) + shadowed.add(name) + modules.sort() + links = [] + for name, ispkg in modules: + if ispkg: + template = ('' + '{name} (package)') + else: + template = ('' + '{name}') + link = template.format(name=name) + links.append(link) + contents.append(html.index_columns(dir, + links, css_class='section modules')) + content = ''.join(contents) + template = ('
    ' + '

    Index of Modules

    ' + ' {content}' + '
    ' + '' + ) + return 'Index of Modules', template.format(content=content) + def html_navbar(): - version = html.escape("%s [%s, %s]" % (platform.python_version(), - platform.python_build()[0], - platform.python_compiler())) + version = "%s [%s, %s]" % (platform.python_version(), + platform.python_build()[0], + platform.python_compiler()) return """
    - Python %s
    %s + Python %s
    %s

    -
    +
    Module Index : Topics : Keywords
    -
    + -
      -
    +     +
    +
    - """ % (version, html.escape(platform.platform(terse=True))) - - def html_index(): - """Module Index page.""" - - def bltinlink(name): - return '%s' % (name, name) - - heading = html.heading( - 'Index of Modules', - '#ffffff', '#7799ee') - names = [name for name in sys.builtin_module_names - if name != '__main__'] - contents = html.multicolumn(names, bltinlink) - contents = [heading, '

    ' + html.bigsection( - 'Built-in Modules', '#ffffff', '#ee77aa', contents)] - - seen = {} - for dir in sys.path: - contents.append(html.index(dir, seen)) - - contents.append( - '

    pydoc by Ka-Ping Yee' - '<ping@lfw.org>') - return 'Index of Modules', ''.join(contents) +

     
    + """ % (version, platform.platform(terse=True)) def html_search(key): """Search results page.""" @@ -2420,64 +2520,60 @@ def _url_handler(url, content_type="text/html"): def onerror(modname): pass ModuleScanner().run(callback, key, onerror=onerror) - - # format page - def bltinlink(name): - return '%s' % (name, name) - - results = [] - heading = html.heading( - 'Search Results', - '#ffffff', '#7799ee') - for name, desc in search_result: - results.append(bltinlink(name) + desc) - contents = heading + html.bigsection( - 'key = %s' % key, '#ffffff', '#ee77aa', '
    '.join(results)) - return 'Search Results', contents + link_list = ['%s%s' % (name, name, desc) + for name, desc in search_result] + content = html.index_lines('key = %s' % key, link_list, + css_class='section modules') + template = ('
    ' + '

    Search Results

    ' + ' {content}' + '
    ' + ) + return 'Search Results', template.format(content=content) def html_getfile(path): """Get and display a source file listing safely.""" path = urllib.parse.unquote(path) with tokenize.open(path) as fp: lines = html.escape(fp.read()) - body = '
    %s
    ' % lines - heading = html.heading( - 'File Listing', - '#ffffff', '#7799ee') - contents = heading + html.bigsection( - 'File: %s' % path, '#ffffff', '#ee77aa', body) - return 'getfile %s' % path, contents + title = 'getfile %s' % path.replace('%20', ' ') + template = ('
    ' + '

    File Listing

    ' + '
    ' + '
    File: {path}
    ' + '
    {lines}
    ' + '
    ' + '
    ' + '
    ' + ) + return title, template.format(path=path, lines=lines) def html_topics(): """Index of topic texts available.""" - - def bltinlink(name): - return '%s' % (name, name) - - heading = html.heading( - 'INDEX', - '#ffffff', '#7799ee') - names = sorted(Helper.topics.keys()) - - contents = html.multicolumn(names, bltinlink) - contents = heading + html.bigsection( - 'Topics', '#ffffff', '#ee77aa', contents) - return 'Topics', contents + link_list = ['%s' % (name, name) + for name in sorted(Helper.topics.keys())] + content = html.index_columns('Topics', link_list, + css_class="section topics") + template = ('
    ' + '

    Index

    ' + ' {content}' + '
    ' + ) + return 'Topics', template.format(content=content) def html_keywords(): """Index of keywords.""" - heading = html.heading( - 'INDEX', - '#ffffff', '#7799ee') - names = sorted(Helper.keywords.keys()) - - def bltinlink(name): - return '%s' % (name, name) - - contents = html.multicolumn(names, bltinlink) - contents = heading + html.bigsection( - 'Keywords', '#ffffff', '#ee77aa', contents) - return 'Keywords', contents + link_list = ['%s' % (name, name) + for name in sorted(Helper.keywords.keys())] + content = html.index_columns('Keywords', link_list, + css_class="section topics") + template = ('
    ' + '

    Index

    ' + ' {content}' + '
    ' + ) + return 'Keywords', template.format(content=content) def html_topicpage(topic): """Topic or keyword help page.""" @@ -2485,25 +2581,49 @@ def _url_handler(url, content_type="text/html"): htmlhelp = Helper(buf, buf) contents, xrefs = htmlhelp._gettopic(topic) if topic in htmlhelp.keywords: - title = 'KEYWORD' + title = 'Keyword' else: - title = 'TOPIC' - heading = html.heading( - '%s' % title, - '#ffffff', '#7799ee') - contents = '
    %s
    ' % html.markup(contents) - contents = html.bigsection(topic , '#ffffff','#ee77aa', contents) - if xrefs: - xrefs = sorted(xrefs.split()) - - def bltinlink(name): - return '%s' % (name, name) - - xrefs = html.multicolumn(xrefs, bltinlink) - xrefs = html.section('Related help topics: ', - '#ffffff', '#ee77aa', xrefs) - return ('%s %s' % (title, topic), - ''.join((heading, contents, xrefs))) + title = 'Topic' + text = html.markup(contents) + link_list = ['%s' % (name, name) + for name in sorted(xrefs.split())] + xrefs = html.index_columns('Related help Topics', link_list, + css_class="section topics") + values = dict( + title=title, + topic=topic, + text=text, + xrefs=xrefs, + ) + template = ('
    ' + '

    {title}

    ' + '
    ' + '
    {topic}
    ' + '
    {text}
    ' + '
    ' + ' {xrefs}' + '
    ' + ) + return '%s %s' % (title, topic), template.format(**values) + + def html_error(exc, url): + values = dict( + title = url, + exc = repr(exc), + err = str(exc), + ) + template = ('
    ' + '

    Error

    ' + '
    ' + '
    {title}
    ' + '
    ' + '

    {exc}' + '

    {err}' + '

    ' + '
    ' + '
    ' + ) + return "Error - " + url, template.format(**values) def html_getobj(url): obj = locate(url, forceload=1) @@ -2529,35 +2649,25 @@ def _url_handler(url, content_type="text/html"): if url.endswith('.html'): url = url[:-5] try: - if url in ("", "index"): - title, content = html_index() + if url.endswith('.html'): + url = url[:-5] + if url.startswith('/'): + url = url[1:] + if url.startswith("get?key="): + url = url[8:] + if url in ("", ".", "index"): + title, content = html_modules() elif url == "topics": title, content = html_topics() elif url == "keywords": title, content = html_keywords() - elif '=' in url: - op, _, url = url.partition('=') - if op == "search?key": - title, content = html_search(url) - elif op == "getfile?key": - title, content = html_getfile(url) - elif op == "topic?key": - # try topics first, then objects. - try: - title, content = html_topicpage(url) - except ValueError: - title, content = html_getobj(url) - elif op == "get?key": - # try objects first, then topics. - if url in ("", "index"): - title, content = html_index() - else: - try: - title, content = html_getobj(url) - except ValueError: - title, content = html_topicpage(url) - else: - raise ValueError('bad pydoc url') + elif url.startswith("search?key="): + title, content = html_search(url[11:]) + elif url.startswith("getfile?key="): + path = url[12:] + title, content = html_getfile(path) + elif url in Helper.keywords or url in Helper.topics: + title, content = html_topicpage(url) else: title, content = html_getobj(url) except Exception as exc: diff --git a/Lib/pydoc_data/_pydoc.css b/Lib/pydoc_data/_pydoc.css index f036ef37a5..b39cc3506e 100644 --- a/Lib/pydoc_data/_pydoc.css +++ b/Lib/pydoc_data/_pydoc.css @@ -4,3 +4,231 @@ Contents of this file are subject to change without notice. */ + +/* Setting underline on hover only is less busy. */ +a:link{text-decoration: none;} +a:visited{text-decoration: none;} +a:hover, a:active{text-decoration: underline;} + +body{ + margin: 0; + padding: 0; + width: 100%; + font-size: 100%; /* Improves scaling consistency. */ + color: #000000; + background-color: #f8f8f8; +} + + +/* Contains header, navbar, and content and sets page padding. */ +#page{padding: 1em;} + + +/* Contains title, version, and navigation bar. */ +#page-header{width: 100%;} + + +/* Title */ +#page-title{ + display: inline-block; + margin: 0; + padding: 0 2em 0 0; + color: #5599cc; + background-color: #f8f8f8; +} + +/* Version info */ +#python_version{ + display: inline-block; + margin: 0; + padding: 0; + font-style: italic; + color: #888888; + background-color: #f8f8f8; +} + +/* Navigation bar. */ +#navbar{ + margin: 0; + padding: .2em; + color: #000000; + background-color: #f0f0f4; + border: 1px solid #888888; + overflow: auto; +} +#navbar li{ + margin: 0; + padding: .25em .5em .25em .5em; + list-style: none; + display: inline-block; +} +#navbar form{ + margin: 0; + padding: 0; + display: inline-block; +} +#navbar a{padding-right: 1em;} + + +/* Contains main content. */ +#page-content{ + margin-top: 1em; + overflow: auto; +} + +/* Content title. */ +#subject{ + margin: 0; + padding: .25em; + color: #ffffff; + background-color: #5599cc; +} + + +/* A content section that has a title. + + Combine these with a section type to set the + title colors. + + Use:
    +
    + */ +dl.section dt{ + font-weight: bold; + padding: .75em; +} +dl.section dd{ + padding: 1em; + color: #000000; + background-color: #f8f8f8; +} + +/* A section with no left vertical bar. */ +dl.subsection dt{ + font-weight: bold; + padding: .25em .25em .25em .5em; +} +dl.subsection dd{ + margin-left: 0; + padding: 1ex; + color: #000000; + background-color: #f8f8f8; +} + +/* Set title colors for section and sub-section. */ +dl.modules{ + color: #ffffff; + background-color: #aa55cc; +} + +dl.module{} /* These are not used yet. */ + +dl.classes{} + +dl.class{} + +dl.methods{} + +dl.method{} + +dl.functions{} + +dl.function{} + +dl.data{} + +ul.data-item li{} + +dl.file{ + color: #ffffff; + background-color: #009900; +} + +dl.topics{ + color: #ffffff; + background-color: #5f99cc; +} + +dl.topic{ + color: #ffffff; + background-color: #009900; +} + +dl.error{ + color: #ffffff; + background-color: #cc4444; +} + + + +/* index */ +ul.index-lines{padding-left: 9ex;} +ul.index-lines li{ + text-indent: -8ex; + list-style: none; +} + + +/* index aligned in columns */ +ul.index-columns{ + margin: 0; + padding: 0; + list-style: none; + overflow: auto; /* Limit floats. */ +} +ul.index-columns li{ + margin: 0 1em .2em 0; + width: 15em; + float: left; +} + + +/* links to modules and packages */ +span.module {} + +span.package { + font-style: italic; + color: #555; + background-color: #f8f8f8; +} +span.package a{ + font-style: normal; + font-weight: bold; + font-size: 98%; /* Bold effects floats without this. */ +} + + +pre.docstring{ + margin: 0; + padding: .25em; +} + + +pre.topic-info{ + margin: 0; + padding: .25em; + color: #000000; + background-color: #ffffff; + border: 1px solid #aaaaaa; +} + + +pre.python-code{ + margin: 0; + padding: .25em; + color: #000000; + background-color: #ffffff; + border: 1px solid #aaaaaa; + overflow: auto; +} +pre.python-code code{ + color: #000000; + background-color: #f4f4ff; /* Shows white space. */ +} + + +#page-footer p{ + color: #888888; + background-color: #f8f8f8; + text-align: right; +}