summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
authorDasIch <dasdasich@gmail.com>2010-08-15 11:55:46 +0200
committerDasIch <dasdasich@gmail.com>2010-08-15 11:55:46 +0200
commit7926331c6fa1d80e08ae4d6c19bc1cfdce9e16c8 (patch)
treec31e72f4dc43e03502213c08a6d036492ea98856 /sphinx
parentc8f16b61cc6682fbbe47a5902b3c92e4b9336be0 (diff)
parentc0e116c026aebb10854d8e083e702f6290403116 (diff)
downloadsphinx-7926331c6fa1d80e08ae4d6c19bc1cfdce9e16c8.tar.gz
merge with lehmannro/sphinx-i18n
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/__init__.py24
-rw-r--r--sphinx/application.py7
-rw-r--r--sphinx/builders/epub.py145
-rw-r--r--sphinx/builders/html.py91
-rw-r--r--sphinx/builders/htmlhelp.py3
-rw-r--r--sphinx/builders/linkcheck.py19
-rw-r--r--sphinx/builders/qthelp.py14
-rw-r--r--sphinx/config.py39
-rw-r--r--sphinx/directives/__init__.py7
-rw-r--r--sphinx/directives/code.py4
-rw-r--r--sphinx/directives/other.py7
-rw-r--r--sphinx/domains/cpp.py4
-rw-r--r--sphinx/domains/javascript.py2
-rw-r--r--sphinx/domains/python.py94
-rw-r--r--sphinx/domains/rst.py14
-rw-r--r--sphinx/environment.py31
-rw-r--r--sphinx/ext/autodoc.py94
-rw-r--r--sphinx/ext/coverage.py5
-rw-r--r--sphinx/ext/doctest.py6
-rw-r--r--sphinx/ext/graphviz.py1
-rw-r--r--sphinx/ext/inheritance_diagram.py2
-rw-r--r--sphinx/ext/intersphinx.py44
-rw-r--r--sphinx/ext/oldcmarkup.py15
-rw-r--r--sphinx/ext/viewcode.py6
-rw-r--r--sphinx/highlighting.py6
-rw-r--r--sphinx/locale/__init__.py10
-rw-r--r--sphinx/locale/bn/LC_MESSAGES/sphinx.js1
-rw-r--r--sphinx/locale/bn/LC_MESSAGES/sphinx.mobin0 -> 12509 bytes
-rw-r--r--sphinx/locale/bn/LC_MESSAGES/sphinx.po698
-rw-r--r--sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js2
-rw-r--r--sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mobin8836 -> 10252 bytes
-rw-r--r--sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po222
-rw-r--r--sphinx/pycode/__init__.py6
-rw-r--r--sphinx/pycode/nodes.py2
-rw-r--r--sphinx/pycode/pgen2/literals.py2
-rw-r--r--sphinx/pycode/pgen2/tokenize.py4
-rw-r--r--sphinx/quickstart.py81
-rw-r--r--sphinx/roles.py21
-rw-r--r--sphinx/texinputs/sphinx.sty1
-rw-r--r--sphinx/themes/basic/layout.html2
-rw-r--r--sphinx/util/__init__.py57
-rw-r--r--sphinx/util/docfields.py16
-rw-r--r--sphinx/util/jsonimpl.py48
-rw-r--r--sphinx/util/nodes.py4
-rw-r--r--sphinx/util/osutil.py12
-rw-r--r--sphinx/util/pycompat.py59
-rw-r--r--sphinx/versioning.py148
-rw-r--r--sphinx/writers/latex.py72
-rw-r--r--sphinx/writers/text.py2
49 files changed, 1731 insertions, 423 deletions
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 37b6ecef..1ea2e7bf 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -9,11 +9,14 @@
:license: BSD, see LICENSE for details.
"""
+# Keep this file executable as-is in Python 3!
+# (Otherwise getting the version out of it from setup.py is impossible.)
+
import sys
from os import path
-__version__ = '1.0b2+'
-__released__ = '1.0b2' # used when Sphinx builds its own docs
+__version__ = '1.1pre'
+__released__ = '1.1 (hg)' # used when Sphinx builds its own docs
package_dir = path.abspath(path.dirname(__file__))
@@ -35,13 +38,14 @@ if '+' in __version__ or 'pre' in __version__:
def main(argv=sys.argv):
if sys.version_info[:3] < (2, 4, 0):
- print >>sys.stderr, \
- 'Error: Sphinx requires at least Python 2.4 to run.'
+ sys.stderr.write('Error: Sphinx requires at least '
+ 'Python 2.4 to run.\n')
return 1
try:
from sphinx import cmdline
- except ImportError, err:
+ except ImportError:
+ err = sys.exc_info()[1]
errstr = str(err)
if errstr.lower().startswith('no module named'):
whichmod = errstr[16:]
@@ -54,14 +58,14 @@ def main(argv=sys.argv):
whichmod = 'roman module (which is distributed with Docutils)'
hint = ('This can happen if you upgraded docutils using\n'
'easy_install without uninstalling the old version'
- 'first.')
+ 'first.\n')
else:
whichmod += ' module'
- print >>sys.stderr, ('Error: The %s cannot be found. '
- 'Did you install Sphinx and its dependencies '
- 'correctly?' % whichmod)
+ sys.stderr.write('Error: The %s cannot be found. '
+ 'Did you install Sphinx and its dependencies '
+ 'correctly?\n' % whichmod)
if hint:
- print >> sys.stderr, hint
+ sys.stderr.write(hint)
return 1
raise
return cmdline.main(argv)
diff --git a/sphinx/application.py b/sphinx/application.py
index 3ffd86c2..b3d2aebc 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -37,9 +37,6 @@ from sphinx.util.osutil import ENOENT
from sphinx.util.console import bold
-# Directive is either new-style or old-style
-clstypes = (type, types.ClassType)
-
# List of all known core events. Maps name to arguments description.
events = {
'builder-inited': '',
@@ -109,7 +106,9 @@ class Sphinx(object):
if self.confdir is None:
self.confdir = self.srcdir
- # load all extension modules
+ # backwards compatibility: activate old C markup
+ self.setup_extension('sphinx.ext.oldcmarkup')
+ # load all user-given extension modules
for extension in self.config.extensions:
self.setup_extension(extension)
# the config file itself can be an extension
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index 9767391e..aea07d4d 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -11,15 +11,17 @@
"""
import os
+import re
import codecs
-from os import path
import zipfile
+from os import path
from docutils import nodes
-from docutils.transforms import Transform
+from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.osutil import EEXIST
+from sphinx.util.smartypants import sphinx_smarty_pants as ssp
# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
@@ -119,29 +121,10 @@ _media_types = {
'.ttf': 'application/x-font-ttf',
}
-
-# The transform to show link targets
-
-class VisibleLinksTransform(Transform):
- """
- Add the link target of referances to the text, unless it is already
- present in the description.
- """
-
- # This transform must run after the references transforms
- default_priority = 680
-
- def apply(self):
- for ref in self.document.traverse(nodes.reference):
- uri = ref.get('refuri', '')
- if ( uri.startswith('http:') or uri.startswith('https:') or \
- uri.startswith('ftp:') ) and uri not in ref.astext():
- uri = _link_target_template % {'uri': uri}
- if uri:
- idx = ref.parent.index(ref) + 1
- link = nodes.inline(uri, uri)
- link['classes'].append(_css_link_target_class)
- ref.parent.insert(idx, link)
+# Regular expression to match colons only in local fragment identifiers.
+# If the URI contains a colon before the #,
+# it is an external link that should not change.
+_refuri_re = re.compile("([^#:]*#)(.*)")
# The epub publisher
@@ -170,7 +153,6 @@ class EpubBuilder(StandaloneHTMLBuilder):
# the output files for epub must be .html only
self.out_suffix = '.html'
self.playorder = 0
- self.app.add_transform(VisibleLinksTransform)
def get_theme_config(self):
return self.config.epub_theme, {}
@@ -194,17 +176,20 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute
# toctree-l[1-8] on the parent node?
- if isinstance(doctree, nodes.reference):
+ if isinstance(doctree, nodes.reference) and doctree.has_key('refuri'):
+ refuri = doctree['refuri']
+ if refuri.startswith('http://') or refuri.startswith('https://') \
+ or refuri.startswith('irc:') or refuri.startswith('mailto:'):
+ return result
classes = doctree.parent.attributes['classes']
- level = 1
- for l in range(8, 0, -1): # or range(1, 8)?
- if (_toctree_template % l) in classes:
- level = l
- result.append({
- 'level': level,
- 'refuri': self.esc(doctree['refuri']),
- 'text': self.esc(doctree.astext())
- })
+ for level in range(8, 0, -1): # or range(1, 8)?
+ if (_toctree_template % level) in classes:
+ result.append({
+ 'level': level,
+ 'refuri': self.esc(refuri),
+ 'text': ssp(self.esc(doctree.astext()))
+ })
+ break
else:
for elem in doctree.children:
result = self.get_refnodes(elem, result)
@@ -220,21 +205,97 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.refnodes.insert(0, {
'level': 1,
'refuri': self.esc(self.config.master_doc + '.html'),
- 'text': self.esc(self.env.titles[self.config.master_doc].astext())
+ 'text': ssp(self.esc(
+ self.env.titles[self.config.master_doc].astext()))
})
for file, text in reversed(self.config.epub_pre_files):
self.refnodes.insert(0, {
'level': 1,
- 'refuri': self.esc(file + '.html'),
- 'text': self.esc(text)
+ 'refuri': self.esc(file),
+ 'text': ssp(self.esc(text))
})
for file, text in self.config.epub_post_files:
self.refnodes.append({
'level': 1,
- 'refuri': self.esc(file + '.html'),
- 'text': self.esc(text)
+ 'refuri': self.esc(file),
+ 'text': ssp(self.esc(text))
})
+ def fix_fragment(self, match):
+ """Return a href attribute with colons replaced by hyphens.
+ """
+ return match.group(1) + match.group(2).replace(':', '-')
+
+ def fix_ids(self, tree):
+ """Replace colons with hyphens in href and id attributes.
+ Some readers crash because they interpret the part as a
+ transport protocol specification.
+ """
+ for node in tree.traverse(nodes.reference):
+ if 'refuri' in node:
+ m = _refuri_re.match(node['refuri'])
+ if m:
+ node['refuri'] = self.fix_fragment(m)
+ if 'refid' in node:
+ node['refid'] = node['refid'].replace(':', '-')
+ for node in tree.traverse(addnodes.desc_signature):
+ ids = node.attributes['ids']
+ newids = []
+ for id in ids:
+ newids.append(id.replace(':', '-'))
+ node.attributes['ids'] = newids
+
+ def add_visible_links(self, tree):
+ """Append visible link targets after external links.
+ """
+ for node in tree.traverse(nodes.reference):
+ uri = node.get('refuri', '')
+ if (uri.startswith('http:') or uri.startswith('https:') or
+ uri.startswith('ftp:')) and uri not in node.astext():
+ uri = _link_target_template % {'uri': uri}
+ if uri:
+ idx = node.parent.index(node) + 1
+ link = nodes.inline(uri, uri)
+ link['classes'].append(_css_link_target_class)
+ node.parent.insert(idx, link)
+
+ def write_doc(self, docname, doctree):
+ """Write one document file.
+ This method is overwritten in order to fix fragment identifiers
+ and to add visible external links.
+ """
+ self.fix_ids(doctree)
+ self.add_visible_links(doctree)
+ return StandaloneHTMLBuilder.write_doc(self, docname, doctree)
+
+ def fix_genindex(self, tree):
+ """Fix href attributes for genindex pages.
+ """
+ # XXX: modifies tree inline
+ # Logic modeled from themes/basic/genindex.html
+ for key, columns in tree:
+ for entryname, (links, subitems) in columns:
+ for (i, link) in enumerate(links):
+ m = _refuri_re.match(link)
+ if m:
+ links[i] = self.fix_fragment(m)
+ for subentryname, subentrylinks in subitems:
+ for (i, link) in enumerate(subentrylinks):
+ m = _refuri_re.match(link)
+ if m:
+ subentrylinks[i] = self.fix_fragment(m)
+
+ def handle_page(self, pagename, addctx, templatename='page.html',
+ outfilename=None, event_arg=None):
+ """Create a rendered page.
+ This method is overwritten for genindex pages in order to fix
+ href link attributes.
+ """
+ if pagename.startswith('genindex'):
+ self.fix_genindex(addctx['genindexentries'])
+ StandaloneHTMLBuilder.handle_page(self, pagename, addctx, templatename,
+ outfilename, event_arg)
+
# Finish by building the epub file
def handle_finish(self):
@@ -380,7 +441,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
navstack.append(navlist)
navlist = []
level += 1
- if lastnode:
+ if lastnode and self.config.epub_tocdup:
# Insert starting point in subtoc with same playOrder
navlist.append(self.new_navpoint(lastnode, level, False))
navlist.append(self.new_navpoint(node, level))
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 6b3eada7..5a7d49cd 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -30,12 +30,12 @@ from docutils.frontend import OptionParser
from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __version__
-from sphinx.util import copy_static_entry
+from sphinx.util import jsonimpl, copy_static_entry
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, ustrftime, copyfile
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.matching import patmatch, compile_matchers
-from sphinx.util.pycompat import any
+from sphinx.util.pycompat import any, b
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.search import js_index
@@ -47,14 +47,6 @@ from sphinx.util.console import bold, darkgreen, brown
from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
SmartyPantsHTMLTranslator
-try:
- import json
-except ImportError:
- try:
- import simplejson as json
- except ImportError:
- json = None
-
#: the filename for the inventory of objects
INVENTORY_FILENAME = 'objects.inv'
#: the filename for the "last build" file (for serializing builders)
@@ -71,6 +63,7 @@ class StandaloneHTMLBuilder(Builder):
out_suffix = '.html'
link_suffix = '.html' # defaults to matching out_suffix
indexer_format = js_index
+ indexer_dumps_unicode = True
supported_image_types = ['image/svg+xml', 'image/png',
'image/gif', 'image/jpeg']
searchindex_filename = 'searchindex.js'
@@ -99,7 +92,7 @@ class StandaloneHTMLBuilder(Builder):
self.init_templates()
self.init_highlighter()
self.init_translator_class()
- if self.config.html_file_suffix:
+ if self.config.html_file_suffix is not None:
self.out_suffix = self.config.html_file_suffix
if self.config.html_link_suffix is not None:
@@ -154,8 +147,9 @@ class StandaloneHTMLBuilder(Builder):
cfgdict = dict((name, self.config[name])
for (name, desc) in self.config.values.iteritems()
if desc[1] == 'html')
- self.config_hash = md5(str(cfgdict)).hexdigest()
- self.tags_hash = md5(str(sorted(self.tags))).hexdigest()
+ self.config_hash = md5(unicode(cfgdict).encode('utf-8')).hexdigest()
+ self.tags_hash = md5(unicode(sorted(self.tags)).encode('utf-8')) \
+ .hexdigest()
old_config_hash = old_tags_hash = ''
try:
fp = open(path.join(self.outdir, '.buildinfo'))
@@ -207,7 +201,7 @@ class StandaloneHTMLBuilder(Builder):
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
- doc = new_document('<partial node>')
+ doc = new_document(b('<partial node>'))
doc.append(node)
if self._publisher is None:
@@ -735,10 +729,12 @@ class StandaloneHTMLBuilder(Builder):
self.info(bold('dumping object inventory... '), nonl=True)
f = open(path.join(self.outdir, INVENTORY_FILENAME), 'wb')
try:
- f.write('# Sphinx inventory version 2\n')
- f.write('# Project: %s\n' % self.config.project.encode('utf-8'))
- f.write('# Version: %s\n' % self.config.version.encode('utf-8'))
- f.write('# The remainder of this file is compressed using zlib.\n')
+ f.write((u'# Sphinx inventory version 2\n'
+ u'# Project: %s\n'
+ u'# Version: %s\n'
+ u'# The remainder of this file is compressed using zlib.\n'
+ % (self.config.project, self.config.version)
+ ).encode('utf-8'))
compressor = zlib.compressobj(9)
for domainname, domain in self.env.domains.iteritems():
for name, dispname, type, docname, anchor, prio in \
@@ -750,11 +746,9 @@ class StandaloneHTMLBuilder(Builder):
if dispname == name:
dispname = u'-'
f.write(compressor.compress(
- '%s %s:%s %s %s %s\n' % (name.encode('utf-8'),
- domainname.encode('utf-8'),
- type.encode('utf-8'), prio,
- uri.encode('utf-8'),
- dispname.encode('utf-8'))))
+ (u'%s %s:%s %s %s %s\n' % (name, domainname, type,
+ prio, uri, dispname)
+ ).encode('utf-8')))
f.write(compressor.flush())
finally:
f.close()
@@ -766,7 +760,10 @@ class StandaloneHTMLBuilder(Builder):
searchindexfn = path.join(self.outdir, self.searchindex_filename)
# first write to a temporary file, so that if dumping fails,
# the existing index won't be overwritten
- f = open(searchindexfn + '.tmp', 'wb')
+ if self.indexer_dumps_unicode:
+ f = codecs.open(searchindexfn + '.tmp', 'w', encoding='utf-8')
+ else:
+ f = open(searchindexfn + '.tmp', 'wb')
try:
self.indexer.dump(f, self.indexer_format)
finally:
@@ -855,8 +852,14 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
def get_doc_context(self, docname, body, metatags):
# no relation links...
toc = self.env.get_toctree_for(self.config.master_doc, self, False)
- self.fix_refuris(toc)
- toc = self.render_partial(toc)['fragment']
+ # if there is no toctree, toc is None
+ if toc:
+ self.fix_refuris(toc)
+ toc = self.render_partial(toc)['fragment']
+ display_toc = True
+ else:
+ toc = ''
+ display_toc = False
return dict(
parents = [],
prev = None,
@@ -869,7 +872,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
rellinks = [],
sourcename = '',
toc = toc,
- display_toc = True,
+ display_toc = display_toc,
)
def write(self, *ignored):
@@ -917,6 +920,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
#: implements a `dump`, `load`, `dumps` and `loads` functions
#: (pickle, simplejson etc.)
implementation = None
+ implementation_dumps_unicode = False
#: the filename for the global context file
globalcontext_filename = None
@@ -939,6 +943,17 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
return docname[:-5] # up to sep
return docname + SEP
+ def dump_context(self, context, filename):
+ if self.implementation_dumps_unicode:
+ f = codecs.open(filename, 'w', encoding='utf-8')
+ else:
+ f = open(filename, 'wb')
+ try:
+ # XXX: the third argument is pickle-specific!
+ self.implementation.dump(context, f, 2)
+ finally:
+ f.close()
+
def handle_page(self, pagename, ctx, templatename='page.html',
outfilename=None, event_arg=None):
ctx['current_page_name'] = pagename
@@ -952,11 +967,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
ctx, event_arg)
ensuredir(path.dirname(outfilename))
- f = open(outfilename, 'wb')
- try:
- self.implementation.dump(ctx, f, 2)
- finally:
- f.close()
+ self.dump_context(ctx, outfilename)
# if there is a source file, copy the source file for the
# "show source" link
@@ -969,11 +980,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
def handle_finish(self):
# dump the global context
outfilename = path.join(self.outdir, self.globalcontext_filename)
- f = open(outfilename, 'wb')
- try:
- self.implementation.dump(self.globalcontext, f, 2)
- finally:
- f.close()
+ self.dump_context(self.globalcontext, outfilename)
# super here to dump the search index
StandaloneHTMLBuilder.handle_finish(self)
@@ -993,7 +1000,9 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
A Builder that dumps the generated HTML into pickle files.
"""
implementation = pickle
+ implementation_dumps_unicode = False
indexer_format = pickle
+ indexer_dumps_unicode = False
name = 'pickle'
out_suffix = '.fpickle'
globalcontext_filename = 'globalcontext.pickle'
@@ -1007,15 +1016,17 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
"""
A builder that dumps the generated HTML into JSON files.
"""
- implementation = json
- indexer_format = json
+ implementation = jsonimpl
+ implementation_dumps_unicode = True
+ indexer_format = jsonimpl
+ indexer_dumps_unicode = True
name = 'json'
out_suffix = '.fjson'
globalcontext_filename = 'globalcontext.json'
searchindex_filename = 'searchindex.json'
def init(self):
- if json is None:
+ if jsonimpl.json is None:
raise SphinxError(
'The module simplejson (or json in Python >= 2.6) '
'is not available. The JSONHTMLBuilder builder will not work.')
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
index 538f4c84..e3a58e72 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -258,7 +258,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
def write_index(title, refs, subitems):
def write_param(name, value):
item = ' <param name="%s" value="%s">\n' % (name, value)
- f.write(item.encode('ascii', 'xmlcharrefreplace'))
+ f.write(item.encode('ascii', 'xmlcharrefreplace')
+ .decode('ascii'))
title = cgi.escape(title)
f.write('<LI> <OBJECT type="text/sitemap">\n')
write_param('Keyword', title)
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index c9bc363d..4a0bab63 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -16,7 +16,7 @@ from urllib2 import build_opener, HTTPError
from docutils import nodes
from sphinx.builders import Builder
-from sphinx.util.console import purple, red, darkgreen
+from sphinx.util.console import purple, red, darkgreen, darkgray
# create an opener that will simulate a browser user-agent
opener = build_opener()
@@ -71,9 +71,12 @@ class CheckExternalLinksBuilder(Builder):
break
lineno = node.line
+ if len(uri) == 0 or uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
+ return
+
+ if lineno:
+ self.info('(line %3d) ' % lineno, nonl=1)
if uri[0:5] == 'http:' or uri[0:6] == 'https:':
- if lineno:
- self.info('(line %3d) ' % lineno, nonl=1)
self.info(uri, nonl=1)
if uri in self.broken:
@@ -98,15 +101,9 @@ class CheckExternalLinksBuilder(Builder):
self.write_entry('redirected', docname,
lineno, uri + ' to ' + s)
self.redirected[uri] = (r, s)
- elif len(uri) == 0 or uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
- return
else:
- self.warn(uri + ' - ' + red('malformed!'))
- self.write_entry('malformed', docname, lineno, uri)
- if self.app.quiet:
- self.warn('malformed link: %s' % uri,
- '%s:%s' % (self.env.doc2path(docname), lineno))
- self.app.statuscode = 1
+ self.info(uri + ' - ' + darkgray('local'))
+ self.write_entry('local', docname, lineno, uri)
if self.broken:
self.app.statuscode = 1
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index ffc52334..e86f1921 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -130,8 +130,16 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
for indexname, indexcls, content, collapse in self.domain_indices:
item = section_template % {'title': indexcls.localname,
'ref': '%s.html' % indexname}
- sections.append(' '*4*4 + item)
- sections = '\n'.join(sections)
+ sections.append((' ' * 4 * 4 + item).encode('utf-8'))
+ # sections may be unicode strings or byte strings, we have to make sure
+ # they are all byte strings before joining them
+ new_sections = []
+ for section in sections:
+ if isinstance(section, unicode):
+ new_sections.append(section.encode('utf-8'))
+ else:
+ new_sections.append(section)
+ sections = u'\n'.encode('utf-8').join(new_sections)
# keywords
keywords = []
@@ -230,7 +238,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
link = node['refuri']
title = escape(node.astext()).replace('"','&quot;')
item = section_template % {'title': title, 'ref': link}
- item = ' '*4*indentlevel + item.encode('ascii', 'xmlcharrefreplace')
+ item = u' ' * 4 * indentlevel + item
parts.append(item.encode('ascii', 'xmlcharrefreplace'))
elif isinstance(node, nodes.bullet_list):
for subnode in node:
diff --git a/sphinx/config.py b/sphinx/config.py
index e1075ff6..6c27f85f 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -11,13 +11,18 @@
import os
import re
+import sys
from os import path
from sphinx.errors import ConfigError
from sphinx.util.osutil import make_filename
+from sphinx.util.pycompat import bytes, b, convert_with_2to3
-nonascii_re = re.compile(r'[\x80-\xff]')
+nonascii_re = re.compile(b(r'[\x80-\xff]'))
+CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
+if sys.version_info >= (3, 0):
+ CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
class Config(object):
"""Configuration file abstraction."""
@@ -124,6 +129,7 @@ class Config(object):
epub_post_files = ([], 'env'),
epub_exclude_files = ([], 'env'),
epub_tocdepth = (3, 'env'),
+ epub_tocdup = (True, 'env'),
# LaTeX options
latex_documents = ([], None),
@@ -162,12 +168,30 @@ class Config(object):
config['tags'] = tags
olddir = os.getcwd()
try:
+ # we promise to have the config dir as current dir while the
+ # config file is executed
+ os.chdir(dirname)
+ # get config source
+ f = open(config_file, 'rb')
try:
- os.chdir(dirname)
- execfile(config['__file__'], config)
+ source = f.read()
+ finally:
+ f.close()
+ try:
+ # compile to a code object, handle syntax errors
+ try:
+ code = compile(source, config_file, 'exec')
+ except SyntaxError:
+ if convert_with_2to3:
+ # maybe the file uses 2.x syntax; try to refactor to
+ # 3.x syntax using 2to3
+ source = convert_with_2to3(config_file)
+ code = compile(source, config_file, 'exec')
+ else:
+ raise
+ exec code in config
except SyntaxError, err:
- raise ConfigError('There is a syntax error in your '
- 'configuration file: ' + str(err))
+ raise ConfigError(CONFIG_SYNTAX_ERROR % err)
finally:
os.chdir(olddir)
@@ -181,10 +205,11 @@ class Config(object):
# check all string values for non-ASCII characters in bytestrings,
# since that can result in UnicodeErrors all over the place
for name, value in self._raw_config.iteritems():
- if isinstance(value, str) and nonascii_re.search(value):
+ if isinstance(value, bytes) and nonascii_re.search(value):
warn('the config value %r is set to a string with non-ASCII '
'characters; this can lead to Unicode errors occurring. '
- 'Please use Unicode strings, e.g. u"Content".' % name)
+ 'Please use Unicode strings, e.g. %r.' % (name, u'Content')
+ )
def init_values(self):
config = self._raw_config
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 6c03b8e5..48c44178 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -32,6 +32,7 @@ except AttributeError:
# RE to strip backslash escapes
+nl_escape_re = re.compile(r'\\\n')
strip_backslash_re = re.compile(r'\\(?=[^\\])')
@@ -57,10 +58,12 @@ class ObjectDescription(Directive):
"""
Retrieve the signatures to document from the directive arguments. By
default, signatures are given as arguments, one per line.
+
+ Backslash-escaping of newlines is supported.
"""
+ lines = nl_escape_re.sub('', self.arguments[0]).split('\n')
# remove backslashes to support (dummy) escapes; helps Vim highlighting
- return [strip_backslash_re.sub('', sig.strip())
- for sig in self.arguments[0].split('\n')]
+ return [strip_backslash_re.sub('', line.strip()) for line in lines]
def handle_signature(self, sig, signode):
"""
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index aff4395f..1808cdab 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -102,7 +102,7 @@ class LiteralInclude(Directive):
rel_fn = filename[1:]
else:
docdir = path.dirname(env.doc2path(env.docname, base=None))
- rel_fn = path.normpath(path.join(docdir, filename))
+ rel_fn = path.join(docdir, filename)
try:
fn = path.join(env.srcdir, rel_fn)
except UnicodeDecodeError:
@@ -119,7 +119,7 @@ class LiteralInclude(Directive):
encoding = self.options.get('encoding', env.config.source_encoding)
codec_info = codecs.lookup(encoding)
try:
- f = codecs.StreamReaderWriter(open(fn, 'U'),
+ f = codecs.StreamReaderWriter(open(fn, 'rb'),
codec_info[2], codec_info[3], 'strict')
lines = f.readlines()
f.close()
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index 5ce1ce1a..332c4084 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -215,12 +215,7 @@ class VersionChange(Directive):
else:
ret = [node]
env = self.state.document.settings.env
- env.versionchanges.setdefault(node['version'], []).append(
- (node['type'], env.temp_data['docname'], self.lineno,
- # XXX: python domain specific
- env.temp_data.get('py:module'),
- env.temp_data.get('object'),
- node.astext()))
+ env.note_versionchange(node['type'], node['version'], node, self.lineno)
return ret
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 4dac8925..8df89459 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -110,7 +110,7 @@ class DefinitionError(Exception):
return self.description
def __str__(self):
- return unicode(self.encode('utf-8'))
+ return unicode(self).encode('utf-8')
class DefExpr(object):
@@ -132,6 +132,8 @@ class DefExpr(object):
def __ne__(self, other):
return not self.__eq__(other)
+ __hash__ = None
+
def clone(self):
"""Close a definition expression node"""
return deepcopy(self)
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index 890af8e1..582e2adc 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -56,7 +56,7 @@ class JSObject(ObjectDescription):
else:
# just a function or constructor
objectname = ''
- fullname = ''
+ fullname = name
signode['object'] = objectname
signode['fullname'] = fullname
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index fc808699..cd87bfbd 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -356,6 +356,9 @@ class PyModule(Directive):
env.domaindata['py']['modules'][modname] = \
(env.docname, self.options.get('synopsis', ''),
self.options.get('platform', ''), 'deprecated' in self.options)
+ # make a duplicate entry in 'objects' to facilitate searching for the
+ # module in PythonDomain.find_obj()
+ env.domaindata['py']['objects'][modname] = (env.docname, 'module')
targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
self.state.document.note_explicit_target(targetnode)
ret = [targetnode]
@@ -544,7 +547,7 @@ class PythonDomain(Domain):
if fn == docname:
del self.data['modules'][modname]
- def find_obj(self, env, modname, classname, name, type, searchorder=0):
+ def find_obj(self, env, modname, classname, name, type, searchmode=0):
"""
Find a Python object for "name", perhaps using the given module and/or
classname. Returns a list of (name, object entry) tuples.
@@ -560,22 +563,31 @@ class PythonDomain(Domain):
matches = []
newname = None
- if searchorder == 1:
- if modname and classname and \
- modname + '.' + classname + '.' + name in objects:
- newname = modname + '.' + classname + '.' + name
- elif modname and modname + '.' + name in objects:
- newname = modname + '.' + name
- elif name in objects:
- newname = name
- else:
- # "fuzzy" searching mode
- searchname = '.' + name
- matches = [(name, objects[name]) for name in objects
- if name.endswith(searchname)]
+ if searchmode == 1:
+ objtypes = self.objtypes_for_role(type)
+ if modname and classname:
+ fullname = modname + '.' + classname + '.' + name
+ if fullname in objects and objects[fullname][1] in objtypes:
+ newname = fullname
+ if not newname:
+ if modname and modname + '.' + name in objects and \
+ objects[modname + '.' + name][1] in objtypes:
+ newname = modname + '.' + name
+ elif name in objects and objects[name][1] in objtypes:
+ newname = name
+ else:
+ # "fuzzy" searching mode
+ searchname = '.' + name
+ matches = [(name, objects[name]) for name in objects
+ if name.endswith(searchname)
+ and objects[name][1] in objtypes]
else:
+ # NOTE: searching for exact match, object type is not considered
if name in objects:
newname = name
+ elif type == 'mod':
+ # only exact matches allowed for modules
+ return []
elif classname and classname + '.' + name in objects:
newname = classname + '.' + name
elif modname and modname + '.' + name in objects:
@@ -597,33 +609,35 @@ class PythonDomain(Domain):
def resolve_xref(self, env, fromdocname, builder,
type, target, node, contnode):
- if (type == 'mod' or
- type == 'obj' and target in self.data['modules']):
- docname, synopsis, platform, deprecated = \
- self.data['modules'].get(target, ('','','', ''))
- if not docname:
- return None
- else:
- title = '%s%s%s' % ((platform and '(%s) ' % platform),
- synopsis,
- (deprecated and ' (deprecated)' or ''))
- return make_refnode(builder, fromdocname, docname,
- 'module-' + target, contnode, title)
+ modname = node.get('py:module')
+ clsname = node.get('py:class')
+ searchmode = node.hasattr('refspecific') and 1 or 0
+ matches = self.find_obj(env, modname, clsname, target,
+ type, searchmode)
+ if not matches:
+ return None
+ elif len(matches) > 1:
+ env.warn(fromdocname,
+ 'more than one target found for cross-reference '
+ '%r: %s' % (target,
+ ', '.join(match[0] for match in matches)),
+ node.line)
+ name, obj = matches[0]
+
+ if obj[1] == 'module':
+ # get additional info for modules
+ docname, synopsis, platform, deprecated = self.data['modules'][name]
+ assert docname == obj[0]
+ title = name
+ if synopsis:
+ title += ': ' + synopsis
+ if deprecated:
+ title += _(' (deprecated)')
+ if platform:
+ title += ' (' + platform + ')'
+ return make_refnode(builder, fromdocname, docname,
+ 'module-' + name, contnode, title)
else:
- modname = node.get('py:module')
- clsname = node.get('py:class')
- searchorder = node.hasattr('refspecific') and 1 or 0
- matches = self.find_obj(env, modname, clsname, target,
- type, searchorder)
- if not matches:
- return None
- elif len(matches) > 1:
- env.warn(fromdocname,
- 'more than one target found for cross-reference '
- '%r: %s' % (target,
- ', '.join(match[0] for match in matches)),
- node.line)
- name, obj = matches[0]
return make_refnode(builder, fromdocname, obj[0], name,
contnode, name)
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
index 04092eab..d3ffc6bd 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -28,9 +28,10 @@ class ReSTMarkup(ObjectDescription):
"""
def add_target_and_index(self, name, sig, signode):
- if name not in self.state.document.ids:
- signode['names'].append(name)
- signode['ids'].append(name)
+ targetname = self.objtype + '-' + name
+ if targetname not in self.state.document.ids:
+ signode['names'].append(targetname)
+ signode['ids'].append(targetname)
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
@@ -47,7 +48,7 @@ class ReSTMarkup(ObjectDescription):
indextext = self.get_index_text(self.objtype, name)
if indextext:
self.indexnode['entries'].append(('single', indextext,
- name, name))
+ targetname, targetname))
def get_index_text(self, objectname, name):
if self.objtype == 'directive':
@@ -129,8 +130,9 @@ class ReSTDomain(Domain):
if (objtype, target) in objects:
return make_refnode(builder, fromdocname,
objects[objtype, target],
- target, contnode, target)
+ objtype + '-' + target,
+ contnode, target + ' ' + objtype)
def get_objects(self):
for (typ, name), docname in self.data['objects'].iteritems():
- yield name, name, typ, docname, name, 1
+ yield name, name, typ, docname, typ + '-' + name, 1
diff --git a/sphinx/environment.py b/sphinx/environment.py
index b03e4625..6339675b 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -11,6 +11,7 @@
import re
import os
+import sys
import time
import types
import codecs
@@ -40,10 +41,11 @@ from sphinx.util import url_re, get_matching_docs, docname_join, \
from sphinx.util.nodes import clean_astext, make_refnode, extract_messages
from sphinx.util.osutil import movefile, SEP, ustrftime
from sphinx.util.matching import compile_matchers
-from sphinx.util.pycompat import all
+from sphinx.util.pycompat import all, class_types
from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _, init as init_locale
+fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
orig_role_function = roles.role
orig_directive_function = directives.directive
@@ -64,7 +66,7 @@ default_settings = {
# This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files.
-ENV_VERSION = 36
+ENV_VERSION = 38
default_substitutions = set([
@@ -81,7 +83,7 @@ class WarningStream(object):
self.warnfunc = warnfunc
def write(self, text):
if text.strip():
- self.warnfunc(text, None, '')
+ self.warnfunc(text.strip(), None, '')
class NoUri(Exception):
@@ -289,7 +291,7 @@ class BuildEnvironment:
if key.startswith('_') or \
isinstance(val, types.ModuleType) or \
isinstance(val, types.FunctionType) or \
- isinstance(val, (type, types.ClassType)):
+ isinstance(val, class_types):
del self.config[key]
try:
pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
@@ -421,14 +423,14 @@ class BuildEnvironment:
If base is a path string, return absolute path under that.
If suffix is not None, add it instead of config.source_suffix.
"""
+ docname = docname.replace(SEP, path.sep)
suffix = suffix or self.config.source_suffix
if base is True:
- return path.join(self.srcdir,
- docname.replace(SEP, path.sep)) + suffix
+ return path.join(self.srcdir, docname) + suffix
elif base is None:
- return docname.replace(SEP, path.sep) + suffix
+ return docname + suffix
else:
- return path.join(base, docname.replace(SEP, path.sep)) + suffix
+ return path.join(base, docname) + suffix
def find_files(self, config):
"""
@@ -666,6 +668,8 @@ class BuildEnvironment:
class SphinxSourceClass(FileInput):
def decode(self_, data):
+ if isinstance(data, unicode):
+ return data
return data.decode(self_.encoding, 'sphinx')
def read(self_):
@@ -687,7 +691,7 @@ class BuildEnvironment:
destination_class=NullOutput)
pub.set_components(None, 'restructuredtext', None)
pub.process_programmatic_settings(None, self.settings, None)
- pub.set_source(None, src_path)
+ pub.set_source(None, src_path.encode(fs_encoding))
pub.set_destination(None, None)
try:
pub.publish()
@@ -771,6 +775,12 @@ class BuildEnvironment:
def note_dependency(self, filename):
self.dependencies.setdefault(self.docname, set()).add(filename)
+ def note_versionchange(self, type, version, node, lineno):
+ self.versionchanges.setdefault(version, []).append(
+ (type, self.temp_data['docname'], lineno,
+ self.temp_data.get('py:module'),
+ self.temp_data.get('object'), node.astext()))
+
# post-processing of read doctrees
def filter_messages(self, doctree):
@@ -1521,8 +1531,9 @@ class BuildEnvironment:
i += 1
# group the entries by letter
- def keyfunc2((k, v), letters=string.ascii_uppercase + '_'):
+ def keyfunc2(item, letters=string.ascii_uppercase + '_'):
# hack: mutating the subitems dicts to a list in the keyfunc
+ k, v = item
v[1] = sorted((si, se) for (si, (se, void)) in v[1].iteritems())
# now calculate the key
letter = k[0].upper()
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index adf08bcd..eef181de 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -14,7 +14,7 @@
import re
import sys
import inspect
-from types import FunctionType, BuiltinFunctionType, MethodType, ClassType
+from types import FunctionType, BuiltinFunctionType, MethodType
from docutils import nodes
from docutils.utils import assemble_option_dict
@@ -27,15 +27,10 @@ from sphinx.application import ExtensionError
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util.compat import Directive
from sphinx.util.inspect import isdescriptor, safe_getmembers, safe_getattr
+from sphinx.util.pycompat import base_exception, class_types
from sphinx.util.docstrings import prepare_docstring
-try:
- base_exception = BaseException
-except NameError:
- base_exception = Exception
-
-
#: extended signature RE: with explicit module name separated by ::
py_ext_sig_re = re.compile(
r'''^ ([\w.]+::)? # explicit module name
@@ -256,6 +251,9 @@ class Documenter(object):
self.retann = None
# the object to document (set after import_object succeeds)
self.object = None
+ self.object_name = None
+ # the parent/owner of the object to document
+ self.parent = None
# the module analyzer to get at attribute docs, or None
self.analyzer = None
@@ -321,9 +319,13 @@ class Documenter(object):
"""
try:
__import__(self.modname)
+ parent = None
obj = self.module = sys.modules[self.modname]
for part in self.objpath:
+ parent = obj
obj = self.get_attr(obj, part)
+ self.object_name = part
+ self.parent = parent
self.object = obj
return True
# this used to only catch SyntaxError, ImportError and AttributeError,
@@ -416,9 +418,11 @@ class Documenter(object):
def get_doc(self, encoding=None):
"""Decode and return lines of the docstring(s) for the object."""
docstring = self.get_attr(self.object, '__doc__', None)
- if docstring:
- # make sure we have Unicode docstrings, then sanitize and split
- # into lines
+ # make sure we have Unicode docstrings, then sanitize and split
+ # into lines
+ if isinstance(docstring, unicode):
+ return [prepare_docstring(docstring)]
+ elif docstring:
return [prepare_docstring(force_decode(docstring, encoding))]
return []
@@ -438,8 +442,11 @@ class Documenter(object):
# set sourcename and add content from attribute documentation
if self.analyzer:
# prevent encoding errors when the file name is non-ASCII
- filename = unicode(self.analyzer.srcname,
- sys.getfilesystemencoding(), 'replace')
+ if not isinstance(self.analyzer.srcname, unicode):
+ filename = unicode(self.analyzer.srcname,
+ sys.getfilesystemencoding(), 'replace')
+ else:
+ filename = self.analyzer.srcname
sourcename = u'%s:docstring of %s' % (filename, self.fullname)
attr_docs = self.analyzer.find_attr_docs()
@@ -866,7 +873,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
- return isinstance(member, (type, ClassType))
+ return isinstance(member, class_types)
def import_object(self):
ret = ModuleLevelDocumenter.import_object(self)
@@ -939,9 +946,12 @@ class ClassDocumenter(ModuleLevelDocumenter):
docstrings = [initdocstring]
else:
docstrings.append(initdocstring)
-
- return [prepare_docstring(force_decode(docstring, encoding))
- for docstring in docstrings]
+ doc = []
+ for docstring in docstrings:
+ if not isinstance(docstring, unicode):
+ docstring = force_decode(docstring, encoding)
+ doc.append(prepare_docstring(docstring))
+ return doc
def add_content(self, more_content, no_docstring=False):
if self.doc_as_attr:
@@ -972,7 +982,7 @@ class ExceptionDocumenter(ClassDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
- return isinstance(member, (type, ClassType)) and \
+ return isinstance(member, class_types) and \
issubclass(member, base_exception)
@@ -1004,24 +1014,38 @@ class MethodDocumenter(ClassLevelDocumenter):
return inspect.isroutine(member) and \
not isinstance(parent, ModuleDocumenter)
- def import_object(self):
- ret = ClassLevelDocumenter.import_object(self)
- if isinstance(self.object, classmethod) or \
- (isinstance(self.object, MethodType) and
- self.object.im_self is not None):
- self.directivetype = 'classmethod'
- # document class and static members before ordinary ones
- self.member_order = self.member_order - 1
- elif isinstance(self.object, FunctionType) or \
- (isinstance(self.object, BuiltinFunctionType) and
- hasattr(self.object, '__self__') and
- self.object.__self__ is not None):
- self.directivetype = 'staticmethod'
- # document class and static members before ordinary ones
- self.member_order = self.member_order - 1
- else:
- self.directivetype = 'method'
- return ret
+ if sys.version_info >= (3, 0):
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ obj_from_parent = self.parent.__dict__.get(self.object_name)
+ if isinstance(obj_from_parent, classmethod):
+ self.directivetype = 'classmethod'
+ self.member_order = self.member_order - 1
+ elif isinstance(obj_from_parent, staticmethod):
+ self.directivetype = 'staticmethod'
+ self.member_order = self.member_order - 1
+ else:
+ self.directivetype = 'method'
+ return ret
+ else:
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ if isinstance(self.object, classmethod) or \
+ (isinstance(self.object, MethodType) and
+ self.object.im_self is not None):
+ self.directivetype = 'classmethod'
+ # document class and static members before ordinary ones
+ self.member_order = self.member_order - 1
+ elif isinstance(self.object, FunctionType) or \
+ (isinstance(self.object, BuiltinFunctionType) and
+ hasattr(self.object, '__self__') and
+ self.object.__self__ is not None):
+ self.directivetype = 'staticmethod'
+ # document class and static members before ordinary ones
+ self.member_order = self.member_order - 1
+ else:
+ self.directivetype = 'method'
+ return ret
def format_args(self):
if inspect.isbuiltin(self.object) or \
diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py
index 4924d30b..f41820e2 100644
--- a/sphinx/ext/coverage.py
+++ b/sphinx/ext/coverage.py
@@ -173,8 +173,11 @@ class CoverageBuilder(Builder):
attrs = []
+ for attr_name in dir(obj):
+ attr = getattr(obj, attr_name)
for attr_name, attr in inspect.getmembers(
- obj, inspect.ismethod):
+ obj, lambda x: inspect.ismethod(x) or \
+ inspect.isfunction(x)):
if attr_name[0] == '_':
# starts with an underscore, ignore it
continue
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
index 9d681f90..62fbfdff 100644
--- a/sphinx/ext/doctest.py
+++ b/sphinx/ext/doctest.py
@@ -149,14 +149,14 @@ class TestCode(object):
class SphinxDocTestRunner(doctest.DocTestRunner):
def summarize(self, out, verbose=None):
- io = StringIO.StringIO()
+ string_io = StringIO.StringIO()
old_stdout = sys.stdout
- sys.stdout = io
+ sys.stdout = string_io
try:
res = doctest.DocTestRunner.summarize(self, verbose)
finally:
sys.stdout = old_stdout
- out(io.getvalue())
+ out(string_io.getvalue())
return res
def _DocTestRunner__patched_linecache_getlines(self, filename,
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index 106de7a6..257ff1b6 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -93,6 +93,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
Render graphviz code into a PNG or PDF output file.
"""
hashkey = code.encode('utf-8') + str(options) + \
+ str(self.builder.config.graphviz_dot) + \
str(self.builder.config.graphviz_dot_args)
fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format)
if hasattr(self.builder, 'imgpath'):
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index b930d8ca..a12bad25 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-"""
+r"""
sphinx.ext.inheritance_diagram
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index 4fb3805f..251f5c55 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -26,6 +26,7 @@
import time
import zlib
+import codecs
import urllib2
import posixpath
from os import path
@@ -33,19 +34,26 @@ from os import path
from docutils import nodes
from sphinx.builders.html import INVENTORY_FILENAME
+from sphinx.util.pycompat import b
+
handlers = [urllib2.ProxyHandler(), urllib2.HTTPRedirectHandler(),
urllib2.HTTPHandler()]
-if hasattr(urllib2, 'HTTPSHandler'):
+try:
handlers.append(urllib2.HTTPSHandler)
+except NameError:
+ pass
urllib2.install_opener(urllib2.build_opener(*handlers))
+UTF8StreamReader = codecs.lookup('utf-8')[2]
+
def read_inventory_v1(f, uri, join):
+ f = UTF8StreamReader(f)
invdata = {}
line = f.next()
- projname = line.rstrip()[11:].decode('utf-8')
+ projname = line.rstrip()[11:]
line = f.next()
version = line.rstrip()[11:]
for line in f:
@@ -68,25 +76,25 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
projname = line.rstrip()[11:].decode('utf-8')
line = f.readline()
version = line.rstrip()[11:].decode('utf-8')
- line = f.readline()
+ line = f.readline().decode('utf-8')
if 'zlib' not in line:
raise ValueError
def read_chunks():
decompressor = zlib.decompressobj()
- for chunk in iter(lambda: f.read(bufsize), ''):
+ for chunk in iter(lambda: f.read(bufsize), b('')):
yield decompressor.decompress(chunk)
yield decompressor.flush()
def split_lines(iter):
- buf = ''
+ buf = b('')
for chunk in iter:
buf += chunk
- lineend = buf.find('\n')
+ lineend = buf.find(b('\n'))
while lineend != -1:
yield buf[:lineend].decode('utf-8')
buf = buf[lineend+1:]
- lineend = buf.find('\n')
+ lineend = buf.find(b('\n'))
assert not buf
for line in split_lines(read_chunks()):
@@ -109,13 +117,13 @@ def fetch_inventory(app, uri, inv):
if inv.find('://') != -1:
f = urllib2.urlopen(inv)
else:
- f = open(path.join(app.srcdir, inv))
+ f = open(path.join(app.srcdir, inv), 'rb')
except Exception, err:
app.warn('intersphinx inventory %r not fetchable due to '
'%s: %s' % (inv, err.__class__, err))
return
try:
- line = f.readline().rstrip()
+ line = f.readline().rstrip().decode('utf-8')
try:
if line == '# Sphinx inventory version 1':
invdata = read_inventory_v1(f, uri, join)
@@ -191,10 +199,12 @@ def missing_reference(app, env, node, contnode):
return
objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
to_try = [(env.intersphinx_inventory, target)]
+ in_set = None
if ':' in target:
# first part may be the foreign doc set name
setname, newtarget = target.split(':', 1)
if setname in env.intersphinx_named_inventory:
+ in_set = setname
to_try.append((env.intersphinx_named_inventory[setname], newtarget))
for inventory, target in to_try:
for objtype in objtypes:
@@ -203,11 +213,25 @@ def missing_reference(app, env, node, contnode):
proj, version, uri, dispname = inventory[objtype][target]
newnode = nodes.reference('', '', internal=False, refuri=uri,
reftitle='(in %s v%s)' % (proj, version))
- if dispname == '-':
+ if node.get('refexplicit'):
+ # use whatever title was given
newnode.append(contnode)
+ elif dispname == '-':
+ # use whatever title was given, but strip prefix
+ title = contnode.astext()
+ if in_set and title.startswith(in_set+':'):
+ newnode.append(contnode.__class__(title[len(in_set)+1:],
+ title[len(in_set)+1:]))
+ else:
+ newnode.append(contnode)
else:
+ # else use the given display name (used for :ref:)
newnode.append(contnode.__class__(dispname, dispname))
return newnode
+ # at least get rid of the ':' in the target if no explicit title given
+ if in_set is not None and not node.get('refexplicit', True):
+ if len(contnode) and isinstance(contnode[0], nodes.Text):
+ contnode[0] = nodes.Text(newtarget, contnode[0].rawsource)
def setup(app):
diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py
index 62f5ee28..571d82a5 100644
--- a/sphinx/ext/oldcmarkup.py
+++ b/sphinx/ext/oldcmarkup.py
@@ -13,6 +13,10 @@ from docutils.parsers.rst import directives
from sphinx.util.compat import Directive
+_warned_oldcmarkup = False
+WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \
+ '(e.g. c:function instead of cfunction), see ' \
+ 'http://sphinx.pocoo.org/domains.html'
class OldCDirective(Directive):
has_content = True
@@ -26,6 +30,10 @@ class OldCDirective(Directive):
def run(self):
env = self.state.document.settings.env
+ if not env.app._oldcmarkup_warned:
+ print 'XXXYYY'
+ env.warn(env.docname, WARNING_MSG, self.lineno)
+ env.app._oldcmarkup_warned = True
newname = 'c:' + self.name[1:]
newdir = env.lookup_domain_element('directive', newname)[0]
return newdir(newname, self.arguments, self.options,
@@ -35,12 +43,18 @@ class OldCDirective(Directive):
def old_crole(typ, rawtext, text, lineno, inliner, options={}, content=[]):
env = inliner.document.settings.env
+ if not typ:
+ typ = env.config.default_role
+ if not env.app._oldcmarkup_warned:
+ env.warn(env.docname, WARNING_MSG)
+ env.app._oldcmarkup_warned = True
newtyp = 'c:' + typ[1:]
newrole = env.lookup_domain_element('role', newtyp)[0]
return newrole(newtyp, rawtext, text, lineno, inliner, options, content)
def setup(app):
+ app._oldcmarkup_warned = False
app.add_directive('cfunction', OldCDirective)
app.add_directive('cmember', OldCDirective)
app.add_directive('cmacro', OldCDirective)
@@ -50,3 +64,4 @@ def setup(app):
app.add_role('cfunc', old_crole)
app.add_role('cmacro', old_crole)
app.add_role('ctype', old_crole)
+ app.add_role('cmember', old_crole)
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 80b887c0..b9bb9d77 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -31,7 +31,11 @@ def doctree_read(app, doctree):
env._viewcode_modules[modname] = False
return
analyzer.find_tags()
- entry = analyzer.code.decode(analyzer.encoding), analyzer.tags, {}
+ if not isinstance(analyzer.code, unicode):
+ code = analyzer.code.decode(analyzer.encoding)
+ else:
+ code = analyzer.code
+ entry = code, analyzer.tags, {}
env._viewcode_modules[modname] = entry
elif entry is False:
return
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index f5ea859c..6d710919 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -156,7 +156,7 @@ class PygmentsBridge(object):
if sys.version_info >= (2, 5):
src = 'from __future__ import with_statement\n' + src
- if isinstance(src, unicode):
+ if sys.version_info < (3, 0) and isinstance(src, unicode):
# Non-ASCII chars will only occur in string literals
# and comments. If we wanted to give them to the parser
# correctly, we'd have to find out the correct source
@@ -175,7 +175,7 @@ class PygmentsBridge(object):
return True
def highlight_block(self, source, lang, linenos=False, warn=None):
- if isinstance(source, str):
+ if not isinstance(source, unicode):
source = source.decode()
if not pygments:
return self.unhighlighted(source)
@@ -240,7 +240,7 @@ class PygmentsBridge(object):
# no HTML styles needed
return ''
if self.dest == 'html':
- return self.fmter[0].get_style_defs()
+ return self.fmter[0].get_style_defs('.highlight')
else:
styledefs = self.fmter[0].get_style_defs()
# workaround for Pygments < 0.12
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index 02583ff8..48116991 100644
--- a/sphinx/locale/__init__.py
+++ b/sphinx/locale/__init__.py
@@ -8,6 +8,8 @@
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+
+import sys
import gettext
import UserString
@@ -178,8 +180,12 @@ pairindextypes = {
translators = {}
-def _(message):
- return translators['sphinx'].ugettext(message)
+if sys.version_info >= (3, 0):
+ def _(message):
+ return translators['sphinx'].gettext(message)
+else:
+ def _(message):
+ return translators['sphinx'].ugettext(message)
def init(locale_dirs, language, catalog='sphinx'):
"""
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.js b/sphinx/locale/bn/LC_MESSAGES/sphinx.js
new file mode 100644
index 00000000..277cd3d0
--- /dev/null
+++ b/sphinx/locale/bn/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "bn", "plural_expr": "(n != 1)", "messages": {"Search Results": "\u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8\u09c7\u09b0 \u09ab\u09b2\u09be\u09ab\u09b2", "Preparing search...": "\u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8\u09c7\u09b0 \u09aa\u09cd\u09b0\u09b8\u09cd\u09a4\u09c1\u09a4\u09bf \u099a\u09b2\u099b\u09c7...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "\u0986\u09aa\u09a8\u09be\u09b0 \u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8\u09c7 \u0995\u09c7\u09be\u09a8 \u09ab\u09b2\u09be\u09ab\u09b2 \u09aa\u09be\u0993\u09df\u09be \u09af\u09be\u09df\u09a8\u09bf\u0964 \u0986\u09aa\u09a8\u09be\u09b0 \u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8\u09c7\u09b0 \u09b6\u09ac\u09cd\u09a6\u0997\u09c1\u09b2\u09c7\u09be\u09b0 \u09b8\u09a0\u09bf\u0995 \u09ac\u09be\u09a8\u09be\u09a8 \u0993 \u09ac\u09bf\u09ad\u09be\u0997 \u09a8\u09bf\u09b0\u09cd\u09ac\u09be\u099a\u09a8 \u09a8\u09bf\u09b6\u09cd\u099a\u09bf\u09a4 \u0995\u09b0\u09c1\u09a8\u0964", "Search finished, found %s page(s) matching the search query.": "\u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8 \u09b6\u09c7\u09b7 \u09b9\u09df\u09c7\u099b\u09c7, \u09ab\u09b2\u09be\u09ab\u09b2\u09c7 %s-\u099f\u09bf \u09aa\u09be\u09a4\u09be \u09aa\u09be\u0993\u09df\u09be \u0997\u09c7\u099b\u09c7\u0964", ", in ": ", -", "Permalink to this headline": "\u098f\u0987 \u09b6\u09bf\u09b0\u09c7\u09be\u09a8\u09be\u09ae\u09c7\u09b0 \u09aa\u09be\u09b0\u09cd\u09ae\u09be\u09b2\u09bf\u0999\u09cd\u0995", "Searching": "\u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8 \u099a\u09b2\u099b\u09c7", "Permalink to this definition": "\u098f\u0987 \u09b8\u0982\u099c\u09cd\u099e\u09be\u09b0 \u09aa\u09be\u09b0\u09cd\u09ae\u09be\u09b2\u09bf\u0999\u09cd\u0995", "Hide Search Matches": "\u0985\u09a8\u09c1\u09b8\u09a8\u09cd\u09a7\u09be\u09a8\u09c7\u09b0 \u09ae\u09cd\u09af\u09be\u099a\u0997\u09c1\u09b2\u09c7\u09be \u09b2\u09c1\u0995\u09be\u09a8"}}); \ No newline at end of file
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.mo b/sphinx/locale/bn/LC_MESSAGES/sphinx.mo
new file mode 100644
index 00000000..9b60397e
--- /dev/null
+++ b/sphinx/locale/bn/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.po b/sphinx/locale/bn/LC_MESSAGES/sphinx.po
new file mode 100644
index 00000000..d5141c79
--- /dev/null
+++ b/sphinx/locale/bn/LC_MESSAGES/sphinx.po
@@ -0,0 +1,698 @@
+# Translations template for Sphinx.
+# Copyright (C) 2009 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx 1.0pre/[?1034h2e1ab15e035e\n"
+"Report-Msgid-Bugs-To: nasim.haque@gmail.com\n"
+"POT-Creation-Date: 2009-11-08 16:28+0100\n"
+"PO-Revision-Date: 2009-11-10 13:42+0100\n"
+"Last-Translator: Nasimul Haque <nasim.haque@gmail.com>\n"
+"Language-Team: Nasimul Haque <nasim.haque@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.4\n"
+
+#: sphinx/environment.py:130
+#: sphinx/writers/latex.py:184
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/environment.py:348
+#: sphinx/themes/basic/genindex-single.html:2
+#: sphinx/themes/basic/genindex-split.html:2
+#: sphinx/themes/basic/genindex-split.html:5
+#: sphinx/themes/basic/genindex.html:2
+#: sphinx/themes/basic/genindex.html:5
+#: sphinx/themes/basic/genindex.html:48
+#: sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:190
+msgid "Index"
+msgstr "ইনডেক্স"
+
+#: sphinx/environment.py:349
+#: sphinx/writers/latex.py:189
+msgid "Module Index"
+msgstr "মডিউল ইনডেক্স"
+
+#: sphinx/environment.py:350
+#: sphinx/themes/basic/defindex.html:16
+msgid "Search Page"
+msgstr "অনুসন্ধান পাতা"
+
+#: sphinx/roles.py:167
+#, python-format
+msgid "Python Enhancement Proposals!PEP %s"
+msgstr "পাইথন উন্নয়ন পরামর্শ!PEP %s"
+
+#: sphinx/builders/changes.py:70
+msgid "Builtins"
+msgstr "বিল্টইন সমূহ"
+
+#: sphinx/builders/changes.py:72
+msgid "Module level"
+msgstr "মডিউল লেভেল"
+
+#: sphinx/builders/html.py:224
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:243
+#: sphinx/themes/basic/defindex.html:21
+msgid "General Index"
+msgstr "সাধারণ ইনডেক্স"
+
+#: sphinx/builders/html.py:243
+msgid "index"
+msgstr "ইনডেক্স"
+
+#: sphinx/builders/html.py:247
+#: sphinx/builders/htmlhelp.py:220
+#: sphinx/builders/qthelp.py:133
+#: sphinx/themes/basic/defindex.html:19
+#: sphinx/themes/basic/modindex.html:2
+#: sphinx/themes/basic/modindex.html:13
+#: sphinx/themes/scrolls/modindex.html:2
+#: sphinx/themes/scrolls/modindex.html:13
+msgid "Global Module Index"
+msgstr "গ্লোবাল মডিউল ইনডেক্স"
+
+#: sphinx/builders/html.py:248
+msgid "modules"
+msgstr "মডিউল সমূহ"
+
+#: sphinx/builders/html.py:304
+msgid "next"
+msgstr "পরবর্তী"
+
+#: sphinx/builders/html.py:313
+msgid "previous"
+msgstr "পূর্ববর্তী"
+
+#: sphinx/builders/latex.py:162
+msgid " (in "
+msgstr "(-"
+
+#: sphinx/directives/__init__.py:78
+#: sphinx/directives/__init__.py:79
+#: sphinx/directives/__init__.py:80
+#: sphinx/directives/__init__.py:81
+msgid "Raises"
+msgstr "রেইজেস"
+
+#: sphinx/directives/__init__.py:82
+#: sphinx/directives/__init__.py:83
+#: sphinx/directives/__init__.py:84
+msgid "Variable"
+msgstr "ভ্যারিয়েবল"
+
+#: sphinx/directives/__init__.py:85
+#: sphinx/directives/__init__.py:86
+#: sphinx/directives/__init__.py:92
+#: sphinx/directives/__init__.py:93
+msgid "Returns"
+msgstr "রিটার্নস"
+
+#: sphinx/directives/__init__.py:94
+msgid "Return type"
+msgstr "রিটার্ন টাইপ"
+
+#: sphinx/directives/__init__.py:169
+msgid "Parameter"
+msgstr "প্যারামিটার"
+
+#: sphinx/directives/__init__.py:173
+msgid "Parameters"
+msgstr "প্যারামিটার"
+
+#: sphinx/directives/other.py:127
+msgid "Section author: "
+msgstr "অনুচ্ছেদ লেখক:"
+
+#: sphinx/directives/other.py:129
+msgid "Module author: "
+msgstr "মডিউল লেখক:"
+
+#: sphinx/directives/other.py:131
+msgid "Author: "
+msgstr "লেখক:"
+
+#: sphinx/directives/other.py:233
+msgid "See also"
+msgstr "আরও দেখুন"
+
+#: sphinx/domains/c.py:124
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C ফাংশন)"
+
+#: sphinx/domains/c.py:126
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C মেম্বার)"
+
+#: sphinx/domains/c.py:128
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C ম্যাক্রো)"
+
+#: sphinx/domains/c.py:130
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C টাইপ)"
+
+#: sphinx/domains/c.py:132
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C ভ্যারিয়েবল)"
+
+#: sphinx/domains/c.py:162
+msgid "C function"
+msgstr "C ফাংশন"
+
+#: sphinx/domains/c.py:163
+msgid "C member"
+msgstr "C মেম্বার"
+
+#: sphinx/domains/c.py:164
+msgid "C macro"
+msgstr "C ম্যাক্রো"
+
+#: sphinx/domains/c.py:165
+msgid "C type"
+msgstr "C টাইপ"
+
+#: sphinx/domains/c.py:166
+msgid "C variable"
+msgstr "C ভ্যারিয়েবল"
+
+#: sphinx/domains/python.py:186
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (বিল্ট-ইন ফাংশন)"
+
+#: sphinx/domains/python.py:187
+#: sphinx/domains/python.py:244
+#: sphinx/domains/python.py:256
+#: sphinx/domains/python.py:269
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s মডিউলে)"
+
+#: sphinx/domains/python.py:190
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (বিল্ট-ইন ভ্যারিয়েবল)"
+
+#: sphinx/domains/python.py:191
+#: sphinx/domains/python.py:282
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s মডিউলে)"
+
+#: sphinx/domains/python.py:207
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (বিল্ট-ইন ক্লাস)"
+
+#: sphinx/domains/python.py:208
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s ক্লাসে)"
+
+#: sphinx/domains/python.py:248
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s (%s.%s মেথড)"
+
+#: sphinx/domains/python.py:250
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s মেথড)"
+
+#: sphinx/domains/python.py:260
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s (%s.%s স্ট্যাটিক মেথড)"
+
+#: sphinx/domains/python.py:263
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s স্ট্যাটিক মেথড)"
+
+#: sphinx/domains/python.py:273
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s ক্লাস মেথড)"
+
+#: sphinx/domains/python.py:276
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s ক্লাস মেথড)"
+
+#: sphinx/domains/python.py:286
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s এ্যট্রিবিউট)"
+
+#: sphinx/domains/python.py:288
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s এ্যট্রিবিউট)"
+
+#: sphinx/domains/python.py:334
+msgid "Platforms: "
+msgstr "প্লাটফরম:"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s (module)"
+msgstr "%s (মডিউল)"
+
+#: sphinx/domains/python.py:396
+msgid "function"
+msgstr "ফাংশন"
+
+#: sphinx/domains/python.py:397
+msgid "data"
+msgstr "ডাটা"
+
+#: sphinx/domains/python.py:398
+msgid "class"
+msgstr "ক্লাস"
+
+#: sphinx/domains/python.py:399
+#: sphinx/locale/__init__.py:161
+msgid "exception"
+msgstr "এক্সেপশন"
+
+#: sphinx/domains/python.py:400
+msgid "method"
+msgstr "মেথড"
+
+#: sphinx/domains/python.py:401
+msgid "attribute"
+msgstr "এ্যট্রিবিউট"
+
+#: sphinx/domains/python.py:402
+#: sphinx/locale/__init__.py:157
+msgid "module"
+msgstr "মডিউল"
+
+#: sphinx/domains/std.py:67
+#: sphinx/domains/std.py:83
+#, python-format
+msgid "environment variable; %s"
+msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল; %s"
+
+#: sphinx/domains/std.py:156
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sকমান্ড লাইন অপশন; %s"
+
+#: sphinx/domains/std.py:324
+msgid "glossary term"
+msgstr "শব্দকোষ"
+
+#: sphinx/domains/std.py:325
+msgid "grammar token"
+msgstr "ব্যকরণ টোকেন"
+
+#: sphinx/domains/std.py:326
+msgid "environment variable"
+msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল"
+
+#: sphinx/domains/std.py:327
+msgid "program option"
+msgstr "প্রোগ্রাম অপশন"
+
+#: sphinx/ext/autodoc.py:892
+#, python-format
+msgid " Bases: %s"
+msgstr "বেস: %s"
+
+#: sphinx/ext/autodoc.py:925
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ":class:`%s` এর উপনাম"
+
+#: sphinx/ext/todo.py:40
+msgid "Todo"
+msgstr "অসমাপ্ত কাজ"
+
+#: sphinx/ext/todo.py:98
+#, python-format
+msgid "(The original entry is located in %s, line %d and can be found "
+msgstr "(%s, %d লাইনে মূল অন্তর্ভুক্তিটি রয়েছে, যা পাওয়া যাবে"
+
+#: sphinx/ext/todo.py:104
+msgid "here"
+msgstr "এখানে"
+
+#: sphinx/locale/__init__.py:138
+msgid "Attention"
+msgstr "দৃষ্টি আকর্ষণ"
+
+#: sphinx/locale/__init__.py:139
+msgid "Caution"
+msgstr "সতর্কীকরণ"
+
+#: sphinx/locale/__init__.py:140
+msgid "Danger"
+msgstr "বিপজ্জনক"
+
+#: sphinx/locale/__init__.py:141
+msgid "Error"
+msgstr "ভুল (এরর)"
+
+#: sphinx/locale/__init__.py:142
+msgid "Hint"
+msgstr "আভাস"
+
+#: sphinx/locale/__init__.py:143
+msgid "Important"
+msgstr "গুরুত্বপূর্ণ"
+
+#: sphinx/locale/__init__.py:144
+msgid "Note"
+msgstr "নোট"
+
+#: sphinx/locale/__init__.py:145
+msgid "See Also"
+msgstr "আরও দেখুন"
+
+#: sphinx/locale/__init__.py:146
+msgid "Tip"
+msgstr "পরামর্শ"
+
+#: sphinx/locale/__init__.py:147
+msgid "Warning"
+msgstr "সতর্কতা"
+
+#: sphinx/locale/__init__.py:151
+#, python-format
+msgid "New in version %s"
+msgstr "%s ভার্সনে নতুন"
+
+#: sphinx/locale/__init__.py:152
+#, python-format
+msgid "Changed in version %s"
+msgstr "%s ভার্সনে পরিবর্তিত"
+
+#: sphinx/locale/__init__.py:153
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s ভার্সন থেকে ডেপ্রিকেটেড"
+
+#: sphinx/locale/__init__.py:158
+msgid "keyword"
+msgstr "কিওয়ার্ড"
+
+#: sphinx/locale/__init__.py:159
+msgid "operator"
+msgstr "অপারেটর"
+
+#: sphinx/locale/__init__.py:160
+msgid "object"
+msgstr "অবজেক্ট"
+
+#: sphinx/locale/__init__.py:162
+msgid "statement"
+msgstr "স্ট্যাটমেন্ট"
+
+#: sphinx/locale/__init__.py:163
+msgid "built-in function"
+msgstr "বিল্ট-ইন ফাংশন"
+
+#: sphinx/themes/basic/defindex.html:2
+msgid "Overview"
+msgstr "ভুমিকা"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Indices and tables:"
+msgstr "ইনডেক্স ও টেবিল সমূহ:"
+
+#: sphinx/themes/basic/defindex.html:14
+msgid "Complete Table of Contents"
+msgstr "পূর্ণাঙ্গ সূচীপত্র"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "lists all sections and subsections"
+msgstr "সকল অনুচ্ছেদ সমূহের তালিকা"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "search this documentation"
+msgstr "এই সহায়িকাতে অনুসন্ধা করুন"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "quick access to all modules"
+msgstr "সকল মডিউলে দ্রুত প্রবেশ"
+
+#: sphinx/themes/basic/defindex.html:22
+msgid "all functions, classes, terms"
+msgstr "সকল ফাংশন, ক্লাস, টার্ম"
+
+#: sphinx/themes/basic/genindex-single.html:5
+#, python-format
+msgid "Index &ndash; %(key)s"
+msgstr "ইনডেক্স &ndash; %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:44
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex-split.html:27
+#: sphinx/themes/basic/genindex.html:54
+msgid "Full index on one page"
+msgstr "এক পাতায় সম্পূর্ণ ইনডেক্স"
+
+#: sphinx/themes/basic/genindex-split.html:7
+msgid "Index pages by letter"
+msgstr "বর্ণানুসারে ইনডেক্স পাতা"
+
+#: sphinx/themes/basic/genindex-split.html:15
+msgid "can be huge"
+msgstr "খুব বড় হতে পারে"
+
+#: sphinx/themes/basic/layout.html:10
+msgid "Navigation"
+msgstr "নেভিগেশন"
+
+#: sphinx/themes/basic/layout.html:42
+msgid "Table Of Contents"
+msgstr "সূচীপত্র"
+
+#: sphinx/themes/basic/layout.html:48
+msgid "Previous topic"
+msgstr "পূর্ববর্তী টপিক"
+
+#: sphinx/themes/basic/layout.html:50
+msgid "previous chapter"
+msgstr "পূর্ববর্তী অধ্যায়"
+
+#: sphinx/themes/basic/layout.html:53
+msgid "Next topic"
+msgstr "পরবর্তী টপিক"
+
+#: sphinx/themes/basic/layout.html:55
+msgid "next chapter"
+msgstr "পরবর্তী অধ্যায়"
+
+#: sphinx/themes/basic/layout.html:60
+msgid "This Page"
+msgstr "এই পাতা"
+
+#: sphinx/themes/basic/layout.html:63
+msgid "Show Source"
+msgstr "সোর্স দেখুন"
+
+#: sphinx/themes/basic/layout.html:73
+msgid "Quick search"
+msgstr "দ্রুত অনুসন্ধান"
+
+#: sphinx/themes/basic/layout.html:76
+msgid "Go"
+msgstr "যান"
+
+#: sphinx/themes/basic/layout.html:81
+msgid "Enter search terms or a module, class or function name."
+msgstr "অনুসন্ধানের জন্য টার্ম, মডিউল, ক্লাস অথবা ফাংশনের নাম দিন।"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "%(docstitle)s এর মধ্যে খুঁজুন"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "এই ডকুমেন্ট সম্পর্কে"
+
+#: sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:2
+#: sphinx/themes/basic/search.html:5
+msgid "Search"
+msgstr "অনুসন্ধান"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "কপিরাইট"
+
+#: sphinx/themes/basic/layout.html:187
+#: sphinx/themes/scrolls/layout.html:83
+#, python-format
+msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "&copy; <a href=\"%(path)s\">কপিরাইট</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:189
+#: sphinx/themes/scrolls/layout.html:85
+#, python-format
+msgid "&copy; Copyright %(copyright)s."
+msgstr "&copy; কপিরাইট %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:193
+#: sphinx/themes/scrolls/layout.html:89
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "%(last_updated)s সর্বশেষ পরিবর্তন করা হয়েছে।"
+
+#: sphinx/themes/basic/layout.html:196
+#: sphinx/themes/scrolls/layout.html:92
+#, python-format
+msgid "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s."
+msgstr "<a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s দিয়ে তৈরী।"
+
+#: sphinx/themes/basic/modindex.html:36
+#: sphinx/themes/scrolls/modindex.html:37
+msgid "Deprecated"
+msgstr "ডেপ্রিকেটেড"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s-এ খুঁজুন"
+
+#: sphinx/themes/basic/search.html:9
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"অনুসন্ধান করার জন্য অনুগ্রহপূর্বক জাভাস্ক্রিপ্ট \n"
+" সক্রিয় করুন।"
+
+#: sphinx/themes/basic/search.html:14
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"এখান থেকে এই নথিগুলোতে আপনি অনুসন্ধান করতে পারবেন। \n"
+" আপনার কাঙ্ক্ষিত শব্দসমূহ নিচের বাক্সে লিখুন এবং \"অনুসন্ধান\" বাটনে ক্লিক করুন।\n"
+" উল্লেখ্য, সকল শব্দসমূহের উপস্থিতি নিয়ে অনুসন্ধান করা হবে। যেসব পাতায় সকল\n"
+" শব্দ নেই সেগুলো বাদ দেয়া হবে।"
+
+#: sphinx/themes/basic/search.html:21
+msgid "search"
+msgstr "খুঁজুন"
+
+#: sphinx/themes/basic/search.html:25
+#: sphinx/themes/basic/static/searchtools.js:473
+msgid "Search Results"
+msgstr "অনুসন্ধানের ফলাফল"
+
+#: sphinx/themes/basic/search.html:27
+msgid "Your search did not match any results."
+msgstr "আপনার অনুসন্ধানে কোন ফলাফল পাওয়া যায়নি।"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
+msgstr "%(version)s &mdash; %(docstitle)s-এ পরিবর্তন সমূহ"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s &mdash; %(docstitle)s"
+msgstr "%(filename)s &mdash; %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "স্বয়ংক্রিয়ভাবে তৈরী %(version)s-এ পরিবর্তন সমূহের তালিকা।"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "লাইব্রেরির পরিবর্তন"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API পরিবর্তন"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "অন্যান্য পরিবর্তন"
+
+#: sphinx/themes/basic/static/doctools.js:138
+#: sphinx/writers/html.py:462
+#: sphinx/writers/html.py:467
+msgid "Permalink to this headline"
+msgstr "এই শিরোনামের পার্মালিঙ্ক"
+
+#: sphinx/themes/basic/static/doctools.js:144
+#: sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "এই সংজ্ঞার পার্মালিঙ্ক"
+
+#: sphinx/themes/basic/static/doctools.js:173
+msgid "Hide Search Matches"
+msgstr "অনুসন্ধানের ম্যাচগুলো লুকান"
+
+#: sphinx/themes/basic/static/searchtools.js:274
+msgid "Searching"
+msgstr "অনুসন্ধান চলছে"
+
+#: sphinx/themes/basic/static/searchtools.js:279
+msgid "Preparing search..."
+msgstr "অনুসন্ধানের প্রস্তুতি চলছে..."
+
+#: sphinx/themes/basic/static/searchtools.js:352
+msgid ", in "
+msgstr ", -"
+
+#: sphinx/themes/basic/static/searchtools.js:475
+msgid "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
+msgstr "আপনার অনুসন্ধানে কোন ফলাফল পাওয়া যায়নি। আপনার অনুসন্ধানের শব্দগুলোর সঠিক বানান ও বিভাগ নির্বাচন নিশ্চিত করুন।"
+
+#: sphinx/themes/basic/static/searchtools.js:477
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "অনুসন্ধান শেষ হয়েছে, ফলাফলে %s-টি পাতা পাওয়া গেছে।"
+
+#: sphinx/writers/latex.py:187
+msgid "Release"
+msgstr "রিলিজ"
+
+#: sphinx/writers/latex.py:579
+msgid "Footnotes"
+msgstr "পাদটীকা"
+
+#: sphinx/writers/latex.py:647
+msgid "continued from previous page"
+msgstr "পূর্ববর্তী পাতা হতে চলমান"
+
+#: sphinx/writers/latex.py:652
+msgid "Continued on next page"
+msgstr "পরবর্তী পাতাতে চলমান"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "প্লাটফরম: %s"
+
+#: sphinx/writers/text.py:428
+msgid "[image]"
+msgstr "[ছবি]"
+
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
index dbfaab85..312d0fc7 100644
--- a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
+++ b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
@@ -1 +1 @@
-Documentation.addTranslations({"locale": "pt_BR", "plural_expr": "(n > 1)", "messages": {"Search Results": "Resultados da Pesquisa", "Preparing search...": "Preparando pesquisa...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Sua pesquisa n\u00e3o encontrou nenhum documento. Por favor assegure-se de que todas as palavras foram digitadas corretamente e de que voc\u00ea tenha selecionado o m\u00ednimo de categorias.", "Search finished, found %s page(s) matching the search query.": "Pesquisa finalizada, foram encontrada(s) %s p\u00e1gina(s) que conferem com o crit\u00e9rio de pesquisa.", ", in ": ", em ", "Expand sidebar": "", "Permalink to this headline": "Link permanente para este t\u00edtulo", "Searching": "Pesquisando", "Collapse sidebar": "", "Permalink to this definition": "Link permanente para esta defini\u00e7\u00e3o", "Hide Search Matches": "Esconder Resultados da Pesquisa"}}); \ No newline at end of file
+Documentation.addTranslations({"locale": "pt_BR", "plural_expr": "(n > 1)", "messages": {"Search Results": "Resultados da Pesquisa", "Preparing search...": "Preparando pesquisa...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Sua pesquisa n\u00e3o encontrou nenhum documento. Por favor assegure-se de que todas as palavras foram digitadas corretamente e de que voc\u00ea tenha selecionado o m\u00ednimo de categorias.", "Search finished, found %s page(s) matching the search query.": "Pesquisa finalizada, foram encontrada(s) %s p\u00e1gina(s) que conferem com o crit\u00e9rio de pesquisa.", ", in ": ", em ", "Expand sidebar": "Expandir painel lateral", "Permalink to this headline": "Link permanente para este t\u00edtulo", "Searching": "Pesquisando", "Collapse sidebar": "Recolher painel lateral", "Permalink to this definition": "Link permanente para esta defini\u00e7\u00e3o", "Hide Search Matches": "Esconder Resultados da Pesquisa"}}); \ No newline at end of file
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo
index b644a114..67c1ce54 100644
--- a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo
+++ b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
index 44e2053a..7df9013e 100644
--- a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
+++ b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Sphinx 0.5\n"
"Report-Msgid-Bugs-To: roger.demetrescu@gmail.com\n"
"POT-Creation-Date: 2008-11-09 19:46+0100\n"
-"PO-Revision-Date: 2010-05-24 23:54+0200\n"
+"PO-Revision-Date: 2010-06-20 18:34-0300\n"
"Last-Translator: Roger Demetrescu <roger.demetrescu@gmail.com>\n"
"Language-Team: pt_BR <roger.demetrescu@gmail.com>\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
@@ -17,7 +17,8 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.4\n"
-#: sphinx/environment.py:106 sphinx/writers/latex.py:184
+#: sphinx/environment.py:106
+#: sphinx/writers/latex.py:184
#: sphinx/writers/manpage.py:67
#, python-format
msgid "%B %d, %Y"
@@ -41,7 +42,8 @@ msgstr "Módulo"
msgid "%b %d, %Y"
msgstr "%d/%m/%Y"
-#: sphinx/builders/html.py:285 sphinx/themes/basic/defindex.html:30
+#: sphinx/builders/html.py:285
+#: sphinx/themes/basic/defindex.html:30
msgid "General Index"
msgstr "Índice Geral"
@@ -70,9 +72,8 @@ msgid "Module author: "
msgstr "Autor do módulo: "
#: sphinx/directives/other.py:131
-#, fuzzy
msgid "Code author: "
-msgstr "Autor do módulo: "
+msgstr "Autor do código: "
#: sphinx/directives/other.py:133
msgid "Author: "
@@ -85,18 +86,21 @@ msgstr "Veja também"
#: sphinx/domains/__init__.py:253
#, python-format
msgid "%s %s"
-msgstr ""
+msgstr "%s %s"
-#: sphinx/domains/c.py:51 sphinx/domains/python.py:49
+#: sphinx/domains/c.py:51
+#: sphinx/domains/python.py:49
msgid "Parameters"
msgstr "Parâmetros"
-#: sphinx/domains/c.py:54 sphinx/domains/javascript.py:137
+#: sphinx/domains/c.py:54
+#: sphinx/domains/javascript.py:137
#: sphinx/domains/python.py:59
msgid "Returns"
msgstr "Retorna"
-#: sphinx/domains/c.py:56 sphinx/domains/python.py:61
+#: sphinx/domains/c.py:56
+#: sphinx/domains/python.py:61
msgid "Return type"
msgstr "Tipo de retorno"
@@ -125,12 +129,15 @@ msgstr "%s (tipo C)"
msgid "%s (C variable)"
msgstr "%s (variável C)"
-#: sphinx/domains/c.py:171 sphinx/domains/cpp.py:1031
-#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:497
+#: sphinx/domains/c.py:171
+#: sphinx/domains/cpp.py:1031
+#: sphinx/domains/javascript.py:166
+#: sphinx/domains/python.py:497
msgid "function"
msgstr "função"
-#: sphinx/domains/c.py:172 sphinx/domains/cpp.py:1032
+#: sphinx/domains/c.py:172
+#: sphinx/domains/cpp.py:1032
msgid "member"
msgstr "membro"
@@ -138,14 +145,14 @@ msgstr "membro"
msgid "macro"
msgstr "macro"
-#: sphinx/domains/c.py:174 sphinx/domains/cpp.py:1033
+#: sphinx/domains/c.py:174
+#: sphinx/domains/cpp.py:1033
msgid "type"
msgstr "tipo"
#: sphinx/domains/c.py:175
-#, fuzzy
msgid "variable"
-msgstr "Variável"
+msgstr "variável"
#: sphinx/domains/cpp.py:876
#, python-format
@@ -167,16 +174,19 @@ msgstr "%s (membro C++)"
msgid "%s (C++ function)"
msgstr "%s (função C++)"
-#: sphinx/domains/cpp.py:1030 sphinx/domains/python.py:499
+#: sphinx/domains/cpp.py:1030
+#: sphinx/domains/python.py:499
msgid "class"
msgstr "classe"
-#: sphinx/domains/javascript.py:117 sphinx/domains/python.py:221
+#: sphinx/domains/javascript.py:117
+#: sphinx/domains/python.py:221
#, python-format
msgid "%s() (built-in function)"
msgstr "%s() (função interna)"
-#: sphinx/domains/javascript.py:118 sphinx/domains/python.py:285
+#: sphinx/domains/javascript.py:118
+#: sphinx/domains/python.py:285
#, python-format
msgid "%s() (%s method)"
msgstr "%s() (método %s)"
@@ -184,41 +194,44 @@ msgstr "%s() (método %s)"
#: sphinx/domains/javascript.py:120
#, python-format
msgid "%s (global variable or constant)"
-msgstr ""
+msgstr "%s (variável global ou constante)"
-#: sphinx/domains/javascript.py:122 sphinx/domains/python.py:323
+#: sphinx/domains/javascript.py:122
+#: sphinx/domains/python.py:323
#, python-format
msgid "%s (%s attribute)"
msgstr "%s (atributo %s)"
#: sphinx/domains/javascript.py:131
-#, fuzzy
msgid "Arguments"
msgstr "Parâmetros"
#: sphinx/domains/javascript.py:134
msgid "Throws"
-msgstr ""
+msgstr "Gera"
-#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:498
+#: sphinx/domains/javascript.py:167
+#: sphinx/domains/python.py:498
msgid "data"
-msgstr ""
+msgstr "dado"
-#: sphinx/domains/javascript.py:168 sphinx/domains/python.py:504
+#: sphinx/domains/javascript.py:168
+#: sphinx/domains/python.py:504
msgid "attribute"
msgstr "atributo"
#: sphinx/domains/python.py:53
-#, fuzzy
msgid "Variables"
-msgstr "Variável"
+msgstr "Variáveis"
#: sphinx/domains/python.py:56
msgid "Raises"
msgstr "Levanta"
-#: sphinx/domains/python.py:222 sphinx/domains/python.py:279
-#: sphinx/domains/python.py:291 sphinx/domains/python.py:304
+#: sphinx/domains/python.py:222
+#: sphinx/domains/python.py:279
+#: sphinx/domains/python.py:291
+#: sphinx/domains/python.py:304
#, python-format
msgid "%s() (in module %s)"
msgstr "%s() (no módulo %s)"
@@ -228,7 +241,8 @@ msgstr "%s() (no módulo %s)"
msgid "%s (built-in variable)"
msgstr "%s (variável interna)"
-#: sphinx/domains/python.py:226 sphinx/domains/python.py:317
+#: sphinx/domains/python.py:226
+#: sphinx/domains/python.py:317
#, python-format
msgid "%s (in module %s)"
msgstr "%s (no módulo %s)"
@@ -259,14 +273,14 @@ msgid "%s() (%s static method)"
msgstr "%s() (método estático %s)"
#: sphinx/domains/python.py:308
-#, fuzzy, python-format
+#, python-format
msgid "%s() (%s.%s class method)"
-msgstr "%s() (método %s.%s)"
+msgstr "%s() (método de classe %s.%s)"
#: sphinx/domains/python.py:311
-#, fuzzy, python-format
+#, python-format
msgid "%s() (%s class method)"
-msgstr "%s() (método %s)"
+msgstr "%s() (método de classe %s)"
#: sphinx/domains/python.py:321
#, python-format
@@ -283,9 +297,8 @@ msgid "%s (module)"
msgstr "%s (módulo)"
#: sphinx/domains/python.py:429
-#, fuzzy
msgid "Python Module Index"
-msgstr "Índice do Módulo"
+msgstr "Índice de Módulos do Python"
#: sphinx/domains/python.py:430
msgid "modules"
@@ -295,47 +308,49 @@ msgstr "módulos"
msgid "Deprecated"
msgstr "Obsoleto"
-#: sphinx/domains/python.py:500 sphinx/locale/__init__.py:162
+#: sphinx/domains/python.py:500
+#: sphinx/locale/__init__.py:162
msgid "exception"
msgstr "exceção"
#: sphinx/domains/python.py:501
msgid "method"
-msgstr ""
+msgstr "método"
#: sphinx/domains/python.py:502
-#, fuzzy, python-format
+#, python-format
msgid "class method"
-msgstr "%s() (método %s)"
+msgstr "método de classe"
#: sphinx/domains/python.py:503
msgid "static method"
msgstr "método estático"
-#: sphinx/domains/python.py:505 sphinx/locale/__init__.py:158
+#: sphinx/domains/python.py:505
+#: sphinx/locale/__init__.py:158
msgid "module"
msgstr "módulo"
#: sphinx/domains/rst.py:53
#, python-format
msgid "%s (directive)"
-msgstr ""
+msgstr "%s (diretiva)"
#: sphinx/domains/rst.py:55
-#, fuzzy, python-format
+#, python-format
msgid "%s (role)"
-msgstr "%s (módulo)"
+msgstr "%s (papel)"
#: sphinx/domains/rst.py:103
msgid "directive"
-msgstr ""
+msgstr "diretiva"
#: sphinx/domains/rst.py:104
-#, fuzzy
msgid "role"
-msgstr "módulo"
+msgstr "papel"
-#: sphinx/domains/std.py:68 sphinx/domains/std.py:84
+#: sphinx/domains/std.py:68
+#: sphinx/domains/std.py:84
#, python-format
msgid "environment variable; %s"
msgstr "váriavel de ambiente; %s"
@@ -347,15 +362,15 @@ msgstr "%sopção de linha de comando; %s"
#: sphinx/domains/std.py:328
msgid "glossary term"
-msgstr ""
+msgstr "Termo de glossário"
#: sphinx/domains/std.py:329
msgid "grammar token"
-msgstr ""
+msgstr "token de gramática"
#: sphinx/domains/std.py:330
msgid "reference label"
-msgstr ""
+msgstr "rótulo de referência"
#: sphinx/domains/std.py:331
msgid "environment variable"
@@ -363,13 +378,16 @@ msgstr "váriavel de ambiente"
#: sphinx/domains/std.py:332
msgid "program option"
-msgstr ""
+msgstr "opção de programa"
-#: sphinx/domains/std.py:360 sphinx/themes/basic/genindex-single.html:11
+#: sphinx/domains/std.py:360
+#: sphinx/themes/basic/genindex-single.html:11
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
-#: sphinx/themes/basic/genindex.html:11 sphinx/themes/basic/genindex.html:14
-#: sphinx/themes/basic/genindex.html:50 sphinx/themes/basic/layout.html:125
+#: sphinx/themes/basic/genindex.html:11
+#: sphinx/themes/basic/genindex.html:14
+#: sphinx/themes/basic/genindex.html:50
+#: sphinx/themes/basic/layout.html:125
#: sphinx/writers/latex.py:173
msgid "Index"
msgstr "Índice"
@@ -378,19 +396,20 @@ msgstr "Índice"
msgid "Module Index"
msgstr "Índice do Módulo"
-#: sphinx/domains/std.py:362 sphinx/themes/basic/defindex.html:25
+#: sphinx/domains/std.py:362
+#: sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr "Página de Pesquisa"
#: sphinx/ext/autodoc.py:917
#, python-format
msgid " Bases: %s"
-msgstr ""
+msgstr " Bases: %s"
#: sphinx/ext/autodoc.py:950
#, python-format
msgid "alias of :class:`%s`"
-msgstr ""
+msgstr "apelido de :class:`%s`"
#: sphinx/ext/todo.py:41
msgid "Todo"
@@ -407,29 +426,28 @@ msgstr "entrada original"
#: sphinx/ext/viewcode.py:66
msgid "[source]"
-msgstr ""
+msgstr "[código fonte]"
#: sphinx/ext/viewcode.py:109
msgid "[docs]"
-msgstr ""
+msgstr "[documentos]"
#: sphinx/ext/viewcode.py:123
-#, fuzzy
msgid "Module code"
-msgstr "módulo"
+msgstr "Código do módulo"
#: sphinx/ext/viewcode.py:129
#, python-format
msgid "<h1>Source code for %s</h1>"
-msgstr ""
+msgstr "<h1>Código fonte de %s</h1>"
#: sphinx/ext/viewcode.py:156
msgid "Overview: module code"
-msgstr ""
+msgstr "Visão geral: código do módulo"
#: sphinx/ext/viewcode.py:157
msgid "<h1>All modules for which code is available</h1>"
-msgstr ""
+msgstr "<h1>Todos os módulos onde este código está disponível</h1>"
#: sphinx/locale/__init__.py:139
msgid "Attention"
@@ -506,26 +524,31 @@ msgstr "comando"
msgid "built-in function"
msgstr "função interna"
-#: sphinx/themes/agogo/layout.html:45 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/agogo/layout.html:45
+#: sphinx/themes/basic/globaltoc.html:10
#: sphinx/themes/basic/localtoc.html:11
msgid "Table Of Contents"
msgstr "Tabela de Conteúdo"
-#: sphinx/themes/agogo/layout.html:49 sphinx/themes/basic/layout.html:128
-#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:14
+#: sphinx/themes/agogo/layout.html:49
+#: sphinx/themes/basic/layout.html:128
+#: sphinx/themes/basic/search.html:11
+#: sphinx/themes/basic/search.html:14
msgid "Search"
msgstr "Pesquisar"
-#: sphinx/themes/agogo/layout.html:52 sphinx/themes/basic/searchbox.html:15
+#: sphinx/themes/agogo/layout.html:52
+#: sphinx/themes/basic/searchbox.html:15
msgid "Go"
msgstr "Ir"
-#: sphinx/themes/agogo/layout.html:57 sphinx/themes/basic/searchbox.html:20
-#, fuzzy
+#: sphinx/themes/agogo/layout.html:57
+#: sphinx/themes/basic/searchbox.html:20
msgid "Enter search terms or a module, class or function name."
-msgstr "Informe o nome de um módulo, classe ou função."
+msgstr "Digite os termos da busca ou o nome de um módulo, classe ou função."
-#: sphinx/themes/agogo/layout.html:78 sphinx/themes/basic/sourcelink.html:14
+#: sphinx/themes/agogo/layout.html:78
+#: sphinx/themes/basic/sourcelink.html:14
msgid "Show Source"
msgstr "Exibir Fonte"
@@ -615,12 +638,8 @@ msgstr "Última atualização em %(last_updated)s."
#: sphinx/themes/basic/layout.html:189
#, python-format
-msgid ""
-"Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
-"%(sphinx_version)s."
-msgstr ""
-"Criado com <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
-"%(sphinx_version)s."
+msgid "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s."
+msgstr "Criado com <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s."
#: sphinx/themes/basic/opensearch.xml:4
#, python-format
@@ -647,10 +666,9 @@ msgstr "próximo capítulo"
msgid ""
"Please activate JavaScript to enable the search\n"
" functionality."
-msgstr ""
+msgstr "Por favor ative o JavaScript para habilitar a funcionalidade de pesquisa."
#: sphinx/themes/basic/search.html:23
-#, fuzzy
msgid ""
"From here you can search these documents. Enter your search\n"
" words into the box below and click \"search\". Note that the search\n"
@@ -658,11 +676,9 @@ msgid ""
" containing fewer words won't appear in the result list."
msgstr ""
"A partir daqui você pode pesquisar estes documentos. Preencha suas \n"
-" palavras de pesquisa na caixa abaixo e clique em \"pesquisar\". "
-"Observe que a função de pesquisa\n"
+" palavras de pesquisa na caixa abaixo e clique em \"pesquisar\". Observe que a função de pesquisa\n"
" irá pesquisar automaticamente por todas as palavras.\n"
-" Páginas contendo menos palavras não irão aparecer na lista de "
-"resultado."
+" Páginas contendo menos palavras não irão aparecer na lista de resultado."
#: sphinx/themes/basic/search.html:30
msgid "search"
@@ -713,12 +729,14 @@ msgstr "Alterações na API C"
msgid "Other changes"
msgstr "Outras alterações"
-#: sphinx/themes/basic/static/doctools.js:154 sphinx/writers/html.py:482
+#: sphinx/themes/basic/static/doctools.js:154
+#: sphinx/writers/html.py:482
#: sphinx/writers/html.py:487
msgid "Permalink to this headline"
msgstr "Link permanente para este título"
-#: sphinx/themes/basic/static/doctools.js:160 sphinx/writers/html.py:87
+#: sphinx/themes/basic/static/doctools.js:160
+#: sphinx/writers/html.py:87
msgid "Permalink to this definition"
msgstr "Link permanente para esta definição"
@@ -739,51 +757,45 @@ msgid ", in "
msgstr ", em "
#: sphinx/themes/basic/static/searchtools.js:491
-msgid ""
-"Your search did not match any documents. Please make sure that all words "
-"are spelled correctly and that you've selected enough categories."
-msgstr ""
-"Sua pesquisa não encontrou nenhum documento. Por favor assegure-se de que"
-" todas as palavras foram digitadas corretamente e de que você tenha "
-"selecionado o mínimo de categorias."
+msgid "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
+msgstr "Sua pesquisa não encontrou nenhum documento. Por favor assegure-se de que todas as palavras foram digitadas corretamente e de que você tenha selecionado o mínimo de categorias."
#: sphinx/themes/basic/static/searchtools.js:493
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
-msgstr ""
-"Pesquisa finalizada, foram encontrada(s) %s página(s) que conferem com o "
-"critério de pesquisa."
+msgstr "Pesquisa finalizada, foram encontrada(s) %s página(s) que conferem com o critério de pesquisa."
#: sphinx/themes/default/static/sidebar.js:66
msgid "Expand sidebar"
-msgstr ""
+msgstr "Expandir painel lateral"
#: sphinx/themes/default/static/sidebar.js:79
#: sphinx/themes/default/static/sidebar.js:106
msgid "Collapse sidebar"
-msgstr ""
+msgstr "Recolher painel lateral"
#: sphinx/themes/haiku/layout.html:26
msgid "Contents"
-msgstr ""
+msgstr "Conteúdo"
#: sphinx/writers/latex.py:171
msgid "Release"
msgstr "Versão"
-#: sphinx/writers/latex.py:572 sphinx/writers/manpage.py:178
+#: sphinx/writers/latex.py:572
+#: sphinx/writers/manpage.py:178
msgid "Footnotes"
-msgstr ""
+msgstr "Notas de rodapé"
#: sphinx/writers/latex.py:641
msgid "continued from previous page"
-msgstr ""
+msgstr "continuação da página anterior"
#: sphinx/writers/latex.py:646
-#, fuzzy
msgid "Continued on next page"
-msgstr "Índice completo em uma página"
+msgstr "Continua na próxima página"
#: sphinx/writers/text.py:422
msgid "[image]"
msgstr "[imagem]"
+
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index b8e2fded..ef92297c 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -18,6 +18,7 @@ from sphinx.errors import PycodeError
from sphinx.pycode import nodes
from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
from sphinx.util import get_module_source
+from sphinx.util.pycompat import next
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
@@ -98,7 +99,8 @@ class AttrDocVisitor(nodes.NodeVisitor):
if not pnode or pnode.type not in (token.INDENT, token.DEDENT):
break
prefix = pnode.get_prefix()
- prefix = prefix.decode(self.encoding)
+ if not isinstance(prefix, unicode):
+ prefix = prefix.decode(self.encoding)
docstring = prepare_commentdoc(prefix)
self.add_docstring(node, docstring)
@@ -278,7 +280,7 @@ class ModuleAnalyzer(object):
result[fullname] = (dtype, startline, endline)
expect_indent = False
if tok in ('def', 'class'):
- name = tokeniter.next()[1]
+ name = next(tokeniter)[1]
namespace.append(name)
fullname = '.'.join(namespace)
stack.append((tok, fullname, spos[0], indent))
diff --git a/sphinx/pycode/nodes.py b/sphinx/pycode/nodes.py
index e7184677..fc6eb93a 100644
--- a/sphinx/pycode/nodes.py
+++ b/sphinx/pycode/nodes.py
@@ -29,6 +29,8 @@ class BaseNode(object):
return NotImplemented
return not self._eq(other)
+ __hash__ = None
+
def get_prev_sibling(self):
"""Return previous child in parent's children, or None."""
if self.parent is None:
diff --git a/sphinx/pycode/pgen2/literals.py b/sphinx/pycode/pgen2/literals.py
index 31900291..d4893702 100644
--- a/sphinx/pycode/pgen2/literals.py
+++ b/sphinx/pycode/pgen2/literals.py
@@ -66,7 +66,7 @@ uni_escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3}|"
def evalString(s, encoding=None):
regex = escape_re
repl = escape
- if encoding:
+ if encoding and not isinstance(s, unicode):
s = s.decode(encoding)
if s.startswith('u') or s.startswith('U'):
regex = uni_escape_re
diff --git a/sphinx/pycode/pgen2/tokenize.py b/sphinx/pycode/pgen2/tokenize.py
index 4489db89..7ad9f012 100644
--- a/sphinx/pycode/pgen2/tokenize.py
+++ b/sphinx/pycode/pgen2/tokenize.py
@@ -143,7 +143,9 @@ class TokenError(Exception): pass
class StopTokenizing(Exception): pass
-def printtoken(type, token, (srow, scol), (erow, ecol), line): # for testing
+def printtoken(type, token, scell, ecell, line): # for testing
+ srow, scol = scell
+ erow, ecol = ecell
print "%d,%d-%d,%d:\t%s\t%s" % \
(srow, scol, erow, ecol, tok_name[type], repr(token))
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index e656d218..fdac4cbe 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -9,8 +9,9 @@
:license: BSD, see LICENSE for details.
"""
-import sys, os, time
+import sys, os, time, re
from os import path
+from codecs import open
TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
@@ -20,10 +21,23 @@ from sphinx.util.console import purple, bold, red, turquoise, \
nocolor, color_terminal
from sphinx.util import texescape
+# function to get input from terminal -- overridden by the test suite
+try:
+ # this raw_input is not converted by 2to3
+ term_input = raw_input
+except NameError:
+ term_input = input
+
PROMPT_PREFIX = '> '
-QUICKSTART_CONF = '''\
+if sys.version_info >= (3, 0):
+ # prevents that the file is checked for being written in Python 2.x syntax
+ QUICKSTART_CONF = '#!/usr/bin/env python3\n'
+else:
+ QUICKSTART_CONF = ''
+
+QUICKSTART_CONF += '''\
# -*- coding: utf-8 -*-
#
# %(project)s documentation build configuration file, created by
@@ -42,7 +56,7 @@ import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
+#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
@@ -186,8 +200,8 @@ html_static_path = ['%(dot)sstatic']
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = '%(project_fn)sdoc'
@@ -279,6 +293,9 @@ epub_copyright = u'%(copyright_str)s'
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
'''
INTERSPHINX_CONFIG = '''
@@ -667,20 +684,22 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
prompt = purple(PROMPT_PREFIX + '%s [%s]: ' % (text, default))
else:
prompt = purple(PROMPT_PREFIX + text + ': ')
- x = raw_input(prompt)
+ x = term_input(prompt)
if default and not x:
x = default
- if x.decode('ascii', 'replace').encode('ascii', 'replace') != x:
- if TERM_ENCODING:
- x = x.decode(TERM_ENCODING)
- else:
- print turquoise('* Note: non-ASCII characters entered '
- 'and terminal encoding unknown -- assuming '
- 'UTF-8 or Latin-1.')
- try:
- x = x.decode('utf-8')
- except UnicodeDecodeError:
- x = x.decode('latin1')
+ if not isinstance(x, unicode):
+ # for Python 2.x, try to get a Unicode string out of it
+ if x.decode('ascii', 'replace').encode('ascii', 'replace') != x:
+ if TERM_ENCODING:
+ x = x.decode(TERM_ENCODING)
+ else:
+ print turquoise('* Note: non-ASCII characters entered '
+ 'and terminal encoding unknown -- assuming '
+ 'UTF-8 or Latin-1.')
+ try:
+ x = x.decode('utf-8')
+ except UnicodeDecodeError:
+ x = x.decode('latin1')
try:
x = validator(x)
except ValidationError, err:
@@ -690,6 +709,18 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
d[key] = x
+if sys.version_info >= (3, 0):
+ # remove Unicode literal prefixes
+ _unicode_string_re = re.compile(r"[uU]('.*?')")
+ def _convert_python_source(source):
+ return _unicode_string_re.sub('\\1', source)
+
+ for f in ['QUICKSTART_CONF', 'EPUB_CONFIG', 'INTERSPHINX_CONFIG']:
+ globals()[f] = _convert_python_source(globals()[f])
+
+ del _unicode_string_re, _convert_python_source
+
+
def inner_main(args):
d = {}
texescape.init()
@@ -845,28 +876,28 @@ directly.'''
if d['ext_intersphinx']:
conf_text += INTERSPHINX_CONFIG
- f = open(path.join(srcdir, 'conf.py'), 'w')
- f.write(conf_text.encode('utf-8'))
+ f = open(path.join(srcdir, 'conf.py'), 'w', encoding='utf-8')
+ f.write(conf_text)
f.close()
masterfile = path.join(srcdir, d['master'] + d['suffix'])
- f = open(masterfile, 'w')
- f.write((MASTER_FILE % d).encode('utf-8'))
+ f = open(masterfile, 'w', encoding='utf-8')
+ f.write(MASTER_FILE % d)
f.close()
if d['makefile']:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
# use binary mode, to avoid writing \r\n on Windows
- f = open(path.join(d['path'], 'Makefile'), 'wb')
- f.write((MAKEFILE % d).encode('utf-8'))
+ f = open(path.join(d['path'], 'Makefile'), 'wb', encoding='utf-8')
+ f.write(MAKEFILE % d)
f.close()
if d['batchfile']:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
- f = open(path.join(d['path'], 'make.bat'), 'w')
- f.write((BATCHFILE % d).encode('utf-8'))
+ f = open(path.join(d['path'], 'make.bat'), 'w', encoding='utf-8')
+ f.write(BATCHFILE % d)
f.close()
print
diff --git a/sphinx/roles.py b/sphinx/roles.py
index 0164d757..0ea0ec48 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -105,9 +105,9 @@ class XRefRole(object):
classes = ['xref', domain, '%s-%s' % (domain, role)]
# if the first character is a bang, don't cross-reference at all
if text[0:1] == '!':
- text = utils.unescape(text)
+ text = utils.unescape(text)[1:]
if self.fix_parens:
- text, tgt = self._fix_parens(env, False, text[1:], "")
+ text, tgt = self._fix_parens(env, False, text, "")
innernode = self.innernodeclass(rawtext, text, classes=classes)
return self.result_nodes(inliner.document, env, innernode,
is_ref=False)
@@ -173,6 +173,10 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
indexnode['entries'] = [
('single', _('Python Enhancement Proposals!PEP %s') % text,
targetid, 'PEP %s' % text)]
+ anchor = ''
+ anchorindex = text.find('#')
+ if anchorindex > 0:
+ text, anchor = text[:anchorindex], text[anchorindex:]
try:
pepnum = int(text)
except ValueError:
@@ -182,12 +186,17 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
return [prb], [msg]
ref = inliner.document.settings.pep_base_url + 'pep-%04d' % pepnum
sn = nodes.strong('PEP '+text, 'PEP '+text)
- rn = nodes.reference('', '', internal=False, refuri=ref, classes=[typ])
+ rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
+ classes=[typ])
rn += sn
return [indexnode, targetnode, rn], []
elif typ == 'rfc':
indexnode['entries'] = [('single', 'RFC; RFC %s' % text,
targetid, 'RFC %s' % text)]
+ anchor = ''
+ anchorindex = text.find('#')
+ if anchorindex > 0:
+ text, anchor = text[:anchorindex], text[anchorindex:]
try:
rfcnum = int(text)
except ValueError:
@@ -197,7 +206,8 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
return [prb], [msg]
ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
sn = nodes.strong('RFC '+text, 'RFC '+text)
- rn = nodes.reference('', '', internal=False, refuri=ref, classes=[typ])
+ rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
+ classes=[typ])
rn += sn
return [indexnode, targetnode, rn], []
@@ -205,8 +215,9 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
_amp_re = re.compile(r'(?<!&)&(?![&\s])')
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ text = utils.unescape(text)
if typ == 'menuselection':
- text = utils.unescape(text).replace('-->', u'\N{TRIANGULAR BULLET}')
+ text = text.replace('-->', u'\N{TRIANGULAR BULLET}')
spans = _amp_re.split(text)
node = nodes.emphasis(rawtext=rawtext)
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index be8a6c15..b5381392 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -446,6 +446,7 @@
linkcolor=InnerLinkColor,filecolor=OuterLinkColor,
menucolor=OuterLinkColor,urlcolor=OuterLinkColor,
citecolor=InnerLinkColor]{hyperref}
+\RequirePackage[figure,table]{hypcap}
% From docutils.writers.latex2e
\providecommand{\DUspan}[2]{%
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 1dac6693..e31e8544 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -14,7 +14,7 @@
{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
- (not sidebars == []) %}
+ (sidebars != []) %}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 8d1298cd..a434f3a8 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -18,6 +18,8 @@ import tempfile
import posixpath
import traceback
from os import path
+from codecs import open
+from collections import deque
import docutils
from docutils.utils import relative_path
@@ -140,8 +142,8 @@ def copy_static_entry(source, targetdir, builder, context={},
target = path.join(targetdir, path.basename(source))
if source.lower().endswith('_t') and builder.templates:
# templated!
- fsrc = open(source, 'rb')
- fdst = open(target[:-2], 'wb')
+ fsrc = open(source, 'r', encoding='utf-8')
+ fdst = open(target[:-2], 'w', encoding='utf-8')
fdst.write(builder.templates.render_string(fsrc.read(), context))
fsrc.close()
fdst.close()
@@ -162,17 +164,23 @@ def copy_static_entry(source, targetdir, builder, context={},
shutil.copytree(source, target)
+_DEBUG_HEADER = '''\
+# Sphinx version: %s
+# Docutils version: %s %s
+# Jinja2 version: %s
+'''
+
def save_traceback():
"""
Save the current exception's traceback in a temporary file.
"""
exc = traceback.format_exc()
fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
- os.write(fd, '# Sphinx version: %s\n' % sphinx.__version__)
- os.write(fd, '# Docutils version: %s %s\n' % (docutils.__version__,
- docutils.__version_details__))
- os.write(fd, '# Jinja2 version: %s\n' % jinja2.__version__)
- os.write(fd, exc)
+ os.write(fd, (_DEBUG_HEADER %
+ (sphinx.__version__,
+ docutils.__version__, docutils.__version_details__,
+ jinja2.__version__)).encode('utf-8'))
+ os.write(fd, exc.encode('utf-8'))
os.close(fd)
return path
@@ -290,3 +298,38 @@ def format_exception_cut_frames(x=1):
res += tbres[-x:]
res += traceback.format_exception_only(typ, val)
return ''.join(res)
+
+class PeekableIterator(object):
+ """
+ An iterator which wraps any iterable and makes it possible to peek to see
+ what's the next item.
+ """
+ def __init__(self, iterable):
+ self.remaining = deque()
+ self._iterator = iter(iterable)
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """
+ Returns the next item from the iterator.
+ """
+ if self.remaining:
+ return self.remaining.popleft()
+ return self._iterator.next()
+
+ def push(self, item):
+ """
+ Pushes the `item` on the internal stack, it will be returned on the
+ next :meth:`next` call.
+ """
+ self.remaining.append(item)
+
+ def peek(self):
+ """
+ Returns the next item without changing the state of the iterator.
+ """
+ item = self.next()
+ self.push(item)
+ return item
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index c975b9b5..6ce6d82b 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -141,9 +141,16 @@ class TypedField(GroupedField):
par = nodes.paragraph()
par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
if fieldarg in types:
- typename = u''.join(n.astext() for n in types[fieldarg])
par += nodes.Text(' (')
- par += self.make_xref(self.typerolename, domain, typename)
+ # NOTE: using .pop() here to prevent a single type node to be
+ # inserted twice into the doctree, which leads to
+ # inconsistencies later when references are resolved
+ fieldtype = types.pop(fieldarg)
+ if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text):
+ typename = u''.join(n.astext() for n in fieldtype)
+ par += self.make_xref(self.typerolename, domain, typename)
+ else:
+ par += fieldtype
par += nodes.Text(')')
par += nodes.Text(' -- ')
par += content
@@ -222,7 +229,10 @@ class DocFieldTransformer(object):
if is_typefield:
# filter out only inline nodes; others will result in invalid
# markup being written out
- content = filter(lambda n: isinstance(n, nodes.Inline), content)
+ content = filter(
+ lambda n: isinstance(n, nodes.Inline) or
+ isinstance(n, nodes.Text),
+ content)
if content:
types.setdefault(typename, {})[fieldarg] = content
continue
diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py
new file mode 100644
index 00000000..fda85b5e
--- /dev/null
+++ b/sphinx/util/jsonimpl.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.jsonimpl
+ ~~~~~~~~~~~~~~~~~~~~
+
+ JSON serializer implementation wrapper.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import UserString
+
+try:
+ import json
+ # json-py's json module has not JSONEncoder; this will raise AttributeError
+ # if json-py is imported instead of the built-in json module
+ JSONEncoder = json.JSONEncoder
+except (ImportError, AttributeError):
+ try:
+ import simplejson as json
+ JSONEncoder = json.JSONEncoder
+ except ImportError:
+ json = None
+ JSONEncoder = object
+
+
+class SphinxJSONEncoder(JSONEncoder):
+ """JSONEncoder subclass that forces translation proxies."""
+ def default(self, obj):
+ if isinstance(obj, UserString.UserString):
+ return unicode(obj)
+ return JSONEncoder.default(self, obj)
+
+
+def dump(obj, fp, *args, **kwds):
+ kwds['cls'] = SphinxJSONEncoder
+ return json.dump(obj, fp, *args, **kwds)
+
+def dumps(obj, *args, **kwds):
+ kwds['cls'] = SphinxJSONEncoder
+ return json.dumps(obj, *args, **kwds)
+
+def load(*args, **kwds):
+ return json.load(*args, **kwds)
+
+def loads(*args, **kwds):
+ return json.loads(*args, **kwds)
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 3728eac9..c2f96f07 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -10,11 +10,11 @@
"""
import re
-import types
from docutils import nodes
from sphinx import addnodes
+from sphinx.util.pycompat import class_types
# \x00 means the "<" was backslash-escaped
@@ -129,7 +129,7 @@ def _new_traverse(self, condition=None,
if include_self and descend and not siblings and not ascend:
if condition is None:
return self._all_traverse([])
- elif isinstance(condition, (types.ClassType, type)):
+ elif isinstance(condition, class_types):
return self._fast_traverse(condition, [])
return self._old_traverse(condition, include_self,
descend, siblings, ascend)
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index beab38cb..9943b207 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -11,6 +11,7 @@
import os
import re
+import sys
import time
import errno
import shutil
@@ -124,7 +125,10 @@ no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
def make_filename(string):
return no_fn_re.sub('', string)
-
-def ustrftime(format, *args):
- # strftime for unicode strings
- return time.strftime(unicode(format).encode('utf-8'), *args).decode('utf-8')
+if sys.version_info < (3, 0):
+ def ustrftime(format, *args):
+ # strftime for unicode strings
+ return time.strftime(unicode(format).encode('utf-8'), *args) \
+ .decode('utf-8')
+else:
+ ustrftime = time.strftime
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index bdd9507d..5f23bbe1 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -12,6 +12,65 @@
import sys
import codecs
import encodings
+import re
+
+try:
+ from types import ClassType
+ class_types = (type, ClassType)
+except ImportError:
+ # Python 3
+ class_types = (type,)
+
+
+# the ubiquitous "bytes" helper function
+if sys.version_info >= (3, 0):
+ def b(s):
+ return s.encode('utf-8')
+else:
+ b = str
+
+
+# Support for running 2to3 over config files
+
+if sys.version_info < (3, 0):
+ # no need to refactor on 2.x versions
+ convert_with_2to3 = None
+else:
+ def convert_with_2to3(filepath):
+ from lib2to3.refactor import RefactoringTool, get_fixers_from_package
+ from lib2to3.pgen2.parse import ParseError
+ fixers = get_fixers_from_package('lib2to3.fixes')
+ refactoring_tool = RefactoringTool(fixers)
+ source = refactoring_tool._read_python_source(filepath)[0]
+ try:
+ tree = refactoring_tool.refactor_string(source, 'conf.py')
+ except ParseError, err:
+ # do not propagate lib2to3 exceptions
+ lineno, offset = err.context[1]
+ # try to match ParseError details with SyntaxError details
+ raise SyntaxError(err.msg, (filepath, lineno, offset, err.value))
+ return unicode(tree)
+
+
+try:
+ base_exception = BaseException
+except NameError:
+ base_exception = Exception
+
+
+try:
+ next = next
+except NameError:
+ # this is on Python 2, where the method is called "next" (it is refactored
+ # to __next__ by 2to3, but in that case never executed)
+ def next(iterator):
+ return iterator.next()
+
+
+try:
+ bytes = bytes
+except NameError:
+ bytes = str
try:
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
new file mode 100644
index 00000000..d0ea18a7
--- /dev/null
+++ b/sphinx/versioning.py
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.versioning
+ ~~~~~~~~~~~~~~~~~
+
+ Implements the low-level algorithms Sphinx uses for the versioning of
+ doctrees.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from uuid import uuid4
+from itertools import product
+try:
+ from itertools import izip_longest as zip_longest
+except ImportError:
+ from itertools import zip_longest
+from difflib import SequenceMatcher
+
+from sphinx.util import PeekableIterator
+
+def add_uids(doctree, condition):
+ """
+ Adds a unique id to every node in the `doctree` which matches the condition
+ and yields it.
+
+ :param doctree:
+ A :class:`docutils.nodes.document` instance.
+
+ :param condition:
+ A callable which returns either ``True`` or ``False`` for a given node.
+ """
+ for node in doctree.traverse(condition):
+ node.uid = uuid4().hex
+ yield node
+
+def merge_node(old, new):
+ """
+ Merges the `old` node with the `new` one, if it's successful the `new` node
+ get's the unique identifier of the `new` one and ``True`` is returned. If
+ the merge is unsuccesful ``False`` is returned.
+ """
+ equals, changed, replaced = make_diff(old.rawsource,
+ new.rawsource)
+ if equals or changed:
+ new.uid = old.uid
+ return True
+ return False
+
+def merge_doctrees(old, new, condition):
+ """
+ Merges the `old` doctree with the `new` one while looking at nodes matching
+ the `condition`.
+
+ Each node which replaces another one or has been added to the `new` doctree
+ will be yielded.
+
+ :param condition:
+ A callable which returns either ``True`` or ``False`` for a given node.
+ """
+ old_iter = PeekableIterator(old.traverse(condition))
+ new_iter = PeekableIterator(new.traverse(condition))
+ old_nodes = []
+ new_nodes = []
+ for old_node, new_node in zip_longest(old_iter, new_iter):
+ if old_node is None:
+ new_nodes.append(new_node)
+ continue
+ if new_node is None:
+ old_nodes.append(old_node)
+ continue
+ if not merge_node(old_node, new_node):
+ if old_nodes:
+ for i, very_old_node in enumerate(old_nodes):
+ if merge_node(very_old_node, new_node):
+ del old_nodes[i]
+ # If the last identified node which has not matched the
+ # unidentified node matches the current one, we have to
+ # assume that the last unidentified one has been
+ # inserted.
+ #
+ # As the required time multiplies with each insert, we
+ # want to avoid that by checking if the next
+ # unidentified node matches the current identified one
+ # and if so we make a shift.
+ if i == len(old_nodes):
+ next_new_node = new_iter.next()
+ if not merge_node(old_node, next_new_node):
+ new_iter.push(next_new_node)
+ break
+ else:
+ old_nodes.append(old_node)
+ new_nodes.append(new_node)
+ for (i, new_node), (j, old_node) in product(enumerate(new_nodes),
+ enumerate(old_nodes)):
+ if merge_node(old_node, new_node):
+ del new_nodes[i]
+ del old_nodes[j]
+ for node in new_nodes:
+ node.uid = uuid4().hex
+ # Yielding the new nodes here makes it possible to use this generator
+ # like add_uids
+ yield node
+
+def make_diff(old, new):
+ """
+ Takes two strings `old` and `new` and returns a :class:`tuple` of boolean
+ values ``(equals, changed, replaced)``.
+
+ equals
+
+ ``True`` if the `old` string and the `new` one are equal.
+
+ changed
+
+ ``True`` if the `new` string is a changed version of the `old` one.
+
+ replaced
+
+ ``True`` if the `new` string and the `old` string are totally
+ different.
+
+ .. note:: This assumes the two strings are human readable text or at least
+ something very similar to that, otherwise it can not detect if
+ the string has been changed or replaced. In any case the
+ detection should not be considered reliable.
+ """
+ if old == new:
+ return True, False, False
+ if new in old or levenshtein_distance(old, new) / (len(old) / 100.0) < 70:
+ return False, True, False
+ return False, False, True
+
+def levenshtein_distance(a, b):
+ if len(a) < len(b):
+ a, b = b, a
+ if not a:
+ return len(b)
+ previous_row = xrange(len(b) + 1)
+ for i, column1 in enumerate(a):
+ current_row = [i + 1]
+ for j, column2 in enumerate(b):
+ insertions = previous_row[j + 1] + 1
+ deletions = current_row[j] + 1
+ substitutions = previous_row[j] + (column1 != column2)
+ current_row.append(min(insertions, deletions, substitutions))
+ previous_row = current_row
+ return previous_row[-1]
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index ea12f003..de0bbdf2 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -224,6 +224,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
else:
self.top_sectionlevel = 1
self.next_section_ids = set()
+ self.next_figure_ids = set()
+ self.next_table_ids = set()
# flags
self.verbatim = None
self.in_title = 0
@@ -250,7 +252,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'\\label{%s}' % self.idescape(id)
def hyperlink(self, id):
- return '\\hyperref[%s]{' % (self.idescape(id))
+ return '{\\hyperref[%s]{' % (self.idescape(id))
def hyperpageref(self, id):
return '\\autopageref*{%s}' % (self.idescape(id))
@@ -314,7 +316,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# ... and all others are the appendices
self.body.append(u'\n\\appendix\n')
self.first_document = -1
- if node.has_key('docname'):
+ if 'docname' in node:
self.body.append(self.hypertarget(':doc'))
# "- 1" because the level is increased before the title is visited
self.sectionlevel = self.top_sectionlevel - 1
@@ -633,7 +635,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
if self.table.longtable and self.table.caption is not None:
self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption)
-
+ if self.table.caption is not None:
+ for id in self.next_table_ids:
+ self.body.append(self.hypertarget(id, anchor=False))
+ self.next_table_ids.clear()
if self.table.longtable:
self.body.append('\\hline\n')
self.body.append('\\endfirsthead\n\n')
@@ -694,7 +699,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.table.rowcount += 1
def visit_entry(self, node):
- if node.has_key('morerows') or node.has_key('morecols'):
+ if 'morerows' in node or 'morecols' in node:
raise UnsupportedError('%s:%s: column or row spanning cells are '
'not yet implemented.' %
(self.curfilestack[-1], node.line or ''))
@@ -751,7 +756,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_term(self, node):
ctx = '}] \\leavevmode'
- if node.has_key('ids') and node['ids']:
+ if node.get('ids'):
ctx += self.hypertarget(node['ids'][0])
self.body.append('\\item[{')
self.context.append(ctx)
@@ -833,20 +838,20 @@ class LaTeXTranslator(nodes.NodeVisitor):
post = []
include_graphics_options = []
is_inline = self.is_inline(node)
- if attrs.has_key('scale'):
+ if 'scale' in attrs:
# Could also be done with ``scale`` option to
# ``\includegraphics``; doing it this way for consistency.
pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
post.append('}')
- if attrs.has_key('width'):
+ if 'width' in attrs:
w = self.latex_image_length(attrs['width'])
if w:
include_graphics_options.append('width=%s' % w)
- if attrs.has_key('height'):
+ if 'height' in attrs:
h = self.latex_image_length(attrs['height'])
if h:
include_graphics_options.append('height=%s' % h)
- if attrs.has_key('align'):
+ if 'align' in attrs:
align_prepost = {
# By default latex aligns the top of an image.
(1, 'top'): ('', ''),
@@ -887,13 +892,17 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_figure(self, node):
- if node.has_key('width') and node.get('align', '') in ('left', 'right'):
+ ids = ''
+ for id in self.next_figure_ids:
+ ids += self.hypertarget(id, anchor=False)
+ self.next_figure_ids.clear()
+ if 'width' in node and node.get('align', '') in ('left', 'right'):
self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
(node['align'] == 'right' and 'r' or 'l',
node['width']))
- self.context.append('\\end{wrapfigure}\n')
+ self.context.append(ids + '\\end{wrapfigure}\n')
else:
- if (not node.attributes.has_key('align') or
+ if (not 'align' in node.attributes or
node.attributes['align'] == 'center'):
# centering does not add vertical space like center.
align = '\n\\centering'
@@ -903,7 +912,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
align = '\\begin{flush%s}' % node.attributes['align']
align_end = '\\end{flush%s}' % node.attributes['align']
self.body.append('\\begin{figure}[htbp]%s\n' % align)
- self.context.append('%s\\end{figure}\n' % align_end)
+ self.context.append(ids + align_end + '\\end{figure}\n')
def depart_figure(self, node):
self.body.append(self.context.pop())
@@ -963,8 +972,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def add_target(id):
# indexing uses standard LaTeX index markup, so the targets
# will be generated differently
- if not id.startswith('index-'):
- self.body.append(self.hypertarget(id))
+ if id.startswith('index-'):
+ return
+ # do not generate \phantomsection in \section{}
+ anchor = not self.in_title
+ self.body.append(self.hypertarget(id, anchor=anchor))
# postpone the labels until after the sectioning command
parindex = node.parent.index(node)
@@ -980,6 +992,20 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.next_section_ids.add(node['refid'])
self.next_section_ids.update(node['ids'])
return
+ elif isinstance(next, nodes.figure):
+ # labels for figures go in the figure body, not before
+ if node.get('refid'):
+ self.next_figure_ids.add(node['refid'])
+ self.next_figure_ids.update(node['ids'])
+ return
+ elif isinstance(next, nodes.table):
+ # same for tables, but only if they have a caption
+ for n in node:
+ if isinstance(n, nodes.title):
+ if node.get('refid'):
+ self.next_table_ids.add(node['refid'])
+ self.next_table_ids.update(node['ids'])
+ return
except IndexError:
pass
if 'refuri' in node:
@@ -1048,9 +1074,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
id = self.curfilestack[-1] + ':' + uri[1:]
self.body.append(self.hyperlink(id))
if self.builder.config.latex_show_pagerefs:
- self.context.append('} (%s)' % self.hyperpageref(id))
+ self.context.append('}} (%s)' % self.hyperpageref(id))
else:
- self.context.append('}')
+ self.context.append('}}')
elif uri.startswith('%'):
# references to documents or labels inside documents
hashindex = uri.find('#')
@@ -1064,12 +1090,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
if len(node) and hasattr(node[0], 'attributes') and \
'std-term' in node[0].get('classes', []):
# don't add a pageref for glossary terms
- self.context.append('}')
+ self.context.append('}}')
else:
if self.builder.config.latex_show_pagerefs:
- self.context.append('} (%s)' % self.hyperpageref(id))
+ self.context.append('}} (%s)' % self.hyperpageref(id))
else:
- self.context.append('}')
+ self.context.append('}}')
elif uri.startswith('@token'):
if self.in_production_list:
self.body.append('\\token{')
@@ -1151,7 +1177,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.no_contractions -= 1
if self.in_title:
self.body.append(r'\texttt{%s}' % content)
- elif node.has_key('role') and node['role'] == 'samp':
+ elif node.get('role') == 'samp':
self.body.append(r'\samp{%s}' % content)
else:
self.body.append(r'\code{%s}' % content)
@@ -1180,10 +1206,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
code = self.verbatim.rstrip('\n')
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
- if node.has_key('language'):
+ if 'language' in node:
# code-block directives
lang = node['language']
- if node.has_key('linenos'):
+ if 'linenos' in node:
linenos = node['linenos']
hlcode = self.highlighter.highlight_block(code, lang, linenos)
# workaround for Unicode issue
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index 98528d5b..b28b2379 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -390,7 +390,7 @@ class TextTranslator(nodes.NodeVisitor):
self.add_text(''.join(out) + '\n')
def writerow(row):
- lines = map(None, *row)
+ lines = zip(*row)
for line in lines:
out = ['|']
for i, cell in enumerate(line):