mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Checkin my holiday work:
- Add "changes" builder to quickly get an overview over all "versionadded/changed/deprecated" directives for a certain version - Cross-reference keywords - Fix some problems in the webapp and the latex writer
This commit is contained in:
8
TODO
8
TODO
@@ -4,18 +4,18 @@ Global TODO
|
||||
Sphinx
|
||||
******
|
||||
|
||||
- section numbers
|
||||
- split the general index
|
||||
- HTML section numbers?
|
||||
- split the general index?
|
||||
- add OpenSearch
|
||||
- "seealso" links to external examples, see http://svn.python.org/projects/sandbox/trunk/seealso/ and http://effbot.org/zone/idea-seealso.htm
|
||||
- write a "printable" builder (export to latex, most probably)
|
||||
- "often used" combo box in sidebar
|
||||
- link to keywords
|
||||
- source file cross-references?
|
||||
|
||||
Web App
|
||||
*******
|
||||
|
||||
- fix /download
|
||||
|
||||
- discuss and debug comments system
|
||||
- prepare for databases other than sqlite for comments
|
||||
- add search via Xapian or Nucular (Python indexer - nucular.sf.net)
|
||||
|
||||
@@ -35,6 +35,7 @@ options: -b <builder> -- builder to use (one of %s)
|
||||
-D <setting=value> -- override a setting in sourcedir/conf.py
|
||||
-N -- do not do colored output
|
||||
-q -- no output on stdout, just warnings on stderr
|
||||
-P -- run Pdb on exception
|
||||
modi:
|
||||
* without -a and without filenames, write new and changed files.
|
||||
* with -a, write all files.
|
||||
@@ -43,7 +44,7 @@ modi:
|
||||
|
||||
def main(argv):
|
||||
try:
|
||||
opts, args = getopt.getopt(argv[1:], 'ab:d:O:D:NEq')
|
||||
opts, args = getopt.getopt(argv[1:], 'ab:d:O:D:NEqP')
|
||||
srcdirname = path.abspath(args[0])
|
||||
if not path.isdir(srcdirname):
|
||||
print >>sys.stderr, 'Error: Cannot find source directory.'
|
||||
@@ -69,7 +70,7 @@ def main(argv):
|
||||
return 1
|
||||
|
||||
builder = all_files = None
|
||||
opt_help = freshenv = False
|
||||
opt_help = freshenv = use_pdb = False
|
||||
status = sys.stdout
|
||||
options = {}
|
||||
confoverrides = {}
|
||||
@@ -111,6 +112,8 @@ def main(argv):
|
||||
freshenv = True
|
||||
elif opt == '-q':
|
||||
status = StringIO()
|
||||
elif opt == '-P':
|
||||
use_pdb = True
|
||||
|
||||
if not sys.stdout.isatty() or sys.platform == 'win32':
|
||||
# Windows' cmd box doesn't understand ANSI sequences
|
||||
@@ -128,17 +131,23 @@ def main(argv):
|
||||
print ' * %s: %s' % (optname, description)
|
||||
return 0
|
||||
|
||||
builderobj = builderobj(srcdirname, outdirname, doctreedir, options,
|
||||
status_stream=status,
|
||||
warning_stream=sys.stderr,
|
||||
confoverrides=confoverrides,
|
||||
freshenv=freshenv)
|
||||
if all_files:
|
||||
builderobj.build_all()
|
||||
elif filenames:
|
||||
builderobj.build_specific(filenames)
|
||||
else:
|
||||
builderobj.build_update()
|
||||
try:
|
||||
builderobj = builderobj(srcdirname, outdirname, doctreedir, options,
|
||||
status_stream=status,
|
||||
warning_stream=sys.stderr,
|
||||
confoverrides=confoverrides,
|
||||
freshenv=freshenv)
|
||||
if all_files:
|
||||
builderobj.build_all()
|
||||
elif filenames:
|
||||
builderobj.build_specific(filenames)
|
||||
else:
|
||||
builderobj.build_update()
|
||||
except:
|
||||
if not use_pdb:
|
||||
raise
|
||||
import pdb
|
||||
pdb.post_mortem(sys.exc_info()[2])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -19,6 +19,7 @@ import shutil
|
||||
import cPickle as pickle
|
||||
import cStringIO as StringIO
|
||||
from os import path
|
||||
from cgi import escape
|
||||
|
||||
from docutils.io import StringOutput, FileOutput, DocTreeInput
|
||||
from docutils.core import publish_parts
|
||||
@@ -33,7 +34,7 @@ from .patchlevel import get_version_info, get_sys_version_info
|
||||
from .htmlwriter import HTMLWriter
|
||||
from .latexwriter import LaTeXWriter
|
||||
from .environment import BuildEnvironment, NoUri
|
||||
from .highlighting import pygments, get_stylesheet
|
||||
from .highlighting import pygments, highlight_block, get_stylesheet
|
||||
from .util.console import bold, purple, green
|
||||
|
||||
from . import addnodes
|
||||
@@ -194,66 +195,74 @@ class Builder(object):
|
||||
def build_update(self):
|
||||
"""Only rebuild files changed or added since last build."""
|
||||
self.load_env()
|
||||
to_build = list(self.get_outdated_files())
|
||||
to_build = self.get_outdated_files()
|
||||
if not to_build:
|
||||
self.msg('no target files are out of date, exiting.')
|
||||
return
|
||||
self.build(to_build,
|
||||
summary='targets for %d source files that are '
|
||||
'out of date' % len(to_build))
|
||||
if isinstance(to_build, str):
|
||||
self.build([], to_build)
|
||||
else:
|
||||
to_build = list(to_build)
|
||||
self.build(to_build,
|
||||
summary='targets for %d source files that are '
|
||||
'out of date' % len(to_build))
|
||||
|
||||
def build(self, filenames, summary=None):
|
||||
if summary:
|
||||
self.msg('building [%s]:' % self.name, nonl=1)
|
||||
self.msg(summary, nobold=1)
|
||||
|
||||
updated_filenames = []
|
||||
# while reading, collect all warnings from docutils
|
||||
with collect_env_warnings(self):
|
||||
self.msg('reading, updating environment:', nonl=1)
|
||||
iterator = self.env.update(self.config)
|
||||
self.msg(iterator.next(), nobold=1)
|
||||
self.msg(iterator.next(), nonl=1, nobold=1)
|
||||
for filename in iterator:
|
||||
if not updated_filenames:
|
||||
self.msg('')
|
||||
updated_filenames.append(filename)
|
||||
self.msg(purple(filename), nonl=1, nobold=1)
|
||||
self.msg()
|
||||
|
||||
# save the environment
|
||||
self.msg('pickling the env...', nonl=True)
|
||||
self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
||||
self.msg('done', nobold=True)
|
||||
if updated_filenames:
|
||||
# save the environment
|
||||
self.msg('pickling the env...', nonl=True)
|
||||
self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
||||
self.msg('done', nobold=True)
|
||||
|
||||
# global actions
|
||||
self.msg('checking consistency...')
|
||||
self.env.check_consistency()
|
||||
# global actions
|
||||
self.msg('checking consistency...')
|
||||
self.env.check_consistency()
|
||||
|
||||
# another indirection to support methods which don't build files
|
||||
# individually
|
||||
self.write(filenames)
|
||||
self.write(filenames, updated_filenames)
|
||||
|
||||
# finish (write style files etc.)
|
||||
self.msg('finishing...')
|
||||
self.finish()
|
||||
self.msg('done!')
|
||||
|
||||
def write(self, filenames):
|
||||
def write(self, build_filenames, updated_filenames):
|
||||
if build_filenames is None: # build_all
|
||||
build_filenames = self.env.all_files
|
||||
filenames = set(build_filenames) | set(updated_filenames)
|
||||
|
||||
# add all toctree-containing files that may have changed
|
||||
for filename in list(filenames):
|
||||
for tocfilename in self.env.files_to_rebuild.get(filename, []):
|
||||
filenames.add(tocfilename)
|
||||
filenames.add('contents.rst')
|
||||
|
||||
self.msg('creating index...')
|
||||
self.env.create_index(self)
|
||||
if filenames:
|
||||
# add all TOC files that may have changed
|
||||
filenames_set = set(filenames)
|
||||
for filename in filenames:
|
||||
for tocfilename in self.env.files_to_rebuild.get(filename, []):
|
||||
filenames_set.add(tocfilename)
|
||||
filenames_set.add('contents.rst')
|
||||
else:
|
||||
# build all
|
||||
filenames_set = set(self.env.all_files)
|
||||
|
||||
self.prepare_writing(filenames_set)
|
||||
self.prepare_writing(filenames)
|
||||
|
||||
# write target files
|
||||
with collect_env_warnings(self):
|
||||
self.msg('writing output...')
|
||||
for filename in status_iterator(sorted(filenames_set), green,
|
||||
for filename in status_iterator(sorted(filenames), green,
|
||||
stream=self.status_stream):
|
||||
doctree = self.env.get_and_resolve_doctree(filename, self)
|
||||
self.write_file(filename, doctree)
|
||||
@@ -595,7 +604,8 @@ class WebHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
# if there is a source file, copy the source file for the "show source" link
|
||||
if context.get('sourcename'):
|
||||
source_name = path.join(self.outdir, 'sources', os_path(context['sourcename']))
|
||||
source_name = path.join(self.outdir, 'sources',
|
||||
os_path(context['sourcename']))
|
||||
ensuredir(path.dirname(source_name))
|
||||
shutil.copyfile(path.join(self.srcdir, os_path(filename)), source_name)
|
||||
|
||||
@@ -652,8 +662,7 @@ class LaTeXBuilder(Builder):
|
||||
self.filenames = []
|
||||
|
||||
def get_outdated_files(self):
|
||||
# XXX always rebuild everything for now
|
||||
return ['dummy']
|
||||
return 'all documents' # for now
|
||||
|
||||
def get_target_uri(self, source_filename, typ=None):
|
||||
if typ == 'token':
|
||||
@@ -677,9 +686,7 @@ class LaTeXBuilder(Builder):
|
||||
and not fn.endswith('index.rst')]:
|
||||
yield (howto, 'howto-'+howto[6:-4]+'.tex', 'howto')
|
||||
|
||||
def write(self, filenames):
|
||||
# "filenames" is ignored here...
|
||||
|
||||
def write(self, *ignored):
|
||||
# first, assemble the "special" docs that are in every PDF
|
||||
specials = []
|
||||
for fname in ["glossary", "about", "license", "copyright"]:
|
||||
@@ -695,8 +702,8 @@ class LaTeXBuilder(Builder):
|
||||
destination_path=path.join(self.outdir, targetname),
|
||||
encoding='utf-8')
|
||||
print "processing", targetname + "...",
|
||||
doctree = self.assemble_doctree(sourcename,
|
||||
specials=(docclass == 'manual') and specials or [])
|
||||
doctree = self.assemble_doctree(
|
||||
sourcename, specials=(docclass == 'manual') and specials or [])
|
||||
print "writing...",
|
||||
doctree.settings = docsettings
|
||||
doctree.settings.filename = sourcename
|
||||
@@ -743,9 +750,119 @@ class LaTeXBuilder(Builder):
|
||||
path.join(self.outdir, filename))
|
||||
|
||||
|
||||
class ChangesBuilder(Builder):
|
||||
"""
|
||||
Write a summary with all versionadded/changed directives.
|
||||
"""
|
||||
name = 'changes'
|
||||
|
||||
def init(self):
|
||||
from ._jinja import Environment, FileSystemLoader
|
||||
templates_path = path.join(path.dirname(__file__), 'templates')
|
||||
jinja_env = Environment(loader=FileSystemLoader(templates_path),
|
||||
# disable traceback, more likely that something in the
|
||||
# application is broken than in the templates
|
||||
friendly_traceback=False)
|
||||
self.ftemplate = jinja_env.get_template('versionchanges_frameset.html')
|
||||
self.vtemplate = jinja_env.get_template('versionchanges.html')
|
||||
self.stemplate = jinja_env.get_template('rstsource.html')
|
||||
|
||||
def get_outdated_files(self):
|
||||
return self.outdir
|
||||
|
||||
typemap = {
|
||||
'versionadded': 'added',
|
||||
'versionchanged': 'changed',
|
||||
'deprecated': 'deprecated',
|
||||
}
|
||||
|
||||
def write(self, *ignored):
|
||||
ver = self.config['version']
|
||||
libchanges = {}
|
||||
apichanges = []
|
||||
otherchanges = {}
|
||||
self.msg('writing summary file...')
|
||||
for type, filename, lineno, module, descname, content in \
|
||||
self.env.versionchanges[ver]:
|
||||
ttext = self.typemap[type]
|
||||
context = content.replace('\n', ' ')
|
||||
if descname and filename.startswith('c-api'):
|
||||
if not descname:
|
||||
continue
|
||||
if context:
|
||||
entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
|
||||
else:
|
||||
entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
|
||||
apichanges.append((entry, filename, lineno))
|
||||
elif descname or module:
|
||||
if not module:
|
||||
module = 'Builtins'
|
||||
if not descname:
|
||||
descname = 'Module level'
|
||||
if context:
|
||||
entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
|
||||
else:
|
||||
entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
|
||||
libchanges.setdefault(module, []).append((entry, filename, lineno))
|
||||
else:
|
||||
if not context:
|
||||
continue
|
||||
entry = '<i>%s:</i> %s' % (ttext.capitalize(), context)
|
||||
title = self.env.titles[filename].astext()
|
||||
otherchanges.setdefault((filename, title), []).append(
|
||||
(entry, filename, lineno))
|
||||
|
||||
ctx = {
|
||||
'version': ver,
|
||||
'libchanges': sorted(libchanges.iteritems()),
|
||||
'apichanges': sorted(apichanges),
|
||||
'otherchanges': sorted(otherchanges.iteritems()),
|
||||
}
|
||||
with open(path.join(self.outdir, 'index.html'), 'w') as f:
|
||||
f.write(self.ftemplate.render(ctx))
|
||||
with open(path.join(self.outdir, 'changes.html'), 'w') as f:
|
||||
f.write(self.vtemplate.render(ctx))
|
||||
|
||||
hltext = ['.. versionadded:: %s' % ver,
|
||||
'.. versionchanged:: %s' % ver,
|
||||
'.. deprecated:: %s' % ver]
|
||||
|
||||
def hl(no, line):
|
||||
line = '<a name="L%s"> </a>' % no + escape(line)
|
||||
for x in hltext:
|
||||
if x in line:
|
||||
line = '<span class="hl">%s</span>' % line
|
||||
break
|
||||
return line
|
||||
|
||||
self.msg('copying source files...')
|
||||
for filename in self.env.all_files:
|
||||
with open(path.join(self.srcdir, os_path(filename))) as f:
|
||||
lines = f.readlines()
|
||||
targetfn = path.join(self.outdir, 'rst', os_path(filename)) + '.html'
|
||||
ensuredir(path.dirname(targetfn))
|
||||
with codecs.open(targetfn, 'w', 'utf8') as f:
|
||||
text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
|
||||
ctx = {'filename': filename, 'text': text}
|
||||
f.write(self.stemplate.render(ctx))
|
||||
shutil.copyfile(path.join(path.dirname(__file__), 'style', 'default.css'),
|
||||
path.join(self.outdir, 'default.css'))
|
||||
|
||||
def hl(self, text, ver):
|
||||
text = escape(text)
|
||||
for directive in ['versionchanged', 'versionadded', 'deprecated']:
|
||||
text = text.replace('.. %s:: %s' % (directive, ver),
|
||||
'<b>.. %s:: %s</b>' % (directive, ver))
|
||||
return text
|
||||
|
||||
def finish(self):
|
||||
pass
|
||||
|
||||
|
||||
builders = {
|
||||
'html': StandaloneHTMLBuilder,
|
||||
'web': WebHTMLBuilder,
|
||||
'htmlhelp': HTMLHelpBuilder,
|
||||
'latex': LaTeXBuilder,
|
||||
'changes': ChangesBuilder,
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ def version_directive(name, arguments, options, content, lineno,
|
||||
else:
|
||||
ret = [node]
|
||||
env = state.document.settings.env
|
||||
env.note_versionchange(node['type'], node['version'], node)
|
||||
env.note_versionchange(node['type'], node['version'], node, lineno)
|
||||
return ret
|
||||
|
||||
version_directive.arguments = (1, 1, 1)
|
||||
|
||||
@@ -52,7 +52,7 @@ default_settings = {
|
||||
|
||||
# This is increased every time a new environment attribute is added
|
||||
# to properly invalidate pickle files.
|
||||
ENV_VERSION = 13
|
||||
ENV_VERSION = 14
|
||||
|
||||
|
||||
def walk_depth(node, depth, maxdepth):
|
||||
@@ -222,7 +222,7 @@ class BuildEnvironment:
|
||||
self.indexentries = {} # filename -> list of
|
||||
# (type, string, target, aliasname)
|
||||
self.versionchanges = {} # version -> list of
|
||||
# (type, filename, module, descname, content)
|
||||
# (type, filename, lineno, module, descname, content)
|
||||
|
||||
# These are set while parsing a file
|
||||
self.filename = None # current file name
|
||||
@@ -383,7 +383,8 @@ class BuildEnvironment:
|
||||
|
||||
if save_parsed:
|
||||
# save the parsed doctree
|
||||
doctree_filename = path.join(self.doctreedir, os_path(filename)[:-3] + 'doctree')
|
||||
doctree_filename = path.join(self.doctreedir,
|
||||
os_path(filename)[:-3] + 'doctree')
|
||||
dirname = path.dirname(doctree_filename)
|
||||
if not path.isdir(dirname):
|
||||
os.makedirs(dirname)
|
||||
@@ -528,9 +529,9 @@ class BuildEnvironment:
|
||||
self.indexentries.setdefault(self.filename, []).append(
|
||||
(type, string, targetid, aliasname))
|
||||
|
||||
def note_versionchange(self, type, version, node):
|
||||
def note_versionchange(self, type, version, node, lineno):
|
||||
self.versionchanges.setdefault(version, []).append(
|
||||
(type, self.filename, self.currmodule, self.currdesc, node.deepcopy()))
|
||||
(type, self.filename, lineno, self.currmodule, self.currdesc, node.astext()))
|
||||
# -------
|
||||
|
||||
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
|
||||
@@ -603,6 +604,8 @@ class BuildEnvironment:
|
||||
|
||||
try:
|
||||
if typ == 'ref':
|
||||
# reference to the named label; the final node will contain the
|
||||
# section name after the label
|
||||
filename, labelid, sectname = self.labels.get(target, ('','',''))
|
||||
if not filename:
|
||||
newnode = doctree.reporter.system_message(
|
||||
@@ -620,6 +623,20 @@ class BuildEnvironment:
|
||||
newnode['refuri'] = builder.get_relative_uri(
|
||||
docfilename, filename) + '#' + labelid
|
||||
newnode.append(innernode)
|
||||
elif typ == 'keyword':
|
||||
# keywords are referenced by named labels
|
||||
filename, labelid, _ = self.labels.get(target, ('','',''))
|
||||
if not filename:
|
||||
self._warnfunc('%s: unknown keyword: %s' % (docfilename, target))
|
||||
newnode = contnode
|
||||
else:
|
||||
newnode = nodes.reference('', '')
|
||||
if filename == docfilename:
|
||||
newnode['refid'] = labelid
|
||||
else:
|
||||
newnode['refuri'] = builder.get_relative_uri(
|
||||
docfilename, filename) + '#' + labelid
|
||||
newnode.append(contnode)
|
||||
elif typ in ('token', 'term', 'envvar', 'option'):
|
||||
filename, labelid = self.reftargets.get((typ, target), ('', ''))
|
||||
if not filename:
|
||||
@@ -656,10 +673,12 @@ class BuildEnvironment:
|
||||
synopsis, (' (deprecated)' if deprecated else ''))
|
||||
newnode.append(contnode)
|
||||
else:
|
||||
# "descrefs"
|
||||
modname = node['modname']
|
||||
clsname = node['classname']
|
||||
searchorder = 1 if node.hasattr('refspecific') else 0
|
||||
name, desc = self.find_desc(modname, clsname, target, typ, searchorder)
|
||||
name, desc = self.find_desc(modname, clsname,
|
||||
target, typ, searchorder)
|
||||
if not desc:
|
||||
newnode = contnode
|
||||
else:
|
||||
|
||||
@@ -25,6 +25,7 @@ from . import highlighting
|
||||
HEADER = r'''%% Generated by Sphinx.
|
||||
\documentclass[%(papersize)s,%(pointsize)s]{%(docclass)s}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[colorlinks,breaklinks]{hyperref}
|
||||
\title{%(title)s}
|
||||
\date{%(date)s}
|
||||
@@ -408,7 +409,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# this is a list in the source, but should be rendered as a
|
||||
# comma-separated list here
|
||||
self.body.append('\n\n')
|
||||
self.body.append(', '.join(n.astext() for n in node.children[0].children))
|
||||
self.body.append(', '.join(n.astext() for n in node.children[0].children) + '.')
|
||||
self.body.append('\n\n')
|
||||
raise nodes.SkipNode
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ generic_docroles = {
|
||||
'dfn' : nodes.emphasis,
|
||||
'guilabel' : nodes.strong,
|
||||
'kbd' : nodes.literal,
|
||||
'keyword' : nodes.literal,
|
||||
'mailheader' : addnodes.literal_emphasis,
|
||||
'makevar' : nodes.Text,
|
||||
'manpage' : addnodes.literal_emphasis,
|
||||
@@ -172,6 +171,7 @@ specific_docroles = {
|
||||
|
||||
'mod' : xfileref_role,
|
||||
|
||||
'keyword': xfileref_role,
|
||||
'ref': xfileref_role,
|
||||
'token' : xfileref_role,
|
||||
'term': xfileref_role,
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
"""
|
||||
import re
|
||||
import pickle
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from docutils.nodes import Text, NodeVisitor
|
||||
|
||||
from .util.stemmer import PorterStemmer
|
||||
from .util.json import dump_json, load_json
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ div.sidebar input {
|
||||
div.modulecloud {
|
||||
margin: -5px 10px 5px 10px;
|
||||
padding: 10px;
|
||||
font-size: 110%;
|
||||
line-height: 160%;
|
||||
border: 1px solid #cbe7e5;
|
||||
background-color: #f2fbfd;
|
||||
@@ -708,6 +707,7 @@ pre {
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
|
||||
15
sphinx/templates/rstsource.html
Normal file
15
sphinx/templates/rstsource.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ filename }} — Python Documentation</title>
|
||||
<style type="text/css">
|
||||
.hl { background-color: yellow }
|
||||
</style>
|
||||
</head>
|
||||
<body style="font-size: 90%">
|
||||
<pre>
|
||||
{{ text }}
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -54,6 +54,9 @@
|
||||
<input type="hidden" name="check_keywords" value="yes">
|
||||
<input type="hidden" name="area" value="default">
|
||||
</form>
|
||||
{% if builder == 'web' %}
|
||||
<p style="font-size: 90%">Enter a module, class or function name.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
33
sphinx/templates/versionchanges.html
Normal file
33
sphinx/templates/versionchanges.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{% macro entries changes %}
|
||||
<ul>{% for entry, filename, lineno in changes %}
|
||||
<li><a href="rst/{{ filename }}.html#L{{ lineno-10 }}" target="src">{{ entry }}</a></li>
|
||||
{% endfor %}</ul>
|
||||
{% endmacro -%}
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="default.css">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Changes in Version {{ version }} — Python Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="body">
|
||||
<h1>Automatically generated list of changes in version {{ version }}</h1>
|
||||
<h2>Library changes</h2>
|
||||
{% for modname, changes in libchanges %}
|
||||
<h4>{{ modname }}</h4>
|
||||
{{ entries(changes) }}
|
||||
{% endfor %}
|
||||
<h2>C API changes</h2>
|
||||
{{ entries(apichanges) }}
|
||||
<h2>Other changes</h2>
|
||||
{% for (fn, title), changes in otherchanges %}
|
||||
<h4>{{ title }} <span style="font-size: 50%">({{ fn }})</span></h4>
|
||||
{{ entries(changes) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
11
sphinx/templates/versionchanges_frameset.html
Normal file
11
sphinx/templates/versionchanges_frameset.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
|
||||
"http://www.w3.org/TR/html4/frameset.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Changes in Version {{ version }} — Python Documentation</title>
|
||||
</head>
|
||||
<frameset cols="45%,*">
|
||||
<frame name="main" src="changes.html">
|
||||
<frame name="src" src="about:blank">
|
||||
</frameset>
|
||||
</html>
|
||||
@@ -1,5 +1,5 @@
|
||||
%
|
||||
% howto.cls for the Python documentation
|
||||
% howto.cls for Sphinx
|
||||
%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
@@ -34,7 +34,7 @@
|
||||
% This gives us all the Python-specific markup that we really want.
|
||||
% This should come last. Do not change this.
|
||||
%
|
||||
\RequirePackage{python}
|
||||
\RequirePackage{sphinx}
|
||||
|
||||
% This comes after python.sty because it otherwise defines its own
|
||||
% "seealso" command.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%
|
||||
% manual.cls for the Python documentation
|
||||
% manual.cls for Sphinx
|
||||
%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
@@ -43,9 +43,9 @@
|
||||
% This gives us all the Python-specific markup that we really want.
|
||||
% This should come last. Do not change this.
|
||||
%
|
||||
\RequirePackage{python}
|
||||
\RequirePackage{sphinx}
|
||||
|
||||
% This comes after python.sty because it otherwise defines its own
|
||||
% This comes after sphinx.sty because it otherwise defines its own
|
||||
% "seealso" command.
|
||||
\RequirePackage{makeidx}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
%
|
||||
% python.sty for the Python docummentation [works only with Latex2e]
|
||||
% sphinx.sty
|
||||
%
|
||||
% Adapted from the old python.sty, mostly written by Fred Drake,
|
||||
% by Georg Brandl.
|
||||
%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesPackage{python}
|
||||
[1998/01/11 LaTeX package (Python markup)]
|
||||
\ProvidesPackage{sphinx}
|
||||
[2007/12/30 LaTeX package (Sphinx markup)]
|
||||
|
||||
\RequirePackage{textcomp}
|
||||
\RequirePackage{longtable}
|
||||
@@ -310,17 +313,6 @@
|
||||
\newcommand{\refexmodindex}[1]{\py@refmodule{#1}{extension }}
|
||||
\newcommand{\refstmodindex}[1]{\py@refmodule{#1}{standard }}
|
||||
|
||||
% Refer to a module's documentation using a hyperlink of the module's
|
||||
% name, at least if we're building PDF:
|
||||
\ifpdf
|
||||
\newcommand{\refmodule}[2][\py@modulebadkey]{%
|
||||
\ifx\py@modulebadkey#1\def\py@modulekey{#2}\else\def\py@modulekey{#1}\fi%
|
||||
\py@linkToName{label-module-\py@modulekey}{\module{#2}}%
|
||||
}
|
||||
\else
|
||||
\newcommand{\refmodule}[2][\py@modulebadkey]{\module{#2}}
|
||||
\fi
|
||||
|
||||
% support for the module index
|
||||
\newif\ifpy@UseModuleIndex
|
||||
\py@UseModuleIndexfalse
|
||||
@@ -839,9 +831,7 @@
|
||||
|
||||
% Also for consistency: spell Python "Python", not "python"!
|
||||
|
||||
% code is the most difficult one...
|
||||
\newcommand{\code}[1]{\textrm{\@vobeyspaces\@noligs\def\{{\char`\{}\def\}{\char`\}}\def\~{\char`\~}\def\^{\char`\^}\def\e{\char`\\}\def\${\char`\$}\def\#{\char`\#}\def\&{\char`\&}\def\%{\char`\%}%
|
||||
\texttt{#1}}}
|
||||
\newcommand{\code}[1]{\texttt{#1}}
|
||||
|
||||
\newcommand{\bfcode}[1]{\code{\bfseries#1}} % bold-faced code font
|
||||
\newcommand{\csimplemacro}[1]{\code{#1}}
|
||||
@@ -861,28 +851,6 @@
|
||||
\newcommand{\file}[1]{`\filenq{#1}'}
|
||||
\newcommand{\filenq}[1]{{\py@smallsize\textsf{\let\e=\textbackslash#1}}}
|
||||
|
||||
% Use this def/redef approach for \url{} since hyperref defined this already,
|
||||
% but only if we actually used hyperref:
|
||||
%\ifpdf
|
||||
% \newcommand{\url}[1]{{%
|
||||
% \py@pdfstartlink%
|
||||
% attr{ /Border [0 0 0] }%
|
||||
% user{%
|
||||
% /Subtype/Link%
|
||||
% /A<<%
|
||||
% /Type/Action%
|
||||
% /S/URI%
|
||||
% /URI(#1)%
|
||||
% >>%
|
||||
% }%
|
||||
% \py@LinkColor% color of the link text
|
||||
% \py@smallsize\sf #1%
|
||||
% \py@NormalColor% Turn it back off; these are declarative
|
||||
% \pdfendlink}% and don't appear bound to the current
|
||||
% }% formatting "box".
|
||||
%\else
|
||||
% \newcommand{\url}[1]{\mbox{\py@smallsize\textsf{#1}}}
|
||||
%\fi
|
||||
\newcommand{\email}[1]{{\py@smallsize\textsf{#1}}}
|
||||
\newcommand{\newsgroup}[1]{{\py@smallsize\textsf{#1}}}
|
||||
|
||||
@@ -891,14 +859,6 @@
|
||||
\let\moreargs=\py@moreargs%
|
||||
\var{#1}}}}
|
||||
|
||||
% I'd really like to get rid of this!
|
||||
\newif\iftexi\texifalse
|
||||
|
||||
% This is used to get l2h to put the copyright and abstract on
|
||||
% a separate HTML page.
|
||||
\newif\ifhtml\htmlfalse
|
||||
|
||||
|
||||
% These should be used for all references to identifiers which are
|
||||
% used to refer to instances of specific language constructs. See the
|
||||
% names for specific semantic assignments.
|
||||
@@ -947,29 +907,6 @@
|
||||
% Note that \longprogramopt provides the '--'!
|
||||
\newcommand{\longprogramopt}[1]{\strong{-{}-#1}}
|
||||
|
||||
% \ulink{link text}{URL}
|
||||
\ifpdf
|
||||
\newcommand{\ulink}[2]{{%
|
||||
% For PDF, we *should* only generate a link when the URL is absolute.
|
||||
\py@pdfstartlink%
|
||||
attr{ /Border [0 0 0] }%
|
||||
user{%
|
||||
/Subtype/Link%
|
||||
/A<<%
|
||||
/Type/Action%
|
||||
/S/URI%
|
||||
/URI(#2)%
|
||||
>>%
|
||||
}%
|
||||
\py@LinkColor% color of the link text
|
||||
#1%
|
||||
\py@NormalColor% Turn it back off; these are declarative
|
||||
\pdfendlink}% and don't appear bound to the current
|
||||
}% formatting "box".
|
||||
\else
|
||||
\newcommand{\ulink}[2]{#1}
|
||||
\fi
|
||||
|
||||
% cited titles: \citetitle{Title of Work}
|
||||
% online: \citetitle[url-to-resource]{Title of Work}
|
||||
\ifpdf
|
||||
@@ -1160,27 +1097,6 @@
|
||||
\end{center}%
|
||||
}
|
||||
|
||||
% XXX Don't think we can use this yet, though it cleans up some
|
||||
% tedious markup. There's no equivalent for the HTML transform yet,
|
||||
% and that needs to exist. I don't know how to write it.
|
||||
%
|
||||
% This should really have something that makes it easier to bind a
|
||||
% table's ``Notes'' column and an associated tablenotes environment,
|
||||
% and generates the right magic for getting the numbers right in the
|
||||
% table.
|
||||
%
|
||||
% So this is quite incomplete.
|
||||
%
|
||||
\newcounter{py@tablenotescounter}
|
||||
\newenvironment{tablenotes}{%
|
||||
\noindent Notes:
|
||||
\par
|
||||
\setcounter{py@tablenotescounter}{0}
|
||||
\begin{list}{(\arabic{py@tablenotescounter})}%
|
||||
{\usecounter{py@tablenotescounter}}
|
||||
}{\end{list}}
|
||||
|
||||
|
||||
% Cross-referencing (AMK, new impl. FLD)
|
||||
% Sample usage:
|
||||
% \begin{seealso}
|
||||
@@ -88,7 +88,7 @@ class AdminPanel(object):
|
||||
Log the user out.
|
||||
"""
|
||||
req.logout()
|
||||
return RedirectResponse('admin/login/')
|
||||
return RedirectResponse('@admin/login/')
|
||||
|
||||
def do_change_password(self, req):
|
||||
"""
|
||||
|
||||
@@ -43,13 +43,16 @@ class AntiSpam(object):
|
||||
else:
|
||||
lines = [l.strip() for l in data.splitlines()
|
||||
if not l.startswith('#')]
|
||||
f = file(bad_content_file, 'w')
|
||||
f.write('\n'.join(lines))
|
||||
with file(bad_content_file, 'w') as f:
|
||||
f.write('\n'.join(lines))
|
||||
last_change = int(time.time())
|
||||
|
||||
if lines is None:
|
||||
with file(bad_content_file) as f:
|
||||
lines = [l.strip() for l in f]
|
||||
try:
|
||||
with file(bad_content_file) as f:
|
||||
lines = [l.strip() for l in f]
|
||||
except:
|
||||
lines = []
|
||||
self.rules = [re.compile(rule) for rule in lines if rule]
|
||||
|
||||
def is_spam(self, fields):
|
||||
|
||||
@@ -28,8 +28,7 @@ from collections import defaultdict
|
||||
|
||||
from .feed import Feed
|
||||
from .mail import Email
|
||||
from .util import render_template, render_simple_template, get_target_uri, \
|
||||
blackhole_dict, striptags
|
||||
from .util import render_template, get_target_uri, blackhole_dict, striptags
|
||||
from .admin import AdminPanel
|
||||
from .userdb import UserDatabase
|
||||
from .robots import robots_txt
|
||||
@@ -39,9 +38,9 @@ from .database import connect, set_connection, Comment
|
||||
from .wsgiutil import Request, Response, RedirectResponse, \
|
||||
JSONResponse, SharedDataMiddleware, NotFound, get_base_uri
|
||||
|
||||
from ..util import relative_uri, shorten_result
|
||||
from ..util import relative_uri
|
||||
from ..search import SearchFrontend
|
||||
from ..writer import HTMLWriter
|
||||
from ..htmlwriter import HTMLWriter
|
||||
from ..builder import LAST_BUILD_FILENAME, ENV_PICKLE_FILENAME
|
||||
|
||||
from docutils.io import StringOutput
|
||||
@@ -88,6 +87,7 @@ comments_methods = {
|
||||
class MockBuilder(object):
|
||||
def get_relative_uri(self, from_, to):
|
||||
return ''
|
||||
name = 'web'
|
||||
|
||||
|
||||
NoCache = object()
|
||||
@@ -139,8 +139,7 @@ class DocumentationApplication(object):
|
||||
|
||||
|
||||
def load_env(self, new_mtime):
|
||||
env_lock.acquire()
|
||||
try:
|
||||
with env_lock:
|
||||
if self.buildmtime == new_mtime:
|
||||
# happens if another thread already reloaded the env
|
||||
return
|
||||
@@ -153,8 +152,6 @@ class DocumentationApplication(object):
|
||||
self.search_frontend = SearchFrontend(pickle.load(f))
|
||||
self.buildmtime = new_mtime
|
||||
self.cache.clear()
|
||||
finally:
|
||||
env_lock.release()
|
||||
|
||||
|
||||
def search(self, req):
|
||||
@@ -209,9 +206,11 @@ class DocumentationApplication(object):
|
||||
warning_stream = StringIO.StringIO()
|
||||
env2 = copy.deepcopy(self.env)
|
||||
destination = StringOutput(encoding='utf-8')
|
||||
writer = HTMLWriter(env2.config)
|
||||
builder = MockBuilder()
|
||||
builder.config = env2.config
|
||||
writer = HTMLWriter(builder)
|
||||
doctree = env2.read_file(page_id, pathname, save_parsed=False)
|
||||
doctree = env2.get_and_resolve_doctree(page_id, MockBuilder(), doctree)
|
||||
doctree = env2.get_and_resolve_doctree(page_id, builder, doctree)
|
||||
doctree.settings = OptionParser(defaults=env2.settings,
|
||||
components=(writer,)).get_default_values()
|
||||
doctree.reporter = Reporter(page_id, 2, 4, stream=warning_stream)
|
||||
|
||||
@@ -71,11 +71,6 @@ def render_template(req, template_name, *contexts):
|
||||
return tmpl.render(context)
|
||||
|
||||
|
||||
def render_simple_template(template_name, context):
|
||||
tmpl = jinja_env.get_template(template_name)
|
||||
return tmpl.render(context)
|
||||
|
||||
|
||||
class lazy_property(object):
|
||||
"""
|
||||
Descriptor implementing a "lazy property", i.e. the function
|
||||
|
||||
Reference in New Issue
Block a user