mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Move converter to its own dir.
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Documentation converter - high level functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
import codecs
|
||||
from os import path
|
||||
|
||||
from .tokenizer import Tokenizer
|
||||
from .latexparser import DocParser
|
||||
from .restwriter import RestWriter
|
||||
from .filenamemap import (fn_mapping, copyfiles_mapping, newfiles_mapping,
|
||||
rename_mapping, dirs_to_make, toctree_mapping,
|
||||
amendments_mapping)
|
||||
from .console import red, green
|
||||
|
||||
def convert_file(infile, outfile, doraise=True, splitchap=False,
|
||||
toctree=None, deflang=None, labelprefix=''):
|
||||
inf = codecs.open(infile, 'r', 'latin1')
|
||||
p = DocParser(Tokenizer(inf.read()).tokenize(), infile)
|
||||
if not splitchap:
|
||||
outf = codecs.open(outfile, 'w', 'utf-8')
|
||||
else:
|
||||
outf = None
|
||||
r = RestWriter(outf, splitchap, toctree, deflang, labelprefix)
|
||||
try:
|
||||
r.write_document(p.parse())
|
||||
if splitchap:
|
||||
for i, chapter in enumerate(r.chapters[1:]):
|
||||
coutf = codecs.open('%s/%d_%s' % (
|
||||
path.dirname(outfile), i+1, path.basename(outfile)),
|
||||
'w', 'utf-8')
|
||||
coutf.write(chapter.getvalue())
|
||||
coutf.close()
|
||||
else:
|
||||
outf.close()
|
||||
return 1, r.warnings
|
||||
except Exception, err:
|
||||
if doraise:
|
||||
raise
|
||||
return 0, str(err)
|
||||
|
||||
|
||||
def convert_dir(outdirname, *args):
|
||||
# make directories
|
||||
for dirname in dirs_to_make:
|
||||
try:
|
||||
os.mkdir(path.join(outdirname, dirname))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# copy files (currently only non-tex includes)
|
||||
for oldfn, newfn in copyfiles_mapping.iteritems():
|
||||
newpathfn = path.join(outdirname, newfn)
|
||||
globfns = glob.glob(oldfn)
|
||||
if len(globfns) == 1 and not path.isdir(newpathfn):
|
||||
shutil.copyfile(globfns[0], newpathfn)
|
||||
else:
|
||||
for globfn in globfns:
|
||||
shutil.copyfile(globfn, path.join(newpathfn,
|
||||
path.basename(globfn)))
|
||||
|
||||
# convert tex files
|
||||
# "doc" is not converted. It must be rewritten anyway.
|
||||
for subdir in ('api', 'dist', 'ext', 'inst', 'commontex',
|
||||
'lib', 'mac', 'ref', 'tut', 'whatsnew'):
|
||||
if args and subdir not in args:
|
||||
continue
|
||||
if subdir not in fn_mapping:
|
||||
continue
|
||||
newsubdir = fn_mapping[subdir]['__newname__']
|
||||
deflang = fn_mapping[subdir].get('__defaulthighlightlang__')
|
||||
labelprefix = fn_mapping[subdir].get('__labelprefix__', '')
|
||||
for filename in sorted(os.listdir(subdir)):
|
||||
if not filename.endswith('.tex'):
|
||||
continue
|
||||
filename = filename[:-4] # strip extension
|
||||
newname = fn_mapping[subdir][filename]
|
||||
if newname is None:
|
||||
continue
|
||||
if newname.endswith(':split'):
|
||||
newname = newname[:-6]
|
||||
splitchap = True
|
||||
else:
|
||||
splitchap = False
|
||||
if '/' not in newname:
|
||||
outfilename = path.join(outdirname, newsubdir, newname + '.rst')
|
||||
else:
|
||||
outfilename = path.join(outdirname, newname + '.rst')
|
||||
toctree = toctree_mapping.get(path.join(subdir, filename))
|
||||
infilename = path.join(subdir, filename + '.tex')
|
||||
print green(infilename),
|
||||
success, state = convert_file(infilename, outfilename, False,
|
||||
splitchap, toctree, deflang, labelprefix)
|
||||
if not success:
|
||||
print red("ERROR:")
|
||||
print red(" " + state)
|
||||
else:
|
||||
if state:
|
||||
print "warnings:"
|
||||
for warning in state:
|
||||
print " " + warning
|
||||
|
||||
# rename files, e.g. splitted ones
|
||||
for oldfn, newfn in rename_mapping.iteritems():
|
||||
try:
|
||||
if newfn is None:
|
||||
os.unlink(path.join(outdirname, oldfn))
|
||||
else:
|
||||
os.rename(path.join(outdirname, oldfn),
|
||||
path.join(outdirname, newfn))
|
||||
except OSError, err:
|
||||
if err.errno == 2:
|
||||
continue
|
||||
raise
|
||||
|
||||
# copy new files
|
||||
srcdirname = path.join(path.dirname(__file__), 'newfiles')
|
||||
for fn, newfn in newfiles_mapping.iteritems():
|
||||
shutil.copyfile(path.join(srcdirname, fn),
|
||||
path.join(outdirname, newfn))
|
||||
|
||||
# make amendments
|
||||
for newfn, (pre, post) in amendments_mapping.iteritems():
|
||||
fn = path.join(outdirname, newfn)
|
||||
try:
|
||||
ft = open(fn).read()
|
||||
except Exception, err:
|
||||
print "Error making amendments to %s: %s" % (newfn, err)
|
||||
continue
|
||||
else:
|
||||
fw = open(fn, 'w')
|
||||
fw.write(pre)
|
||||
fw.write(ft)
|
||||
fw.write(post)
|
||||
fw.close()
|
||||
@@ -1,101 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Console utils
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Format colored console output.
|
||||
|
||||
:copyright: 1998-2004 by the Gentoo Foundation.
|
||||
:copyright: 2006-2007 by Georg Brandl.
|
||||
:license: GNU GPL.
|
||||
"""
|
||||
|
||||
esc_seq = "\x1b["
|
||||
|
||||
codes = {}
|
||||
codes["reset"] = esc_seq + "39;49;00m"
|
||||
|
||||
codes["bold"] = esc_seq + "01m"
|
||||
codes["faint"] = esc_seq + "02m"
|
||||
codes["standout"] = esc_seq + "03m"
|
||||
codes["underline"] = esc_seq + "04m"
|
||||
codes["blink"] = esc_seq + "05m"
|
||||
codes["overline"] = esc_seq + "06m" # Who made this up? Seriously.
|
||||
|
||||
ansi_color_codes = []
|
||||
for x in xrange(30, 38):
|
||||
ansi_color_codes.append("%im" % x)
|
||||
ansi_color_codes.append("%i;01m" % x)
|
||||
|
||||
rgb_ansi_colors = [
|
||||
'0x000000', '0x555555', '0xAA0000', '0xFF5555',
|
||||
'0x00AA00', '0x55FF55', '0xAA5500', '0xFFFF55',
|
||||
'0x0000AA', '0x5555FF', '0xAA00AA', '0xFF55FF',
|
||||
'0x00AAAA', '0x55FFFF', '0xAAAAAA', '0xFFFFFF'
|
||||
]
|
||||
|
||||
for x in xrange(len(rgb_ansi_colors)):
|
||||
codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
|
||||
|
||||
del x
|
||||
|
||||
codes["black"] = codes["0x000000"]
|
||||
codes["darkgray"] = codes["0x555555"]
|
||||
|
||||
codes["red"] = codes["0xFF5555"]
|
||||
codes["darkred"] = codes["0xAA0000"]
|
||||
|
||||
codes["green"] = codes["0x55FF55"]
|
||||
codes["darkgreen"] = codes["0x00AA00"]
|
||||
|
||||
codes["yellow"] = codes["0xFFFF55"]
|
||||
codes["brown"] = codes["0xAA5500"]
|
||||
|
||||
codes["blue"] = codes["0x5555FF"]
|
||||
codes["darkblue"] = codes["0x0000AA"]
|
||||
|
||||
codes["fuchsia"] = codes["0xFF55FF"]
|
||||
codes["purple"] = codes["0xAA00AA"]
|
||||
|
||||
codes["teal"] = codes["0x00AAAA"]
|
||||
codes["turquoise"] = codes["0x55FFFF"]
|
||||
|
||||
codes["white"] = codes["0xFFFFFF"]
|
||||
codes["lightgray"] = codes["0xAAAAAA"]
|
||||
|
||||
codes["darkteal"] = codes["turquoise"]
|
||||
codes["darkyellow"] = codes["brown"]
|
||||
codes["fuscia"] = codes["fuchsia"]
|
||||
codes["white"] = codes["bold"]
|
||||
|
||||
def nocolor():
|
||||
"turn off colorization"
|
||||
for code in codes:
|
||||
codes[code] = ""
|
||||
|
||||
def reset_color():
|
||||
return codes["reset"]
|
||||
|
||||
def colorize(color_key, text):
|
||||
return codes[color_key] + text + codes["reset"]
|
||||
|
||||
functions_colors = [
|
||||
"bold", "white", "teal", "turquoise", "darkteal",
|
||||
"fuscia", "fuchsia", "purple", "blue", "darkblue",
|
||||
"green", "darkgreen", "yellow", "brown",
|
||||
"darkyellow", "red", "darkred"
|
||||
]
|
||||
|
||||
def create_color_func(color_key):
|
||||
"""
|
||||
Return a function that formats its argument in the given color.
|
||||
"""
|
||||
def derived_func(text):
|
||||
return colorize(color_key, text)
|
||||
return derived_func
|
||||
|
||||
ns = locals()
|
||||
for c in functions_colors:
|
||||
ns[c] = create_color_func(c)
|
||||
|
||||
del c, ns
|
||||
@@ -1,297 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python documentation LaTeX parser - document nodes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
|
||||
class DocNode(object):
|
||||
""" A node in the document tree. """
|
||||
def __repr__(self):
|
||||
return '%s()' % self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
raise RuntimeError('cannot stringify docnodes')
|
||||
|
||||
def walk(self):
|
||||
return []
|
||||
|
||||
|
||||
class CommentNode(DocNode):
|
||||
""" A comment. """
|
||||
def __init__(self, comment):
|
||||
assert isinstance(comment, basestring)
|
||||
self.comment = comment
|
||||
|
||||
def __repr__(self):
|
||||
return 'CommentNode(%r)' % self.comment
|
||||
|
||||
|
||||
class RootNode(DocNode):
|
||||
""" A whole document. """
|
||||
def __init__(self, filename, children):
|
||||
self.filename = filename
|
||||
self.children = children
|
||||
self.params = {}
|
||||
self.labels = {}
|
||||
|
||||
def __repr__(self):
|
||||
return 'RootNode(%r, %r)' % (self.filename, self.children)
|
||||
|
||||
def walk(self):
|
||||
return self.children
|
||||
|
||||
def transform(self):
|
||||
""" Do restructurings not possible during parsing. """
|
||||
def do_descenvs(node):
|
||||
r""" Make \xxxlines an attribute of the parent xxxdesc node. """
|
||||
for subnode in node.walk():
|
||||
do_descenvs(subnode)
|
||||
if isinstance(node, DescEnvironmentNode):
|
||||
for subnode in node.content.walk():
|
||||
if isinstance(subnode, DescLineCommandNode):
|
||||
node.additional.append((subnode.cmdname, subnode.args))
|
||||
|
||||
do_descenvs(self)
|
||||
|
||||
|
||||
class NodeList(DocNode, list):
|
||||
""" A list of subnodes. """
|
||||
def __init__(self, children=None):
|
||||
list.__init__(self, children or [])
|
||||
|
||||
def __repr__(self):
|
||||
return 'NL%s' % list.__repr__(self)
|
||||
|
||||
def walk(self):
|
||||
return self
|
||||
|
||||
def append(self, node):
|
||||
assert isinstance(node, DocNode)
|
||||
if type(node) is EmptyNode:
|
||||
return
|
||||
elif self and isinstance(node, TextNode) and \
|
||||
type(self[-1]) is TextNode:
|
||||
self[-1].text += node.text
|
||||
elif type(node) is NodeList:
|
||||
list.extend(self, node)
|
||||
elif type(node) is VerbatimNode and self and \
|
||||
isinstance(self[-1], ParaSepNode):
|
||||
# don't allow a ParaSepNode before VerbatimNode
|
||||
# because this breaks ReST's '::'
|
||||
self[-1] = node
|
||||
else:
|
||||
list.append(self, node)
|
||||
|
||||
def flatten(self):
|
||||
if len(self) > 1:
|
||||
return self
|
||||
elif len(self) == 1:
|
||||
return self[0]
|
||||
else:
|
||||
return EmptyNode()
|
||||
|
||||
|
||||
class ParaSepNode(DocNode):
|
||||
""" A node for paragraph separator. """
|
||||
def __repr__(self):
|
||||
return 'Para'
|
||||
|
||||
|
||||
class TextNode(DocNode):
|
||||
""" A node containing text. """
|
||||
def __init__(self, text):
|
||||
assert isinstance(text, basestring)
|
||||
self.text = text
|
||||
|
||||
def __repr__(self):
|
||||
if type(self) is TextNode:
|
||||
return 'T%r' % self.text
|
||||
else:
|
||||
return '%s(%r)' % (self.__class__.__name__, self.text)
|
||||
|
||||
|
||||
class EmptyNode(TextNode):
|
||||
""" An empty node. """
|
||||
def __init__(self, *args):
|
||||
self.text = ''
|
||||
|
||||
|
||||
class NbspNode(TextNode):
|
||||
""" A non-breaking space. """
|
||||
def __init__(self, *args):
|
||||
# this breaks ReST markup (!)
|
||||
#self.text = u'\N{NO-BREAK SPACE}'
|
||||
self.text = ' '
|
||||
|
||||
def __repr__(self):
|
||||
return 'NBSP'
|
||||
|
||||
|
||||
simplecmd_mapping = {
|
||||
'ldots': u'...',
|
||||
'moreargs': '...',
|
||||
'unspecified': '...',
|
||||
'ASCII': 'ASCII',
|
||||
'UNIX': 'Unix',
|
||||
'Unix': 'Unix',
|
||||
'POSIX': 'POSIX',
|
||||
'LaTeX': 'LaTeX',
|
||||
'EOF': 'EOF',
|
||||
'Cpp': 'C++',
|
||||
'C': 'C',
|
||||
'sub': u'--> ',
|
||||
'textbackslash': '\\\\',
|
||||
'textunderscore': '_',
|
||||
'texteuro': u'\N{EURO SIGN}',
|
||||
'textasciicircum': u'^',
|
||||
'textasciitilde': u'~',
|
||||
'textgreater': '>',
|
||||
'textless': '<',
|
||||
'textbar': '|',
|
||||
'backslash': '\\\\',
|
||||
'tilde': '~',
|
||||
'copyright': u'\N{COPYRIGHT SIGN}',
|
||||
# \e is mostly inside \code and therefore not escaped.
|
||||
'e': '\\',
|
||||
'infinity': u'\N{INFINITY}',
|
||||
'plusminus': u'\N{PLUS-MINUS SIGN}',
|
||||
'leq': u'\N{LESS-THAN OR EQUAL TO}',
|
||||
'geq': u'\N{GREATER-THAN OR EQUAL TO}',
|
||||
'pi': u'\N{GREEK SMALL LETTER PI}',
|
||||
'AA': u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}',
|
||||
}
|
||||
|
||||
class SimpleCmdNode(TextNode):
|
||||
""" A command resulting in simple text. """
|
||||
def __init__(self, cmdname, args):
|
||||
self.text = simplecmd_mapping[cmdname]
|
||||
|
||||
|
||||
class BreakNode(DocNode):
|
||||
""" A line break. """
|
||||
def __repr__(self):
|
||||
return 'BR'
|
||||
|
||||
|
||||
class CommandNode(DocNode):
|
||||
""" A general command. """
|
||||
def __init__(self, cmdname, args):
|
||||
self.cmdname = cmdname
|
||||
self.args = args
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r)' % (self.__class__.__name__, self.cmdname, self.args)
|
||||
|
||||
def walk(self):
|
||||
return self.args
|
||||
|
||||
|
||||
class DescLineCommandNode(CommandNode):
|
||||
""" A \\xxxline command. """
|
||||
|
||||
|
||||
class InlineNode(CommandNode):
|
||||
""" A node with inline markup. """
|
||||
def walk(self):
|
||||
return []
|
||||
|
||||
|
||||
class IndexNode(InlineNode):
|
||||
""" An index-generating command. """
|
||||
def __init__(self, cmdname, args):
|
||||
self.cmdname = cmdname
|
||||
# tricky -- this is to make this silent in paragraphs
|
||||
# while still generating index entries for textonly()
|
||||
self.args = []
|
||||
self.indexargs = args
|
||||
|
||||
|
||||
class SectioningNode(CommandNode):
|
||||
""" A heading node. """
|
||||
|
||||
|
||||
class EnvironmentNode(DocNode):
|
||||
""" An environment. """
|
||||
def __init__(self, envname, args, content):
|
||||
self.envname = envname
|
||||
self.args = args
|
||||
self.content = content
|
||||
|
||||
def __repr__(self):
|
||||
return 'EnvironmentNode(%r, %r, %r)' % (self.envname,
|
||||
self.args, self.content)
|
||||
|
||||
def walk(self):
|
||||
return [self.content]
|
||||
|
||||
|
||||
class DescEnvironmentNode(EnvironmentNode):
|
||||
""" An xxxdesc environment. """
|
||||
def __init__(self, envname, args, content):
|
||||
self.envname = envname
|
||||
self.args = args
|
||||
self.additional = []
|
||||
self.content = content
|
||||
|
||||
def __repr__(self):
|
||||
return 'DescEnvironmentNode(%r, %r, %r)' % (self.envname,
|
||||
self.args, self.content)
|
||||
|
||||
|
||||
class TableNode(EnvironmentNode):
|
||||
def __init__(self, numcols, headings, lines):
|
||||
self.numcols = numcols
|
||||
self.headings = headings
|
||||
self.lines = lines
|
||||
|
||||
def __repr__(self):
|
||||
return 'TableNode(%r, %r, %r)' % (self.numcols,
|
||||
self.headings, self.lines)
|
||||
|
||||
def walk(self):
|
||||
return []
|
||||
|
||||
|
||||
class VerbatimNode(DocNode):
|
||||
""" A verbatim code block. """
|
||||
def __init__(self, content):
|
||||
self.content = content
|
||||
|
||||
def __repr__(self):
|
||||
return 'VerbatimNode(%r)' % self.content
|
||||
|
||||
|
||||
class ListNode(DocNode):
|
||||
""" A list. """
|
||||
def __init__(self, items):
|
||||
self.items = items
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items)
|
||||
|
||||
def walk(self):
|
||||
return [item[1] for item in self.items]
|
||||
|
||||
|
||||
class ItemizeNode(ListNode):
|
||||
""" An enumeration with bullets. """
|
||||
|
||||
|
||||
class EnumerateNode(ListNode):
|
||||
""" An enumeration with numbers. """
|
||||
|
||||
|
||||
class DescriptionNode(ListNode):
|
||||
""" A description list. """
|
||||
|
||||
|
||||
class DefinitionsNode(ListNode):
|
||||
""" A definition list. """
|
||||
|
||||
|
||||
class ProductionListNode(ListNode):
|
||||
""" A grammar production list. """
|
||||
@@ -1,122 +0,0 @@
|
||||
Index: inst/inst.tex
|
||||
===================================================================
|
||||
--- inst/inst.tex (Revision 54633)
|
||||
+++ inst/inst.tex (Arbeitskopie)
|
||||
@@ -324,32 +324,6 @@
|
||||
section~\ref{custom-install} on custom installations.
|
||||
|
||||
|
||||
-% This rather nasty macro is used to generate the tables that describe
|
||||
-% each installation scheme. It's nasty because it takes two arguments
|
||||
-% for each "slot" in an installation scheme, there will soon be more
|
||||
-% than five of these slots, and TeX has a limit of 10 arguments to a
|
||||
-% macro. Uh-oh.
|
||||
-
|
||||
-\newcommand{\installscheme}[8]
|
||||
- {\begin{tableiii}{l|l|l}{textrm}
|
||||
- {Type of file}
|
||||
- {Installation Directory}
|
||||
- {Override option}
|
||||
- \lineiii{pure module distribution}
|
||||
- {\filevar{#1}\filenq{#2}}
|
||||
- {\longprogramopt{install-purelib}}
|
||||
- \lineiii{non-pure module distribution}
|
||||
- {\filevar{#3}\filenq{#4}}
|
||||
- {\longprogramopt{install-platlib}}
|
||||
- \lineiii{scripts}
|
||||
- {\filevar{#5}\filenq{#6}}
|
||||
- {\longprogramopt{install-scripts}}
|
||||
- \lineiii{data}
|
||||
- {\filevar{#7}\filenq{#8}}
|
||||
- {\longprogramopt{install-data}}
|
||||
- \end{tableiii}}
|
||||
-
|
||||
-
|
||||
\section{Alternate Installation}
|
||||
\label{alt-install}
|
||||
|
||||
@@ -399,10 +373,23 @@
|
||||
The \longprogramopt{home} option defines the installation base
|
||||
directory. Files are installed to the following directories under the
|
||||
installation base as follows:
|
||||
-\installscheme{home}{/lib/python}
|
||||
- {home}{/lib/python}
|
||||
- {home}{/bin}
|
||||
- {home}{/share}
|
||||
+\begin{tableiii}{l|l|l}{textrm}
|
||||
+ {Type of file}
|
||||
+ {Installation Directory}
|
||||
+ {Override option}
|
||||
+ \lineiii{pure module distribution}
|
||||
+ {\filevar{home}\filenq{/lib/python}}
|
||||
+ {\longprogramopt{install-purelib}}
|
||||
+ \lineiii{non-pure module distribution}
|
||||
+ {\filevar{home}\filenq{/lib/python}}
|
||||
+ {\longprogramopt{install-platlib}}
|
||||
+ \lineiii{scripts}
|
||||
+ {\filevar{home}\filenq{/bin}}
|
||||
+ {\longprogramopt{install-scripts}}
|
||||
+ \lineiii{data}
|
||||
+ {\filevar{home}\filenq{/share}}
|
||||
+ {\longprogramopt{install-data}}
|
||||
+\end{tableiii}
|
||||
|
||||
|
||||
\versionchanged[The \longprogramopt{home} option used to be supported
|
||||
@@ -452,10 +439,23 @@
|
||||
etc.) If \longprogramopt{exec-prefix} is not supplied, it defaults to
|
||||
\longprogramopt{prefix}. Files are installed as follows:
|
||||
|
||||
-\installscheme{prefix}{/lib/python2.\filevar{X}/site-packages}
|
||||
- {exec-prefix}{/lib/python2.\filevar{X}/site-packages}
|
||||
- {prefix}{/bin}
|
||||
- {prefix}{/share}
|
||||
+\begin{tableiii}{l|l|l}{textrm}
|
||||
+ {Type of file}
|
||||
+ {Installation Directory}
|
||||
+ {Override option}
|
||||
+ \lineiii{pure module distribution}
|
||||
+ {\filevar{prefix}\filenq{/lib/python2.\filevar{X}/site-packages}}
|
||||
+ {\longprogramopt{install-purelib}}
|
||||
+ \lineiii{non-pure module distribution}
|
||||
+ {\filevar{exec-prefix}\filenq{/lib/python2.\filevar{X}/site-packages}}
|
||||
+ {\longprogramopt{install-platlib}}
|
||||
+ \lineiii{scripts}
|
||||
+ {\filevar{prefix}\filenq{/bin}}
|
||||
+ {\longprogramopt{install-scripts}}
|
||||
+ \lineiii{data}
|
||||
+ {\filevar{prefix}\filenq{/share}}
|
||||
+ {\longprogramopt{install-data}}
|
||||
+\end{tableiii}
|
||||
|
||||
There is no requirement that \longprogramopt{prefix} or
|
||||
\longprogramopt{exec-prefix} actually point to an alternate Python
|
||||
@@ -502,11 +502,24 @@
|
||||
The installation base is defined by the \longprogramopt{prefix} option;
|
||||
the \longprogramopt{exec-prefix} option is not supported under Windows.
|
||||
Files are installed as follows:
|
||||
-\installscheme{prefix}{}
|
||||
- {prefix}{}
|
||||
- {prefix}{\textbackslash{}Scripts}
|
||||
- {prefix}{\textbackslash{}Data}
|
||||
|
||||
+\begin{tableiii}{l|l|l}{textrm}
|
||||
+ {Type of file}
|
||||
+ {Installation Directory}
|
||||
+ {Override option}
|
||||
+ \lineiii{pure module distribution}
|
||||
+ {\filevar{prefix}\filenq{}}
|
||||
+ {\longprogramopt{install-purelib}}
|
||||
+ \lineiii{non-pure module distribution}
|
||||
+ {\filevar{prefix}\filenq{}}
|
||||
+ {\longprogramopt{install-platlib}}
|
||||
+ \lineiii{scripts}
|
||||
+ {\filevar{prefix}\filenq{\textbackslash{}Scripts}}
|
||||
+ {\longprogramopt{install-scripts}}
|
||||
+ \lineiii{data}
|
||||
+ {\filevar{prefix}\filenq{\textbackslash{}Data}}
|
||||
+ {\longprogramopt{install-data}}
|
||||
+\end{tableiii}
|
||||
|
||||
|
||||
\section{Custom Installation}
|
||||
@@ -1,636 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Map LaTeX filenames to ReST filenames
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
# '' means: use same name, strip prefix if applicable.
|
||||
# None means: don't translate at all.
|
||||
|
||||
_mapping = {
|
||||
'lib': {
|
||||
'__newname__' : 'library',
|
||||
|
||||
'asttable': '',
|
||||
'compiler': '',
|
||||
'distutils': '',
|
||||
'email': '',
|
||||
'emailcharsets': 'email.charset',
|
||||
'emailencoders': 'email.encoders',
|
||||
'emailexc': 'email.errors',
|
||||
'emailgenerator': 'email.generator',
|
||||
'emailheaders': 'email.header',
|
||||
'emailiter': 'email.iterators',
|
||||
'emailmessage': 'email.message',
|
||||
'emailmimebase': 'email.mime',
|
||||
'emailparser': 'email.parser',
|
||||
'emailutil': 'email.util',
|
||||
'libaifc': '',
|
||||
'libanydbm': '',
|
||||
'libarray': '',
|
||||
'libascii': 'curses.ascii',
|
||||
'libast': '',
|
||||
'libasynchat': '',
|
||||
'libasyncore': '',
|
||||
'libatexit': '',
|
||||
'libaudioop': '',
|
||||
'libbase64': '',
|
||||
'libbasehttp': 'basehttpserver',
|
||||
'libbastion': '',
|
||||
'libbinascii': '',
|
||||
'libbinhex': '',
|
||||
'libbisect': '',
|
||||
'libbltin': '__builtin__',
|
||||
'libbsddb': '',
|
||||
'libbz2': '',
|
||||
'libcalendar': '',
|
||||
'libcfgparser': 'configparser',
|
||||
'libcgihttp': 'cgihttpserver',
|
||||
'libcgi': '',
|
||||
'libcgitb': '',
|
||||
'libchunk': '',
|
||||
'libcmath': '',
|
||||
'libcmd': '',
|
||||
'libcodecs': '',
|
||||
'libcodeop': '',
|
||||
'libcode': '',
|
||||
'libcollections': '',
|
||||
'libcolorsys': '',
|
||||
'libcommands': '',
|
||||
'libcompileall': '',
|
||||
'libcontextlib': '',
|
||||
'libcookielib': '',
|
||||
'libcookie': '',
|
||||
'libcopyreg': 'copy_reg',
|
||||
'libcopy': '',
|
||||
'libcrypt': '',
|
||||
'libcsv': '',
|
||||
'libctypes': '',
|
||||
'libcursespanel': 'curses.panel',
|
||||
'libcurses': '',
|
||||
'libdatetime': '',
|
||||
'libdbhash': '',
|
||||
'libdbm': '',
|
||||
'libdecimal': '',
|
||||
'libdifflib': '',
|
||||
'libdircache': '',
|
||||
'libdis': '',
|
||||
'libdl': '',
|
||||
'libdoctest': '',
|
||||
'libdocxmlrpc': 'docxmlrpcserver',
|
||||
'libdumbdbm': '',
|
||||
'libdummythreading': 'dummy_threading',
|
||||
'libdummythread': 'dummy_thread',
|
||||
'liberrno': '',
|
||||
'libetree': 'xml.etree.elementtree',
|
||||
'libfcntl': '',
|
||||
'libfilecmp': '',
|
||||
'libfileinput': '',
|
||||
'libfnmatch': '',
|
||||
'libformatter': '',
|
||||
'libfpectl': '',
|
||||
'libfpformat': '',
|
||||
'libftplib': '',
|
||||
'libfunctools': '',
|
||||
'libfuture': '__future__',
|
||||
'libgc': '',
|
||||
'libgdbm': '',
|
||||
'libgetopt': '',
|
||||
'libgetpass': '',
|
||||
'libgettext': '',
|
||||
'libglob': '',
|
||||
'libgrp': '',
|
||||
'libgzip': '',
|
||||
'libhashlib': '',
|
||||
'libheapq': '',
|
||||
'libhmac': '',
|
||||
'libhotshot': '',
|
||||
'libhtmllib': '',
|
||||
'libhtmlparser': '',
|
||||
'libhttplib': '',
|
||||
'libimageop': '',
|
||||
'libimaplib': '',
|
||||
'libimgfile': '',
|
||||
'libimghdr': '',
|
||||
'libimp': '',
|
||||
'libinspect': '',
|
||||
'libitertools': '',
|
||||
'libjpeg': '',
|
||||
'libkeyword': '',
|
||||
'liblinecache': '',
|
||||
'liblocale': '',
|
||||
'liblogging': '',
|
||||
'libmailbox': '',
|
||||
'libmailcap': '',
|
||||
'libmain': '__main__',
|
||||
'libmarshal': '',
|
||||
'libmath': '',
|
||||
'libmd5': '',
|
||||
'libmhlib': '',
|
||||
'libmimetools': '',
|
||||
'libmimetypes': '',
|
||||
'libmimewriter': '',
|
||||
'libmimify': '',
|
||||
'libmmap': '',
|
||||
'libmodulefinder': '',
|
||||
'libmsilib': '',
|
||||
'libmsvcrt': '',
|
||||
'libmultifile': '',
|
||||
'libmutex': '',
|
||||
'libnetrc': '',
|
||||
'libnew': '',
|
||||
'libnis': '',
|
||||
'libnntplib': '',
|
||||
'liboperator': '',
|
||||
'liboptparse': '',
|
||||
'libos': '',
|
||||
'libossaudiodev': '',
|
||||
'libparser': '',
|
||||
'libpdb': '',
|
||||
'libpickle': '',
|
||||
'libpickletools': '',
|
||||
'libpipes': '',
|
||||
'libpkgutil': '',
|
||||
'libplatform': '',
|
||||
'libpopen2': '',
|
||||
'libpoplib': '',
|
||||
'libposixpath': 'os.path',
|
||||
'libposix': '',
|
||||
'libpprint': '',
|
||||
'libprofile': '',
|
||||
'libpty': '',
|
||||
'libpwd': '',
|
||||
'libpyclbr': '',
|
||||
'libpycompile': 'py_compile',
|
||||
'libpydoc': '',
|
||||
'libpyexpat': '',
|
||||
'libqueue': '',
|
||||
'libquopri': '',
|
||||
'librandom': '',
|
||||
'libreadline': '',
|
||||
'librepr': '',
|
||||
'libre': '',
|
||||
'libresource': '',
|
||||
'librexec': '',
|
||||
'librfc822': '',
|
||||
'librlcompleter': '',
|
||||
'librobotparser': '',
|
||||
'librunpy': '',
|
||||
'libsched': '',
|
||||
'libselect': '',
|
||||
'libsets': '',
|
||||
'libsgmllib': '',
|
||||
'libsha': '',
|
||||
'libshelve': '',
|
||||
'libshlex': '',
|
||||
'libshutil': '',
|
||||
'libsignal': '',
|
||||
'libsimplehttp': 'simplehttpserver',
|
||||
'libsimplexmlrpc': 'simplexmlrpcserver',
|
||||
'libsite': '',
|
||||
'libsmtpd': '',
|
||||
'libsmtplib': '',
|
||||
'libsndhdr': '',
|
||||
'libsocket': '',
|
||||
'libsocksvr': 'socketserver',
|
||||
'libspwd': '',
|
||||
'libsqlite3': '',
|
||||
'libstat': '',
|
||||
'libstatvfs': '',
|
||||
'libstringio': '',
|
||||
'libstringprep': '',
|
||||
'libstring': '',
|
||||
'libstruct': '',
|
||||
'libsunaudio': '',
|
||||
'libsunau': '',
|
||||
'libsubprocess': '',
|
||||
'libsymbol': '',
|
||||
'libsyslog': '',
|
||||
'libsys': '',
|
||||
'libtabnanny': '',
|
||||
'libtarfile': '',
|
||||
'libtelnetlib': '',
|
||||
'libtempfile': '',
|
||||
'libtermios': '',
|
||||
'libtest': '',
|
||||
'libtextwrap': '',
|
||||
'libthreading': '',
|
||||
'libthread': '',
|
||||
'libtimeit': '',
|
||||
'libtime': '',
|
||||
'libtokenize': '',
|
||||
'libtoken': '',
|
||||
'libtraceback': '',
|
||||
'libtrace': '',
|
||||
'libtty': '',
|
||||
'libturtle': '',
|
||||
'libtypes': '',
|
||||
'libunicodedata': '',
|
||||
'libunittest': '',
|
||||
'liburllib2': '',
|
||||
'liburllib': '',
|
||||
'liburlparse': '',
|
||||
'libuserdict': '',
|
||||
'libuser': '',
|
||||
'libuuid': '',
|
||||
'libuu': '',
|
||||
'libwarnings': '',
|
||||
'libwave': '',
|
||||
'libweakref': '',
|
||||
'libwebbrowser': '',
|
||||
'libwhichdb': '',
|
||||
'libwinreg': '_winreg',
|
||||
'libwinsound': '',
|
||||
'libwsgiref': '',
|
||||
'libxdrlib': '',
|
||||
'libxmllib': '',
|
||||
'libxmlrpclib': '',
|
||||
'libzipfile': '',
|
||||
'libzipimport': '',
|
||||
'libzlib': '',
|
||||
'tkinter': '',
|
||||
'xmldomminidom': 'xml.dom.minidom',
|
||||
'xmldompulldom': 'xml.dom.pulldom',
|
||||
'xmldom': 'xml.dom',
|
||||
'xmletree': 'xml.etree',
|
||||
'xmlsaxhandler': 'xml.sax.handler',
|
||||
'xmlsaxreader': 'xml.sax.reader',
|
||||
'xmlsax': 'xml.sax',
|
||||
'xmlsaxutils': 'xml.sax.utils',
|
||||
'libal': '',
|
||||
'libcd': '',
|
||||
'libfl': '',
|
||||
'libfm': '',
|
||||
'libgl': '',
|
||||
'libposixfile': '',
|
||||
|
||||
# specials
|
||||
'libundoc': '',
|
||||
'libintro': '',
|
||||
|
||||
'libconsts': 'constants',
|
||||
'libexcs': 'exceptions',
|
||||
'libfuncs': 'functions',
|
||||
'libobjs': 'objects',
|
||||
'libstdtypes': 'stdtypes',
|
||||
|
||||
# mainfiles
|
||||
'lib': None,
|
||||
'mimelib': None,
|
||||
|
||||
# obsolete
|
||||
'libni': None,
|
||||
'libcmpcache': None,
|
||||
'libcmp': None,
|
||||
|
||||
# chapter overviews
|
||||
'fileformats': '',
|
||||
'filesys': '',
|
||||
'frameworks': '',
|
||||
'i18n': '',
|
||||
'internet': '',
|
||||
'ipc': '',
|
||||
'language': '',
|
||||
'archiving': '',
|
||||
'custominterp': '',
|
||||
'datatypes': '',
|
||||
'development': '',
|
||||
'markup': '',
|
||||
'modules': '',
|
||||
'netdata': '',
|
||||
'numeric': '',
|
||||
'persistence': '',
|
||||
'windows': '',
|
||||
'libsun': '',
|
||||
'libmm': '',
|
||||
'liballos': '',
|
||||
'libcrypto': '',
|
||||
'libsomeos': '',
|
||||
'libsgi': '',
|
||||
'libmisc': '',
|
||||
'libpython': '',
|
||||
'librestricted': '',
|
||||
'libstrings': '',
|
||||
'libunix': '',
|
||||
},
|
||||
|
||||
'ref': {
|
||||
'__newname__': 'reference',
|
||||
'ref': None,
|
||||
'ref1': 'introduction',
|
||||
'ref2': 'lexical_analysis',
|
||||
'ref3': 'datamodel',
|
||||
'ref4': 'executionmodel',
|
||||
'ref5': 'expressions',
|
||||
'ref6': 'simple_stmts',
|
||||
'ref7': 'compound_stmts',
|
||||
'ref8': 'toplevel_components',
|
||||
},
|
||||
|
||||
'tut': {
|
||||
'__newname__': 'tutorial',
|
||||
'__labelprefix__': 'tut-',
|
||||
'tut': 'tutorial:split',
|
||||
'glossary': 'glossary',
|
||||
},
|
||||
|
||||
'api': {
|
||||
'__newname__': 'c-api',
|
||||
'__defaulthighlightlang__': 'c',
|
||||
'api': None,
|
||||
|
||||
'abstract': '',
|
||||
'concrete': '',
|
||||
'exceptions': '',
|
||||
'init': '',
|
||||
'intro': '',
|
||||
'memory': '',
|
||||
'newtypes': '',
|
||||
'refcounting': '',
|
||||
'utilities': '',
|
||||
'veryhigh': '',
|
||||
},
|
||||
|
||||
'ext': {
|
||||
'__newname__': 'extending',
|
||||
'__defaulthighlightlang__': 'c',
|
||||
'ext': None,
|
||||
|
||||
'building': '',
|
||||
'embedding': '',
|
||||
'extending': 'extending',
|
||||
'newtypes': '',
|
||||
'windows': '',
|
||||
},
|
||||
|
||||
'dist': {
|
||||
'__newname__': 'distutils',
|
||||
'dist': 'distutils:split',
|
||||
'sysconfig': '',
|
||||
},
|
||||
|
||||
'mac': {
|
||||
'__newname__': 'maclib',
|
||||
'mac': None,
|
||||
|
||||
'libaepack': 'aepack',
|
||||
'libaetools': 'aetools',
|
||||
'libaetypes': 'aetypes',
|
||||
'libautogil': 'autogil',
|
||||
'libcolorpicker': 'colorpicker',
|
||||
'libframework': 'framework',
|
||||
'libgensuitemodule': 'gensuitemodule',
|
||||
'libmacic': 'macic',
|
||||
'libmacos': 'macos',
|
||||
'libmacostools': 'macostools',
|
||||
'libmac': 'mac',
|
||||
'libmacui': 'macui',
|
||||
'libminiae': 'miniae',
|
||||
'libscrap': 'scrap',
|
||||
'scripting': '',
|
||||
'toolbox': '',
|
||||
'undoc': '',
|
||||
'using': '',
|
||||
|
||||
},
|
||||
|
||||
'inst': {
|
||||
'__newname__': 'install',
|
||||
'__defaulthighlightlang__': 'none',
|
||||
'inst': 'index',
|
||||
},
|
||||
|
||||
'whatsnew': {
|
||||
'__newname__': 'whatsnew',
|
||||
'whatsnew20': '2.0',
|
||||
'whatsnew21': '2.1',
|
||||
'whatsnew22': '2.2',
|
||||
'whatsnew23': '2.3',
|
||||
'whatsnew24': '2.4',
|
||||
'whatsnew25': '2.5',
|
||||
'whatsnew26': '2.6',
|
||||
'whatsnew30': '3.0',
|
||||
},
|
||||
|
||||
'commontex': {
|
||||
'__newname__': '',
|
||||
'boilerplate': None,
|
||||
'patchlevel': None,
|
||||
'copyright': '',
|
||||
'license': '',
|
||||
'reportingbugs': 'bugs',
|
||||
},
|
||||
}
|
||||
|
||||
fn_mapping = {}
|
||||
|
||||
for dir, files in _mapping.iteritems():
|
||||
newmap = fn_mapping[dir] = {}
|
||||
for fn in files:
|
||||
if not fn.startswith('_') and files[fn] == '':
|
||||
if fn.startswith(dir):
|
||||
newmap[fn] = fn[len(dir):]
|
||||
else:
|
||||
newmap[fn] = fn
|
||||
else:
|
||||
newmap[fn] = files[fn]
|
||||
|
||||
|
||||
# new directories to create
|
||||
dirs_to_make = [
|
||||
'c-api',
|
||||
'data',
|
||||
'distutils',
|
||||
'documenting',
|
||||
'extending',
|
||||
'includes',
|
||||
'includes/sqlite3',
|
||||
'install',
|
||||
'maclib',
|
||||
'library',
|
||||
'reference',
|
||||
'tutorial',
|
||||
'whatsnew',
|
||||
'tools',
|
||||
]
|
||||
|
||||
# includefiles for \verbatiminput and \input
|
||||
includes_mapping = {
|
||||
'../../Parser/Python.asdl': None, # XXX
|
||||
'../../Lib/test/exception_hierarchy.txt': None,
|
||||
'emailmessage': 'email.message.rst',
|
||||
'emailparser': 'email.parser.rst',
|
||||
'emailgenerator': 'email.generator.rst',
|
||||
'emailmimebase': 'email.mime.rst',
|
||||
'emailheaders': 'email.header.rst',
|
||||
'emailcharsets': 'email.charset.rst',
|
||||
'emailencoders': 'email.encoders.rst',
|
||||
'emailexc': 'email.errors.rst',
|
||||
'emailutil': 'email.util.rst',
|
||||
'emailiter': 'email.iterators.rst',
|
||||
}
|
||||
|
||||
# new files to copy from converter/newfiles
|
||||
newfiles_mapping = {
|
||||
'conf.py': 'conf.py',
|
||||
'TODO': 'TODO',
|
||||
'ACKS': 'ACKS',
|
||||
|
||||
'ref_index.rst': 'reference/index.rst',
|
||||
'tutorial_index.rst': 'tutorial/index.rst',
|
||||
'modules_index.rst': 'library/index.rst',
|
||||
'mac_index.rst': 'maclib/index.rst',
|
||||
'ext_index.rst': 'extending/index.rst',
|
||||
'api_index.rst': 'c-api/index.rst',
|
||||
'dist_index.rst': 'distutils/index.rst',
|
||||
'contents.rst': 'contents.rst',
|
||||
'about.rst': 'about.rst',
|
||||
|
||||
'doc.rst': 'documenting/index.rst',
|
||||
'doc_intro.rst': 'documenting/intro.rst',
|
||||
'doc_style.rst': 'documenting/style.rst',
|
||||
'doc_sphinx.rst': 'documenting/sphinx.rst',
|
||||
'doc_rest.rst': 'documenting/rest.rst',
|
||||
'doc_markup.rst': 'documenting/markup.rst',
|
||||
}
|
||||
|
||||
# copy files from the old doc tree
|
||||
copyfiles_mapping = {
|
||||
'api/refcounts.dat': 'data',
|
||||
'lib/email-*.py': 'includes',
|
||||
'lib/minidom-example.py': 'includes',
|
||||
'lib/tzinfo-examples.py': 'includes',
|
||||
'lib/sqlite3/*.py': 'includes/sqlite3',
|
||||
'ext/*.c': 'includes',
|
||||
'ext/*.py': 'includes',
|
||||
'commontex/typestruct.h': 'includes',
|
||||
}
|
||||
|
||||
# files to rename
|
||||
rename_mapping = {
|
||||
'tutorial/1_tutorial.rst': None, # delete
|
||||
'tutorial/2_tutorial.rst': 'tutorial/appetite.rst',
|
||||
'tutorial/3_tutorial.rst': 'tutorial/interpreter.rst',
|
||||
'tutorial/4_tutorial.rst': 'tutorial/introduction.rst',
|
||||
'tutorial/5_tutorial.rst': 'tutorial/controlflow.rst',
|
||||
'tutorial/6_tutorial.rst': 'tutorial/datastructures.rst',
|
||||
'tutorial/7_tutorial.rst': 'tutorial/modules.rst',
|
||||
'tutorial/8_tutorial.rst': 'tutorial/inputoutput.rst',
|
||||
'tutorial/9_tutorial.rst': 'tutorial/errors.rst',
|
||||
'tutorial/10_tutorial.rst': 'tutorial/classes.rst',
|
||||
'tutorial/11_tutorial.rst': 'tutorial/stdlib.rst',
|
||||
'tutorial/12_tutorial.rst': 'tutorial/stdlib2.rst',
|
||||
'tutorial/13_tutorial.rst': 'tutorial/whatnow.rst',
|
||||
'tutorial/14_tutorial.rst': 'tutorial/interactive.rst',
|
||||
'tutorial/15_tutorial.rst': 'tutorial/floatingpoint.rst',
|
||||
'tutorial/16_tutorial.rst': None, # delete
|
||||
|
||||
'distutils/1_distutils.rst': 'distutils/introduction.rst',
|
||||
'distutils/2_distutils.rst': 'distutils/setupscript.rst',
|
||||
'distutils/3_distutils.rst': 'distutils/configfile.rst',
|
||||
'distutils/4_distutils.rst': 'distutils/sourcedist.rst',
|
||||
'distutils/5_distutils.rst': 'distutils/builtdist.rst',
|
||||
'distutils/6_distutils.rst': 'distutils/packageindex.rst',
|
||||
'distutils/7_distutils.rst': 'distutils/uploading.rst',
|
||||
'distutils/8_distutils.rst': 'distutils/examples.rst',
|
||||
'distutils/9_distutils.rst': 'distutils/extending.rst',
|
||||
'distutils/10_distutils.rst': 'distutils/commandref.rst',
|
||||
'distutils/11_distutils.rst': 'distutils/apiref.rst',
|
||||
}
|
||||
|
||||
# toctree entries
|
||||
toctree_mapping = {
|
||||
'mac/scripting': ['gensuitemodule', 'aetools', 'aepack', 'aetypes', 'miniae'],
|
||||
'mac/toolbox': ['colorpicker'],
|
||||
'mac/undoc': [],
|
||||
'lib/libstrings': ['string', 're', 'struct', 'difflib', 'stringio', 'textwrap',
|
||||
'codecs', 'unicodedata', 'stringprep', 'fpformat'],
|
||||
'lib/datatypes': ['datetime', 'calendar', 'collections', 'heapq', 'bisect',
|
||||
'array', 'sets', 'sched', 'mutex', 'queue', 'weakref',
|
||||
'userdict', 'types', 'new', 'copy', 'pprint', 'repr'],
|
||||
'lib/numeric': ['math', 'cmath', 'decimal', 'random', 'itertools', 'functools',
|
||||
'operator'],
|
||||
'lib/netdata': ['email', 'mailcap', 'mailbox', 'mhlib', 'mimetools', 'mimetypes',
|
||||
'mimewriter', 'mimify', 'multifile', 'rfc822',
|
||||
'base64', 'binhex', 'binascii', 'quopri', 'uu'],
|
||||
'lib/markup': ['htmlparser', 'sgmllib', 'htmllib', 'pyexpat', 'xml.dom',
|
||||
'xml.dom.minidom', 'xml.dom.pulldom', 'xml.sax', 'xml.sax.handler',
|
||||
'xml.sax.utils', 'xml.sax.reader', 'xml.etree.elementtree'],
|
||||
'lib/fileformats': ['csv', 'configparser', 'robotparser', 'netrc', 'xdrlib'],
|
||||
'lib/libcrypto': ['hashlib', 'hmac', 'md5', 'sha'],
|
||||
'lib/filesys': ['os.path', 'fileinput', 'stat', 'statvfs', 'filecmp',
|
||||
'tempfile', 'glob', 'fnmatch', 'linecache', 'shutil', 'dircache'],
|
||||
'lib/archiving': ['zlib', 'gzip', 'bz2', 'zipfile', 'tarfile'],
|
||||
'lib/persistence': ['pickle', 'copy_reg', 'shelve', 'marshal', 'anydbm',
|
||||
'whichdb', 'dbm', 'gdbm', 'dbhash', 'bsddb', 'dumbdbm',
|
||||
'sqlite3'],
|
||||
'lib/liballos': ['os', 'time', 'optparse', 'getopt', 'logging', 'getpass',
|
||||
'curses', 'curses.ascii', 'curses.panel', 'platform',
|
||||
'errno', 'ctypes'],
|
||||
'lib/libsomeos': ['select', 'thread', 'threading', 'dummy_thread', 'dummy_threading',
|
||||
'mmap', 'readline', 'rlcompleter'],
|
||||
'lib/libunix': ['posix', 'pwd', 'spwd', 'grp', 'crypt', 'dl', 'termios', 'tty',
|
||||
'pty', 'fcntl', 'pipes', 'posixfile', 'resource', 'nis',
|
||||
'syslog', 'commands'],
|
||||
'lib/ipc': ['subprocess', 'socket', 'signal', 'popen2', 'asyncore', 'asynchat'],
|
||||
'lib/internet': ['webbrowser', 'cgi', 'cgitb', 'wsgiref', 'urllib', 'urllib2',
|
||||
'httplib', 'ftplib', 'poplib', 'imaplib',
|
||||
'nntplib', 'smtplib', 'smtpd', 'telnetlib', 'uuid', 'urlparse',
|
||||
'socketserver', 'basehttpserver', 'simplehttpserver',
|
||||
'cgihttpserver', 'cookielib', 'cookie', 'xmlrpclib',
|
||||
'simplexmlrpcserver', 'docxmlrpcserver'],
|
||||
'lib/libmm': ['audioop', 'imageop', 'aifc', 'sunau', 'wave', 'chunk',
|
||||
'colorsys', 'imghdr', 'sndhdr', 'ossaudiodev'],
|
||||
'lib/i18n': ['gettext', 'locale'],
|
||||
'lib/frameworks': ['cmd', 'shlex'],
|
||||
'lib/development': ['pydoc', 'doctest', 'unittest', 'test'],
|
||||
'lib/libpython': ['sys', '__builtin__', '__main__', 'warnings', 'contextlib',
|
||||
'atexit', 'traceback', '__future__', 'gc', 'inspect',
|
||||
'site', 'user', 'fpectl'],
|
||||
'lib/custominterp': ['code', 'codeop'],
|
||||
'lib/librestricted': ['rexec', 'bastion'],
|
||||
'lib/modules': ['imp', 'zipimport', 'pkgutil', 'modulefinder', 'runpy'],
|
||||
'lib/language': ['parser', 'symbol', 'token', 'keyword', 'tokenize',
|
||||
'tabnanny', 'pyclbr', 'py_compile', 'compileall', 'dis',
|
||||
'pickletools', 'distutils'],
|
||||
'lib/compiler': ['ast'],
|
||||
'lib/libmisc': ['formatter'],
|
||||
'lib/libsgi': ['al', 'cd', 'fl', 'fm', 'gl', 'imgfile', 'jpeg'],
|
||||
'lib/libsun': ['sunaudio'],
|
||||
'lib/windows': ['msilib', 'msvcrt', '_winreg', 'winsound'],
|
||||
'lib/tkinter': [],
|
||||
}
|
||||
|
||||
# map sourcefilename to [pre, post]
|
||||
amendments_mapping = {
|
||||
'license.rst': ['''\
|
||||
.. highlightlang:: none
|
||||
|
||||
*******************
|
||||
History and License
|
||||
*******************
|
||||
|
||||
''', ''],
|
||||
|
||||
'bugs.rst': ['''\
|
||||
**************
|
||||
Reporting Bugs
|
||||
**************
|
||||
|
||||
''', ''],
|
||||
|
||||
'copyright.rst': ['''\
|
||||
*********
|
||||
Copyright
|
||||
*********
|
||||
|
||||
''', ''],
|
||||
|
||||
'install/index.rst': ['''\
|
||||
.. _install-index:
|
||||
|
||||
''', ''],
|
||||
}
|
||||
@@ -1,697 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python documentation LaTeX file parser
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For more documentation, look into the ``restwriter.py`` file.
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
from .docnodes import CommentNode, RootNode, NodeList, ParaSepNode, \
|
||||
TextNode, EmptyNode, NbspNode, SimpleCmdNode, BreakNode, CommandNode, \
|
||||
DescLineCommandNode, InlineNode, IndexNode, SectioningNode, \
|
||||
EnvironmentNode, DescEnvironmentNode, TableNode, VerbatimNode, \
|
||||
ListNode, ItemizeNode, EnumerateNode, DescriptionNode, \
|
||||
DefinitionsNode, ProductionListNode
|
||||
|
||||
from .util import umlaut, empty
|
||||
|
||||
|
||||
class ParserError(Exception):
|
||||
def __init__(self, msg, lineno):
|
||||
Exception.__init__(self, msg, lineno)
|
||||
|
||||
def __str__(self):
|
||||
return '%s, line %s' % self.args
|
||||
|
||||
|
||||
def generic_command(name, argspec, nodetype=CommandNode):
|
||||
def handle(self):
|
||||
args = self.parse_args('\\'+name, argspec)
|
||||
return nodetype(name, args)
|
||||
return handle
|
||||
|
||||
def sectioning_command(name):
|
||||
""" Special handling for sectioning commands: move labels directly following
|
||||
a sectioning command before it, as required by reST. """
|
||||
def handle(self):
|
||||
args = self.parse_args('\\'+name, 'M')
|
||||
snode = SectioningNode(name, args)
|
||||
for l, t, v, r in self.tokens:
|
||||
if t == 'command' and v == 'label':
|
||||
largs = self.parse_args('\\label', 'T')
|
||||
snode.args[0] = NodeList([snode.args[0], CommandNode('label', largs)])
|
||||
break
|
||||
if t == 'text':
|
||||
if not v.strip():
|
||||
# discard whitespace; after a section that's no problem
|
||||
continue
|
||||
self.tokens.push((l, t, v, r))
|
||||
break
|
||||
# no label followed
|
||||
return snode
|
||||
return handle
|
||||
|
||||
def generic_environment(name, argspec, nodetype=EnvironmentNode):
|
||||
def handle(self):
|
||||
args = self.parse_args(name, argspec)
|
||||
return nodetype(name, args, self.parse_until(self.environment_end))
|
||||
return handle
|
||||
|
||||
|
||||
class DocParserMeta(type):
|
||||
def __init__(cls, name, bases, dict):
|
||||
for nodetype, commands in cls.generic_commands.iteritems():
|
||||
for cmdname, argspec in commands.iteritems():
|
||||
setattr(cls, 'handle_' + cmdname,
|
||||
generic_command(cmdname, argspec, nodetype))
|
||||
|
||||
for cmdname in cls.sectioning_commands:
|
||||
setattr(cls, 'handle_' + cmdname, sectioning_command(cmdname))
|
||||
|
||||
for nodetype, envs in cls.generic_envs.iteritems():
|
||||
for envname, argspec in envs.iteritems():
|
||||
setattr(cls, 'handle_%s_env' % envname,
|
||||
generic_environment(envname, argspec, nodetype))
|
||||
|
||||
|
||||
class DocParser(object):
|
||||
""" Parse a Python documentation LaTeX file. """
|
||||
__metaclass__ = DocParserMeta
|
||||
|
||||
def __init__(self, tokenstream, filename):
|
||||
self.tokens = tokenstream
|
||||
self.filename = filename
|
||||
|
||||
def parse(self):
|
||||
self.rootnode = RootNode(self.filename, None)
|
||||
self.rootnode.children = self.parse_until(None)
|
||||
self.rootnode.transform()
|
||||
return self.rootnode
|
||||
|
||||
def parse_until(self, condition=None, endatbrace=False):
|
||||
nodelist = NodeList()
|
||||
bracelevel = 0
|
||||
for l, t, v, r in self.tokens:
|
||||
if condition and condition(t, v, bracelevel):
|
||||
return nodelist.flatten()
|
||||
if t == 'command':
|
||||
if len(v) == 1 and not v.isalpha():
|
||||
nodelist.append(self.handle_special_command(v))
|
||||
continue
|
||||
handler = getattr(self, 'handle_' + v, None)
|
||||
if not handler:
|
||||
raise ParserError('no handler for \\%s command' % v, l)
|
||||
nodelist.append(handler())
|
||||
elif t == 'bgroup':
|
||||
bracelevel += 1
|
||||
elif t == 'egroup':
|
||||
if bracelevel == 0 and endatbrace:
|
||||
return nodelist.flatten()
|
||||
bracelevel -= 1
|
||||
elif t == 'comment':
|
||||
nodelist.append(CommentNode(v))
|
||||
elif t == 'tilde':
|
||||
nodelist.append(NbspNode())
|
||||
elif t == 'mathmode':
|
||||
pass # ignore math mode
|
||||
elif t == 'parasep':
|
||||
nodelist.append(ParaSepNode())
|
||||
else:
|
||||
# includes 'boptional' and 'eoptional' which don't have a
|
||||
# special meaning in text
|
||||
nodelist.append(TextNode(v))
|
||||
return nodelist.flatten()
|
||||
|
||||
def parse_args(self, cmdname, argspec):
|
||||
""" Helper to parse arguments of a command. """
|
||||
# argspec: M = mandatory, T = mandatory, check text-only,
|
||||
# O = optional, Q = optional, check text-only
|
||||
args = []
|
||||
def optional_end(type, value, bracelevel):
|
||||
return type == 'eoptional' and bracelevel == 0
|
||||
|
||||
for i, c in enumerate(argspec):
|
||||
assert c in 'OMTQ'
|
||||
nextl, nextt, nextv, nextr = self.tokens.pop()
|
||||
while nextt == 'comment' or (nextt == 'text' and nextv.isspace()):
|
||||
nextl, nextt, nextv, nextr = self.tokens.pop()
|
||||
|
||||
if c in 'OQ':
|
||||
if nextt == 'boptional':
|
||||
arg = self.parse_until(optional_end)
|
||||
if c == 'Q' and not isinstance(arg, TextNode):
|
||||
raise ParserError('%s: argument %d must be text only' %
|
||||
(cmdname, i), nextl)
|
||||
args.append(arg)
|
||||
else:
|
||||
# not given
|
||||
args.append(EmptyNode())
|
||||
self.tokens.push((nextl, nextt, nextv, nextr))
|
||||
continue
|
||||
|
||||
if nextt == 'bgroup':
|
||||
arg = self.parse_until(None, endatbrace=True)
|
||||
if c == 'T' and not isinstance(arg, TextNode):
|
||||
raise ParserError('%s: argument %d must be text only' %
|
||||
(cmdname, i), nextl)
|
||||
args.append(arg)
|
||||
else:
|
||||
if nextt != 'text':
|
||||
raise ParserError('%s: non-grouped non-text arguments not '
|
||||
'supported' % cmdname, nextl)
|
||||
args.append(TextNode(nextv[0]))
|
||||
self.tokens.push((nextl, nextt, nextv[1:], nextr[1:]))
|
||||
return args
|
||||
|
||||
sectioning_commands = [
|
||||
'chapter',
|
||||
'chapter*',
|
||||
'section',
|
||||
'subsection',
|
||||
'subsubsection',
|
||||
'paragraph',
|
||||
]
|
||||
|
||||
generic_commands = {
|
||||
CommandNode: {
|
||||
'label': 'T',
|
||||
|
||||
'localmoduletable': '',
|
||||
'verbatiminput': 'T',
|
||||
'input': 'T',
|
||||
'centerline': 'M',
|
||||
|
||||
# Pydoc specific commands
|
||||
'versionadded': 'OT',
|
||||
'versionchanged': 'OT',
|
||||
'deprecated': 'TM',
|
||||
'XX' 'X': 'M', # used in dist.tex ;)
|
||||
|
||||
# module-specific
|
||||
'declaremodule': 'QTT',
|
||||
'platform': 'T',
|
||||
'modulesynopsis': 'M',
|
||||
'moduleauthor': 'TT',
|
||||
'sectionauthor': 'TT',
|
||||
|
||||
# reference lists
|
||||
'seelink': 'TMM',
|
||||
'seemodule': 'QTM',
|
||||
'seepep': 'TMM',
|
||||
'seerfc': 'TTM',
|
||||
'seetext': 'M',
|
||||
'seetitle': 'OMM',
|
||||
'seeurl': 'MM',
|
||||
},
|
||||
|
||||
DescLineCommandNode: {
|
||||
# additional items for ...desc
|
||||
'funcline': 'TM',
|
||||
'funclineni': 'TM',
|
||||
'methodline': 'QTM',
|
||||
'methodlineni': 'QTM',
|
||||
'memberline': 'QT',
|
||||
'memberlineni': 'QT',
|
||||
'dataline': 'T',
|
||||
'datalineni': 'T',
|
||||
'cfuncline': 'MTM',
|
||||
'cmemberline': 'TTT',
|
||||
'csimplemacroline': 'T',
|
||||
'ctypeline': 'QT',
|
||||
'cvarline': 'TT',
|
||||
},
|
||||
|
||||
InlineNode: {
|
||||
# specials
|
||||
'footnote': 'M',
|
||||
'frac': 'TT',
|
||||
'refmodule': 'QT',
|
||||
'citetitle': 'QT',
|
||||
'ulink': 'MT',
|
||||
'url': 'M',
|
||||
|
||||
# mapped to normal
|
||||
'textrm': 'M',
|
||||
'b': 'M',
|
||||
'email': 'M', # email addresses are recognized by ReST
|
||||
|
||||
# mapped to **strong**
|
||||
'textbf': 'M',
|
||||
'strong': 'M',
|
||||
|
||||
# mapped to *emphasized*
|
||||
'textit': 'M',
|
||||
'emph': 'M',
|
||||
|
||||
# mapped to ``code``
|
||||
'bfcode': 'M',
|
||||
'code': 'M',
|
||||
'samp': 'M',
|
||||
'character': 'M',
|
||||
'texttt': 'M',
|
||||
|
||||
# mapped to `default role`
|
||||
'var': 'M',
|
||||
|
||||
# mapped to [brackets]
|
||||
'optional': 'M',
|
||||
|
||||
# mapped to :role:`text`
|
||||
'cdata': 'M',
|
||||
'cfunction': 'M', # -> :cfunc:
|
||||
'class': 'M',
|
||||
'command': 'M',
|
||||
'constant': 'M', # -> :const:
|
||||
'csimplemacro': 'M', # -> :cmacro:
|
||||
'ctype': 'M',
|
||||
'data': 'M', # NEW
|
||||
'dfn': 'M',
|
||||
'envvar': 'M',
|
||||
'exception': 'M', # -> :exc:
|
||||
'file': 'M',
|
||||
'filenq': 'M',
|
||||
'filevar': 'M',
|
||||
'function': 'M', # -> :func:
|
||||
'grammartoken': 'M', # -> :token:
|
||||
'guilabel': 'M',
|
||||
'kbd': 'M',
|
||||
'keyword': 'M',
|
||||
'mailheader': 'M',
|
||||
'makevar': 'M',
|
||||
'manpage': 'MM',
|
||||
'member': 'M',
|
||||
'menuselection': 'M',
|
||||
'method': 'M', # -> :meth:
|
||||
'mimetype': 'M',
|
||||
'module': 'M', # -> :mod:
|
||||
'newsgroup': 'M',
|
||||
'option': 'M',
|
||||
'pep': 'M',
|
||||
'program': 'M',
|
||||
'programopt': 'M', # -> :option:
|
||||
'longprogramopt': 'M', # -> :option:
|
||||
'ref': 'T',
|
||||
'regexp': 'M',
|
||||
'rfc': 'M',
|
||||
'token': 'M',
|
||||
|
||||
'NULL': '',
|
||||
# these are defined via substitutions
|
||||
'shortversion': '',
|
||||
'version': '',
|
||||
'today': '',
|
||||
},
|
||||
|
||||
SimpleCmdNode: {
|
||||
# these are directly mapped to text
|
||||
'AA': '', # A as in Angstrom
|
||||
'ASCII': '',
|
||||
'C': '',
|
||||
'Cpp': '',
|
||||
'EOF': '',
|
||||
'LaTeX': '',
|
||||
'POSIX': '',
|
||||
'UNIX': '',
|
||||
'Unix': '',
|
||||
'backslash': '',
|
||||
'copyright': '',
|
||||
'e': '', # backslash
|
||||
'geq': '',
|
||||
'infinity': '',
|
||||
'ldots': '',
|
||||
'leq': '',
|
||||
'moreargs': '',
|
||||
'pi': '',
|
||||
'plusminus': '',
|
||||
'sub': '', # menu separator
|
||||
'textbackslash': '',
|
||||
'textunderscore': '',
|
||||
'texteuro': '',
|
||||
'textasciicircum': '',
|
||||
'textasciitilde': '',
|
||||
'textgreater': '',
|
||||
'textless': '',
|
||||
'textbar': '',
|
||||
'tilde': '',
|
||||
'unspecified': '',
|
||||
},
|
||||
|
||||
IndexNode: {
|
||||
'bifuncindex': 'T',
|
||||
'exindex': 'T',
|
||||
'kwindex': 'T',
|
||||
'obindex': 'T',
|
||||
'opindex': 'T',
|
||||
'refmodindex': 'T',
|
||||
'refexmodindex': 'T',
|
||||
'refbimodindex': 'T',
|
||||
'refstmodindex': 'T',
|
||||
'stindex': 'T',
|
||||
'index': 'M',
|
||||
'indexii': 'TT',
|
||||
'indexiii': 'TTT',
|
||||
'indexiv': 'TTTT',
|
||||
'ttindex': 'T',
|
||||
'withsubitem': 'TM',
|
||||
},
|
||||
|
||||
# These can be safely ignored
|
||||
EmptyNode: {
|
||||
'setindexsubitem': 'T',
|
||||
'tableofcontents': '',
|
||||
'makeindex': '',
|
||||
'makemodindex': '',
|
||||
'maketitle': '',
|
||||
'appendix': '',
|
||||
'documentclass': 'OM',
|
||||
'usepackage': 'OM',
|
||||
'noindent': '',
|
||||
'protect': '',
|
||||
'ifhtml': '',
|
||||
'fi': '',
|
||||
},
|
||||
}
|
||||
|
||||
generic_envs = {
|
||||
EnvironmentNode: {
|
||||
# generic LaTeX environments
|
||||
'abstract': '',
|
||||
'quote': '',
|
||||
'quotation': '',
|
||||
|
||||
'notice': 'Q',
|
||||
'seealso': '',
|
||||
'seealso*': '',
|
||||
},
|
||||
|
||||
DescEnvironmentNode: {
|
||||
# information units
|
||||
'datadesc': 'T',
|
||||
'datadescni': 'T',
|
||||
'excclassdesc': 'TM',
|
||||
'excdesc': 'T',
|
||||
'funcdesc': 'TM',
|
||||
'funcdescni': 'TM',
|
||||
'classdesc': 'TM',
|
||||
'classdesc*': 'T',
|
||||
'memberdesc': 'QT',
|
||||
'memberdescni': 'QT',
|
||||
'methoddesc': 'QMM',
|
||||
'methoddescni': 'QMM',
|
||||
'opcodedesc': 'TT',
|
||||
|
||||
'cfuncdesc': 'MTM',
|
||||
'cmemberdesc': 'TTT',
|
||||
'csimplemacrodesc': 'T',
|
||||
'ctypedesc': 'QT',
|
||||
'cvardesc': 'TT',
|
||||
},
|
||||
}
|
||||
|
||||
# ------------------------- special handlers -----------------------------
|
||||
|
||||
def handle_special_command(self, cmdname):
|
||||
if cmdname in '{}%$^#&_ ':
|
||||
# these are just escapes for special LaTeX commands
|
||||
return TextNode(cmdname)
|
||||
elif cmdname in '\'`~"c':
|
||||
# accents and umlauts
|
||||
nextl, nextt, nextv, nextr = self.tokens.next()
|
||||
if nextt == 'bgroup':
|
||||
_, nextt, _, _ = self.tokens.next()
|
||||
if nextt != 'egroup':
|
||||
raise ParserError('wrong argtype for \\%s' % cmdname, nextl)
|
||||
return TextNode(cmdname)
|
||||
if nextt != 'text':
|
||||
# not nice, but {\~} = ~
|
||||
self.tokens.push((nextl, nextt, nextv, nextr))
|
||||
return TextNode(cmdname)
|
||||
c = umlaut(cmdname, nextv[0])
|
||||
self.tokens.push((nextl, nextt, nextv[1:], nextr[1:]))
|
||||
return TextNode(c)
|
||||
elif cmdname == '\\':
|
||||
return BreakNode()
|
||||
raise ParserError('no handler for \\%s command' % cmdname,
|
||||
self.tokens.peek()[0])
|
||||
|
||||
def handle_begin(self):
|
||||
envname, = self.parse_args('begin', 'T')
|
||||
handler = getattr(self, 'handle_%s_env' % envname.text, None)
|
||||
if not handler:
|
||||
raise ParserError('no handler for %s environment' % envname.text,
|
||||
self.tokens.peek()[0])
|
||||
return handler()
|
||||
|
||||
# ------------------------- command handlers -----------------------------
|
||||
|
||||
def mk_metadata_handler(self, name, mdname=None):
|
||||
if mdname is None:
|
||||
mdname = name
|
||||
def handler(self):
|
||||
data, = self.parse_args('\\'+name, 'M')
|
||||
self.rootnode.params[mdname] = data
|
||||
return EmptyNode()
|
||||
return handler
|
||||
|
||||
handle_title = mk_metadata_handler(None, 'title')
|
||||
handle_author = mk_metadata_handler(None, 'author')
|
||||
handle_authoraddress = mk_metadata_handler(None, 'authoraddress')
|
||||
handle_date = mk_metadata_handler(None, 'date')
|
||||
handle_release = mk_metadata_handler(None, 'release')
|
||||
handle_setshortversion = mk_metadata_handler(None, 'setshortversion',
|
||||
'shortversion')
|
||||
handle_setreleaseinfo = mk_metadata_handler(None, 'setreleaseinfo',
|
||||
'releaseinfo')
|
||||
|
||||
def handle_note(self):
|
||||
note = self.parse_args('\\note', 'M')[0]
|
||||
return EnvironmentNode('notice', [TextNode('note')], note)
|
||||
|
||||
def handle_warning(self):
|
||||
warning = self.parse_args('\\warning', 'M')[0]
|
||||
return EnvironmentNode('notice', [TextNode('warning')], warning)
|
||||
|
||||
def handle_ifx(self):
|
||||
for l, t, v, r in self.tokens:
|
||||
if t == 'command' and v == 'fi':
|
||||
break
|
||||
return EmptyNode()
|
||||
|
||||
def handle_c(self):
|
||||
return self.handle_special_command('c')
|
||||
|
||||
def handle_mbox(self):
|
||||
return self.parse_args('\\mbox', 'M')[0]
|
||||
|
||||
def handle_leftline(self):
|
||||
return self.parse_args('\\leftline', 'M')[0]
|
||||
|
||||
def handle_Large(self):
|
||||
return self.parse_args('\\Large', 'M')[0]
|
||||
|
||||
def handle_pytype(self):
|
||||
# \pytype{x} is synonymous to \class{x} now
|
||||
return self.handle_class()
|
||||
|
||||
def handle_nodename(self):
|
||||
return self.handle_label()
|
||||
|
||||
def handle_verb(self):
|
||||
# skip delimiter
|
||||
l, t, v, r = self.tokens.next()
|
||||
l, t, v, r = self.tokens.next()
|
||||
assert t == 'text'
|
||||
node = InlineNode('code', [TextNode(r)])
|
||||
# skip delimiter
|
||||
l, t, v, r = self.tokens.next()
|
||||
return node
|
||||
|
||||
def handle_locallinewidth(self):
|
||||
return EmptyNode()
|
||||
|
||||
def handle_linewidth(self):
|
||||
return EmptyNode()
|
||||
|
||||
def handle_setlength(self):
|
||||
self.parse_args('\\setlength', 'MM')
|
||||
return EmptyNode()
|
||||
|
||||
def handle_stmodindex(self):
|
||||
arg, = self.parse_args('\\stmodindex', 'T')
|
||||
return CommandNode('declaremodule', [EmptyNode(),
|
||||
TextNode(u'standard'),
|
||||
arg])
|
||||
|
||||
def handle_indexname(self):
|
||||
return EmptyNode()
|
||||
|
||||
def handle_renewcommand(self):
|
||||
self.parse_args('\\renewcommand', 'MM')
|
||||
return EmptyNode()
|
||||
|
||||
# ------------------------- environment handlers -------------------------
|
||||
|
||||
def handle_document_env(self):
|
||||
return self.parse_until(self.environment_end)
|
||||
|
||||
handle_sloppypar_env = handle_document_env
|
||||
handle_flushleft_env = handle_document_env
|
||||
handle_math_env = handle_document_env
|
||||
|
||||
def handle_verbatim_env(self):
|
||||
text = []
|
||||
for l, t, v, r in self.tokens:
|
||||
if t == 'command' and v == 'end' :
|
||||
tok = self.tokens.peekmany(3)
|
||||
if tok[0][1] == 'bgroup' and \
|
||||
tok[1][1] == 'text' and \
|
||||
tok[1][2] == 'verbatim' and \
|
||||
tok[2][1] == 'egroup':
|
||||
self.tokens.popmany(3)
|
||||
break
|
||||
text.append(r)
|
||||
return VerbatimNode(TextNode(''.join(text)))
|
||||
|
||||
# involved math markup must be corrected manually
|
||||
def handle_displaymath_env(self):
|
||||
text = ['XXX: translate this math']
|
||||
for l, t, v, r in self.tokens:
|
||||
if t == 'command' and v == 'end' :
|
||||
tok = self.tokens.peekmany(3)
|
||||
if tok[0][1] == 'bgroup' and \
|
||||
tok[1][1] == 'text' and \
|
||||
tok[1][2] == 'displaymath' and \
|
||||
tok[2][1] == 'egroup':
|
||||
self.tokens.popmany(3)
|
||||
break
|
||||
text.append(r)
|
||||
return VerbatimNode(TextNode(''.join(text)))
|
||||
|
||||
# alltt is different from verbatim because it allows markup
|
||||
def handle_alltt_env(self):
|
||||
nodelist = NodeList()
|
||||
for l, t, v, r in self.tokens:
|
||||
if self.environment_end(t, v):
|
||||
break
|
||||
if t == 'command':
|
||||
if len(v) == 1 and not v.isalpha():
|
||||
nodelist.append(self.handle_special_command(v))
|
||||
continue
|
||||
handler = getattr(self, 'handle_' + v, None)
|
||||
if not handler:
|
||||
raise ParserError('no handler for \\%s command' % v, l)
|
||||
nodelist.append(handler())
|
||||
elif t == 'comment':
|
||||
nodelist.append(CommentNode(v))
|
||||
else:
|
||||
# all else is appended raw
|
||||
nodelist.append(TextNode(r))
|
||||
return VerbatimNode(nodelist.flatten())
|
||||
|
||||
def handle_itemize_env(self, nodetype=ItemizeNode):
|
||||
items = []
|
||||
# a usecase for nonlocal :)
|
||||
running = [False]
|
||||
|
||||
def item_condition(t, v, bracelevel):
|
||||
if self.environment_end(t, v):
|
||||
del running[:]
|
||||
return True
|
||||
if t == 'command' and v == 'item':
|
||||
return True
|
||||
return False
|
||||
|
||||
# the text until the first \item is discarded
|
||||
self.parse_until(item_condition)
|
||||
while running:
|
||||
itemname, = self.parse_args('\\item', 'O')
|
||||
itemcontent = self.parse_until(item_condition)
|
||||
items.append([itemname, itemcontent])
|
||||
return nodetype(items)
|
||||
|
||||
def handle_enumerate_env(self):
|
||||
return self.handle_itemize_env(EnumerateNode)
|
||||
|
||||
def handle_description_env(self):
|
||||
return self.handle_itemize_env(DescriptionNode)
|
||||
|
||||
def handle_definitions_env(self):
|
||||
items = []
|
||||
running = [False]
|
||||
|
||||
def item_condition(t, v, bracelevel):
|
||||
if self.environment_end(t, v):
|
||||
del running[:]
|
||||
return True
|
||||
if t == 'command' and v == 'term':
|
||||
return True
|
||||
return False
|
||||
|
||||
# the text until the first \item is discarded
|
||||
self.parse_until(item_condition)
|
||||
while running:
|
||||
itemname, = self.parse_args('\\term', 'M')
|
||||
itemcontent = self.parse_until(item_condition)
|
||||
items.append([itemname, itemcontent])
|
||||
return DefinitionsNode(items)
|
||||
|
||||
def mk_table_handler(self, envname, numcols):
|
||||
def handle_table(self):
|
||||
args = self.parse_args('table'+envname, 'TT' + 'M'*numcols)
|
||||
firstcolformat = args[1].text
|
||||
headings = args[2:]
|
||||
lines = []
|
||||
for l, t, v, r in self.tokens:
|
||||
# XXX: everything outside of \linexxx is lost here
|
||||
if t == 'command':
|
||||
if v == 'line'+envname:
|
||||
lines.append(self.parse_args('\\line'+envname,
|
||||
'M'*numcols))
|
||||
elif v == 'end':
|
||||
arg = self.parse_args('\\end', 'T')
|
||||
assert arg[0].text.endswith('table'+envname), arg[0].text
|
||||
break
|
||||
for line in lines:
|
||||
if not empty(line[0]):
|
||||
line[0] = InlineNode(firstcolformat, [line[0]])
|
||||
return TableNode(numcols, headings, lines)
|
||||
return handle_table
|
||||
|
||||
handle_tableii_env = mk_table_handler(None, 'ii', 2)
|
||||
handle_longtableii_env = handle_tableii_env
|
||||
handle_tableiii_env = mk_table_handler(None, 'iii', 3)
|
||||
handle_longtableiii_env = handle_tableiii_env
|
||||
handle_tableiv_env = mk_table_handler(None, 'iv', 4)
|
||||
handle_longtableiv_env = handle_tableiv_env
|
||||
handle_tablev_env = mk_table_handler(None, 'v', 5)
|
||||
handle_longtablev_env = handle_tablev_env
|
||||
|
||||
def handle_productionlist_env(self):
|
||||
env_args = self.parse_args('productionlist', 'Q')
|
||||
items = []
|
||||
for l, t, v, r in self.tokens:
|
||||
# XXX: everything outside of \production is lost here
|
||||
if t == 'command':
|
||||
if v == 'production':
|
||||
items.append(self.parse_args('\\production', 'TM'))
|
||||
elif v == 'productioncont':
|
||||
args = self.parse_args('\\productioncont', 'M')
|
||||
args.insert(0, EmptyNode())
|
||||
items.append(args)
|
||||
elif v == 'end':
|
||||
arg = self.parse_args('\\end', 'T')
|
||||
assert arg[0].text == 'productionlist'
|
||||
break
|
||||
node = ProductionListNode(items)
|
||||
# the argument specifies a production group
|
||||
node.arg = env_args[0]
|
||||
return node
|
||||
|
||||
def environment_end(self, t, v, bracelevel=0):
|
||||
if t == 'command' and v == 'end':
|
||||
self.parse_args('\\end', 'T')
|
||||
return True
|
||||
return False
|
||||
@@ -1,197 +0,0 @@
|
||||
Contributors to the Python Documentation
|
||||
----------------------------------------
|
||||
|
||||
This file lists people who have contributed in some way to the Python
|
||||
documentation. It is probably not complete -- if you feel that you or
|
||||
anyone else should be on this list, please let us know (send email to
|
||||
docs@python.org), and we'll be glad to correct the problem.
|
||||
|
||||
It is only with the input and contributions of the Python community
|
||||
that Python has such wonderful documentation -- Thank You!
|
||||
|
||||
|
||||
* Aahz
|
||||
* Michael Abbott
|
||||
* Steve Alexander
|
||||
* Jim Ahlstrom
|
||||
* Fred Allen
|
||||
* A. Amoroso
|
||||
* Pehr Anderson
|
||||
* Oliver Andrich
|
||||
* Jesús Cea Avión
|
||||
* Daniel Barclay
|
||||
* Chris Barker
|
||||
* Don Bashford
|
||||
* Anthony Baxter
|
||||
* Bennett Benson
|
||||
* Jonathan Black
|
||||
* Robin Boerdijk
|
||||
* Michal Bozon
|
||||
* Aaron Brancotti
|
||||
* Keith Briggs
|
||||
* Lee Busby
|
||||
* Lorenzo M. Catucci
|
||||
* Mauro Cicognini
|
||||
* Gilles Civario
|
||||
* Mike Clarkson
|
||||
* Steve Clift
|
||||
* Dave Cole
|
||||
* Matthew Cowles
|
||||
* Jeremy Craven
|
||||
* Andrew Dalke
|
||||
* Ben Darnell
|
||||
* L. Peter Deutsch
|
||||
* Robert Donohue
|
||||
* Fred L. Drake, Jr.
|
||||
* Jeff Epler
|
||||
* Michael Ernst
|
||||
* Blame Andy Eskilsson
|
||||
* Carey Evans
|
||||
* Martijn Faassen
|
||||
* Carl Feynman
|
||||
* Hernán Martínez Foffani
|
||||
* Stefan Franke
|
||||
* Jim Fulton
|
||||
* Peter Funk
|
||||
* Lele Gaifax
|
||||
* Matthew Gallagher
|
||||
* Ben Gertzfield
|
||||
* Nadim Ghaznavi
|
||||
* Jonathan Giddy
|
||||
* Shelley Gooch
|
||||
* Nathaniel Gray
|
||||
* Grant Griffin
|
||||
* Thomas Guettler
|
||||
* Anders Hammarquist
|
||||
* Mark Hammond
|
||||
* Harald Hanche-Olsen
|
||||
* Manus Hand
|
||||
* Gerhard Häring
|
||||
* Travis B. Hartwell
|
||||
* Janko Hauser
|
||||
* Bernhard Herzog
|
||||
* Magnus L. Hetland
|
||||
* Konrad Hinsen
|
||||
* Stefan Hoffmeister
|
||||
* Albert Hofkamp
|
||||
* Gregor Hoffleit
|
||||
* Steve Holden
|
||||
* Thomas Holenstein
|
||||
* Gerrit Holl
|
||||
* Rob Hooft
|
||||
* Brian Hooper
|
||||
* Randall Hopper
|
||||
* Michael Hudson
|
||||
* Eric Huss
|
||||
* Jeremy Hylton
|
||||
* Roger Irwin
|
||||
* Jack Jansen
|
||||
* Philip H. Jensen
|
||||
* Pedro Diaz Jimenez
|
||||
* Kent Johnson
|
||||
* Lucas de Jonge
|
||||
* Andreas Jung
|
||||
* Robert Kern
|
||||
* Jim Kerr
|
||||
* Jan Kim
|
||||
* Greg Kochanski
|
||||
* Guido Kollerie
|
||||
* Peter A. Koren
|
||||
* Daniel Kozan
|
||||
* Andrew M. Kuchling
|
||||
* Dave Kuhlman
|
||||
* Erno Kuusela
|
||||
* Detlef Lannert
|
||||
* Piers Lauder
|
||||
* Glyph Lefkowitz
|
||||
* Marc-André Lemburg
|
||||
* Ulf A. Lindgren
|
||||
* Everett Lipman
|
||||
* Mirko Liss
|
||||
* Martin von Löwis
|
||||
* Fredrik Lundh
|
||||
* Jeff MacDonald
|
||||
* John Machin
|
||||
* Andrew MacIntyre
|
||||
* Vladimir Marangozov
|
||||
* Vincent Marchetti
|
||||
* Laura Matson
|
||||
* Daniel May
|
||||
* Doug Mennella
|
||||
* Paolo Milani
|
||||
* Skip Montanaro
|
||||
* Paul Moore
|
||||
* Ross Moore
|
||||
* Sjoerd Mullender
|
||||
* Dale Nagata
|
||||
* Ng Pheng Siong
|
||||
* Koray Oner
|
||||
* Tomas Oppelstrup
|
||||
* Denis S. Otkidach
|
||||
* Zooko O'Whielacronx
|
||||
* William Park
|
||||
* Joonas Paalasmaa
|
||||
* Harri Pasanen
|
||||
* Bo Peng
|
||||
* Tim Peters
|
||||
* Christopher Petrilli
|
||||
* Justin D. Pettit
|
||||
* Chris Phoenix
|
||||
* François Pinard
|
||||
* Paul Prescod
|
||||
* Eric S. Raymond
|
||||
* Edward K. Ream
|
||||
* Sean Reifschneider
|
||||
* Bernhard Reiter
|
||||
* Armin Rigo
|
||||
* Wes Rishel
|
||||
* Jim Roskind
|
||||
* Guido van Rossum
|
||||
* Donald Wallace Rouse II
|
||||
* Nick Russo
|
||||
* Chris Ryland
|
||||
* Constantina S.
|
||||
* Hugh Sasse
|
||||
* Bob Savage
|
||||
* Scott Schram
|
||||
* Neil Schemenauer
|
||||
* Barry Scott
|
||||
* Joakim Sernbrant
|
||||
* Justin Sheehy
|
||||
* Michael Simcich
|
||||
* Ionel Simionescu
|
||||
* Gregory P. Smith
|
||||
* Roy Smith
|
||||
* Clay Spence
|
||||
* Nicholas Spies
|
||||
* Tage Stabell-Kulo
|
||||
* Frank Stajano
|
||||
* Anthony Starks
|
||||
* Greg Stein
|
||||
* Peter Stoehr
|
||||
* Mark Summerfield
|
||||
* Reuben Sumner
|
||||
* Kalle Svensson
|
||||
* Jim Tittsler
|
||||
* Ville Vainio
|
||||
* Martijn Vries
|
||||
* Charles G. Waldman
|
||||
* Greg Ward
|
||||
* Barry Warsaw
|
||||
* Corran Webster
|
||||
* Glyn Webster
|
||||
* Bob Weiner
|
||||
* Eddy Welbourne
|
||||
* Mats Wichmann
|
||||
* Gerry Wiener
|
||||
* Timothy Wild
|
||||
* Collin Winter
|
||||
* Blake Winton
|
||||
* Dan Wolfe
|
||||
* Steven Work
|
||||
* Thomas Wouters
|
||||
* Ka-Ping Yee
|
||||
* Rory Yorke
|
||||
* Moshe Zadka
|
||||
* Milan Zamazal
|
||||
* Cheng Zhang
|
||||
@@ -1,18 +0,0 @@
|
||||
To do after conversion
|
||||
======================
|
||||
|
||||
* fix all references and links marked with `XXX`
|
||||
* adjust all literal include paths
|
||||
* remove all non-literal includes
|
||||
* fix all duplicate labels and undefined label references
|
||||
* fix the email package docs: add a toctree
|
||||
* split very large files and add toctrees
|
||||
* integrate standalone HOWTOs
|
||||
* find out which files get "comments disabled" metadata
|
||||
* double backslashes in production lists
|
||||
* add synopses for each module
|
||||
* write "About these documents"
|
||||
* finish "Documenting Python"
|
||||
* extend copyright.rst
|
||||
* fix the "quadruple" index term
|
||||
* fix :file: and |version| in install
|
||||
@@ -1,18 +0,0 @@
|
||||
=====================
|
||||
About these documents
|
||||
=====================
|
||||
|
||||
These documents are generated from `reStructuredText
|
||||
<http://docutils.sf.net/rst.html>`_ sources by *Sphinx*, a document processor
|
||||
specifically written for the Python documentation.
|
||||
|
||||
In the online version of these documents, you can submit comments and suggest
|
||||
changes directly on the documentation pages.
|
||||
|
||||
Development of the documentation and its toolchain takes place on the
|
||||
docs@python.org mailing list. We're always looking for volunteers wanting
|
||||
to help with the docs, so feel free to send a mail there!
|
||||
|
||||
See :ref:`reporting-bugs` for information how to report bugs in Python itself.
|
||||
|
||||
.. include:: ACKS
|
||||
@@ -1,33 +0,0 @@
|
||||
.. _c-api-index:
|
||||
|
||||
##################################
|
||||
Python/C API Reference Manual
|
||||
##################################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
This manual documents the API used by C and C++ programmers who want to write
|
||||
extension modules or embed Python. It is a companion to :ref:`extending-index`,
|
||||
which describes the general principles of extension writing but does not
|
||||
document the API functions in detail.
|
||||
|
||||
.. warning::
|
||||
|
||||
The current version of this document is somewhat incomplete. However, most of
|
||||
the important functions, types and structures are described.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
intro.rst
|
||||
veryhigh.rst
|
||||
refcounting.rst
|
||||
exceptions.rst
|
||||
utilities.rst
|
||||
abstract.rst
|
||||
concrete.rst
|
||||
init.rst
|
||||
memory.rst
|
||||
newtypes.rst
|
||||
@@ -1,47 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Python documentation build configuration file
|
||||
#
|
||||
# The contents of this file are pickled, so don't put values in the namespace
|
||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||
#
|
||||
|
||||
# The default replacements for |version| and |release|.
|
||||
# If 'auto', Sphinx looks for the Include/patchlevel.h file in the current Python
|
||||
# source tree and replaces the values accordingly.
|
||||
#
|
||||
# The short X.Y version.
|
||||
# version = '2.6'
|
||||
version = 'auto'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# release = '2.6a0'
|
||||
release = 'auto'
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of files that shouldn't be included in the build.
|
||||
unused_files = [
|
||||
'whatsnew/2.0.rst',
|
||||
'whatsnew/2.1.rst',
|
||||
'whatsnew/2.2.rst',
|
||||
'whatsnew/2.3.rst',
|
||||
'whatsnew/2.4.rst',
|
||||
'whatsnew/2.5.rst',
|
||||
'maclib/scrap.rst',
|
||||
'library/xmllib.rst',
|
||||
]
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
last_updated_format = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
use_smartypants = True
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
@@ -1,21 +0,0 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
Python Documentation contents
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
.. toctree::
|
||||
|
||||
whatsnew/2.6.rst
|
||||
tutorial/index.rst
|
||||
reference/index.rst
|
||||
library/index.rst
|
||||
maclib/index.rst
|
||||
extending/index.rst
|
||||
c-api/index.rst
|
||||
distutils/index.rst
|
||||
install/index.rst
|
||||
documenting/index.rst
|
||||
|
||||
bugs.rst
|
||||
about.rst
|
||||
license.rst
|
||||
copyright.rst
|
||||
@@ -1,28 +0,0 @@
|
||||
.. _distutils-index:
|
||||
|
||||
###############################
|
||||
Distributing Python Modules
|
||||
###############################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
This document describes the Python Distribution Utilities ("Distutils") from
|
||||
the module developer's point of view, describing how to use the Distutils to
|
||||
make Python modules and extensions easily available to a wider audience with
|
||||
very little overhead for build/release/install mechanics.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
introduction.rst
|
||||
setupscript.rst
|
||||
configfile.rst
|
||||
sourcedist.rst
|
||||
builtdist.rst
|
||||
packageindex.rst
|
||||
uploading.rst
|
||||
examples.rst
|
||||
extending.rst
|
||||
commandref.rst
|
||||
apiref.rst
|
||||
@@ -1,33 +0,0 @@
|
||||
.. _documenting-index:
|
||||
|
||||
######################
|
||||
Documenting Python
|
||||
######################
|
||||
|
||||
|
||||
The Python language has a substantial body of documentation, much of it
|
||||
contributed by various authors. The markup used for the Python documentation is
|
||||
`reStructuredText`_, developed by the `docutils`_ project, amended by custom
|
||||
directives and using a toolset named *Sphinx* to postprocess the HTML output.
|
||||
|
||||
This document describes the style guide for our documentation, the custom
|
||||
reStructuredText markup introduced to support Python documentation and how it
|
||||
should be used, as well as the Sphinx build system.
|
||||
|
||||
.. _reStructuredText: http://docutils.sf.net/rst.html
|
||||
.. _docutils: http://docutils.sf.net/
|
||||
|
||||
If you're interested in contributing to Python's documentation, there's no need
|
||||
to write reStructuredText if you're not so inclined; plain text contributions
|
||||
are more than welcome as well.
|
||||
|
||||
.. toctree::
|
||||
|
||||
intro.rst
|
||||
style.rst
|
||||
rest.rst
|
||||
markup.rst
|
||||
sphinx.rst
|
||||
|
||||
.. XXX add credits, thanks etc.
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
Python's documentation has long been considered to be good for a free
|
||||
programming language. There are a number of reasons for this, the most
|
||||
important being the early commitment of Python's creator, Guido van Rossum, to
|
||||
providing documentation on the language and its libraries, and the continuing
|
||||
involvement of the user community in providing assistance for creating and
|
||||
maintaining documentation.
|
||||
|
||||
The involvement of the community takes many forms, from authoring to bug reports
|
||||
to just plain complaining when the documentation could be more complete or
|
||||
easier to use.
|
||||
|
||||
This document is aimed at authors and potential authors of documentation for
|
||||
Python. More specifically, it is for people contributing to the standard
|
||||
documentation and developing additional documents using the same tools as the
|
||||
standard documents. This guide will be less useful for authors using the Python
|
||||
documentation tools for topics other than Python, and less useful still for
|
||||
authors not using the tools at all.
|
||||
|
||||
If your interest is in contributing to the Python documentation, but you don't
|
||||
have the time or inclination to learn reStructuredText and the markup structures
|
||||
documented here, there's a welcoming place for you among the Python contributors
|
||||
as well. Any time you feel that you can clarify existing documentation or
|
||||
provide documentation that's missing, the existing documentation team will
|
||||
gladly work with you to integrate your text, dealing with the markup for you.
|
||||
Please don't let the material in this document stand between the documentation
|
||||
and your desire to help out!
|
||||
@@ -1,742 +0,0 @@
|
||||
.. highlightlang:: rest
|
||||
|
||||
Additional Markup Constructs
|
||||
============================
|
||||
|
||||
Sphinx adds a lot of new directives and interpreted text roles to standard reST
|
||||
markup. This section contains the reference material for these facilities.
|
||||
Documentation for "standard" reST constructs is not included here, though
|
||||
they are used in the Python documentation.
|
||||
|
||||
XXX: file-wide metadata
|
||||
|
||||
Meta-information markup
|
||||
-----------------------
|
||||
|
||||
.. describe:: sectionauthor
|
||||
|
||||
Identifies the author of the current section. The argument should include
|
||||
the author's name such that it can be used for presentation (though it isn't)
|
||||
and email address. The domain name portion of the address should be lower
|
||||
case. Example::
|
||||
|
||||
.. sectionauthor:: Guido van Rossum <guido@python.org>
|
||||
|
||||
Currently, this markup isn't reflected in the output in any way, but it helps
|
||||
keep track of contributions.
|
||||
|
||||
|
||||
Module-specific markup
|
||||
----------------------
|
||||
|
||||
The markup described in this section is used to provide information about a
|
||||
module being documented. Each module should be documented in its own file.
|
||||
Normally this markup appears after the title heading of that file; a typical
|
||||
file might start like this::
|
||||
|
||||
:mod:`parrot` -- Dead parrot access
|
||||
===================================
|
||||
|
||||
.. module:: parrot
|
||||
:platform: Unix, Windows
|
||||
:synopsis: Analyze and reanimate dead parrots.
|
||||
.. moduleauthor:: Eric Cleese <eric@python.invalid>
|
||||
.. moduleauthor:: John Idle <john@python.invalid>
|
||||
|
||||
As you can see, the module-specific markup consists of two directives, the
|
||||
``module`` directive and the ``moduleauthor`` directive.
|
||||
|
||||
.. describe:: module
|
||||
|
||||
This directive marks the beginning of the description of a module (or package
|
||||
submodule, in which case the name should be fully qualified, including the
|
||||
package name).
|
||||
|
||||
The ``platform`` option, if present, is a comma-separated list of the
|
||||
platforms on which the module is available (if it is available on all
|
||||
platforms, the option should be omitted). The keys are short identifiers;
|
||||
examples that are in use include "IRIX", "Mac", "Windows", and "Unix". It is
|
||||
important to use a key which has already been used when applicable.
|
||||
|
||||
The ``synopsis`` option should consist of one sentence describing the
|
||||
module's purpose -- it is currently only used in the Global Module Index.
|
||||
|
||||
.. describe:: moduleauthor
|
||||
|
||||
The ``moduleauthor`` directive, which can appear multiple times, names the
|
||||
authors of the module code, just like ``sectionauthor`` names the author(s)
|
||||
of a piece of documentation. It too does not result in any output currently.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
It is important to make the section title of a module-describing file
|
||||
meaningful since that value will be inserted in the table-of-contents trees
|
||||
in overview files.
|
||||
|
||||
|
||||
Information units
|
||||
-----------------
|
||||
|
||||
There are a number of directives used to describe specific features provided by
|
||||
modules. Each directive requires one or more signatures to provide basic
|
||||
information about what is being described, and the content should be the
|
||||
description. The basic version makes entries in the general index; if no index
|
||||
entry is desired, you can give the directive option flag ``:noindex:``. The
|
||||
following example shows all of the features of this directive type::
|
||||
|
||||
.. function:: spam(eggs)
|
||||
ham(eggs)
|
||||
:noindex:
|
||||
|
||||
Spam or ham the foo.
|
||||
|
||||
The signatures of object methods or data attributes should always include the
|
||||
type name (``.. method:: FileInput.input(...)``), even if it is obvious from the
|
||||
context which type they belong to; this is to enable consistent
|
||||
cross-references. If you describe methods belonging to an abstract protocol,
|
||||
such as "context managers", include a (pseudo-)type name too to make the
|
||||
index entries more informative.
|
||||
|
||||
The directives are:
|
||||
|
||||
.. describe:: cfunction
|
||||
|
||||
Describes a C function. The signature should be given as in C, e.g.::
|
||||
|
||||
.. cfunction:: PyObject* PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
|
||||
|
||||
This is also used to describe function-like preprocessor macros. The names
|
||||
of the arguments should be given so they may be used in the description.
|
||||
|
||||
Note that you don't have to backslash-escape asterisks in the signature,
|
||||
as it is not parsed by the reST inliner.
|
||||
|
||||
.. describe:: cmember
|
||||
|
||||
Describes a C struct member. Example signature::
|
||||
|
||||
.. cmember:: PyObject* PyTypeObject.tp_bases
|
||||
|
||||
The text of the description should include the range of values allowed, how
|
||||
the value should be interpreted, and whether the value can be changed.
|
||||
References to structure members in text should use the ``member`` role.
|
||||
|
||||
.. describe:: cmacro
|
||||
|
||||
Describes a "simple" C macro. Simple macros are macros which are used
|
||||
for code expansion, but which do not take arguments so cannot be described as
|
||||
functions. This is not to be used for simple constant definitions. Examples
|
||||
of its use in the Python documentation include :cmacro:`PyObject_HEAD` and
|
||||
:cmacro:`Py_BEGIN_ALLOW_THREADS`.
|
||||
|
||||
.. describe:: ctype
|
||||
|
||||
Describes a C type. The signature should just be the type name.
|
||||
|
||||
.. describe:: cvar
|
||||
|
||||
Describes a global C variable. The signature should include the type, such
|
||||
as::
|
||||
|
||||
.. cvar:: PyObject* PyClass_Type
|
||||
|
||||
.. describe:: data
|
||||
|
||||
Describes global data in a module, including both variables and values used
|
||||
as "defined constants." Class and object attributes are not documented
|
||||
using this environment.
|
||||
|
||||
.. describe:: exception
|
||||
|
||||
Describes an exception class. The signature can, but need not include
|
||||
parentheses with constructor arguments.
|
||||
|
||||
.. describe:: function
|
||||
|
||||
Describes a module-level function. The signature should include the
|
||||
parameters, enclosing optional parameters in brackets. Default values can be
|
||||
given if it enhances clarity. For example::
|
||||
|
||||
.. function:: Timer.repeat([repeat=3[, number=1000000]])
|
||||
|
||||
Object methods are not documented using this directive. Bound object methods
|
||||
placed in the module namespace as part of the public interface of the module
|
||||
are documented using this, as they are equivalent to normal functions for
|
||||
most purposes.
|
||||
|
||||
The description should include information about the parameters required and
|
||||
how they are used (especially whether mutable objects passed as parameters
|
||||
are modified), side effects, and possible exceptions. A small example may be
|
||||
provided.
|
||||
|
||||
.. describe:: class
|
||||
|
||||
Describes a class. The signature can include parentheses with parameters
|
||||
which will be shown as the constructor arguments.
|
||||
|
||||
.. describe:: attribute
|
||||
|
||||
Describes an object data attribute. The description should include
|
||||
information about the type of the data to be expected and whether it may be
|
||||
changed directly.
|
||||
|
||||
.. describe:: method
|
||||
|
||||
Describes an object method. The parameters should not include the ``self``
|
||||
parameter. The description should include similar information to that
|
||||
described for ``function``.
|
||||
|
||||
.. describe:: opcode
|
||||
|
||||
Describes a Python bytecode instruction.
|
||||
|
||||
|
||||
There is also a generic version of these directives:
|
||||
|
||||
.. describe:: describe
|
||||
|
||||
This directive produces the same formatting as the specific ones explained
|
||||
above but does not create index entries or cross-referencing targets. It is
|
||||
used, for example, to describe the directives in this document. Example::
|
||||
|
||||
.. describe:: opcode
|
||||
|
||||
Describes a Python bytecode instruction.
|
||||
|
||||
|
||||
Showing code examples
|
||||
---------------------
|
||||
|
||||
Examples of Python source code or interactive sessions are represented using
|
||||
standard reST literal blocks. They are started by a ``::`` at the end of the
|
||||
preceding paragraph and delimited by indentation.
|
||||
|
||||
Representing an interactive session requires including the prompts and output
|
||||
along with the Python code. No special markup is required for interactive
|
||||
sessions. After the last line of input or output presented, there should not be
|
||||
an "unused" primary prompt; this is an example of what *not* to do::
|
||||
|
||||
>>> 1 + 1
|
||||
2
|
||||
>>>
|
||||
|
||||
Syntax highlighting is handled in a smart way:
|
||||
|
||||
* There is a "highlighting language" for each source file. Per default,
|
||||
this is ``'python'`` as the majority of files will have to highlight Python
|
||||
snippets.
|
||||
|
||||
* Within Python highlighting mode, interactive sessions are recognized
|
||||
automatically and highlighted appropriately.
|
||||
|
||||
* The highlighting language can be changed using the ``highlightlang``
|
||||
directive, used as follows::
|
||||
|
||||
.. highlightlang:: c
|
||||
|
||||
This language is used until the next ``highlightlang`` directive is
|
||||
encountered.
|
||||
|
||||
* The valid values for the highlighting language are:
|
||||
|
||||
* ``python`` (the default)
|
||||
* ``c``
|
||||
* ``rest``
|
||||
* ``none`` (no highlighting)
|
||||
|
||||
* If highlighting with the current language fails, the block is not highlighted
|
||||
in any way.
|
||||
|
||||
Longer displays of verbatim text may be included by storing the example text in
|
||||
an external file containing only plain text. The file may be included using the
|
||||
standard ``include`` directive with the ``literal`` option flag. For example,
|
||||
to include the Python source file :file:`example.py`, use::
|
||||
|
||||
.. include:: example.py
|
||||
:literal:
|
||||
|
||||
|
||||
Inline markup
|
||||
-------------
|
||||
|
||||
As said before, Sphinx uses interpreted text roles to insert semantic markup in
|
||||
documents.
|
||||
|
||||
The default role is ``var``, as that was one of the most common macros used in
|
||||
the old LaTeX docs. That means that you can use ```var``` to refer to a
|
||||
variable named "var".
|
||||
|
||||
For all other roles, you have to write ``:rolename:`content```.
|
||||
|
||||
The following roles refer to objects in modules and are possibly hyperlinked if
|
||||
a matching identifier is found:
|
||||
|
||||
.. describe:: mod
|
||||
|
||||
The name of a module; a dotted name may be used. This should also be used for
|
||||
package names.
|
||||
|
||||
.. describe:: func
|
||||
|
||||
The name of a Python function; dotted names may be used. The role text
|
||||
should include trailing parentheses to enhance readability. The parentheses
|
||||
are stripped when searching for identifiers.
|
||||
|
||||
.. describe:: data
|
||||
|
||||
The name of a module-level variable.
|
||||
|
||||
.. describe:: const
|
||||
|
||||
The name of a "defined" constant. This may be a C-language ``#define``
|
||||
or a Python variable that is not intended to be changed.
|
||||
|
||||
.. describe:: class
|
||||
|
||||
A class name; a dotted name may be used.
|
||||
|
||||
.. describe:: meth
|
||||
|
||||
The name of a method of an object. The role text should include the type
|
||||
name, method name and the trailing parentheses. A dotted name may be used.
|
||||
|
||||
.. describe:: attr
|
||||
|
||||
The name of a data attribute of an object.
|
||||
|
||||
.. describe:: exc
|
||||
|
||||
The name of an exception. A dotted name may be used.
|
||||
|
||||
The name enclosed in this markup can include a module name and/or a class name.
|
||||
For example, ``:func:`filter``` could refer to a function named ``filter`` in
|
||||
the current module, or the built-in function of that name. In contrast,
|
||||
``:func:`foo.filter``` clearly refers to the ``filter`` function in the ``foo``
|
||||
module.
|
||||
|
||||
A similar heuristic is used to determine whether the name is an attribute of
|
||||
the currently documented class.
|
||||
|
||||
The following roles create cross-references to C-language constructs if they
|
||||
are defined in the API documentation:
|
||||
|
||||
.. describe:: cdata
|
||||
|
||||
The name of a C-language variable.
|
||||
|
||||
.. describe:: cfunc
|
||||
|
||||
The name of a C-language function. Should include trailing parentheses.
|
||||
|
||||
.. describe:: cmacro
|
||||
|
||||
The name of a "simple" C macro, as defined above.
|
||||
|
||||
.. describe:: ctype
|
||||
|
||||
The name of a C-language type.
|
||||
|
||||
|
||||
The following role does possibly create a cross-reference, but does not refer
|
||||
to objects:
|
||||
|
||||
.. describe:: token
|
||||
|
||||
The name of a grammar token (used in the reference manual to create links
|
||||
between production displays).
|
||||
|
||||
---------
|
||||
|
||||
The following roles don't do anything special except formatting the text
|
||||
in a different style:
|
||||
|
||||
.. describe:: command
|
||||
|
||||
The name of an OS-level command, such as ``rm``.
|
||||
|
||||
.. describe:: dfn
|
||||
|
||||
Mark the defining instance of a term in the text. (No index entries are
|
||||
generated.)
|
||||
|
||||
.. describe:: envvar
|
||||
|
||||
An environment variable. Index entries are generated.
|
||||
|
||||
.. describe:: file
|
||||
|
||||
The name of a file or directory. Within the contents, you can use curly
|
||||
braces to indicate a "variable" part, for example::
|
||||
|
||||
... is installed in :file:`/usr/lib/python2.{x}/site-packages` ...
|
||||
|
||||
In the built documentation, the ``x`` will be displayed differently to
|
||||
indicate that it is to be replaced by the Python minor version.
|
||||
|
||||
.. describe:: guilabel
|
||||
|
||||
Labels presented as part of an interactive user interface should be marked
|
||||
using ``guilabel``. This includes labels from text-based interfaces such as
|
||||
those created using :mod:`curses` or other text-based libraries. Any label
|
||||
used in the interface should be marked with this role, including button
|
||||
labels, window titles, field names, menu and menu selection names, and even
|
||||
values in selection lists.
|
||||
|
||||
.. describe:: kbd
|
||||
|
||||
Mark a sequence of keystrokes. What form the key sequence takes may depend
|
||||
on platform- or application-specific conventions. When there are no relevant
|
||||
conventions, the names of modifier keys should be spelled out, to improve
|
||||
accessibility for new users and non-native speakers. For example, an
|
||||
*xemacs* key sequence may be marked like ``:kbd:`C-x C-f```, but without
|
||||
reference to a specific application or platform, the same sequence should be
|
||||
marked as ``:kbd:`Control-x Control-f```.
|
||||
|
||||
.. describe:: keyword
|
||||
|
||||
The name of a keyword in a programming language.
|
||||
|
||||
.. describe:: mailheader
|
||||
|
||||
The name of an RFC 822-style mail header. This markup does not imply that
|
||||
the header is being used in an email message, but can be used to refer to any
|
||||
header of the same "style." This is also used for headers defined by the
|
||||
various MIME specifications. The header name should be entered in the same
|
||||
way it would normally be found in practice, with the camel-casing conventions
|
||||
being preferred where there is more than one common usage. For example:
|
||||
``:mailheader:`Content-Type```.
|
||||
|
||||
.. describe:: makevar
|
||||
|
||||
The name of a :command:`make` variable.
|
||||
|
||||
.. describe:: manpage
|
||||
|
||||
A reference to a Unix manual page including the section,
|
||||
e.g. ``:manpage:`ls(1)```.
|
||||
|
||||
.. describe:: menuselection
|
||||
|
||||
Menu selections should be marked using the ``menuselection`` role. This is
|
||||
used to mark a complete sequence of menu selections, including selecting
|
||||
submenus and choosing a specific operation, or any subsequence of such a
|
||||
sequence. The names of individual selections should be separated by
|
||||
``-->``.
|
||||
|
||||
For example, to mark the selection "Start > Programs", use this markup::
|
||||
|
||||
:menuselection:`Start --> Programs`
|
||||
|
||||
When including a selection that includes some trailing indicator, such as the
|
||||
ellipsis some operating systems use to indicate that the command opens a
|
||||
dialog, the indicator should be omitted from the selection name.
|
||||
|
||||
.. describe:: mimetype
|
||||
|
||||
The name of a MIME type, or a component of a MIME type (the major or minor
|
||||
portion, taken alone).
|
||||
|
||||
.. describe:: newsgroup
|
||||
|
||||
The name of a Usenet newsgroup.
|
||||
|
||||
.. describe:: option
|
||||
|
||||
A command-line option to an executable program. The leading hyphen(s) must
|
||||
be included.
|
||||
|
||||
.. describe:: program
|
||||
|
||||
The name of an executable program. This may differ from the file name for
|
||||
the executable for some platforms. In particular, the ``.exe`` (or other)
|
||||
extension should be omitted for Windows programs.
|
||||
|
||||
.. describe:: regexp
|
||||
|
||||
A regular expression. Quotes should not be included.
|
||||
|
||||
.. describe:: var
|
||||
|
||||
A Python or C variable or parameter name.
|
||||
|
||||
|
||||
The following roles generate external links:
|
||||
|
||||
.. describe:: pep
|
||||
|
||||
A reference to a Python Enhancement Proposal. This generates appropriate
|
||||
index entries. The text "PEP *number*\ " is generated; in the HTML output,
|
||||
this text is a hyperlink to an online copy of the specified PEP.
|
||||
|
||||
.. describe:: rfc
|
||||
|
||||
A reference to an Internet Request for Comments. This generates appropriate
|
||||
index entries. The text "RFC *number*\ " is generated; in the HTML output,
|
||||
this text is a hyperlink to an online copy of the specified RFC.
|
||||
|
||||
|
||||
Note that there are no special roles for including hyperlinks as you can use
|
||||
the standard reST markup for that purpose.
|
||||
|
||||
|
||||
.. _doc-ref-role:
|
||||
|
||||
Cross-linking markup
|
||||
--------------------
|
||||
|
||||
To support cross-referencing to arbitrary sections in the documentation, the
|
||||
standard reST labels are "abused" a bit: Every label must precede a section
|
||||
title; and every label name must be unique throughout the entire documentation
|
||||
source.
|
||||
|
||||
You can then reference to these sections using the ``:ref:`label-name``` role.
|
||||
|
||||
Example::
|
||||
|
||||
.. _my-reference-label:
|
||||
|
||||
Section to cross-reference
|
||||
--------------------------
|
||||
|
||||
This is the text of the section.
|
||||
|
||||
It refers to the section itself, see :ref:`my-reference-label`.
|
||||
|
||||
The ``:ref:`` invocation is replaced with the section title.
|
||||
|
||||
|
||||
Paragraph-level markup
|
||||
----------------------
|
||||
|
||||
These directives create short paragraphs and can be used inside information
|
||||
units as well as normal text:
|
||||
|
||||
.. describe:: note
|
||||
|
||||
An especially important bit of information about an API that a user should be
|
||||
aware of when using whatever bit of API the note pertains to. The content of
|
||||
the directive should be written in complete sentences and include all
|
||||
appropriate punctuation.
|
||||
|
||||
Example::
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not suitable for sending spam e-mails.
|
||||
|
||||
.. describe:: warning
|
||||
|
||||
An important bit of information about an API that a user should be very aware
|
||||
of when using whatever bit of API the warning pertains to. The content of
|
||||
the directive should be written in complete sentences and include all
|
||||
appropriate punctuation. This differs from ``note`` in that it is recommended
|
||||
over ``note`` for information regarding security.
|
||||
|
||||
.. describe:: versionadded
|
||||
|
||||
This directive documents the version of Python which added the described
|
||||
feature to the library or C API. When this applies to an entire module, it
|
||||
should be placed at the top of the module section before any prose.
|
||||
|
||||
The first argument must be given and is the version in question; you can add
|
||||
a second argument consisting of a *brief* explanation of the change.
|
||||
|
||||
Example::
|
||||
|
||||
.. versionadded:: 2.5
|
||||
The `spam` parameter.
|
||||
|
||||
Note that there must be no blank line between the directive head and the
|
||||
explanation; this is to make these blocks visually continuous in the markup.
|
||||
|
||||
.. describe:: versionchanged
|
||||
|
||||
Similar to ``versionadded``, but describes when and what changed in the named
|
||||
feature in some way (new parameters, changed side effects, etc.).
|
||||
|
||||
--------------
|
||||
|
||||
.. describe:: seealso
|
||||
|
||||
Many sections include a list of references to module documentation or
|
||||
external documents. These lists are created using the ``seealso`` directive.
|
||||
|
||||
The ``seealso`` directive is typically placed in a section just before any
|
||||
sub-sections. For the HTML output, it is shown boxed off from the main flow
|
||||
of the text.
|
||||
|
||||
The content of the ``seealso`` directive should be a reST definition list.
|
||||
Example::
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`zipfile`
|
||||
Documentation of the :mod:`zipfile` standard module.
|
||||
|
||||
`GNU tar manual, Basic Tar Format <http://link>`_
|
||||
Documentation for tar archive files, including GNU tar extensions.
|
||||
|
||||
.. describe:: rubric
|
||||
|
||||
This directive creates a paragraph heading that is not used to create a
|
||||
table of contents node. It is currently used for the "Footnotes" caption.
|
||||
|
||||
.. describe:: centered
|
||||
|
||||
This directive creates a centered boldfaced paragraph. Use it as follows::
|
||||
|
||||
.. centered::
|
||||
|
||||
Paragraph contents.
|
||||
|
||||
|
||||
Table-of-contents markup
|
||||
------------------------
|
||||
|
||||
Since reST does not have facilities to interconnect several documents, or split
|
||||
documents into multiple output files, Sphinx uses a custom directive to add
|
||||
relations between the single files the documentation is made of, as well as
|
||||
tables of contents. The ``toctree`` directive is the central element.
|
||||
|
||||
.. describe:: toctree
|
||||
|
||||
This directive inserts a "TOC tree" at the current location, using the
|
||||
individual TOCs (including "sub-TOC trees") of the files given in the
|
||||
directive body. A numeric ``maxdepth`` option may be given to indicate the
|
||||
depth of the tree; by default, all levels are included.
|
||||
|
||||
Consider this example (taken from the library reference index)::
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
intro.rst
|
||||
strings.rst
|
||||
datatypes.rst
|
||||
numeric.rst
|
||||
(many more files listed here)
|
||||
|
||||
This accomplishes two things:
|
||||
|
||||
* Tables of contents from all those files are inserted, with a maximum depth
|
||||
of two, that means one nested heading. ``toctree`` directives in those
|
||||
files are also taken into account.
|
||||
* Sphinx knows that the relative order of the files ``intro.rst``,
|
||||
``strings.rst`` and so forth, and it knows that they are children of the
|
||||
shown file, the library index. From this information it generates "next
|
||||
chapter", "previous chapter" and "parent chapter" links.
|
||||
|
||||
In the end, all files included in the build process must occur in one
|
||||
``toctree`` directive; Sphinx will emit a warning if it finds a file that is
|
||||
not included, because that means that this file will not be reachable through
|
||||
standard navigation.
|
||||
|
||||
The special file ``contents.rst`` at the root of the source directory is the
|
||||
"root" of the TOC tree hierarchy; from it the "Contents" page is generated.
|
||||
|
||||
|
||||
Index-generating markup
|
||||
-----------------------
|
||||
|
||||
Sphinx automatically creates index entries from all information units (like
|
||||
functions, classes or attributes) like discussed before.
|
||||
|
||||
However, there is also an explicit directive available, to make the index more
|
||||
comprehensive and enable index entries in documents where information is not
|
||||
mainly contained in information units, such as the language reference.
|
||||
|
||||
The directive is ``index`` and contains one or more index entries. Each entry
|
||||
consists of a type and a value, separated by a colon.
|
||||
|
||||
For example::
|
||||
|
||||
.. index::
|
||||
single: execution!context
|
||||
module: __main__
|
||||
module: sys
|
||||
triple: module; search; path
|
||||
|
||||
This directive contains five entries, which will be converted to entries in the
|
||||
generated index which link to the exact location of the index statement (or, in
|
||||
case of offline media, the corresponding page number).
|
||||
|
||||
The possible entry types are:
|
||||
|
||||
single
|
||||
Creates a single index entry. Can be made a subentry by separating the
|
||||
subentry text with a semicolon (this is also used below to describe what
|
||||
entries are created).
|
||||
pair
|
||||
``pair: loop; statement`` is a shortcut that creates two index entries,
|
||||
namely ``loop; statement`` and ``statement; loop``.
|
||||
triple
|
||||
Likewise, ``triple: module; search; path`` is a shortcut that creates three
|
||||
index entries, which are ``module; search path``, ``search; path, module`` and
|
||||
``path; module search``.
|
||||
module, keyword, operator, object, exception, statement, builtin
|
||||
These all create two index entries. For example, ``module: hashlib`` creates
|
||||
the entries ``module; hashlib`` and ``hashlib; module``.
|
||||
|
||||
|
||||
Grammar production displays
|
||||
---------------------------
|
||||
|
||||
Special markup is available for displaying the productions of a formal grammar.
|
||||
The markup is simple and does not attempt to model all aspects of BNF (or any
|
||||
derived forms), but provides enough to allow context-free grammars to be
|
||||
displayed in a way that causes uses of a symbol to be rendered as hyperlinks to
|
||||
the definition of the symbol. There is this directive:
|
||||
|
||||
.. describe:: productionlist
|
||||
|
||||
This directive is used to enclose a group of productions. Each production is
|
||||
given on a single line and consists of a name, separated by a colon from the
|
||||
following definition. If the definition spans multiple lines, each
|
||||
continuation line must begin with a colon placed at the same column as in the
|
||||
first line.
|
||||
|
||||
Blank lines are not allowed within ``productionlist`` directive arguments.
|
||||
|
||||
The definition can contain token names which are marked as interpreted text
|
||||
(e.g. ``sum ::= `integer` "+" `integer```) -- this generates cross-references
|
||||
to the productions of these tokens. Note that vertical bars used to indicate
|
||||
alternatives must be escaped with backslashes because otherwise they would
|
||||
indicate a substitution reference to the reST parser.
|
||||
|
||||
|
||||
.. XXX describe optional first parameter
|
||||
|
||||
The following is an example taken from the Python Reference Manual::
|
||||
|
||||
.. productionlist::
|
||||
try_stmt: try1_stmt \| try2_stmt
|
||||
try1_stmt: "try" ":" :token:`suite`
|
||||
: ("except" [:token:`expression` ["," :token:`target`]] ":" :token:`suite`)+
|
||||
: ["else" ":" :token:`suite`]
|
||||
: ["finally" ":" :token:`suite`]
|
||||
try2_stmt: "try" ":" :token:`suite`
|
||||
: "finally" ":" :token:`suite`
|
||||
|
||||
|
||||
Substitutions
|
||||
-------------
|
||||
|
||||
The documentation system provides three substitutions that are defined by default.
|
||||
They are set in the build configuration file, see :ref:`doc-build-config`.
|
||||
|
||||
.. describe:: |release|
|
||||
|
||||
Replaced by the Python release the documentation refers to. This is the full
|
||||
version string including alpha/beta/release candidate tags, e.g. ``2.5.2b3``.
|
||||
|
||||
.. describe:: |version|
|
||||
|
||||
Replaced by the Python version the documentation refers to. This consists
|
||||
only of the major and minor version parts, e.g. ``2.5``, even for version
|
||||
2.5.1.
|
||||
|
||||
.. describe:: |today|
|
||||
|
||||
Replaced by either today's date, or the date set in the build configuration
|
||||
file. Normally has the format ``April 14, 2007``.
|
||||
@@ -1,232 +0,0 @@
|
||||
.. highlightlang:: rest
|
||||
|
||||
reStructuredText Primer
|
||||
=======================
|
||||
|
||||
This section is a brief introduction to reStructuredText (reST) concepts and
|
||||
syntax, intended to provide authors with enough information to author
|
||||
documents productively.
|
||||
Since reST was designed to be a simple, unobtrusive markup language, this will
|
||||
not take too long.
|
||||
|
||||
.. seealso::
|
||||
|
||||
The authoritative `reStructuredText User
|
||||
Documentation <http://docutils.sourceforge.net/rst.html>`_.
|
||||
|
||||
|
||||
Paragraphs
|
||||
----------
|
||||
|
||||
The paragraph is the most basic block in a reST document.
|
||||
Paragraphs are simply chunks of text
|
||||
separated by one or more blank lines. As in Python, indentation is significant
|
||||
in reST, so all lines of the same paragraph must be left-aligned
|
||||
to the same level of indentation.
|
||||
|
||||
|
||||
Inline markup
|
||||
-------------
|
||||
|
||||
The standard reST inline markup is quite simple: use
|
||||
|
||||
* one asterisk: ``*text*`` for emphasis (italics),
|
||||
* two asterisks: ``**text**`` for strong emphasis (boldface), and
|
||||
* backquotes: ````text```` for code samples.
|
||||
|
||||
If asterisks or backquotes appear in running text and could be confused with
|
||||
inline markup delimiters, they have to be escaped with a backslash.
|
||||
|
||||
Be aware of some restrictions of this markup:
|
||||
|
||||
* it may not be nested,
|
||||
* content may not start or end with whitespace: ``* text*`` is wrong,
|
||||
* it must be separated from surrounding text by non-word characters. Use a
|
||||
backslash escaped space to work around that: ``thisis\ *one*\ word``.
|
||||
|
||||
These restrictions may be lifted in future versions of the docutils.
|
||||
|
||||
reST also allows for custom "interpreted text roles"', which signify that the
|
||||
enclosed text should be interpreted in a specific way. Sphinx uses this to
|
||||
provide semantic markup and cross-referencing of identifiers, as described in
|
||||
the appropriate section. The general syntax is ``:rolename:`content```.
|
||||
|
||||
|
||||
Lists and Quotes
|
||||
----------------
|
||||
|
||||
List markup is natural: just place an asterisk at the start of a paragraph and
|
||||
indent properly. The same goes for numbered lists; they can also be
|
||||
autonumbered using a ``#`` sign::
|
||||
|
||||
* This is a bulleted list.
|
||||
* It has two items, the second
|
||||
item uses two lines.
|
||||
|
||||
#. This is a numbered list.
|
||||
#. It has two items too.
|
||||
|
||||
Nested lists are possible, but be aware that they must be separated from the
|
||||
parent list items by blank lines::
|
||||
|
||||
* this is
|
||||
* a list
|
||||
|
||||
* with a nested list
|
||||
* and some subitems
|
||||
|
||||
* and here the parent list continues
|
||||
|
||||
Definition lists are created as follows::
|
||||
|
||||
term (up to a line of text)
|
||||
Definition of the term, which must be indented
|
||||
|
||||
and can even consist of multiple paragraphs
|
||||
|
||||
next term
|
||||
Description.
|
||||
|
||||
|
||||
Paragraphs are quoted by just indenting them more than the surrounding
|
||||
paragraphs.
|
||||
|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
Literal code blocks are introduced by ending a paragraph with the special marker
|
||||
``::``. The literal block must be indented, to be able to include blank lines::
|
||||
|
||||
This is a normal text paragraph. The next paragraph is a code sample::
|
||||
|
||||
It is not processed in any way, except
|
||||
that the indentation is removed.
|
||||
|
||||
It can span multiple lines.
|
||||
|
||||
This is a normal text paragraph again.
|
||||
|
||||
The handling of the ``::`` marker is smart:
|
||||
|
||||
* If it occurs as a paragraph of its own, that paragraph is completely left
|
||||
out of the document.
|
||||
* If it is preceded by whitespace, the marker is removed.
|
||||
* If it is preceded by non-whitespace, the marker is replaced by a single
|
||||
colon.
|
||||
|
||||
That way, the second sentence in the above example's first paragraph would be
|
||||
rendered as "The next paragraph is a code sample:".
|
||||
|
||||
|
||||
Hyperlinks
|
||||
----------
|
||||
|
||||
External links
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Use ```Link text <http://target>`_`` for inline web links. If the link text
|
||||
should be the web address, you don't need special markup at all, the parser
|
||||
finds links and mail addresses in ordinary text.
|
||||
|
||||
Internal links
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Internal linking is done via a special reST role, see the section on specific
|
||||
markup, :ref:`doc-ref-role`.
|
||||
|
||||
|
||||
Sections
|
||||
--------
|
||||
|
||||
Section headers are created by underlining (and optionally overlining) the
|
||||
section title with a punctuation character, at least as long as the text::
|
||||
|
||||
=================
|
||||
This is a heading
|
||||
=================
|
||||
|
||||
Normally, there are no heading levels assigned to certain characters as the
|
||||
structure is determined from the succession of headings. However, for the
|
||||
Python documentation, we use this convention:
|
||||
|
||||
* ``#`` with overline, for parts
|
||||
* ``*`` with overline, for chapters
|
||||
* ``=``, for sections
|
||||
* ``-``, for subsections
|
||||
* ``^``, for subsubsections
|
||||
* ``"``, for paragraphs
|
||||
|
||||
|
||||
Explicit Markup
|
||||
---------------
|
||||
|
||||
"Explicit markup" is used in reST for most constructs that need special
|
||||
handling, such as footnotes, specially-highlighted paragraphs, comments, and
|
||||
generic directives.
|
||||
|
||||
An explicit markup block begins with a line starting with ``..`` followed by
|
||||
whitespace and is terminated by the next paragraph at the same level of
|
||||
indentation. (There needs to be a blank line between explicit markup and normal
|
||||
paragraphs. This may all sound a bit complicated, but it is intuitive enough
|
||||
when you write it.)
|
||||
|
||||
|
||||
Directives
|
||||
----------
|
||||
|
||||
A directive is a generic block of explicit markup. Besides roles, it is one of
|
||||
the extension mechanisms of reST, and Sphinx makes heavy use of it.
|
||||
|
||||
Basically, a directive consists of a name, arguments, options and content. (Keep
|
||||
this terminology in mind, it is used in the next chapter describing custom
|
||||
directives.) Looking at this example, ::
|
||||
|
||||
.. function:: foo(x)
|
||||
foo(y, z)
|
||||
:bar: no
|
||||
|
||||
Return a line of text input from the user.
|
||||
|
||||
``function`` is the directive name. It is given two arguments here, the
|
||||
remainder of the first line and the second line, as well as one option ``bar``
|
||||
(as you can see, options are given in the lines immediately following the
|
||||
arguments and indicated by the colons).
|
||||
|
||||
The directive content follows after a blank line and is indented relative to the
|
||||
directive start.
|
||||
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
|
||||
For footnotes, use ``[#]_`` to mark the footnote location, and add the footnote
|
||||
body at the bottom of the document after a "Footnotes" rubric heading, like so::
|
||||
|
||||
Lorem ipsum [#]_ dolor sit amet ... [#]_
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#] Text of the first footnote.
|
||||
.. [#] Text of the second footnote.
|
||||
|
||||
|
||||
Comments
|
||||
--------
|
||||
|
||||
Every explicit markup block which isn't a valid markup construct (like the
|
||||
footnotes above) is regared as a comment.
|
||||
|
||||
|
||||
Source encoding
|
||||
---------------
|
||||
|
||||
Since the easiest way to include special characters like em dashes or copyright
|
||||
signs in reST is to directly write them as Unicode characters, one has to
|
||||
specify an encoding:
|
||||
|
||||
All Python documentation source files must be in UTF-8 encoding, and the HTML
|
||||
documents written from them will be in that encoding as well.
|
||||
|
||||
|
||||
XXX: Gotchas
|
||||
@@ -1,60 +0,0 @@
|
||||
.. highlightlang:: rest
|
||||
|
||||
The Sphinx build system
|
||||
=======================
|
||||
|
||||
XXX: intro...
|
||||
|
||||
.. _doc-build-config:
|
||||
|
||||
The build configuration file
|
||||
----------------------------
|
||||
|
||||
The documentation root, that is the ``Doc`` subdirectory of the source
|
||||
distribution, contains a file named ``conf.py``. This file is called the "build
|
||||
configuration file", and it contains several variables that are read and used
|
||||
during a build run.
|
||||
|
||||
These variables are:
|
||||
|
||||
version : string
|
||||
A string that is used as a replacement for the ``|version|`` reST
|
||||
substitution. It should be the Python version the documentation refers to.
|
||||
This consists only of the major and minor version parts, e.g. ``2.5``, even
|
||||
for version 2.5.1.
|
||||
|
||||
release : string
|
||||
A string that is used as a replacement for the ``|release|`` reST
|
||||
substitution. It should be the full version string including
|
||||
alpha/beta/release candidate tags, e.g. ``2.5.2b3``.
|
||||
|
||||
Both ``release`` and ``version`` can be ``'auto'``, which means that they are
|
||||
determined at runtime from the ``Include/patchlevel.h`` file, if a complete
|
||||
Python source distribution can be found, or else from the interpreter running
|
||||
Sphinx.
|
||||
|
||||
today_fmt : string
|
||||
A ``strftime`` format that is used to format a replacement for the
|
||||
``|today|`` reST substitution.
|
||||
|
||||
today : string
|
||||
A string that can contain a date that should be written to the documentation
|
||||
output literally. If this is nonzero, it is used instead of
|
||||
``strftime(today_fmt)``.
|
||||
|
||||
unused_files : list of strings
|
||||
A list of reST filenames that are to be disregarded during building. This
|
||||
could be docs for temporarily disabled modules or documentation that's not
|
||||
yet ready for public consumption.
|
||||
|
||||
last_updated_format : string
|
||||
If this is not an empty string, it will be given to ``time.strftime()`` and
|
||||
written to each generated output file after "last updated on:".
|
||||
|
||||
use_smartypants : bool
|
||||
If true, use SmartyPants to convert quotes and dashes to the typographically
|
||||
correct entities.
|
||||
|
||||
add_function_parentheses : bool
|
||||
If true, ``()`` will be appended to the content of ``:func:``, ``:meth:`` and
|
||||
``:cfunc:`` cross-references.
|
||||
@@ -1,57 +0,0 @@
|
||||
.. highlightlang:: rest
|
||||
|
||||
Style Guide
|
||||
===========
|
||||
|
||||
The Python documentation should follow the `Apple Publications Style Guide`_
|
||||
wherever possible. This particular style guide was selected mostly because it
|
||||
seems reasonable and is easy to get online.
|
||||
|
||||
.. _Apple Publications Style Guide: http://developer.apple.com/documentation/UserExperience/Conceptual/APStyleGuide/AppleStyleGuide2003.pdf
|
||||
|
||||
Topics which are not covered in the Apple's style guide will be discussed in
|
||||
this document if necessary.
|
||||
|
||||
Footnotes are generally discouraged, though they may be used when they are the
|
||||
best way to present specific information. When a footnote reference is added at
|
||||
the end of the sentence, it should follow the sentence-ending punctuation. The
|
||||
reST markup should appear something like this::
|
||||
|
||||
This sentence has a footnote reference. [#]_ This is the next sentence.
|
||||
|
||||
Footnotes should be gathered at the end of a file, or if the file is very long,
|
||||
at the end of a section. The docutils will automatically create backlinks to the
|
||||
footnote reference.
|
||||
|
||||
Footnotes may appear in the middle of sentences where appropriate.
|
||||
|
||||
Many special names are used in the Python documentation, including the names of
|
||||
operating systems, programming languages, standards bodies, and the like. Most
|
||||
of these entities are not assigned any special markup, but the preferred
|
||||
spellings are given here to aid authors in maintaining the consistency of
|
||||
presentation in the Python documentation.
|
||||
|
||||
Other terms and words deserve special mention as well; these conventions should
|
||||
be used to ensure consistency throughout the documentation:
|
||||
|
||||
CPU
|
||||
For "central processing unit." Many style guides say this should be spelled
|
||||
out on the first use (and if you must use it, do so!). For the Python
|
||||
documentation, this abbreviation should be avoided since there's no
|
||||
reasonable way to predict which occurrence will be the first seen by the
|
||||
reader. It is better to use the word "processor" instead.
|
||||
|
||||
POSIX
|
||||
The name assigned to a particular group of standards. This is always
|
||||
uppercase.
|
||||
|
||||
Python
|
||||
The name of our favorite programming language is always capitalized.
|
||||
|
||||
Unicode
|
||||
The name of a character set and matching encoding. This is always written
|
||||
capitalized.
|
||||
|
||||
Unix
|
||||
The name of the operating system developed at AT&T Bell Labs in the early
|
||||
1970s.
|
||||
@@ -1,34 +0,0 @@
|
||||
.. _extending-index:
|
||||
|
||||
##################################################
|
||||
Extending and Embedding the Python Interpreter
|
||||
##################################################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
This document describes how to write modules in C or C++ to extend the Python
|
||||
interpreter with new modules. Those modules can define new functions but also
|
||||
new object types and their methods. The document also describes how to embed
|
||||
the Python interpreter in another application, for use as an extension language.
|
||||
Finally, it shows how to compile and link extension modules so that they can be
|
||||
loaded dynamically (at run time) into the interpreter, if the underlying
|
||||
operating system supports this feature.
|
||||
|
||||
This document assumes basic knowledge about Python. For an informal
|
||||
introduction to the language, see :ref:`tutorial-index`. :ref:`reference-index`
|
||||
gives a more formal definition of the language. :ref:`modules-index` documents
|
||||
the existing object types, functions and modules (both built-in and written in
|
||||
Python) that give the language its wide application range.
|
||||
|
||||
For a detailed description of the whole Python/C API, see the separate
|
||||
:ref:`c-api-index`.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
extending.rst
|
||||
newtypes.rst
|
||||
building.rst
|
||||
windows.rst
|
||||
embedding.rst
|
||||
@@ -1,34 +0,0 @@
|
||||
.. _maclib-index:
|
||||
|
||||
##############################
|
||||
Macintosh Library Modules
|
||||
##############################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
This library reference manual documents Python's extensions for the Macintosh.
|
||||
It should be used in conjunction with :ref:`library-index`, which documents the
|
||||
standard library and built-in types.
|
||||
|
||||
This manual assumes basic knowledge about the Python language. For an informal
|
||||
introduction to Python, see :ref:`tutorial-index`; :ref:`reference-index`
|
||||
remains the highest authority on syntactic and semantic questions. Finally, the
|
||||
manual entitled :ref:`extending-index` describes how to add new extensions to
|
||||
Python and how to embed it in other applications.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
using.rst
|
||||
mac.rst
|
||||
macic.rst
|
||||
macos.rst
|
||||
macostools.rst
|
||||
macui.rst
|
||||
framework.rst
|
||||
autogil.rst
|
||||
scripting.rst
|
||||
toolbox.rst
|
||||
colorpicker.rst
|
||||
undoc.rst
|
||||
@@ -1,73 +0,0 @@
|
||||
.. _library-index:
|
||||
|
||||
###############################
|
||||
The Python standard library
|
||||
###############################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
While :ref:`reference-index` describes the exact syntax and semantics of the
|
||||
language, it does not describe the standard library that is distributed with the
|
||||
language, and which greatly enhances its immediate usability. This library
|
||||
contains built-in modules (written in C) that provide access to system
|
||||
functionality such as file I/O that would otherwise be inaccessible to Python
|
||||
programmers, as well as modules written in Python that provide standardized
|
||||
solutions for many problems that occur in everyday programming. Some of these
|
||||
modules are explicitly designed to encourage and enhance the portability of
|
||||
Python programs.
|
||||
|
||||
This library reference manual documents Python's standard library, as well as
|
||||
many optional library modules (which may or may not be available, depending on
|
||||
whether the underlying platform supports them and on the configuration choices
|
||||
made at compile time). It also documents the standard types of the language and
|
||||
its built-in functions and exceptions, many of which are not or incompletely
|
||||
documented in the Reference Manual.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
intro.rst
|
||||
functions.rst
|
||||
constants.rst
|
||||
objects.rst
|
||||
stdtypes.rst
|
||||
exceptions.rst
|
||||
|
||||
strings.rst
|
||||
datatypes.rst
|
||||
numeric.rst
|
||||
netdata.rst
|
||||
markup.rst
|
||||
fileformats.rst
|
||||
crypto.rst
|
||||
filesys.rst
|
||||
archiving.rst
|
||||
persistence.rst
|
||||
allos.rst
|
||||
someos.rst
|
||||
unix.rst
|
||||
ipc.rst
|
||||
internet.rst
|
||||
mm.rst
|
||||
tkinter.rst
|
||||
i18n.rst
|
||||
frameworks.rst
|
||||
development.rst
|
||||
pdb.rst
|
||||
profile.rst
|
||||
hotshot.rst
|
||||
timeit.rst
|
||||
trace.rst
|
||||
python.rst
|
||||
custominterp.rst
|
||||
restricted.rst
|
||||
modules.rst
|
||||
language.rst
|
||||
compiler.rst
|
||||
misc.rst
|
||||
sgi.rst
|
||||
sun.rst
|
||||
windows.rst
|
||||
undoc.rst
|
||||
@@ -1,30 +0,0 @@
|
||||
.. _reference-index:
|
||||
|
||||
#################################
|
||||
The Python language reference
|
||||
#################################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
This reference manual describes the syntax and "core semantics" of the
|
||||
language. It is terse, but attempts to be exact and complete. The semantics of
|
||||
non-essential built-in object types and of the built-in functions and modules
|
||||
are described in :ref:`library-index`. For an informal introduction to the
|
||||
language, see :ref:`tutorial-index`. For C or C++ programmers, two additional
|
||||
manuals exist: :ref:`extending-index` describes the high-level picture of how to
|
||||
write a Python extension module, and the :ref:`c-api-index` describes the
|
||||
interfaces available to C/C++ programmers in detail.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
introduction.rst
|
||||
lexical_analysis.rst
|
||||
datamodel.rst
|
||||
executionmodel.rst
|
||||
expressions.rst
|
||||
simple_stmts.rst
|
||||
compound_stmts.rst
|
||||
toplevel_components.rst
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
.. _tutorial-index:
|
||||
|
||||
######################
|
||||
The Python tutorial
|
||||
######################
|
||||
|
||||
:Release: |version|
|
||||
:Date: |today|
|
||||
|
||||
Python is an easy to learn, powerful programming language. It has efficient
|
||||
high-level data structures and a simple but effective approach to
|
||||
object-oriented programming. Python's elegant syntax and dynamic typing,
|
||||
together with its interpreted nature, make it an ideal language for scripting
|
||||
and rapid application development in many areas on most platforms.
|
||||
|
||||
The Python interpreter and the extensive standard library are freely available
|
||||
in source or binary form for all major platforms from the Python Web site,
|
||||
http://www.python.org/, and may be freely distributed. The same site also
|
||||
contains distributions of and pointers to many free third party Python modules,
|
||||
programs and tools, and additional documentation.
|
||||
|
||||
The Python interpreter is easily extended with new functions and data types
|
||||
implemented in C or C++ (or other languages callable from C). Python is also
|
||||
suitable as an extension language for customizable applications.
|
||||
|
||||
This tutorial introduces the reader informally to the basic concepts and
|
||||
features of the Python language and system. It helps to have a Python
|
||||
interpreter handy for hands-on experience, but all examples are self-contained,
|
||||
so the tutorial can be read off-line as well.
|
||||
|
||||
For a description of standard objects and modules, see the Python Library
|
||||
Reference document. The Python Reference Manual gives a more formal definition
|
||||
of the language. To write extensions in C or C++, read Extending and Embedding
|
||||
the Python Interpreter and Python/C API Reference. There are also several books
|
||||
covering Python in depth.
|
||||
|
||||
This tutorial does not attempt to be comprehensive and cover every single
|
||||
feature, or even every commonly used feature. Instead, it introduces many of
|
||||
Python's most noteworthy features, and will give you a good idea of the
|
||||
language's flavor and style. After reading it, you will be able to read and
|
||||
write Python modules and programs, and you will be ready to learn more about the
|
||||
various Python library modules described in the Python Library Reference.
|
||||
|
||||
.. toctree::
|
||||
|
||||
appetite.rst
|
||||
interpreter.rst
|
||||
introduction.rst
|
||||
controlflow.rst
|
||||
datastructures.rst
|
||||
modules.rst
|
||||
inputoutput.rst
|
||||
errors.rst
|
||||
classes.rst
|
||||
stdlib.rst
|
||||
stdlib2.rst
|
||||
whatnow.rst
|
||||
interactive.rst
|
||||
floatingpoint.rst
|
||||
glossary.rst
|
||||
@@ -1,962 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python documentation ReST writer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
How the converter works
|
||||
=======================
|
||||
|
||||
A LaTeX document is tokenized by a `Tokenizer`. The tokens are processed by
|
||||
the `DocParser` class which emits a tree of `DocNode`\s. The `RestWriter`
|
||||
now walks this node tree and generates ReST from that.
|
||||
|
||||
There are some intricacies while writing ReST:
|
||||
|
||||
- Paragraph text must be rewrapped in order to avoid ragged lines. The
|
||||
`textwrap` module does that nicely, but it must obviously operate on a
|
||||
whole paragraph at a time. Therefore the contents of the current paragraph
|
||||
are cached in `self.curpar`. Every time a block level element is
|
||||
encountered, its node handler calls `self.flush_par()` which writes out a
|
||||
paragraph. Because this can be detrimental for the markup at several
|
||||
stages, the `self.noflush` context manager can be used to forbid paragraph
|
||||
flushing temporarily, which means that no block level nodes can be
|
||||
processed.
|
||||
|
||||
- There are no inline comments in ReST. Therefore comments are stored in
|
||||
`self.comments` and written out every time the paragraph is flushed.
|
||||
|
||||
- A similar thing goes for footnotes: `self.footnotes`.
|
||||
|
||||
- Some inline markup cannot contain nested markup. Therefore the function
|
||||
`textonly()` exists which returns a node similar to its argument, but
|
||||
stripped of inline markup.
|
||||
|
||||
- Some constructs need to format non-block-level nodes, but without writing
|
||||
the result to the current paragraph. These use `self.get_node_text()`
|
||||
which writes to a temporary paragraph and returns the resulting markup.
|
||||
|
||||
- Indentation is important. The `self.indent` context manager helps keeping
|
||||
track of indentation levels.
|
||||
|
||||
- Some blocks, like lists, need to prevent the first line from being
|
||||
indented because the indentation space is already filled (e.g. by a
|
||||
bullet). Therefore the `self.indent` context manager accepts a
|
||||
`firstline` flag which can be set to ``False``, resulting in the first
|
||||
line not being indented.
|
||||
|
||||
|
||||
There are some restrictions on markup compared to LaTeX:
|
||||
|
||||
- Table cells may not contain blocks.
|
||||
|
||||
- Hard line breaks don't exist.
|
||||
|
||||
- Block level markup inside "alltt" environments doesn't work.
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
# yay!
|
||||
from __future__ import with_statement
|
||||
|
||||
import re
|
||||
import StringIO
|
||||
import textwrap
|
||||
|
||||
WIDTH = 80
|
||||
INDENT = 3
|
||||
|
||||
new_wordsep_re = re.compile(
|
||||
r'(\s+|' # any whitespace
|
||||
r'(?<=\s)(?::[a-z-]+:)?`\S+|' # interpreted text start
|
||||
r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words
|
||||
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash
|
||||
|
||||
import textwrap
|
||||
# monkey-patch...
|
||||
textwrap.TextWrapper.wordsep_re = new_wordsep_re
|
||||
wrapper = textwrap.TextWrapper(width=WIDTH, break_long_words=False)
|
||||
|
||||
from .docnodes import RootNode, TextNode, NodeList, InlineNode, \
|
||||
CommentNode, EmptyNode
|
||||
from .util import fixup_text, empty, text, my_make_id, \
|
||||
repair_bad_inline_markup
|
||||
from .filenamemap import includes_mapping
|
||||
|
||||
class WriterError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Indenter(object):
|
||||
""" Context manager factory for indentation. """
|
||||
def __init__(self, writer):
|
||||
class IndenterManager(object):
|
||||
def __init__(self, indentlevel, flush, firstline):
|
||||
self.indentlevel = indentlevel
|
||||
self.flush = flush
|
||||
self.firstline = firstline
|
||||
|
||||
def __enter__(self):
|
||||
writer.indentation += (self.indentlevel * ' ')
|
||||
writer.indentfirstline = self.firstline
|
||||
return self
|
||||
|
||||
def __exit__(self, *ignored):
|
||||
if self.flush:
|
||||
writer.flush_par()
|
||||
writer.indentation = writer.indentation[:-self.indentlevel]
|
||||
|
||||
self.manager = IndenterManager
|
||||
|
||||
def __call__(self, indentlevel=INDENT, flush=True, firstline=True):
|
||||
return self.manager(indentlevel, flush, firstline)
|
||||
|
||||
|
||||
class NoFlush(object):
|
||||
""" Convenience context manager. """
|
||||
def __init__(self, writer):
|
||||
self.writer = writer
|
||||
|
||||
def __enter__(self):
|
||||
self.writer.no_flushing += 1
|
||||
|
||||
def __exit__(self, *ignored):
|
||||
self.writer.no_flushing -= 1
|
||||
|
||||
|
||||
class SectionMeta(object):
|
||||
def __init__(self):
|
||||
self.modname = ''
|
||||
self.platform = ''
|
||||
self.synopsis = []
|
||||
self.modauthors = []
|
||||
self.sectauthors = []
|
||||
|
||||
|
||||
class RestWriter(object):
|
||||
""" Write ReST from a node tree. """
|
||||
|
||||
def __init__(self, fp, splitchap=False, toctree=None, deflang=None, labelprefix=''):
|
||||
self.splitchap = splitchap # split output at chapters?
|
||||
if splitchap:
|
||||
self.fp = StringIO.StringIO() # dummy one
|
||||
self.chapters = [self.fp]
|
||||
else:
|
||||
self.fp = fp # file pointer
|
||||
self.toctree = toctree # entries for the TOC tree
|
||||
self.deflang = deflang # default highlighting language
|
||||
self.labelprefix = labelprefix # prefix for all label names
|
||||
|
||||
# indentation tools
|
||||
self.indentation = '' # current indentation string
|
||||
self.indentfirstline = True # indent the first line of next paragraph?
|
||||
self.indented = Indenter(self) # convenience context manager
|
||||
|
||||
# paragraph flushing tools
|
||||
self.flush_cb = None # callback run on next paragraph flush, used
|
||||
# for properly separating field lists from
|
||||
# the following paragraph
|
||||
self.no_flushing = 0 # raise an error on paragraph flush?
|
||||
self.noflush = NoFlush(self) # convenience context manager
|
||||
|
||||
# collected items to output later
|
||||
self.curpar = [] # text in current paragraph
|
||||
self.comments = [] # comments to be output after flushing
|
||||
self.indexentries = [] # indexentries to be output before flushing
|
||||
self.footnotes = [] # footnotes to be output at document end
|
||||
self.warnings = [] # warnings while writing
|
||||
|
||||
# specials
|
||||
self.sectionlabel = '' # most recent \label command
|
||||
self.thisclass = '' # most recent classdesc name
|
||||
self.sectionmeta = None # current section metadata
|
||||
self.noescape = 0 # don't escape text nodes
|
||||
self.indexsubitem = '' # current \withsubitem text
|
||||
|
||||
def write_document(self, rootnode):
|
||||
""" Write a document, represented by a RootNode. """
|
||||
assert type(rootnode) is RootNode
|
||||
|
||||
if self.deflang:
|
||||
self.write_directive('highlightlang', self.deflang)
|
||||
|
||||
self.visit_node(rootnode)
|
||||
self.write_footnotes()
|
||||
|
||||
def new_chapter(self):
|
||||
""" Called if self.splitchap is True. Create a new file pointer
|
||||
and set self.fp to it. """
|
||||
new_fp = StringIO.StringIO()
|
||||
self.chapters.append(new_fp)
|
||||
self.fp = new_fp
|
||||
|
||||
def write(self, text='', nl=True, first=False):
|
||||
""" Write a string to the output file. """
|
||||
if first:
|
||||
self.fp.write((self.indentation if self.indentfirstline else '') + text)
|
||||
self.indentfirstline = True
|
||||
elif text: # don't write indentation only
|
||||
self.fp.write(self.indentation + text)
|
||||
if nl:
|
||||
self.fp.write('\n')
|
||||
|
||||
def write_footnotes(self):
|
||||
""" Write the current footnotes, if any. """
|
||||
self.flush_par()
|
||||
if self.footnotes:
|
||||
self.write('.. rubric:: Footnotes\n')
|
||||
footnotes = self.footnotes
|
||||
self.footnotes = [] # first clear since indented() will flush
|
||||
for footnode in footnotes:
|
||||
self.write('.. [#] ', nl=False)
|
||||
with self.indented(3, firstline=False):
|
||||
self.visit_node(footnode)
|
||||
|
||||
def write_directive(self, name, args='', node=None, spabove=False, spbelow=True):
|
||||
""" Helper to write a ReST directive. """
|
||||
if spabove:
|
||||
self.write()
|
||||
self.write('.. %s::%s' % (name, args and ' '+args))
|
||||
if spbelow:
|
||||
self.write()
|
||||
with self.indented():
|
||||
if node is not None:
|
||||
self.visit_node(node)
|
||||
|
||||
def write_sectionmeta(self):
|
||||
mod = self.sectionmeta
|
||||
self.sectionmeta = None
|
||||
if not mod:
|
||||
return
|
||||
if mod.modname:
|
||||
self.write('.. module:: %s' % mod.modname)
|
||||
if mod.platform:
|
||||
self.write(' :platform: %s' % mod.platform)
|
||||
if mod.synopsis:
|
||||
self.write(' :synopsis: %s' % mod.synopsis[0])
|
||||
for line in mod.synopsis[1:]:
|
||||
self.write(' %s' % line)
|
||||
if mod.modauthors:
|
||||
for author in mod.modauthors:
|
||||
self.write('.. moduleauthor:: %s' % author)
|
||||
if mod.sectauthors:
|
||||
for author in mod.sectauthors:
|
||||
self.write('.. sectionauthor:: %s' % author)
|
||||
self.write()
|
||||
self.write()
|
||||
|
||||
indexentry_mapping = {
|
||||
'index': 'single',
|
||||
'indexii': 'pair',
|
||||
'indexiii': 'triple',
|
||||
'indexiv': 'quadruple',
|
||||
'stindex': 'statement',
|
||||
'ttindex': 'single',
|
||||
'obindex': 'object',
|
||||
'opindex': 'operator',
|
||||
'kwindex': 'keyword',
|
||||
'exindex': 'exception',
|
||||
'bifuncindex': 'builtin',
|
||||
'refmodindex': 'module',
|
||||
'refbimodindex': 'module',
|
||||
'refexmodindex': 'module',
|
||||
'refstmodindex': 'module',
|
||||
}
|
||||
|
||||
def get_indexentries(self, entries):
|
||||
""" Return a list of lines for the index entries. """
|
||||
def format_entry(cmdname, args, subitem):
|
||||
textargs = []
|
||||
for arg in args:
|
||||
if isinstance(arg, TextNode):
|
||||
textarg = text(arg)
|
||||
else:
|
||||
textarg = self.get_node_text(self.get_textonly_node(arg, warn=0))
|
||||
if ';' in textarg:
|
||||
raise WriterError("semicolon in index args: " + textarg)
|
||||
textarg += subitem
|
||||
textarg = textarg.replace('!', '; ')
|
||||
textargs.append(textarg)
|
||||
return '%s: %s' % (self.indexentry_mapping[cmdname],
|
||||
'; '.join(textarg for textarg in textargs
|
||||
if not empty(arg)))
|
||||
|
||||
ret = []
|
||||
if len(entries) == 1:
|
||||
ret.append('.. index:: %s' % format_entry(*entries[0]))
|
||||
else:
|
||||
ret.append('.. index::')
|
||||
for entry in entries:
|
||||
ret.append(' %s' % format_entry(*entry))
|
||||
return ret
|
||||
|
||||
def get_par(self, wrap, width=None):
|
||||
""" Get the contents of the current paragraph.
|
||||
Returns a list if wrap and not indent, else a string. """
|
||||
if not self.curpar:
|
||||
if wrap:
|
||||
return []
|
||||
else:
|
||||
return ''
|
||||
text = ''.join(self.curpar).lstrip()
|
||||
text = repair_bad_inline_markup(text)
|
||||
self.curpar = []
|
||||
if wrap:
|
||||
# returns a list!
|
||||
wrapper.width = width or WIDTH
|
||||
return wrapper.wrap(text)
|
||||
else:
|
||||
return text
|
||||
|
||||
no_warn_textonly = set((
|
||||
'var', 'code', 'textrm', 'emph', 'keyword', 'textit', 'programopt',
|
||||
'cfunction', 'texttt', 'email', 'constant',
|
||||
))
|
||||
|
||||
def get_textonly_node(self, node, cmd='', warn=1):
|
||||
""" Return a similar Node or NodeList that only has TextNode subnodes.
|
||||
|
||||
Warning values:
|
||||
- 0: never warn
|
||||
- 1: warn for markup losing information
|
||||
"""
|
||||
if cmd == 'code':
|
||||
warn = 0
|
||||
def do(subnode):
|
||||
if isinstance(subnode, TextNode):
|
||||
return subnode
|
||||
if isinstance(subnode, NodeList):
|
||||
return NodeList(do(subsubnode) for subsubnode in subnode)
|
||||
if isinstance(subnode, CommentNode):
|
||||
# loses comments, but huh
|
||||
return EmptyNode()
|
||||
if isinstance(subnode, InlineNode):
|
||||
if subnode.cmdname in ('filevar', 'envvar'):
|
||||
return NodeList([TextNode('{'), do(subnode.args[0]), TextNode('}')])
|
||||
if subnode.cmdname == 'optional':
|
||||
# this is not mapped to ReST markup
|
||||
return subnode
|
||||
if len(subnode.args) == 1:
|
||||
if warn == 1 and subnode.cmdname not in self.no_warn_textonly:
|
||||
self.warnings.append('%r: Discarding %s markup in %r' %
|
||||
(cmd, subnode.cmdname, node))
|
||||
return do(subnode.args[0])
|
||||
elif len(subnode.args) == 0:
|
||||
# should only happen for IndexNodes which stay in
|
||||
return subnode
|
||||
elif len(subnode.args) == 2 and subnode.cmdname == 'refmodule':
|
||||
if not warn:
|
||||
return do(subnode.args[1])
|
||||
raise WriterError('get_textonly_node() failed for %r' % subnode)
|
||||
return do(node)
|
||||
|
||||
def get_node_text(self, node, wrap=False, width=None):
|
||||
""" Write the node to a temporary paragraph and return the result
|
||||
as a string. """
|
||||
with self.noflush:
|
||||
self._old_curpar = self.curpar
|
||||
self.curpar = []
|
||||
self.visit_node(node)
|
||||
ret = self.get_par(wrap, width=width)
|
||||
self.curpar = self._old_curpar
|
||||
return ret
|
||||
|
||||
def flush_par(self, nocb=False, nocomments=False):
|
||||
""" Write the current paragraph to the output file.
|
||||
Prepend index entries, append comments and footnotes. """
|
||||
if self.no_flushing:
|
||||
raise WriterError('called flush_par() while noflush active')
|
||||
if self.indexentries:
|
||||
for line in self.get_indexentries(self.indexentries):
|
||||
self.write(line)
|
||||
self.write()
|
||||
self.indexentries = []
|
||||
if self.flush_cb and not nocb:
|
||||
self.flush_cb()
|
||||
self.flush_cb = None
|
||||
par = self.get_par(wrap=True)
|
||||
if par:
|
||||
for i, line in enumerate(par):
|
||||
self.write(line, first=(i==0))
|
||||
self.write()
|
||||
if self.comments and not nocomments:
|
||||
for comment in self.comments:
|
||||
self.write('.. % ' + comment)
|
||||
self.write()
|
||||
self.comments = []
|
||||
|
||||
def visit_wrapped(self, pre, node, post, noescape=False):
|
||||
""" Write a node within a paragraph, wrapped with pre and post strings. """
|
||||
if noescape:
|
||||
self.noescape += 1
|
||||
self.curpar.append(pre)
|
||||
with self.noflush:
|
||||
self.visit_node(node)
|
||||
self.curpar.append(post)
|
||||
if noescape:
|
||||
self.noescape -= 1
|
||||
|
||||
def visit_node(self, node):
|
||||
""" "Write" a node (appends to curpar or writes something). """
|
||||
visitfunc = getattr(self, 'visit_' + node.__class__.__name__, None)
|
||||
if not visitfunc:
|
||||
raise WriterError('no visit function for %s node' % node.__class__)
|
||||
visitfunc(node)
|
||||
|
||||
# ------------------------- node handlers -----------------------------
|
||||
|
||||
def visit_RootNode(self, node):
|
||||
if node.params.get('title'):
|
||||
title = self.get_node_text(node.params['title'])
|
||||
hl = len(title)
|
||||
self.write('*' * (hl+4))
|
||||
self.write(' %s ' % title)
|
||||
self.write('*' * (hl+4))
|
||||
self.write()
|
||||
|
||||
if node.params.get('author'):
|
||||
self.write(':Author: %s%s' %
|
||||
(self.get_node_text(node.params['author']),
|
||||
(' <%s>' % self.get_node_text(node.params['authoremail'])
|
||||
if 'authoremail' in node.params else '')))
|
||||
self.write()
|
||||
|
||||
if node.params.get('date'):
|
||||
self.write(':Date: %s' % self.get_node_text(node.params['date']))
|
||||
self.write()
|
||||
|
||||
if node.params.get('release'):
|
||||
self.write('.. |release| replace:: %s' %
|
||||
self.get_node_text(node.params['release']))
|
||||
self.write()
|
||||
|
||||
self.visit_NodeList(node.children)
|
||||
|
||||
def visit_NodeList(self, nodelist):
|
||||
for node in nodelist:
|
||||
self.visit_node(node)
|
||||
|
||||
def visit_CommentNode(self, node):
|
||||
# no inline comments -> they are all output at the start of a new paragraph
|
||||
self.comments.append(node.comment.strip())
|
||||
|
||||
sectchars = {
|
||||
'chapter': '*',
|
||||
'chapter*': '*',
|
||||
'section': '=',
|
||||
'subsection': '-',
|
||||
'subsubsection': '^',
|
||||
'paragraph': '"',
|
||||
}
|
||||
|
||||
sectdoubleline = [
|
||||
'chapter',
|
||||
'chapter*',
|
||||
]
|
||||
|
||||
def visit_SectioningNode(self, node):
|
||||
self.flush_par()
|
||||
self.sectionlabel = ''
|
||||
self.thisclass = ''
|
||||
self.write()
|
||||
|
||||
if self.splitchap and node.cmdname.startswith('chapter'):
|
||||
self.write_footnotes()
|
||||
self.new_chapter()
|
||||
|
||||
heading = self.get_node_text(node.args[0]).strip()
|
||||
if self.sectionlabel:
|
||||
self.write('.. _%s:\n' % self.sectionlabel)
|
||||
hl = len(heading)
|
||||
if node.cmdname in self.sectdoubleline:
|
||||
self.write(self.sectchars[node.cmdname] * hl)
|
||||
self.write(heading)
|
||||
self.write(self.sectchars[node.cmdname] * hl)
|
||||
self.write()
|
||||
|
||||
def visit_EnvironmentNode(self, node):
|
||||
self.flush_par()
|
||||
envname = node.envname
|
||||
if envname == 'notice':
|
||||
type = text(node.args[0]) or 'note'
|
||||
self.write_directive(type, '', node.content)
|
||||
elif envname in ('seealso', 'seealso*'):
|
||||
self.write_directive('seealso', '', node.content, spabove=True)
|
||||
elif envname == 'abstract':
|
||||
self.write_directive('topic', 'Abstract', node.content, spabove=True)
|
||||
elif envname == 'quote':
|
||||
with self.indented():
|
||||
self.visit_node(node.content)
|
||||
self.write()
|
||||
elif envname == 'quotation':
|
||||
self.write_directive('epigraph', '', node.content, spabove=True)
|
||||
else:
|
||||
raise WriterError('no handler for %s environment' % envname)
|
||||
|
||||
descmap = {
|
||||
'funcdesc': ('function', '0(1)'),
|
||||
'funcdescni': ('function', '0(1)'),
|
||||
'classdesc': ('class', '0(1)'),
|
||||
'classdesc*': ('class', '0'),
|
||||
'methoddesc': ('method', '0.1(2)'),
|
||||
'methoddescni': ('method', '0.1(2)'),
|
||||
'excdesc': ('exception', '0'),
|
||||
'excclassdesc': ('exception', '0(1)'),
|
||||
'datadesc': ('data', '0'),
|
||||
'datadescni': ('data', '0'),
|
||||
'memberdesc': ('attribute', '0.1'),
|
||||
'memberdescni': ('attribute', '0.1'),
|
||||
'opcodedesc': ('opcode', '0 (1)'),
|
||||
|
||||
'cfuncdesc': ('cfunction', '0 1(2)'),
|
||||
'cmemberdesc': ('cmember', '1 0.2'),
|
||||
'csimplemacrodesc': ('cmacro', '0'),
|
||||
'ctypedesc': ('ctype', '1'),
|
||||
'cvardesc': ('cvar', '0 1'),
|
||||
}
|
||||
|
||||
def _write_sig(self, spec, args):
|
||||
# don't escape "*" in signatures
|
||||
self.noescape += 1
|
||||
for c in spec:
|
||||
if c.isdigit():
|
||||
self.visit_node(self.get_textonly_node(args[int(c)]))
|
||||
else:
|
||||
self.curpar.append(c)
|
||||
self.noescape -= 1
|
||||
|
||||
def visit_DescEnvironmentNode(self, node):
|
||||
envname = node.envname
|
||||
if envname not in self.descmap:
|
||||
raise WriterError('no handler for %s environment' % envname)
|
||||
|
||||
self.flush_par()
|
||||
# automatically fill in the class name if not given
|
||||
if envname[:9] == 'classdesc' or envname[:12] == 'excclassdesc':
|
||||
self.thisclass = text(node.args[0])
|
||||
elif envname[:10] in ('methoddesc', 'memberdesc') and not \
|
||||
text(node.args[0]):
|
||||
if not self.thisclass:
|
||||
raise WriterError('No current class for %s member' %
|
||||
text(node.args[1]))
|
||||
node.args[0] = TextNode(self.thisclass)
|
||||
directivename, sigspec = self.descmap[envname]
|
||||
self._write_sig(sigspec, node.args)
|
||||
signature = self.get_par(wrap=False)
|
||||
self.write()
|
||||
self.write('.. %s:: %s' % (directivename, signature))
|
||||
if node.additional:
|
||||
for cmdname, add in node.additional:
|
||||
entry = self.descmap[cmdname.replace('line', 'desc')]
|
||||
if envname[:10] in ('methoddesc', 'memberdesc') and not \
|
||||
text(add[0]):
|
||||
if not self.thisclass:
|
||||
raise WriterError('No current class for %s member' %
|
||||
text(add[1]))
|
||||
add[0] = TextNode(self.thisclass)
|
||||
self._write_sig(entry[1], add)
|
||||
signature = self.get_par(wrap=False)
|
||||
self.write(' %s%s' % (' ' * (len(directivename) - 2),
|
||||
signature))
|
||||
if envname.endswith('ni'):
|
||||
self.write(' :noindex:')
|
||||
self.write()
|
||||
with self.indented():
|
||||
self.visit_node(node.content)
|
||||
|
||||
|
||||
def visit_CommandNode(self, node):
|
||||
cmdname = node.cmdname
|
||||
if cmdname == 'label':
|
||||
labelname = self.labelprefix + text(node.args[0]).lower()
|
||||
if self.no_flushing:
|
||||
# in section
|
||||
self.sectionlabel = labelname
|
||||
else:
|
||||
self.flush_par()
|
||||
self.write('.. _%s:\n' % labelname)
|
||||
return
|
||||
|
||||
elif cmdname in ('declaremodule', 'modulesynopsis',
|
||||
'moduleauthor', 'sectionauthor', 'platform'):
|
||||
self.flush_par(nocb=True, nocomments=True)
|
||||
if not self.sectionmeta:
|
||||
self.sectionmeta = SectionMeta()
|
||||
if cmdname == 'declaremodule':
|
||||
self.sectionmeta.modname = text(node.args[2])
|
||||
elif cmdname == 'modulesynopsis':
|
||||
self.sectionmeta.synopsis = self.get_node_text(
|
||||
self.get_textonly_node(node.args[0], warn=0), wrap=True)
|
||||
elif cmdname == 'moduleauthor':
|
||||
email = text(node.args[1])
|
||||
self.sectionmeta.modauthors.append(
|
||||
'%s%s' % (text(node.args[0]), (email and ' <%s>' % email)))
|
||||
elif cmdname == 'sectionauthor':
|
||||
email = text(node.args[1])
|
||||
self.sectionmeta.sectauthors.append(
|
||||
'%s%s' % (text(node.args[0]), (email and ' <%s>' % email)))
|
||||
elif cmdname == 'platform':
|
||||
self.sectionmeta.platform = text(node.args[0])
|
||||
self.flush_cb = lambda: self.write_sectionmeta()
|
||||
return
|
||||
|
||||
self.flush_par()
|
||||
if cmdname.startswith('see'):
|
||||
i = 2
|
||||
if cmdname == 'seemodule':
|
||||
self.write('Module :mod:`%s`' % text(node.args[1]))
|
||||
elif cmdname == 'seelink':
|
||||
linktext = self.get_node_text(node.args[1])
|
||||
self.write('`%s <%s>`_' % (linktext, text(node.args[0])))
|
||||
elif cmdname == 'seepep':
|
||||
self.write(':pep:`%s` - %s' % (text(node.args[0]),
|
||||
self.get_node_text(node.args[1])))
|
||||
elif cmdname == 'seerfc':
|
||||
self.write(':rfc:`%s` - %s' % (text(node.args[0]),
|
||||
text(node.args[1])))
|
||||
elif cmdname == 'seetitle':
|
||||
if empty(node.args[0]):
|
||||
self.write('%s' % text(node.args[1]))
|
||||
else:
|
||||
self.write('`%s <%s>`_' % (text(node.args[1]),
|
||||
text(node.args[0])))
|
||||
elif cmdname == 'seeurl':
|
||||
i = 1
|
||||
self.write('%s' % text(node.args[0]))
|
||||
elif cmdname == 'seetext':
|
||||
self.visit_node(node.args[0])
|
||||
return
|
||||
with self.indented():
|
||||
self.visit_node(node.args[i])
|
||||
elif cmdname in ('versionchanged', 'versionadded'):
|
||||
self.write('.. %s:: %s' % (cmdname, text(node.args[1])))
|
||||
if not empty(node.args[0]):
|
||||
with self.indented():
|
||||
self.visit_node(node.args[0])
|
||||
self.curpar.append('.')
|
||||
else:
|
||||
self.write()
|
||||
elif cmdname == 'deprecated':
|
||||
self.write_directive('deprecated', text(node.args[0]), node.args[1],
|
||||
spbelow=False)
|
||||
elif cmdname == 'localmoduletable':
|
||||
if self.toctree is not None:
|
||||
self.write_directive('toctree', '', spbelow=True, spabove=True)
|
||||
with self.indented():
|
||||
for entry in self.toctree:
|
||||
self.write(entry + '.rst')
|
||||
else:
|
||||
self.warnings.append('no toctree given, but \\localmoduletable in file')
|
||||
elif cmdname == 'verbatiminput':
|
||||
inclname = text(node.args[0])
|
||||
newname = includes_mapping.get(inclname, '../includes/' + inclname)
|
||||
if newname is None:
|
||||
self.write()
|
||||
self.write('.. XXX includefile %s' % inclname)
|
||||
return
|
||||
self.write()
|
||||
self.write('.. include:: %s' % newname)
|
||||
self.write(' :literal:')
|
||||
self.write()
|
||||
elif cmdname == 'input':
|
||||
inclname = text(node.args[0])
|
||||
newname = includes_mapping.get(inclname, None)
|
||||
if newname is None:
|
||||
self.write('X' 'XX: input{%s} :XX' 'X' % inclname)
|
||||
return
|
||||
self.write_directive('include', newname, spabove=True)
|
||||
elif cmdname == 'centerline':
|
||||
self.write_directive('centered', self.get_node_text(node.args[0]),
|
||||
spabove=True, spbelow=True)
|
||||
elif cmdname == 'XX' 'X':
|
||||
self.visit_wrapped(r'**\*\*** ', node.args[0], ' **\*\***')
|
||||
else:
|
||||
raise WriterError('no handler for %s command' % cmdname)
|
||||
|
||||
def visit_DescLineCommandNode(self, node):
|
||||
# these have already been written as arguments of the corresponding
|
||||
# DescEnvironmentNode
|
||||
pass
|
||||
|
||||
def visit_ParaSepNode(self, node):
|
||||
self.flush_par()
|
||||
|
||||
def visit_VerbatimNode(self, node):
|
||||
if self.comments:
|
||||
# these interfer with the literal block
|
||||
self.flush_par()
|
||||
if self.curpar:
|
||||
last = self.curpar[-1].rstrip(' ')
|
||||
if last.endswith(':'):
|
||||
self.curpar[-1] = last + ':'
|
||||
else:
|
||||
self.curpar.append(' ::')
|
||||
else:
|
||||
self.curpar.append('::')
|
||||
self.flush_par()
|
||||
with self.indented():
|
||||
if isinstance(node.content, TextNode):
|
||||
# verbatim
|
||||
lines = textwrap.dedent(text(node.content).lstrip('\n')).split('\n')
|
||||
if not lines:
|
||||
return
|
||||
else:
|
||||
# alltt, possibly with inline formats
|
||||
lines = self.get_node_text(self.get_textonly_node(
|
||||
node.content, warn=0)).split('\n') + ['']
|
||||
# discard leading blank links
|
||||
while not lines[0].strip():
|
||||
del lines[0]
|
||||
for line in lines:
|
||||
self.write(line)
|
||||
|
||||
note_re = re.compile('^\(\d\)$')
|
||||
|
||||
def visit_TableNode(self, node):
|
||||
self.flush_par()
|
||||
lines = node.lines[:]
|
||||
lines.insert(0, node.headings)
|
||||
fmted_rows = []
|
||||
width = WIDTH - len(self.indentation)
|
||||
realwidths = [0] * node.numcols
|
||||
colwidth = (width / node.numcols) + 5
|
||||
# don't allow paragraphs in table cells for now
|
||||
with self.noflush:
|
||||
for line in lines:
|
||||
cells = []
|
||||
for i, cell in enumerate(line):
|
||||
par = self.get_node_text(cell, wrap=True, width=colwidth)
|
||||
if len(par) == 1 and self.note_re.match(par[0].strip()):
|
||||
# special case: escape "(1)" to avoid enumeration
|
||||
par[0] = '\\' + par[0]
|
||||
maxwidth = max(map(len, par)) if par else 0
|
||||
realwidths[i] = max(realwidths[i], maxwidth)
|
||||
cells.append(par)
|
||||
fmted_rows.append(cells)
|
||||
|
||||
def writesep(char='-'):
|
||||
out = ['+']
|
||||
for width in realwidths:
|
||||
out.append(char * (width+2))
|
||||
out.append('+')
|
||||
self.write(''.join(out))
|
||||
|
||||
def writerow(row):
|
||||
lines = map(None, *row)
|
||||
for line in lines:
|
||||
out = ['|']
|
||||
for i, cell in enumerate(line):
|
||||
if cell:
|
||||
out.append(' ' + cell.ljust(realwidths[i]+1))
|
||||
else:
|
||||
out.append(' ' * (realwidths[i] + 2))
|
||||
out.append('|')
|
||||
self.write(''.join(out))
|
||||
|
||||
writesep('-')
|
||||
writerow(fmted_rows[0])
|
||||
writesep('=')
|
||||
for row in fmted_rows[1:]:
|
||||
writerow(row)
|
||||
writesep('-')
|
||||
self.write()
|
||||
|
||||
def visit_ItemizeNode(self, node):
|
||||
self.flush_par()
|
||||
for title, content in node.items:
|
||||
if not empty(title):
|
||||
# do it like in a description list
|
||||
self.write(self.get_node_text(title))
|
||||
with self.indented():
|
||||
self.visit_node(content)
|
||||
else:
|
||||
self.curpar.append('* ')
|
||||
with self.indented(2, firstline=False):
|
||||
self.visit_node(content)
|
||||
|
||||
def visit_EnumerateNode(self, node):
|
||||
self.flush_par()
|
||||
for title, content in node.items:
|
||||
assert empty(title)
|
||||
self.curpar.append('#. ')
|
||||
with self.indented(3, firstline=False):
|
||||
self.visit_node(content)
|
||||
|
||||
def visit_DescriptionNode(self, node):
|
||||
self.flush_par()
|
||||
for title, content in node.items:
|
||||
self.write(self.get_node_text(title))
|
||||
with self.indented():
|
||||
self.visit_node(content)
|
||||
|
||||
visit_DefinitionsNode = visit_DescriptionNode
|
||||
|
||||
def visit_ProductionListNode(self, node):
|
||||
self.flush_par()
|
||||
arg = text(node.arg)
|
||||
self.write('.. productionlist::%s' % (' '+arg if arg else ''))
|
||||
with self.indented():
|
||||
for item in node.items:
|
||||
if not empty(item[0]):
|
||||
lasttext = text(item[0])
|
||||
self.write('%s: %s' % (
|
||||
text(item[0]).ljust(len(lasttext)),
|
||||
self.get_node_text(item[1])))
|
||||
self.write()
|
||||
|
||||
def visit_EmptyNode(self, node):
|
||||
pass
|
||||
|
||||
def visit_TextNode(self, node):
|
||||
if self.noescape:
|
||||
self.curpar.append(node.text)
|
||||
else:
|
||||
self.curpar.append(fixup_text(node.text))
|
||||
|
||||
visit_NbspNode = visit_TextNode
|
||||
visit_SimpleCmdNode = visit_TextNode
|
||||
|
||||
def visit_BreakNode(self, node):
|
||||
# XXX: linebreaks in ReST?
|
||||
self.curpar.append(' --- ')
|
||||
|
||||
def visit_IndexNode(self, node):
|
||||
if node.cmdname == 'withsubitem':
|
||||
self.indexsubitem = ' ' + text(node.indexargs[0])
|
||||
self.visit_node(node.indexargs[1])
|
||||
self.indexsubitem = ''
|
||||
else:
|
||||
self.indexentries.append((node.cmdname, node.indexargs,
|
||||
self.indexsubitem))
|
||||
|
||||
# maps argumentless commands to text
|
||||
simplecmd_mapping = {
|
||||
'NULL': '*NULL*',
|
||||
'shortversion': '|version|',
|
||||
'version': '|release|',
|
||||
'today': '|today|',
|
||||
}
|
||||
|
||||
# map LaTeX command names to roles: shorter names!
|
||||
role_mapping = {
|
||||
'cfunction': 'cfunc',
|
||||
'constant': 'const',
|
||||
'csimplemacro': 'cmacro',
|
||||
'exception': 'exc',
|
||||
'function': 'func',
|
||||
'grammartoken': 'token',
|
||||
'member': 'attr',
|
||||
'method': 'meth',
|
||||
'module': 'mod',
|
||||
'programopt': 'option',
|
||||
'filenq': 'file',
|
||||
# these mean: no change
|
||||
'cdata': '',
|
||||
'class': '',
|
||||
'command': '',
|
||||
'ctype': '',
|
||||
'data': '', # NEW
|
||||
'dfn': '',
|
||||
'envvar': '',
|
||||
'file': '',
|
||||
'guilabel': '',
|
||||
'kbd': '',
|
||||
'keyword': '',
|
||||
'mailheader': '',
|
||||
'makevar': '',
|
||||
'menuselection': '',
|
||||
'mimetype': '',
|
||||
'newsgroup': '',
|
||||
'option': '',
|
||||
'pep': '',
|
||||
'program': '',
|
||||
'ref': '',
|
||||
'rfc': '',
|
||||
}
|
||||
|
||||
# do not warn about nested inline markup in these roles
|
||||
role_no_warn = set((
|
||||
'cdata', 'cfunction', 'class', 'constant', 'csimplemacro', 'ctype',
|
||||
'data', 'exception', 'function', 'member', 'method', 'module',
|
||||
))
|
||||
|
||||
def visit_InlineNode(self, node):
|
||||
# XXX: no nested markup -- docutils doesn't support it
|
||||
cmdname = node.cmdname
|
||||
if not node.args:
|
||||
self.curpar.append(self.simplecmd_mapping[cmdname])
|
||||
return
|
||||
content = node.args[0]
|
||||
if cmdname in ('code', 'bfcode', 'samp', 'texttt', 'regexp'):
|
||||
self.visit_wrapped('``', self.get_textonly_node(content, 'code',
|
||||
warn=1), '``', noescape=True)
|
||||
elif cmdname in ('emph', 'textit', 'var'):
|
||||
self.visit_wrapped('*', self.get_textonly_node(content, 'emph',
|
||||
warn=1), '*')
|
||||
elif cmdname in ('strong', 'textbf'):
|
||||
self.visit_wrapped('**', self.get_textonly_node(content, 'strong',
|
||||
warn=1), '**')
|
||||
elif cmdname in ('b', 'textrm', 'email'):
|
||||
self.visit_node(content)
|
||||
elif cmdname == 'token':
|
||||
# \token appears in productionlists only
|
||||
self.visit_wrapped('`', self.get_textonly_node(content, 'var',
|
||||
warn=1), '`')
|
||||
elif cmdname == 'ref':
|
||||
self.curpar.append(':ref:`%s%s`' % (self.labelprefix,
|
||||
text(node.args[0]).lower()))
|
||||
elif cmdname == 'refmodule':
|
||||
self.visit_wrapped(':mod:`', node.args[1], '`', noescape=True)
|
||||
elif cmdname == 'optional':
|
||||
self.visit_wrapped('[', content, ']')
|
||||
elif cmdname == 'url':
|
||||
self.visit_node(content)
|
||||
elif cmdname == 'ulink':
|
||||
target = text(node.args[1])
|
||||
if target.startswith('..'):
|
||||
self.visit_wrapped('', content, ' (X' + 'XX reference: %s)' % target)
|
||||
elif not target.startswith(('http:', 'mailto:')):
|
||||
#self.warnings.append('Local \\ulink to %s, use \\ref instead' % target)
|
||||
self.visit_wrapped('', content, ' (X' 'XX reference: %s)' % target)
|
||||
else:
|
||||
self.visit_wrapped('`', self.get_textonly_node(content, 'ulink', warn=1),
|
||||
' <%s>`_' % target)
|
||||
elif cmdname == 'citetitle':
|
||||
target = text(content)
|
||||
if not target:
|
||||
self.visit_node(node.args[1])
|
||||
elif target.startswith('..'):
|
||||
self.visit_wrapped('', node.args[1],
|
||||
' (X' + 'XX reference: %s)' % target)
|
||||
else:
|
||||
self.visit_wrapped('`', self.get_textonly_node(node.args[1],
|
||||
'citetitle', warn=1),
|
||||
' <%s>`_' % target)
|
||||
elif cmdname == 'character':
|
||||
# ``'a'`` is not longer than :character:`a`
|
||||
self.visit_wrapped("``'", content, "'``", noescape=True)
|
||||
elif cmdname == 'manpage':
|
||||
self.curpar.append(':manpage:`')
|
||||
self.visit_node(self.get_textonly_node(content, warn=0))
|
||||
self.visit_wrapped('(', self.get_textonly_node(node.args[1], warn=0), ')')
|
||||
self.curpar.append('`')
|
||||
elif cmdname == 'footnote':
|
||||
self.curpar.append(' [#]_')
|
||||
self.footnotes.append(content)
|
||||
elif cmdname == 'frac':
|
||||
self.visit_wrapped('(', node.args[0], ')/')
|
||||
self.visit_wrapped('(', node.args[1], ')')
|
||||
elif cmdname == 'longprogramopt':
|
||||
self.visit_wrapped(':option:`--', content, '`')
|
||||
elif cmdname == 'filevar':
|
||||
self.visit_wrapped(':file:`{', content, '}`')
|
||||
elif cmdname == '':
|
||||
self.visit_node(content)
|
||||
# stray commands from distutils
|
||||
elif cmdname in ('argument name', 'value', 'attribute', 'option name'):
|
||||
self.visit_wrapped('*', content, '*')
|
||||
else:
|
||||
self.visit_wrapped(':%s:`' % (self.role_mapping[cmdname] or cmdname),
|
||||
self.get_textonly_node(
|
||||
content, cmdname, warn=(cmdname not in self.role_no_warn)), '`')
|
||||
@@ -1,97 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
scanner
|
||||
~~~~~~~
|
||||
|
||||
This library implements a regex based scanner.
|
||||
|
||||
:copyright: 2006-2007 by Armin Ronacher, Georg Brandl.
|
||||
:license: BSD license.
|
||||
"""
|
||||
import re
|
||||
|
||||
|
||||
class EndOfText(RuntimeError):
|
||||
"""
|
||||
Raise if end of text is reached and the user
|
||||
tried to call a match function.
|
||||
"""
|
||||
|
||||
|
||||
class Scanner(object):
|
||||
"""
|
||||
Simple scanner
|
||||
|
||||
All method patterns are regular expression strings (not
|
||||
compiled expressions!)
|
||||
"""
|
||||
|
||||
def __init__(self, text, flags=0):
|
||||
"""
|
||||
:param text: The text which should be scanned
|
||||
:param flags: default regular expression flags
|
||||
"""
|
||||
self.data = text
|
||||
self.data_length = len(text)
|
||||
self.start_pos = 0
|
||||
self.pos = 0
|
||||
self.flags = flags
|
||||
self.last = None
|
||||
self.match = None
|
||||
self._re_cache = {}
|
||||
|
||||
def eos(self):
|
||||
"""`True` if the scanner reached the end of text."""
|
||||
return self.pos >= self.data_length
|
||||
eos = property(eos, eos.__doc__)
|
||||
|
||||
def check(self, pattern):
|
||||
"""
|
||||
Apply `pattern` on the current position and return
|
||||
the match object. (Doesn't touch pos). Use this for
|
||||
lookahead.
|
||||
"""
|
||||
if self.eos:
|
||||
raise EndOfText()
|
||||
if pattern not in self._re_cache:
|
||||
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
||||
return self._re_cache[pattern].match(self.data, self.pos)
|
||||
|
||||
def test(self, pattern):
|
||||
"""Apply a pattern on the current position and check
|
||||
if it patches. Doesn't touch pos."""
|
||||
return self.check(pattern) is not None
|
||||
|
||||
def scan(self, pattern):
|
||||
"""
|
||||
Scan the text for the given pattern and update pos/match
|
||||
and related fields. The return value is a boolen that
|
||||
indicates if the pattern matched. The matched value is
|
||||
stored on the instance as ``match``, the last value is
|
||||
stored as ``last``. ``start_pos`` is the position of the
|
||||
pointer before the pattern was matched, ``pos`` is the
|
||||
end position.
|
||||
"""
|
||||
if self.eos:
|
||||
raise EndOfText()
|
||||
if pattern not in self._re_cache:
|
||||
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
||||
self.last = self.match
|
||||
m = self._re_cache[pattern].match(self.data, self.pos)
|
||||
if m is None:
|
||||
return False
|
||||
self.start_pos = m.start()
|
||||
self.pos = m.end()
|
||||
self.match = m
|
||||
return True
|
||||
|
||||
def get_char(self):
|
||||
"""Scan exactly one char."""
|
||||
self.scan('.')
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %d/%d>' % (
|
||||
self.__class__.__name__,
|
||||
self.pos,
|
||||
self.data_length
|
||||
)
|
||||
@@ -1,124 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python documentation LaTeX file tokenizer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For more documentation, look into the ``restwriter.py`` file.
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from .scanner import Scanner
|
||||
|
||||
class Tokenizer(Scanner):
|
||||
""" Lex a Python doc LaTeX document. """
|
||||
|
||||
specials = {
|
||||
'{': 'bgroup',
|
||||
'}': 'egroup',
|
||||
'[': 'boptional',
|
||||
']': 'eoptional',
|
||||
'~': 'tilde',
|
||||
'$': 'mathmode',
|
||||
}
|
||||
|
||||
@property
|
||||
def mtext(self):
|
||||
return self.match.group()
|
||||
|
||||
def tokenize(self):
|
||||
return TokenStream(self._tokenize())
|
||||
|
||||
def _tokenize(self):
|
||||
lineno = 1
|
||||
while not self.eos:
|
||||
if self.scan(r'\\verb([^a-zA-Z])(.*?)(\1)'):
|
||||
# specialcase \verb here
|
||||
yield lineno, 'command', 'verb', '\\verb'
|
||||
yield lineno, 'text', self.match.group(1), self.match.group(1)
|
||||
yield lineno, 'text', self.match.group(2), self.match.group(2)
|
||||
yield lineno, 'text', self.match.group(3), self.match.group(3)
|
||||
elif self.scan(r'\\([a-zA-Z]+\*?)[ \t]*'):
|
||||
yield lineno, 'command', self.match.group(1), self.mtext
|
||||
elif self.scan(r'\\.'):
|
||||
yield lineno, 'command', self.mtext[1], self.mtext
|
||||
elif self.scan(r'\\\n'):
|
||||
yield lineno, 'text', self.mtext, self.mtext
|
||||
lineno += 1
|
||||
elif self.scan(r'%(.*)\n[ \t]*'):
|
||||
yield lineno, 'comment', self.match.group(1), self.mtext
|
||||
lineno += 1
|
||||
elif self.scan(r'[{}\[\]~$]'):
|
||||
yield lineno, self.specials[self.mtext], self.mtext, self.mtext
|
||||
elif self.scan(r'(\n[ \t]*){2,}'):
|
||||
lines = self.mtext.count('\n')
|
||||
yield lineno, 'parasep', '\n' * lines, self.mtext
|
||||
lineno += lines
|
||||
elif self.scan(r'\n[ \t]*'):
|
||||
yield lineno, 'text', ' ', self.mtext
|
||||
lineno += 1
|
||||
elif self.scan(r'[^\\%}{\[\]~\n]+'):
|
||||
yield lineno, 'text', self.mtext, self.mtext
|
||||
else:
|
||||
raise RuntimeError('unexpected text on line %d: %r' %
|
||||
(lineno, self.data[self.pos:self.pos+100]))
|
||||
|
||||
|
||||
class TokenStream(object):
|
||||
"""
|
||||
A token stream works like a normal generator just that
|
||||
it supports peeking and pushing tokens back to the stream.
|
||||
"""
|
||||
|
||||
def __init__(self, generator):
|
||||
self._generator = generator
|
||||
self._pushed = []
|
||||
self.last = (1, 'initial', '')
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __nonzero__(self):
|
||||
""" Are we at the end of the tokenstream? """
|
||||
if self._pushed:
|
||||
return True
|
||||
try:
|
||||
self.push(self.next())
|
||||
except StopIteration:
|
||||
return False
|
||||
return True
|
||||
|
||||
def pop(self):
|
||||
""" Return the next token from the stream. """
|
||||
if self._pushed:
|
||||
rv = self._pushed.pop()
|
||||
else:
|
||||
rv = self._generator.next()
|
||||
self.last = rv
|
||||
return rv
|
||||
|
||||
next = pop
|
||||
|
||||
def popmany(self, num=1):
|
||||
""" Pop a list of tokens. """
|
||||
return [self.next() for i in range(num)]
|
||||
|
||||
def peek(self):
|
||||
""" Pop and push a token, return it. """
|
||||
token = self.next()
|
||||
self.push(token)
|
||||
return token
|
||||
|
||||
def peekmany(self, num=1):
|
||||
""" Pop and push a list of tokens. """
|
||||
tokens = self.popmany(num)
|
||||
for tok in tokens:
|
||||
self.push(tok)
|
||||
return tokens
|
||||
|
||||
def push(self, item):
|
||||
""" Push a token back to the stream. """
|
||||
self._pushed.append(item)
|
||||
@@ -1,100 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Python documentation conversion utils
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: 2007-2008 by Georg Brandl.
|
||||
:license: BSD.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from docutils.nodes import make_id
|
||||
|
||||
from .docnodes import TextNode, EmptyNode, NodeList
|
||||
|
||||
|
||||
def umlaut(cmd, c):
|
||||
try:
|
||||
if cmd == '"':
|
||||
return {'o': u'ö',
|
||||
'a': u'ä',
|
||||
'u': u'ü',
|
||||
'i': u'ï',
|
||||
'O': u'Ö',
|
||||
'A': u'Ä',
|
||||
'U': u'Ü'}[c]
|
||||
elif cmd == "'":
|
||||
return {'a': u'á',
|
||||
'e': u'é'}[c]
|
||||
elif cmd == '~':
|
||||
return {'n': u'ñ'}[c]
|
||||
elif cmd == 'c':
|
||||
return {'c': u'ç'}[c]
|
||||
elif cmd == '`':
|
||||
return {'o': u'ò'}[c]
|
||||
else:
|
||||
from .latexparser import ParserError
|
||||
raise ParserError('invalid umlaut \\%s' % cmd, 0)
|
||||
except KeyError:
|
||||
from .latexparser import ParserError
|
||||
raise ParserError('unsupported umlaut \\%s%s' % (cmd, c), 0)
|
||||
|
||||
def fixup_text(text):
|
||||
return text.replace('``', '"').replace("''", '"').replace('`', "'").\
|
||||
replace('|', '\\|').replace('*', '\\*')
|
||||
|
||||
def empty(node):
|
||||
return (type(node) is EmptyNode)
|
||||
|
||||
def text(node):
|
||||
""" Return the text for a TextNode or raise an error. """
|
||||
if isinstance(node, TextNode):
|
||||
return node.text
|
||||
elif isinstance(node, NodeList):
|
||||
restext = ''
|
||||
for subnode in node:
|
||||
restext += text(subnode)
|
||||
return restext
|
||||
from .restwriter import WriterError
|
||||
raise WriterError('text() failed for %r' % node)
|
||||
|
||||
markup_re = re.compile(r'(:[a-zA-Z0-9_-]+:)?`(.*?)`')
|
||||
|
||||
def my_make_id(name):
|
||||
""" Like make_id(), but strip roles first. """
|
||||
return make_id(markup_re.sub(r'\2', name))
|
||||
|
||||
alphanum = u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
wordchars_s = alphanum + u'_.-'
|
||||
wordchars_e = alphanum + u'+`(-'
|
||||
bad_markup_re = re.compile(r'(:[a-zA-Z0-9_-]+:)?(`{1,2})[ ]*(.+?)[ ]*(\2)')
|
||||
quoted_code_re = re.compile(r'\\`(``.+?``)\'')
|
||||
paren_re = re.compile(r':(func|meth|cfunc):`(.*?)\(\)`')
|
||||
|
||||
def repair_bad_inline_markup(text):
|
||||
# remove quoting from `\code{x}'
|
||||
xtext = quoted_code_re.sub(r'\1', text)
|
||||
|
||||
# special: the literal backslash
|
||||
xtext = xtext.replace('``\\``', '\x03')
|
||||
# special: literal backquotes
|
||||
xtext = xtext.replace('``````', '\x02')
|
||||
|
||||
# remove () from function markup
|
||||
xtext = paren_re.sub(r':\1:`\2`', xtext)
|
||||
|
||||
ntext = []
|
||||
lasti = 0
|
||||
l = len(xtext)
|
||||
for m in bad_markup_re.finditer(xtext):
|
||||
ntext.append(xtext[lasti:m.start()])
|
||||
s, e = m.start(), m.end()
|
||||
if s != 0 and xtext[s-1:s] in wordchars_s:
|
||||
ntext.append('\\ ')
|
||||
ntext.append((m.group(1) or '') + m.group(2) + m.group(3) + m.group(4))
|
||||
if e != l and xtext[e:e+1] in wordchars_e:
|
||||
ntext.append('\\ ')
|
||||
lasti = m.end()
|
||||
ntext.append(xtext[lasti:])
|
||||
return ''.join(ntext).replace('\x02', '``````').replace('\x03', '``\\``')
|
||||
Reference in New Issue
Block a user