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
|
Sphinx
|
||||||
******
|
******
|
||||||
|
|
||||||
- section numbers
|
- HTML section numbers?
|
||||||
- split the general index
|
- split the general index?
|
||||||
- add OpenSearch
|
- add OpenSearch
|
||||||
- "seealso" links to external examples, see http://svn.python.org/projects/sandbox/trunk/seealso/ and http://effbot.org/zone/idea-seealso.htm
|
- "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
|
- "often used" combo box in sidebar
|
||||||
- link to keywords
|
|
||||||
- source file cross-references?
|
- source file cross-references?
|
||||||
|
|
||||||
Web App
|
Web App
|
||||||
*******
|
*******
|
||||||
|
|
||||||
|
- fix /download
|
||||||
|
|
||||||
- discuss and debug comments system
|
- discuss and debug comments system
|
||||||
- prepare for databases other than sqlite for comments
|
- prepare for databases other than sqlite for comments
|
||||||
- add search via Xapian or Nucular (Python indexer - nucular.sf.net)
|
- 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
|
-D <setting=value> -- override a setting in sourcedir/conf.py
|
||||||
-N -- do not do colored output
|
-N -- do not do colored output
|
||||||
-q -- no output on stdout, just warnings on stderr
|
-q -- no output on stdout, just warnings on stderr
|
||||||
|
-P -- run Pdb on exception
|
||||||
modi:
|
modi:
|
||||||
* without -a and without filenames, write new and changed files.
|
* without -a and without filenames, write new and changed files.
|
||||||
* with -a, write all files.
|
* with -a, write all files.
|
||||||
@@ -43,7 +44,7 @@ modi:
|
|||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
try:
|
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])
|
srcdirname = path.abspath(args[0])
|
||||||
if not path.isdir(srcdirname):
|
if not path.isdir(srcdirname):
|
||||||
print >>sys.stderr, 'Error: Cannot find source directory.'
|
print >>sys.stderr, 'Error: Cannot find source directory.'
|
||||||
@@ -69,7 +70,7 @@ def main(argv):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
builder = all_files = None
|
builder = all_files = None
|
||||||
opt_help = freshenv = False
|
opt_help = freshenv = use_pdb = False
|
||||||
status = sys.stdout
|
status = sys.stdout
|
||||||
options = {}
|
options = {}
|
||||||
confoverrides = {}
|
confoverrides = {}
|
||||||
@@ -111,6 +112,8 @@ def main(argv):
|
|||||||
freshenv = True
|
freshenv = True
|
||||||
elif opt == '-q':
|
elif opt == '-q':
|
||||||
status = StringIO()
|
status = StringIO()
|
||||||
|
elif opt == '-P':
|
||||||
|
use_pdb = True
|
||||||
|
|
||||||
if not sys.stdout.isatty() or sys.platform == 'win32':
|
if not sys.stdout.isatty() or sys.platform == 'win32':
|
||||||
# Windows' cmd box doesn't understand ANSI sequences
|
# Windows' cmd box doesn't understand ANSI sequences
|
||||||
@@ -128,6 +131,7 @@ def main(argv):
|
|||||||
print ' * %s: %s' % (optname, description)
|
print ' * %s: %s' % (optname, description)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
builderobj = builderobj(srcdirname, outdirname, doctreedir, options,
|
builderobj = builderobj(srcdirname, outdirname, doctreedir, options,
|
||||||
status_stream=status,
|
status_stream=status,
|
||||||
warning_stream=sys.stderr,
|
warning_stream=sys.stderr,
|
||||||
@@ -139,6 +143,11 @@ def main(argv):
|
|||||||
builderobj.build_specific(filenames)
|
builderobj.build_specific(filenames)
|
||||||
else:
|
else:
|
||||||
builderobj.build_update()
|
builderobj.build_update()
|
||||||
|
except:
|
||||||
|
if not use_pdb:
|
||||||
|
raise
|
||||||
|
import pdb
|
||||||
|
pdb.post_mortem(sys.exc_info()[2])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import shutil
|
|||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
import cStringIO as StringIO
|
import cStringIO as StringIO
|
||||||
from os import path
|
from os import path
|
||||||
|
from cgi import escape
|
||||||
|
|
||||||
from docutils.io import StringOutput, FileOutput, DocTreeInput
|
from docutils.io import StringOutput, FileOutput, DocTreeInput
|
||||||
from docutils.core import publish_parts
|
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 .htmlwriter import HTMLWriter
|
||||||
from .latexwriter import LaTeXWriter
|
from .latexwriter import LaTeXWriter
|
||||||
from .environment import BuildEnvironment, NoUri
|
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 .util.console import bold, purple, green
|
||||||
|
|
||||||
from . import addnodes
|
from . import addnodes
|
||||||
@@ -194,10 +195,14 @@ class Builder(object):
|
|||||||
def build_update(self):
|
def build_update(self):
|
||||||
"""Only rebuild files changed or added since last build."""
|
"""Only rebuild files changed or added since last build."""
|
||||||
self.load_env()
|
self.load_env()
|
||||||
to_build = list(self.get_outdated_files())
|
to_build = self.get_outdated_files()
|
||||||
if not to_build:
|
if not to_build:
|
||||||
self.msg('no target files are out of date, exiting.')
|
self.msg('no target files are out of date, exiting.')
|
||||||
return
|
return
|
||||||
|
if isinstance(to_build, str):
|
||||||
|
self.build([], to_build)
|
||||||
|
else:
|
||||||
|
to_build = list(to_build)
|
||||||
self.build(to_build,
|
self.build(to_build,
|
||||||
summary='targets for %d source files that are '
|
summary='targets for %d source files that are '
|
||||||
'out of date' % len(to_build))
|
'out of date' % len(to_build))
|
||||||
@@ -207,15 +212,20 @@ class Builder(object):
|
|||||||
self.msg('building [%s]:' % self.name, nonl=1)
|
self.msg('building [%s]:' % self.name, nonl=1)
|
||||||
self.msg(summary, nobold=1)
|
self.msg(summary, nobold=1)
|
||||||
|
|
||||||
|
updated_filenames = []
|
||||||
# while reading, collect all warnings from docutils
|
# while reading, collect all warnings from docutils
|
||||||
with collect_env_warnings(self):
|
with collect_env_warnings(self):
|
||||||
self.msg('reading, updating environment:', nonl=1)
|
self.msg('reading, updating environment:', nonl=1)
|
||||||
iterator = self.env.update(self.config)
|
iterator = self.env.update(self.config)
|
||||||
self.msg(iterator.next(), nobold=1)
|
self.msg(iterator.next(), nonl=1, nobold=1)
|
||||||
for filename in iterator:
|
for filename in iterator:
|
||||||
|
if not updated_filenames:
|
||||||
|
self.msg('')
|
||||||
|
updated_filenames.append(filename)
|
||||||
self.msg(purple(filename), nonl=1, nobold=1)
|
self.msg(purple(filename), nonl=1, nobold=1)
|
||||||
self.msg()
|
self.msg()
|
||||||
|
|
||||||
|
if updated_filenames:
|
||||||
# save the environment
|
# save the environment
|
||||||
self.msg('pickling the env...', nonl=True)
|
self.msg('pickling the env...', nonl=True)
|
||||||
self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
||||||
@@ -227,33 +237,32 @@ class Builder(object):
|
|||||||
|
|
||||||
# another indirection to support methods which don't build files
|
# another indirection to support methods which don't build files
|
||||||
# individually
|
# individually
|
||||||
self.write(filenames)
|
self.write(filenames, updated_filenames)
|
||||||
|
|
||||||
# finish (write style files etc.)
|
# finish (write style files etc.)
|
||||||
self.msg('finishing...')
|
self.msg('finishing...')
|
||||||
self.finish()
|
self.finish()
|
||||||
self.msg('done!')
|
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.msg('creating index...')
|
||||||
self.env.create_index(self)
|
self.env.create_index(self)
|
||||||
if filenames:
|
self.prepare_writing(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)
|
|
||||||
|
|
||||||
# write target files
|
# write target files
|
||||||
with collect_env_warnings(self):
|
with collect_env_warnings(self):
|
||||||
self.msg('writing output...')
|
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):
|
stream=self.status_stream):
|
||||||
doctree = self.env.get_and_resolve_doctree(filename, self)
|
doctree = self.env.get_and_resolve_doctree(filename, self)
|
||||||
self.write_file(filename, doctree)
|
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 there is a source file, copy the source file for the "show source" link
|
||||||
if context.get('sourcename'):
|
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))
|
ensuredir(path.dirname(source_name))
|
||||||
shutil.copyfile(path.join(self.srcdir, os_path(filename)), source_name)
|
shutil.copyfile(path.join(self.srcdir, os_path(filename)), source_name)
|
||||||
|
|
||||||
@@ -652,8 +662,7 @@ class LaTeXBuilder(Builder):
|
|||||||
self.filenames = []
|
self.filenames = []
|
||||||
|
|
||||||
def get_outdated_files(self):
|
def get_outdated_files(self):
|
||||||
# XXX always rebuild everything for now
|
return 'all documents' # for now
|
||||||
return ['dummy']
|
|
||||||
|
|
||||||
def get_target_uri(self, source_filename, typ=None):
|
def get_target_uri(self, source_filename, typ=None):
|
||||||
if typ == 'token':
|
if typ == 'token':
|
||||||
@@ -677,9 +686,7 @@ class LaTeXBuilder(Builder):
|
|||||||
and not fn.endswith('index.rst')]:
|
and not fn.endswith('index.rst')]:
|
||||||
yield (howto, 'howto-'+howto[6:-4]+'.tex', 'howto')
|
yield (howto, 'howto-'+howto[6:-4]+'.tex', 'howto')
|
||||||
|
|
||||||
def write(self, filenames):
|
def write(self, *ignored):
|
||||||
# "filenames" is ignored here...
|
|
||||||
|
|
||||||
# first, assemble the "special" docs that are in every PDF
|
# first, assemble the "special" docs that are in every PDF
|
||||||
specials = []
|
specials = []
|
||||||
for fname in ["glossary", "about", "license", "copyright"]:
|
for fname in ["glossary", "about", "license", "copyright"]:
|
||||||
@@ -695,8 +702,8 @@ class LaTeXBuilder(Builder):
|
|||||||
destination_path=path.join(self.outdir, targetname),
|
destination_path=path.join(self.outdir, targetname),
|
||||||
encoding='utf-8')
|
encoding='utf-8')
|
||||||
print "processing", targetname + "...",
|
print "processing", targetname + "...",
|
||||||
doctree = self.assemble_doctree(sourcename,
|
doctree = self.assemble_doctree(
|
||||||
specials=(docclass == 'manual') and specials or [])
|
sourcename, specials=(docclass == 'manual') and specials or [])
|
||||||
print "writing...",
|
print "writing...",
|
||||||
doctree.settings = docsettings
|
doctree.settings = docsettings
|
||||||
doctree.settings.filename = sourcename
|
doctree.settings.filename = sourcename
|
||||||
@@ -743,9 +750,119 @@ class LaTeXBuilder(Builder):
|
|||||||
path.join(self.outdir, filename))
|
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 = {
|
builders = {
|
||||||
'html': StandaloneHTMLBuilder,
|
'html': StandaloneHTMLBuilder,
|
||||||
'web': WebHTMLBuilder,
|
'web': WebHTMLBuilder,
|
||||||
'htmlhelp': HTMLHelpBuilder,
|
'htmlhelp': HTMLHelpBuilder,
|
||||||
'latex': LaTeXBuilder,
|
'latex': LaTeXBuilder,
|
||||||
|
'changes': ChangesBuilder,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,7 +428,7 @@ def version_directive(name, arguments, options, content, lineno,
|
|||||||
else:
|
else:
|
||||||
ret = [node]
|
ret = [node]
|
||||||
env = state.document.settings.env
|
env = state.document.settings.env
|
||||||
env.note_versionchange(node['type'], node['version'], node)
|
env.note_versionchange(node['type'], node['version'], node, lineno)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
version_directive.arguments = (1, 1, 1)
|
version_directive.arguments = (1, 1, 1)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ default_settings = {
|
|||||||
|
|
||||||
# This is increased every time a new environment attribute is added
|
# This is increased every time a new environment attribute is added
|
||||||
# to properly invalidate pickle files.
|
# to properly invalidate pickle files.
|
||||||
ENV_VERSION = 13
|
ENV_VERSION = 14
|
||||||
|
|
||||||
|
|
||||||
def walk_depth(node, depth, maxdepth):
|
def walk_depth(node, depth, maxdepth):
|
||||||
@@ -222,7 +222,7 @@ class BuildEnvironment:
|
|||||||
self.indexentries = {} # filename -> list of
|
self.indexentries = {} # filename -> list of
|
||||||
# (type, string, target, aliasname)
|
# (type, string, target, aliasname)
|
||||||
self.versionchanges = {} # version -> list of
|
self.versionchanges = {} # version -> list of
|
||||||
# (type, filename, module, descname, content)
|
# (type, filename, lineno, module, descname, content)
|
||||||
|
|
||||||
# These are set while parsing a file
|
# These are set while parsing a file
|
||||||
self.filename = None # current file name
|
self.filename = None # current file name
|
||||||
@@ -383,7 +383,8 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
if save_parsed:
|
if save_parsed:
|
||||||
# save the parsed doctree
|
# 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)
|
dirname = path.dirname(doctree_filename)
|
||||||
if not path.isdir(dirname):
|
if not path.isdir(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
@@ -528,9 +529,9 @@ class BuildEnvironment:
|
|||||||
self.indexentries.setdefault(self.filename, []).append(
|
self.indexentries.setdefault(self.filename, []).append(
|
||||||
(type, string, targetid, aliasname))
|
(type, string, targetid, aliasname))
|
||||||
|
|
||||||
def note_versionchange(self, type, version, node):
|
def note_versionchange(self, type, version, node, lineno):
|
||||||
self.versionchanges.setdefault(version, []).append(
|
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 ------------------------------
|
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
|
||||||
@@ -603,6 +604,8 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if typ == 'ref':
|
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, ('','',''))
|
filename, labelid, sectname = self.labels.get(target, ('','',''))
|
||||||
if not filename:
|
if not filename:
|
||||||
newnode = doctree.reporter.system_message(
|
newnode = doctree.reporter.system_message(
|
||||||
@@ -620,6 +623,20 @@ class BuildEnvironment:
|
|||||||
newnode['refuri'] = builder.get_relative_uri(
|
newnode['refuri'] = builder.get_relative_uri(
|
||||||
docfilename, filename) + '#' + labelid
|
docfilename, filename) + '#' + labelid
|
||||||
newnode.append(innernode)
|
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'):
|
elif typ in ('token', 'term', 'envvar', 'option'):
|
||||||
filename, labelid = self.reftargets.get((typ, target), ('', ''))
|
filename, labelid = self.reftargets.get((typ, target), ('', ''))
|
||||||
if not filename:
|
if not filename:
|
||||||
@@ -656,10 +673,12 @@ class BuildEnvironment:
|
|||||||
synopsis, (' (deprecated)' if deprecated else ''))
|
synopsis, (' (deprecated)' if deprecated else ''))
|
||||||
newnode.append(contnode)
|
newnode.append(contnode)
|
||||||
else:
|
else:
|
||||||
|
# "descrefs"
|
||||||
modname = node['modname']
|
modname = node['modname']
|
||||||
clsname = node['classname']
|
clsname = node['classname']
|
||||||
searchorder = 1 if node.hasattr('refspecific') else 0
|
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:
|
if not desc:
|
||||||
newnode = contnode
|
newnode = contnode
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from . import highlighting
|
|||||||
HEADER = r'''%% Generated by Sphinx.
|
HEADER = r'''%% Generated by Sphinx.
|
||||||
\documentclass[%(papersize)s,%(pointsize)s]{%(docclass)s}
|
\documentclass[%(papersize)s,%(pointsize)s]{%(docclass)s}
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
\usepackage[colorlinks,breaklinks]{hyperref}
|
\usepackage[colorlinks,breaklinks]{hyperref}
|
||||||
\title{%(title)s}
|
\title{%(title)s}
|
||||||
\date{%(date)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
|
# this is a list in the source, but should be rendered as a
|
||||||
# comma-separated list here
|
# comma-separated list here
|
||||||
self.body.append('\n\n')
|
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')
|
self.body.append('\n\n')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ generic_docroles = {
|
|||||||
'dfn' : nodes.emphasis,
|
'dfn' : nodes.emphasis,
|
||||||
'guilabel' : nodes.strong,
|
'guilabel' : nodes.strong,
|
||||||
'kbd' : nodes.literal,
|
'kbd' : nodes.literal,
|
||||||
'keyword' : nodes.literal,
|
|
||||||
'mailheader' : addnodes.literal_emphasis,
|
'mailheader' : addnodes.literal_emphasis,
|
||||||
'makevar' : nodes.Text,
|
'makevar' : nodes.Text,
|
||||||
'manpage' : addnodes.literal_emphasis,
|
'manpage' : addnodes.literal_emphasis,
|
||||||
@@ -172,6 +171,7 @@ specific_docroles = {
|
|||||||
|
|
||||||
'mod' : xfileref_role,
|
'mod' : xfileref_role,
|
||||||
|
|
||||||
|
'keyword': xfileref_role,
|
||||||
'ref': xfileref_role,
|
'ref': xfileref_role,
|
||||||
'token' : xfileref_role,
|
'token' : xfileref_role,
|
||||||
'term': xfileref_role,
|
'term': xfileref_role,
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from docutils.nodes import Text, NodeVisitor
|
from docutils.nodes import Text, NodeVisitor
|
||||||
|
|
||||||
from .util.stemmer import PorterStemmer
|
from .util.stemmer import PorterStemmer
|
||||||
from .util.json import dump_json, load_json
|
from .util.json import dump_json, load_json
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,6 @@ div.sidebar input {
|
|||||||
div.modulecloud {
|
div.modulecloud {
|
||||||
margin: -5px 10px 5px 10px;
|
margin: -5px 10px 5px 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 110%;
|
|
||||||
line-height: 160%;
|
line-height: 160%;
|
||||||
border: 1px solid #cbe7e5;
|
border: 1px solid #cbe7e5;
|
||||||
background-color: #f2fbfd;
|
background-color: #f2fbfd;
|
||||||
@@ -708,6 +707,7 @@ pre {
|
|||||||
tt {
|
tt {
|
||||||
background-color: #ecf0f3;
|
background-color: #ecf0f3;
|
||||||
padding: 0 1px 0 1px;
|
padding: 0 1px 0 1px;
|
||||||
|
font-size: 0.95em;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt.descname {
|
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="check_keywords" value="yes">
|
||||||
<input type="hidden" name="area" value="default">
|
<input type="hidden" name="area" value="default">
|
||||||
</form>
|
</form>
|
||||||
|
{% if builder == 'web' %}
|
||||||
|
<p style="font-size: 90%">Enter a module, class or function name.</p>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</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]
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
% This gives us all the Python-specific markup that we really want.
|
% This gives us all the Python-specific markup that we really want.
|
||||||
% This should come last. Do not change this.
|
% 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 python.sty because it otherwise defines its own
|
||||||
% "seealso" command.
|
% "seealso" command.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
%
|
%
|
||||||
% manual.cls for the Python documentation
|
% manual.cls for Sphinx
|
||||||
%
|
%
|
||||||
|
|
||||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
% This gives us all the Python-specific markup that we really want.
|
% This gives us all the Python-specific markup that we really want.
|
||||||
% This should come last. Do not change this.
|
% 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.
|
% "seealso" command.
|
||||||
\RequirePackage{makeidx}
|
\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]
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
\ProvidesPackage{python}
|
\ProvidesPackage{sphinx}
|
||||||
[1998/01/11 LaTeX package (Python markup)]
|
[2007/12/30 LaTeX package (Sphinx markup)]
|
||||||
|
|
||||||
\RequirePackage{textcomp}
|
\RequirePackage{textcomp}
|
||||||
\RequirePackage{longtable}
|
\RequirePackage{longtable}
|
||||||
@@ -310,17 +313,6 @@
|
|||||||
\newcommand{\refexmodindex}[1]{\py@refmodule{#1}{extension }}
|
\newcommand{\refexmodindex}[1]{\py@refmodule{#1}{extension }}
|
||||||
\newcommand{\refstmodindex}[1]{\py@refmodule{#1}{standard }}
|
\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
|
% support for the module index
|
||||||
\newif\ifpy@UseModuleIndex
|
\newif\ifpy@UseModuleIndex
|
||||||
\py@UseModuleIndexfalse
|
\py@UseModuleIndexfalse
|
||||||
@@ -839,9 +831,7 @@
|
|||||||
|
|
||||||
% Also for consistency: spell Python "Python", not "python"!
|
% Also for consistency: spell Python "Python", not "python"!
|
||||||
|
|
||||||
% code is the most difficult one...
|
\newcommand{\code}[1]{\texttt{#1}}
|
||||||
\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{\bfcode}[1]{\code{\bfseries#1}} % bold-faced code font
|
\newcommand{\bfcode}[1]{\code{\bfseries#1}} % bold-faced code font
|
||||||
\newcommand{\csimplemacro}[1]{\code{#1}}
|
\newcommand{\csimplemacro}[1]{\code{#1}}
|
||||||
@@ -861,28 +851,6 @@
|
|||||||
\newcommand{\file}[1]{`\filenq{#1}'}
|
\newcommand{\file}[1]{`\filenq{#1}'}
|
||||||
\newcommand{\filenq}[1]{{\py@smallsize\textsf{\let\e=\textbackslash#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{\email}[1]{{\py@smallsize\textsf{#1}}}
|
||||||
\newcommand{\newsgroup}[1]{{\py@smallsize\textsf{#1}}}
|
\newcommand{\newsgroup}[1]{{\py@smallsize\textsf{#1}}}
|
||||||
|
|
||||||
@@ -891,14 +859,6 @@
|
|||||||
\let\moreargs=\py@moreargs%
|
\let\moreargs=\py@moreargs%
|
||||||
\var{#1}}}}
|
\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
|
% These should be used for all references to identifiers which are
|
||||||
% used to refer to instances of specific language constructs. See the
|
% used to refer to instances of specific language constructs. See the
|
||||||
% names for specific semantic assignments.
|
% names for specific semantic assignments.
|
||||||
@@ -947,29 +907,6 @@
|
|||||||
% Note that \longprogramopt provides the '--'!
|
% Note that \longprogramopt provides the '--'!
|
||||||
\newcommand{\longprogramopt}[1]{\strong{-{}-#1}}
|
\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}
|
% cited titles: \citetitle{Title of Work}
|
||||||
% online: \citetitle[url-to-resource]{Title of Work}
|
% online: \citetitle[url-to-resource]{Title of Work}
|
||||||
\ifpdf
|
\ifpdf
|
||||||
@@ -1160,27 +1097,6 @@
|
|||||||
\end{center}%
|
\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)
|
% Cross-referencing (AMK, new impl. FLD)
|
||||||
% Sample usage:
|
% Sample usage:
|
||||||
% \begin{seealso}
|
% \begin{seealso}
|
||||||
@@ -88,7 +88,7 @@ class AdminPanel(object):
|
|||||||
Log the user out.
|
Log the user out.
|
||||||
"""
|
"""
|
||||||
req.logout()
|
req.logout()
|
||||||
return RedirectResponse('admin/login/')
|
return RedirectResponse('@admin/login/')
|
||||||
|
|
||||||
def do_change_password(self, req):
|
def do_change_password(self, req):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -43,13 +43,16 @@ class AntiSpam(object):
|
|||||||
else:
|
else:
|
||||||
lines = [l.strip() for l in data.splitlines()
|
lines = [l.strip() for l in data.splitlines()
|
||||||
if not l.startswith('#')]
|
if not l.startswith('#')]
|
||||||
f = file(bad_content_file, 'w')
|
with file(bad_content_file, 'w') as f:
|
||||||
f.write('\n'.join(lines))
|
f.write('\n'.join(lines))
|
||||||
last_change = int(time.time())
|
last_change = int(time.time())
|
||||||
|
|
||||||
if lines is None:
|
if lines is None:
|
||||||
|
try:
|
||||||
with file(bad_content_file) as f:
|
with file(bad_content_file) as f:
|
||||||
lines = [l.strip() for l in f]
|
lines = [l.strip() for l in f]
|
||||||
|
except:
|
||||||
|
lines = []
|
||||||
self.rules = [re.compile(rule) for rule in lines if rule]
|
self.rules = [re.compile(rule) for rule in lines if rule]
|
||||||
|
|
||||||
def is_spam(self, fields):
|
def is_spam(self, fields):
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ from collections import defaultdict
|
|||||||
|
|
||||||
from .feed import Feed
|
from .feed import Feed
|
||||||
from .mail import Email
|
from .mail import Email
|
||||||
from .util import render_template, render_simple_template, get_target_uri, \
|
from .util import render_template, get_target_uri, blackhole_dict, striptags
|
||||||
blackhole_dict, striptags
|
|
||||||
from .admin import AdminPanel
|
from .admin import AdminPanel
|
||||||
from .userdb import UserDatabase
|
from .userdb import UserDatabase
|
||||||
from .robots import robots_txt
|
from .robots import robots_txt
|
||||||
@@ -39,9 +38,9 @@ from .database import connect, set_connection, Comment
|
|||||||
from .wsgiutil import Request, Response, RedirectResponse, \
|
from .wsgiutil import Request, Response, RedirectResponse, \
|
||||||
JSONResponse, SharedDataMiddleware, NotFound, get_base_uri
|
JSONResponse, SharedDataMiddleware, NotFound, get_base_uri
|
||||||
|
|
||||||
from ..util import relative_uri, shorten_result
|
from ..util import relative_uri
|
||||||
from ..search import SearchFrontend
|
from ..search import SearchFrontend
|
||||||
from ..writer import HTMLWriter
|
from ..htmlwriter import HTMLWriter
|
||||||
from ..builder import LAST_BUILD_FILENAME, ENV_PICKLE_FILENAME
|
from ..builder import LAST_BUILD_FILENAME, ENV_PICKLE_FILENAME
|
||||||
|
|
||||||
from docutils.io import StringOutput
|
from docutils.io import StringOutput
|
||||||
@@ -88,6 +87,7 @@ comments_methods = {
|
|||||||
class MockBuilder(object):
|
class MockBuilder(object):
|
||||||
def get_relative_uri(self, from_, to):
|
def get_relative_uri(self, from_, to):
|
||||||
return ''
|
return ''
|
||||||
|
name = 'web'
|
||||||
|
|
||||||
|
|
||||||
NoCache = object()
|
NoCache = object()
|
||||||
@@ -139,8 +139,7 @@ class DocumentationApplication(object):
|
|||||||
|
|
||||||
|
|
||||||
def load_env(self, new_mtime):
|
def load_env(self, new_mtime):
|
||||||
env_lock.acquire()
|
with env_lock:
|
||||||
try:
|
|
||||||
if self.buildmtime == new_mtime:
|
if self.buildmtime == new_mtime:
|
||||||
# happens if another thread already reloaded the env
|
# happens if another thread already reloaded the env
|
||||||
return
|
return
|
||||||
@@ -153,8 +152,6 @@ class DocumentationApplication(object):
|
|||||||
self.search_frontend = SearchFrontend(pickle.load(f))
|
self.search_frontend = SearchFrontend(pickle.load(f))
|
||||||
self.buildmtime = new_mtime
|
self.buildmtime = new_mtime
|
||||||
self.cache.clear()
|
self.cache.clear()
|
||||||
finally:
|
|
||||||
env_lock.release()
|
|
||||||
|
|
||||||
|
|
||||||
def search(self, req):
|
def search(self, req):
|
||||||
@@ -209,9 +206,11 @@ class DocumentationApplication(object):
|
|||||||
warning_stream = StringIO.StringIO()
|
warning_stream = StringIO.StringIO()
|
||||||
env2 = copy.deepcopy(self.env)
|
env2 = copy.deepcopy(self.env)
|
||||||
destination = StringOutput(encoding='utf-8')
|
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.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,
|
doctree.settings = OptionParser(defaults=env2.settings,
|
||||||
components=(writer,)).get_default_values()
|
components=(writer,)).get_default_values()
|
||||||
doctree.reporter = Reporter(page_id, 2, 4, stream=warning_stream)
|
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)
|
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):
|
class lazy_property(object):
|
||||||
"""
|
"""
|
||||||
Descriptor implementing a "lazy property", i.e. the function
|
Descriptor implementing a "lazy property", i.e. the function
|
||||||
|
|||||||
Reference in New Issue
Block a user