Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2514)

Unified Diff: Lib/pydoc.py

Issue 10716: Modernize pydoc to use CSS
Patch Set: Created 2 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | Lib/pydoc_data/_pydoc.css » ('j') | Lib/pydoc_data/_pydoc.css » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Lib/pydoc.py
===================================================================
--- Lib/pydoc.py (revision 87586)
+++ Lib/pydoc.py (working copy)
@@ -2471,234 +2471,299 @@
def page(self, title, contents):
"""Format an HTML page."""
- css_path = "pydoc_data/_pydoc.css"
- css_link = (
- '<link rel="stylesheet" type="text/css" href="%s">' %
- css_path)
- return '''\
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Python: %s</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-%s</head><body bgcolor="#f0f0f8">%s
-</body></html>''' % (title, css_link, contents)
+ values = dict(title=title,
+ css_path="pydoc_data/_pydoc.css",
+ header=html_header(),
+ content=contents,
+ )
+ template = \
+'''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>PyDoc: {title}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="{css_path}">
+ </head>
+ <body>
+ <div id=page>
+ {header}
+ {content}
+ </div>
+ </body>
+</html>
+'''
+ return template.format(**values)
def filelink(self, url, path):
return '<a href="getfile?key=%s">%s</a>' % (url, path)
- html = _HTMLDoc()
+ def _index_section(self, title, items, css_class):
+ """Make an index sub-section"""
+ items = '</li>\n<li>'.join(items)
+ values = dict(title = title,
+ items = items,
ezio.melotti 2011/03/11 23:13:43 The spaces around the = can go.
+ css_class=css_class,
+ )
ezio.melotti 2011/03/11 23:13:43 The ) should be closed on the previous line.
eric.araujo 2011/03/11 23:35:54 That’s done on purpose by Ron so that any future a
ezio.melotti 2011/03/12 14:35:09 I don't think having one more line is a big deal.
+ template = (' <dt>{title}</dt>'
+ ' <dd>'
+ ' <ul class="{css_class}">'
+ ' <li>{items}</li>'
+ ' </ul>'
+ ' </dd>'
ezio.melotti 2011/03/11 23:13:43 It's better to add a \n at the end of the line or
+ )
ezio.melotti 2011/03/11 23:13:43 The ) should be closed on the previous line.
+ return template.format(**values)
- def html_navbar():
- version = "%s [%s, %s]" % (platform.python_version(),
- platform.python_build()[0],
- platform.python_compiler())
- return """
- <div style='float:left'>
- Python %s<br>%s<br><br>
- </div>
- <div style='float:right'>
- <div style='text-align:center'>
- <a href="index.html">Module Index</a>
- : <a href="topics.html">Topics</a>
- : <a href="keywords.html">Keywords</a>
- </div>
- <div>
- <form action="get" style='float:left'>
- <input type=text name=key size=15>
- <input type=submit value="Get">
- &nbsp;&nbsp;&nbsp;
- </form>
- <form action="search" style='float:right'>
- <input type=text name=key size=15>
- <input type=submit value="Search">
- </form>
- </div>
- </div>
- <div clear='all'>&nbsp;</div>
- """ % (version, platform.platform(terse=True))
+ def index_columns(self, title, items, css_class):
+ """Create a index section with columns."""
+ section = html._index_section(title, items,
+ css_class="index-columns")
ezio.melotti 2011/03/11 23:13:43 css_class should be indented under title.
+ template = ('<dl class="{css_class}">'
+ ' {section}'
+ '</dl>'
+ )
ezio.melotti 2011/03/11 23:13:43 See previous comments about \n and the ).
+ return template.format(css_class=css_class, section=section)
- def html_index():
- """Module Index page."""
+ 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 = ('<dl class="{css_class}">'
+ ' {section}'
+ '</dl>'
+ )
+ return template.format(css_class=css_class, section=section)
ezio.melotti 2011/03/11 23:13:43 See previous comments. Also this function is very
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
+ html = _HTMLDoc()
- heading = html.heading(
- '<big><big><strong>Index of Modules</strong></big></big>',
- '#ffffff', '#7799ee')
- names = [name for name in sys.builtin_module_names
- if name != '__main__']
- contents = html.multicolumn(names, bltinlink)
- contents = [heading, '<p>' + html.bigsection(
- 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
+ def html_header():
+ values = dict(version=platform.python_version(),
+ build=platform.python_build()[0],
+ compiler=platform.python_compiler(),
+ platform=platform.platform(terse=True),
+ )
+ template = \
+"""
+<div id="page-header">
+ <h1 id="page-title">PyDoc</h1>
+ <p id="python_version">
+ Python {version} - [{build}, {compiler}, {platform}]
ezio.melotti 2011/03/11 23:13:43 </p>
+ <ul id="navbar">
+ <li><form action="get"><div>
+ <input name="key" size="15" type="text">
+ <input value="Get" type="submit">
+ </div></form></li>
+ <li><form action="search"><div>
+ <input name="key" size="15" type="text">
+ <input value="Search" type="submit">
+ </div></form></li>
+ <li>
+ <a href="index.html">modules</a>
+ <a href="keywords.html">keywords</a>
+ <a href="topics.html">topics</a>
+ </li>
+ </ul>
+</div> <!-- end header -->
+"""
+ return template.format(**values)
- seen = {}
+ def html_modules():
+ """Module Index page."""
+ link_list = ['<a href="%s.html">%s</a>' % (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:
- contents.append(html.index(dir, seen))
+ 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 = ('<span class="package"><a href="{name}.html">'
+ '{name}</a> (package)</span>')
+ else:
+ template = ('<a class="module" href="{name}.html">'
+ '{name}</a>')
ezio.melotti 2011/03/11 23:13:43 I don't like too much the fact that the packages h
eric.araujo 2011/03/11 23:35:54 Why don’t you like it?
ezio.melotti 2011/03/12 14:35:09 Because it's not symmetric, if I want to parse the
+ link = template.format(name=name)
+ links.append(link)
+ contents.append(html.index_columns(dir,
+ links, css_class='section modules'))
+ content =''.join(contents)
ezio.melotti 2011/03/11 23:13:43 Missing space after the =.
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">Index of Modules</h2>'
+ ' {content}'
+ '</div>'
+ '<div id="page-footer">'
+ ' <p>PyDoc by Ka-Ping Yee&lt;ping@lfw.org&gt;'
+ '</div>'
+ )
ezio.melotti 2011/03/11 23:13:43 \n and ). There are also other occurrences later.
+ return 'Index of Modules', template.format(content=content)
- contents.append(
- '<p align=right><font color="#909090" face="helvetica,'
- 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
- '&lt;ping@lfw.org&gt;</font>')
- return 'Index of Modules', ''.join(contents)
-
def html_search(key):
"""Search results page."""
# scan for modules
search_result = []
-
def callback(path, modname, desc):
if modname[-9:] == '.__init__':
modname = modname[:-9] + ' (package)'
- search_result.append((modname, desc and '- ' + desc))
-
+ search_result.append((modname, desc and ' - ' + desc))
with warnings.catch_warnings():
warnings.filterwarnings('ignore') # ignore problems during import
ModuleScanner().run(callback, key)
+ link_list = ['<a href="%s.html">%s</a>%s' % (name, name, desc)
+ for name, desc in search_result]
+ content = html.index_lines('key = %s' % key, link_list,
+ css_class='section modules')
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">Search Results</h2>'
+ ' {content}'
+ '</div>'
+ )
+ return 'Search Results', template.format(content=content)
- # format page
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
-
- results = []
- heading = html.heading(
- '<big><big><strong>Search Results</strong></big></big>',
- '#ffffff', '#7799ee')
- for name, desc in search_result:
- results.append(bltinlink(name) + desc)
- contents = heading + html.bigsection(
- 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
- return 'Search Results', contents
-
def html_getfile(path):
"""Get and display a source file listing safely."""
- path = path.replace('%20', ' ')
with open(path, 'r') as fp:
lines = html.escape(fp.read())
- body = '<pre>%s</pre>' % lines
- heading = html.heading(
- '<big><big><strong>File Listing</strong></big></big>',
- '#ffffff', '#7799ee')
- contents = heading + html.bigsection(
- 'File: %s' % path, '#ffffff', '#ee77aa', body)
- return 'getfile %s' % path, contents
+ title = 'getfile %s' % path.replace('%20', ' ')
ezio.melotti 2011/03/11 23:13:43 urllib.unquote()?
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">File Listing</h2>'
+ ' <dl class="section file">'
+ ' <dt>File: {path}</dt>'
+ ' <dd><pre class="python-code"><code'
+ ' >{lines}</code></pre>'
+ ' </dd>'
+ ' </dl>'
+ '</div>'
+ )
+ return title, template.format(path=path, lines=lines)
def html_topics():
"""Index of topic texts available."""
+ link_list = ['<a href="%s.html">%s</a>' % (name, name)
+ for name in sorted(Helper.topics.keys())]
+ content = html.index_columns('Topics', link_list,
+ css_class="section topics")
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">Index</h2>'
+ ' {content}'
+ '</div>'
+ )
+ return 'Topics', template.format(content=content)
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
-
- heading = html.heading(
- '<big><big><strong>INDEX</strong></big></big>',
- '#ffffff', '#7799ee')
- names = sorted(Helper.topics.keys())
-
- contents = html.multicolumn(names, bltinlink)
- contents = heading + html.bigsection(
- 'Topics', '#ffffff', '#ee77aa', contents)
- return 'Topics', contents
-
def html_keywords():
"""Index of keywords."""
- heading = html.heading(
- '<big><big><strong>INDEX</strong></big></big>',
- '#ffffff', '#7799ee')
- names = sorted(Helper.keywords.keys())
+ link_list = ['<a href="%s.html">%s</a>' % (name, name)
+ for name in sorted(Helper.keywords.keys())]
+ content = html.index_columns('Keywords', link_list,
+ css_class="section topics")
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">Index</h2>'
+ ' {content}'
+ '</div>'
+ )
+ return 'Keywords', template.format(content=content)
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
- contents = html.multicolumn(names, bltinlink)
- contents = heading + html.bigsection(
- 'Keywords', '#ffffff', '#ee77aa', contents)
- return 'Keywords', contents
-
def html_topicpage(topic):
"""Topic or keyword help page."""
buf = io.StringIO()
htmlhelp = Helper(buf, buf)
contents, xrefs = htmlhelp._gettopic(topic)
if topic in htmlhelp.keywords:
- title = 'KEYWORD'
+ title = 'Keyword'
else:
- title = 'TOPIC'
- heading = html.heading(
- '<big><big><strong>%s</strong></big></big>' % title,
- '#ffffff', '#7799ee')
- contents = '<pre>%s</pre>' % contents
- contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
- xrefs = sorted(xrefs.split())
+ title = 'Topic'
+ text = html.markup(contents)
+ link_list = ['<a href="%s.html">%s</a>' % (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,
+ )
ezio.melotti 2011/03/11 23:13:43 I use either: values = dict(foo=bar,
eric.araujo 2011/03/11 23:35:54 I don’t see why you said that: The code uses the s
ezio.melotti 2011/03/12 14:35:09 In the second style the ) is closed under the 'v'
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">{title}</h2>'
+ ' <dl class="section topic">'
+ ' <dt>{topic}</dt>'
+ ' <dd><pre class="topic-info">{text}</pre></dd>'
+ ' </dl>'
+ ' {xrefs}'
+ '</div>'
+ )
+ return '%s %s' % (title, topic), template.format(**values)
- def bltinlink(name):
- return '<a href="%s.html">%s</a>' % (name, name)
+ def html_error(exc, url):
+ values = dict(
+ title = url,
+ exc = repr(exc),
+ err = str(exc),
ezio.melotti 2011/03/11 23:13:43 You can remove the spaces around the =, if you wan
eric.araujo 2011/03/11 23:35:54 This contradicts a previous comment you made :) E
ezio.melotti 2011/03/12 14:35:09 I don't use spaces myself, but it's ok for me if s
+ )
+ template = ('<div id="page-content">'
+ ' <h2 id="subject">Error</h2>'
+ ' <dl class="section error">'
+ ' <dt>{title}</dt>'
+ ' <dd>'
+ ' <p>{exc}'
+ ' <p>{err}'
ezio.melotti 2011/03/11 23:13:43 It's always better to close the </p>, even if it's
eric.araujo 2011/03/11 23:35:54 I agree, it’s more readable to close elements.
+ ' </dd>'
+ ' </dl>'
+ '</div>'
+ )
+ return "Error - " + url, template.format(**values)
- xrefs = html.multicolumn(xrefs, bltinlink)
- xrefs = html.section('Related help topics: ',
- '#ffffff', '#ee77aa', xrefs)
- return ('%s %s' % (title, topic),
- ''.join((heading, contents, xrefs)))
-
- def html_error(url):
- heading = html.heading(
- '<big><big><strong>Error</strong></big></big>',
- '#ffffff', '#ee0000')
- return heading + url
-
def get_html_page(url):
"""Generate an HTML page for url."""
- if url.endswith('.html'):
- url = url[:-5]
- if url.startswith('/'):
- url = url[1:]
- if url.startswith("get?key="):
- url = url[8:]
- title = url
- contents = ''
- if url in ("", ".", "index"):
- title, contents = html_index()
- elif url == "topics":
- title, contents = html_topics()
- elif url == "keywords":
- title, contents = html_keywords()
- elif url.startswith("search?key="):
- title, contents = html_search(url[11:])
- elif url.startswith("getfile?key="):
- url = url[12:]
- try:
- title, contents = html_getfile(url)
- except IOError:
- contents = html_error('could not read file %r' % url)
- title = 'Read Error'
- else:
- obj = None
- try:
+ try:
+ 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 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:
obj = locate(url, forceload=1)
- except ErrorDuringImport as value:
- contents = html.escape(str(value))
- if obj:
+ if obj is None and url != "None":
+ raise ValueError('could not find "%s"' % url)
title = describe(obj)
- contents = html.document(obj, url)
- elif url in Helper.keywords or url in Helper.topics:
- title, contents = html_topicpage(url)
- else:
- contents = html_error(
- 'no Python documentation found for %r' % url)
- title = 'Error'
- return html.page(title, html_navbar() + contents)
+ content = ('<div id="page-content">%s</div>' %
+ html.document(obj, url))
+ except Exception as exc:
+ title, content = html_error(exc, url)
+ return html.page(title, content)
if url.startswith('/'):
url = url[1:]
if content_type == 'text/css':
path_here = os.path.dirname(os.path.realpath(__file__))
- try:
- with open(os.path.join(path_here, url)) as fp:
- return ''.join(fp.readlines())
- except IOError:
- return 'Error: can not open css file %r' % url
+ with open(os.path.join(path_here, url)) as fp:
+ return ''.join(fp.readlines())
elif content_type == 'text/html':
return get_html_page(url)
- return 'Error: unknown content type %r' % content_type
+ raise ValueError('unknown content type: (%r, %r)' % (content_type, url))
def browse(port=0, *, open_browser=True):
@@ -2720,6 +2785,8 @@
print('Server ready at', serverthread.url)
print(server_help_msg)
while serverthread.serving:
+ if serverthread.error:
+ print(serverthread.error)
cmd = input('server> ')
cmd = cmd.lower()
if cmd == 'q':
« no previous file with comments | « no previous file | Lib/pydoc_data/_pydoc.css » ('j') | Lib/pydoc_data/_pydoc.css » ('J')

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7