summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
authorTakayuki Shimizukawa <shimizukawa+bitbucket@gmail.com>2014-05-28 00:08:48 +0900
committerTakayuki Shimizukawa <shimizukawa+bitbucket@gmail.com>2014-05-28 00:08:48 +0900
commit2bea449254abb21a56f4d7193ece32afb2da82f8 (patch)
tree209431e7c8f4ff28f2cbc9e579aeeb570418f41a /sphinx
parent362225b5cf5642e50990d633eae241721ed640b4 (diff)
parent88fe3b0b04f3fff0fce6c9b99d5da73dd5dda880 (diff)
downloadsphinx-2bea449254abb21a56f4d7193ece32afb2da82f8.tar.gz
Merged in vitaut/sphinx/cpp-variadic (pull request #241)
Add support for variadic templates in C++ domain
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/__init__.py2
-rw-r--r--sphinx/application.py13
-rw-r--r--sphinx/builders/changes.py8
-rw-r--r--sphinx/builders/gettext.py19
-rw-r--r--sphinx/builders/html.py22
-rw-r--r--sphinx/builders/latex.py5
-rw-r--r--sphinx/builders/linkcheck.py15
-rw-r--r--sphinx/builders/manpage.py4
-rw-r--r--sphinx/builders/qthelp.py3
-rw-r--r--sphinx/builders/texinfo.py5
-rw-r--r--sphinx/cmdline.py13
-rw-r--r--sphinx/config.py23
-rw-r--r--sphinx/directives/__init__.py3
-rw-r--r--sphinx/directives/other.py3
-rw-r--r--sphinx/domains/__init__.py4
-rw-r--r--sphinx/domains/c.py5
-rw-r--r--sphinx/domains/cpp.py76
-rw-r--r--sphinx/domains/javascript.py6
-rw-r--r--sphinx/domains/python.py13
-rw-r--r--sphinx/domains/rst.py6
-rw-r--r--sphinx/domains/std.py19
-rw-r--r--sphinx/environment.py31
-rw-r--r--sphinx/ext/autodoc.py23
-rw-r--r--sphinx/ext/autosummary/__init__.py3
-rw-r--r--sphinx/ext/autosummary/generate.py5
-rw-r--r--sphinx/ext/coverage.py13
-rw-r--r--sphinx/ext/doctest.py15
-rw-r--r--sphinx/ext/extlinks.py3
-rw-r--r--sphinx/ext/graphviz.py3
-rw-r--r--sphinx/ext/intersphinx.py32
-rw-r--r--sphinx/ext/napoleon/__init__.py13
-rw-r--r--sphinx/ext/napoleon/docstring.py49
-rw-r--r--sphinx/ext/napoleon/iterators.py9
-rw-r--r--sphinx/ext/pngmath.py7
-rw-r--r--sphinx/ext/viewcode.py7
-rw-r--r--sphinx/highlighting.py9
-rw-r--r--sphinx/jinja2glue.py5
-rw-r--r--sphinx/locale/__init__.py20
-rw-r--r--sphinx/pycode/__init__.py14
-rw-r--r--sphinx/pycode/pgen2/literals.py5
-rw-r--r--sphinx/pycode/pgen2/pgen.py28
-rwxr-xr-xsphinx/pycode/pgen2/token.py2
-rw-r--r--sphinx/pycode/pgen2/tokenize.py5
-rw-r--r--sphinx/quickstart.py20
-rw-r--r--sphinx/roles.py5
-rw-r--r--sphinx/search/__init__.py25
-rw-r--r--sphinx/search/ja.py8
-rw-r--r--sphinx/setup_command.py6
-rw-r--r--sphinx/theming.py16
-rw-r--r--sphinx/util/__init__.py24
-rw-r--r--sphinx/util/inspect.py10
-rw-r--r--sphinx/util/jsdump.py10
-rw-r--r--sphinx/util/jsonimpl.py8
-rw-r--r--sphinx/util/osutil.py12
-rw-r--r--sphinx/util/png.py5
-rw-r--r--sphinx/util/pycompat.py53
-rw-r--r--sphinx/util/tags.py4
-rw-r--r--sphinx/util/texescape.py168
-rw-r--r--sphinx/versioning.py7
-rw-r--r--sphinx/websupport/__init__.py3
-rw-r--r--sphinx/websupport/search/__init__.py4
-rw-r--r--sphinx/websupport/search/whooshsearch.py4
-rw-r--r--sphinx/writers/html.py3
-rw-r--r--sphinx/writers/latex.py21
-rw-r--r--sphinx/writers/texinfo.py7
-rw-r--r--sphinx/writers/text.py2
66 files changed, 512 insertions, 481 deletions
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 712bfeca..950eb5ff 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -43,7 +43,7 @@ if '+' in __version__ or 'pre' in __version__:
def main(argv=sys.argv):
"""Sphinx build "main" command-line entry."""
if (sys.version_info[:3] < (2, 6, 0) or
- (3, 0, 0) <= sys.version_info[:3] < (3, 2, 0)):
+ (3, 0, 0) <= sys.version_info[:3] < (3, 3, 0)):
sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n')
return 1
try:
diff --git a/sphinx/application.py b/sphinx/application.py
index 89d1d786..6d1c334b 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -18,8 +18,9 @@ import types
import posixpath
import traceback
from os import path
-from cStringIO import StringIO
+from six import iteritems, itervalues
+from six.moves import cStringIO
from docutils import nodes
from docutils.parsers.rst import convert_directive_function, \
directives, roles
@@ -84,14 +85,14 @@ class Sphinx(object):
self.parallel = parallel
if status is None:
- self._status = StringIO()
+ self._status = cStringIO()
self.quiet = True
else:
self._status = status
self.quiet = False
if warning is None:
- self._warning = StringIO()
+ self._warning = cStringIO()
else:
self._warning = warning
self._warncount = 0
@@ -388,7 +389,7 @@ class Sphinx(object):
def disconnect(self, listener_id):
self.debug('[app] disconnecting event: [id=%s]', listener_id)
- for event in self._listeners.itervalues():
+ for event in itervalues(self._listeners):
event.pop(listener_id, None)
def emit(self, event, *args):
@@ -399,7 +400,7 @@ class Sphinx(object):
pass
results = []
if event in self._listeners:
- for _, callback in self._listeners[event].iteritems():
+ for _, callback in iteritems(self._listeners[event]):
results.append(callback(self, *args))
return results
@@ -443,7 +444,7 @@ class Sphinx(object):
def add_node(self, node, **kwds):
self.debug('[app] adding node: %r', (node, kwds))
nodes._add_node_class_names([node.__name__])
- for key, val in kwds.iteritems():
+ for key, val in iteritems(kwds):
try:
visit, depart = val
except ValueError:
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index 3a52c713..abc18388 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -12,6 +12,8 @@
import codecs
from os import path
+from six import iteritems
+
from sphinx import package_dir
from sphinx.util import copy_static_entry
from sphinx.locale import _
@@ -93,9 +95,9 @@ class ChangesBuilder(Builder):
'version': version,
'docstitle': self.config.html_title,
'shorttitle': self.config.html_short_title,
- 'libchanges': sorted(libchanges.iteritems()),
+ 'libchanges': sorted(iteritems(libchanges)),
'apichanges': sorted(apichanges),
- 'otherchanges': sorted(otherchanges.iteritems()),
+ 'otherchanges': sorted(iteritems(otherchanges)),
'show_copyright': self.config.html_show_copyright,
'show_sphinx': self.config.html_show_sphinx,
}
@@ -142,7 +144,7 @@ class ChangesBuilder(Builder):
finally:
f.close()
themectx = dict(('theme_' + key, val) for (key, val) in
- self.theme.get_options({}).iteritems())
+ iteritems(self.theme.get_options({})))
copy_static_entry(path.join(package_dir, 'themes', 'default',
'static', 'default.css_t'),
self.outdir, self, themectx)
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index e25e780a..f36d0202 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -10,6 +10,7 @@
"""
from __future__ import with_statement
+from __future__ import unicode_literals
from os import path, walk
from codecs import open
@@ -18,6 +19,8 @@ from datetime import datetime, tzinfo, timedelta
from collections import defaultdict
from uuid import uuid4
+from six import iteritems
+
from sphinx.builders import Builder
from sphinx.util import split_index_msg
from sphinx.util.nodes import extract_messages, traverse_translatable_index
@@ -25,7 +28,7 @@ from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog, SEP
from sphinx.util.console import darkgreen, purple, bold
from sphinx.locale import pairindextypes
-POHEADER = ur"""
+POHEADER = r"""
# SOME DESCRIPTIVE TITLE.
# Copyright (C) %(copyright)s
# This file is distributed under the same license as the %(project)s package.
@@ -186,7 +189,7 @@ class MessageCatalogBuilder(I18nBuilder):
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
)
for textdomain, catalog in self.status_iterator(
- self.catalogs.iteritems(), "writing message catalogs... ",
+ iteritems(self.catalogs), "writing message catalogs... ",
darkgreen, len(self.catalogs),
lambda textdomain__: textdomain__[0]):
# noop if config.gettext_compact is set
@@ -202,19 +205,19 @@ class MessageCatalogBuilder(I18nBuilder):
if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..."
- pofile.write(u"#: %s\n" % "\n#: ".join("%s:%s" %
+ pofile.write("#: %s\n" % "\n#: ".join("%s:%s" %
(safe_relpath(source, self.outdir), line)
for source, line, _ in positions))
if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..."
- pofile.write(u"# %s\n" % "\n# ".join(
+ pofile.write("# %s\n" % "\n# ".join(
uid for _, _, uid in positions))
# message contains *one* line of text ready for translation
- message = message.replace(u'\\', ur'\\'). \
- replace(u'"', ur'\"'). \
- replace(u'\n', u'\\n"\n"')
- pofile.write(u'msgid "%s"\nmsgstr ""\n\n' % message)
+ message = message.replace('\\', r'\\'). \
+ replace('"', r'\"'). \
+ replace('\n', '\\n"\n"')
+ pofile.write('msgid "%s"\nmsgstr ""\n\n' % message)
finally:
pofile.close()
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 035c734c..eeda6031 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -14,10 +14,11 @@ import sys
import zlib
import codecs
import posixpath
-import cPickle as pickle
from os import path
from hashlib import md5
+from six import iteritems, itervalues, text_type, string_types
+from six.moves import cPickle as pickle
from docutils import nodes
from docutils.io import DocTreeInput, StringOutput
from docutils.core import Publisher
@@ -31,7 +32,6 @@ 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 b
from sphinx.locale import _
from sphinx.search import js_index
from sphinx.theming import Theme
@@ -58,7 +58,7 @@ def get_stable_hash(obj):
return get_stable_hash(list(obj.items()))
elif isinstance(obj, (list, tuple)):
obj = sorted(get_stable_hash(o) for o in obj)
- return md5(unicode(obj).encode('utf8')).hexdigest()
+ return md5(text_type(obj).encode('utf8')).hexdigest()
class StandaloneHTMLBuilder(Builder):
@@ -163,7 +163,7 @@ class StandaloneHTMLBuilder(Builder):
def get_outdated_docs(self):
cfgdict = dict((name, self.config[name])
- for (name, desc) in self.config.values.iteritems()
+ for (name, desc) in iteritems(self.config.values)
if desc[1] == 'html')
self.config_hash = get_stable_hash(cfgdict)
self.tags_hash = get_stable_hash(sorted(self.tags))
@@ -220,7 +220,7 @@ class StandaloneHTMLBuilder(Builder):
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
- doc = new_document(b('<partial node>'))
+ doc = new_document(b'<partial node>')
doc.append(node)
if self._publisher is None:
@@ -264,7 +264,7 @@ class StandaloneHTMLBuilder(Builder):
# html_domain_indices can be False/True or a list of index names
indices_config = self.config.html_domain_indices
if indices_config:
- for domain in self.env.domains.itervalues():
+ for domain in itervalues(self.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -295,7 +295,7 @@ class StandaloneHTMLBuilder(Builder):
if favicon and os.path.splitext(favicon)[1] != '.ico':
self.warn('html_favicon is not an .ico file')
- if not isinstance(self.config.html_use_opensearch, basestring):
+ if not isinstance(self.config.html_use_opensearch, string_types):
self.warn('html_use_opensearch config value must now be a string')
self.relations = self.env.collect_relations()
@@ -345,7 +345,7 @@ class StandaloneHTMLBuilder(Builder):
if self.theme:
self.globalcontext.update(
('theme_' + key, val) for (key, val) in
- self.theme.get_options(self.theme_options).iteritems())
+ iteritems(self.theme.get_options(self.theme_options)))
self.globalcontext.update(self.config.html_context)
def get_doc_context(self, docname, body, metatags):
@@ -696,7 +696,7 @@ class StandaloneHTMLBuilder(Builder):
sidebars = None
matched = None
customsidebar = None
- for pattern, patsidebars in self.config.html_sidebars.iteritems():
+ for pattern, patsidebars in iteritems(self.config.html_sidebars):
if patmatch(pagename, pattern):
if matched:
if has_wildcard(pattern):
@@ -713,7 +713,7 @@ class StandaloneHTMLBuilder(Builder):
if sidebars is None:
# keep defaults
pass
- elif isinstance(sidebars, basestring):
+ elif isinstance(sidebars, string_types):
# 0.x compatible mode: insert custom sidebar before searchbox
customsidebar = sidebars
sidebars = None
@@ -798,7 +798,7 @@ class StandaloneHTMLBuilder(Builder):
% (self.config.project, self.config.version)
).encode('utf-8'))
compressor = zlib.compressobj(9)
- for domainname, domain in self.env.domains.iteritems():
+ for domainname, domain in iteritems(self.env.domains):
for name, dispname, type, docname, anchor, prio in \
domain.get_objects():
if anchor.endswith(name):
diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py
index f5453305..bf7991cf 100644
--- a/sphinx/builders/latex.py
+++ b/sphinx/builders/latex.py
@@ -12,6 +12,7 @@
import os
from os import path
+from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@@ -56,7 +57,7 @@ class LaTeXBuilder(Builder):
return self.get_target_uri(to, typ)
def init_document_data(self):
- preliminary_document_data = map(list, self.config.latex_documents)
+ preliminary_document_data = [list(x) for x in self.config.latex_documents]
if not preliminary_document_data:
self.warn('no "latex_documents" config value found; no documents '
'will be written')
@@ -152,7 +153,7 @@ class LaTeXBuilder(Builder):
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
- for src, dest in self.images.iteritems():
+ for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index e46c8379..4d8970ef 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -10,14 +10,15 @@
"""
import re
-import Queue
import socket
import threading
from os import path
-from urllib2 import build_opener, unquote, Request, \
- HTTPError, HTTPRedirectHandler
-from HTMLParser import HTMLParser, HTMLParseError
+from six.moves import queue
+from six.moves.urllib.request import build_opener, Request, HTTPRedirectHandler
+from six.moves.urllib.parse import unquote
+from six.moves.urllib.error import HTTPError
+from six.moves.html_parser import HTMLParser, HTMLParseError
from docutils import nodes
from sphinx.builders import Builder
@@ -88,7 +89,7 @@ class CheckExternalLinksBuilder(Builder):
name = 'linkcheck'
def init(self):
- self.to_ignore = map(re.compile, self.app.config.linkcheck_ignore)
+ self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.good = set()
self.broken = {}
self.redirected = {}
@@ -98,8 +99,8 @@ class CheckExternalLinksBuilder(Builder):
open(path.join(self.outdir, 'output.txt'), 'w').close()
# create queues and worker threads
- self.wqueue = Queue.Queue()
- self.rqueue = Queue.Queue()
+ self.wqueue = queue.Queue()
+ self.rqueue = queue.Queue()
self.workers = []
for i in range(self.app.config.linkcheck_workers):
thread = threading.Thread(target=self.check_thread)
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
index 4b360cde..dfbf8986 100644
--- a/sphinx/builders/manpage.py
+++ b/sphinx/builders/manpage.py
@@ -11,11 +11,11 @@
from os import path
+from six import string_types
from docutils.io import FileOutput
from docutils.frontend import OptionParser
from sphinx import addnodes
-from sphinx.errors import SphinxError
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
@@ -55,7 +55,7 @@ class ManualPageBuilder(Builder):
for info in self.config.man_pages:
docname, name, description, authors, section = info
- if isinstance(authors, basestring):
+ if isinstance(authors, string_types):
if authors:
authors = [authors]
else:
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index 1863fb49..c0fff2a6 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -15,6 +15,7 @@ import codecs
import posixpath
from os import path
+from six import text_type
from docutils import nodes
from sphinx import addnodes
@@ -136,7 +137,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
# they are all unicode strings before joining them
new_sections = []
for section in sections:
- if not isinstance(section, unicode):
+ if not isinstance(section, text_type):
new_sections.append(force_decode(section, None))
else:
new_sections.append(section)
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index cc38eb17..53463f3c 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -11,6 +11,7 @@
from os import path
+from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@@ -107,7 +108,7 @@ class TexinfoBuilder(Builder):
return self.get_target_uri(to, typ)
def init_document_data(self):
- preliminary_document_data = map(list, self.config.texinfo_documents)
+ preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
if not preliminary_document_data:
self.warn('no "texinfo_documents" config value found; no documents '
'will be written')
@@ -207,7 +208,7 @@ class TexinfoBuilder(Builder):
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
- for src, dest in self.images.iteritems():
+ for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py
index 07551e67..6e94ffbe 100644
--- a/sphinx/cmdline.py
+++ b/sphinx/cmdline.py
@@ -16,6 +16,7 @@ import getopt
import traceback
from os import path
+from six import text_type, binary_type
from docutils.utils import SystemMessage
from sphinx import __version__
@@ -24,7 +25,7 @@ from sphinx.application import Sphinx
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
from sphinx.util.console import red, nocolor, color_terminal
from sphinx.util.osutil import abspath, fs_encoding
-from sphinx.util.pycompat import terminal_safe, bytes
+from sphinx.util.pycompat import terminal_safe
def usage(argv, msg=None):
@@ -88,7 +89,7 @@ def main(argv):
try:
opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:nNEqQWw:PThvj:',
['help', 'version'])
- except getopt.error, err:
+ except getopt.error as err:
usage(argv, 'Error: %s' % err)
return 1
@@ -183,7 +184,7 @@ def main(argv):
print('Error: -D option argument must be in the form name=value.',
file=sys.stderr)
return 1
- if likely_encoding and isinstance(val, bytes):
+ if likely_encoding and isinstance(val, binary_type):
try:
val = val.decode(likely_encoding)
except UnicodeError:
@@ -199,7 +200,7 @@ def main(argv):
try:
val = int(val)
except ValueError:
- if likely_encoding and isinstance(val, bytes):
+ if likely_encoding and isinstance(val, binary_type):
try:
val = val.decode(likely_encoding)
except UnicodeError:
@@ -271,10 +272,10 @@ def main(argv):
print(terminal_safe(err.args[0]), file=error)
elif isinstance(err, SphinxError):
print(red('%s:' % err.category), file=error)
- print(terminal_safe(unicode(err)), file=error)
+ print(terminal_safe(text_type(err)), file=error)
elif isinstance(err, UnicodeError):
print(red('Encoding error:'), file=error)
- print(terminal_safe(unicode(err)), file=error)
+ print(terminal_safe(text_type(err)), file=error)
tbpath = save_traceback(app)
print(red('The full traceback has been saved in %s, if you want '
'to report the issue to the developers.' % tbpath),
diff --git a/sphinx/config.py b/sphinx/config.py
index 527ea453..1b67f89a 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -11,18 +11,19 @@
import os
import re
-import sys
from os import path
+from six import PY3, iteritems, string_types, binary_type, integer_types
+
from sphinx.errors import ConfigError
from sphinx.locale import l_
from sphinx.util.osutil import make_filename
-from sphinx.util.pycompat import bytes, b, execfile_
+from sphinx.util.pycompat import execfile_
-nonascii_re = re.compile(b(r'[\x80-\xff]'))
+nonascii_re = re.compile(br'[\x80-\xff]')
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
-if sys.version_info >= (3, 0):
+if PY3:
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
class Config(object):
@@ -213,7 +214,7 @@ class Config(object):
self.values = Config.config_values.copy()
config = {}
if 'extensions' in overrides:
- if isinstance(overrides['extensions'], (str, unicode)):
+ if isinstance(overrides['extensions'], string_types):
config['extensions'] = overrides.pop('extensions').split(',')
else:
config['extensions'] = overrides.pop('extensions')
@@ -242,8 +243,8 @@ class Config(object):
def check_unicode(self, warn):
# 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, bytes) and nonascii_re.search(value):
+ for name, value in iteritems(self._raw_config):
+ if isinstance(value, binary_type) 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. %r.' % (name, u'Content')
@@ -251,7 +252,7 @@ class Config(object):
def init_values(self, warn):
config = self._raw_config
- for valname, value in self.overrides.iteritems():
+ for valname, value in iteritems(self.overrides):
if '.' in valname:
realvalname, key = valname.split('.', 1)
config.setdefault(realvalname, {})[key] = value
@@ -260,7 +261,7 @@ class Config(object):
warn('unknown config value %r in override, ignoring' % valname)
continue
defvalue = self.values[valname][0]
- if isinstance(value, (str, unicode)):
+ if isinstance(value, string_types):
if isinstance(defvalue, dict):
warn('cannot override dictionary config setting %r, '
'ignoring (use %r to set individual elements)' %
@@ -268,13 +269,13 @@ class Config(object):
continue
elif isinstance(defvalue, list):
config[valname] = value.split(',')
- elif isinstance(defvalue, (int, long)):
+ elif isinstance(defvalue, integer_types):
try:
config[valname] = int(value)
except ValueError:
warn('invalid number %r for config value %r, ignoring'
% (value, valname))
- elif defvalue is not None and not isinstance(defvalue, (str, unicode)):
+ elif defvalue is not None and not isinstance(defvalue, string_types):
warn('cannot override config setting %r with unsupported type, '
'ignoring' % valname)
else:
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 250a013e..3ac22202 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -11,6 +11,7 @@
import re
+from six import itervalues
from docutils.parsers.rst import Directive, directives
from sphinx import addnodes
@@ -178,7 +179,7 @@ class DefaultDomain(Directive):
domain_name = self.arguments[0].lower()
# if domain_name not in env.domains:
# # try searching by label
- # for domain in env.domains.itervalues():
+ # for domain in itervalues(env.domains):
# if domain.label.lower() == domain_name:
# domain_name = domain.name
# break
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index d28c00fb..01c8c012 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -7,6 +7,7 @@
:license: BSD, see LICENSE for details.
"""
+from six.moves import range
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
@@ -368,7 +369,7 @@ class Only(Directive):
# be placed in the doctree.
n_sects_to_raise = current_depth - nested_depth + 1
parent = self.state.parent
- for i in xrange(n_sects_to_raise):
+ for i in range(n_sects_to_raise):
if parent.parent:
parent = parent.parent
parent.append(node)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
index 200fd515..51b886fd 100644
--- a/sphinx/domains/__init__.py
+++ b/sphinx/domains/__init__.py
@@ -10,6 +10,8 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems
+
from sphinx.errors import SphinxError
from sphinx.locale import _
@@ -153,7 +155,7 @@ class Domain(object):
self._role_cache = {}
self._directive_cache = {}
self._role2type = {}
- for name, obj in self.object_types.iteritems():
+ for name, obj in iteritems(self.object_types):
for rolename in obj.roles:
self._role2type.setdefault(rolename, []).append(name)
self.objtypes_for_role = self._role2type.get
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index d9d5ef24..0ac1b7ab 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -12,6 +12,7 @@
import re
import string
+from six import iteritems
from docutils import nodes
from sphinx import addnodes
@@ -234,7 +235,7 @@ class CDomain(Domain):
}
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
@@ -249,5 +250,5 @@ class CDomain(Domain):
contnode, target)
def get_objects(self):
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in list(self.data['objects'].items()):
yield (refname, refname, type, docname, 'c.' + refname, 1)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 71cc104a..c8505dc8 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -12,6 +12,7 @@
import re
from copy import deepcopy
+from six import iteritems, text_type
from docutils import nodes
from sphinx import addnodes
@@ -21,6 +22,7 @@ from sphinx.domains import Domain, ObjType
from sphinx.directives import ObjectDescription
from sphinx.util.nodes import make_refnode
from sphinx.util.compat import Directive
+from sphinx.util.pycompat import UnicodeMixin
from sphinx.util.docfields import Field, GroupedField
@@ -103,25 +105,22 @@ _id_shortwords = {
}
-class DefinitionError(Exception):
+class DefinitionError(UnicodeMixin, Exception):
def __init__(self, description):
self.description = description
- def __str__(self):
- return unicode(self).encode('utf-8')
-
def __unicode__(self):
return self.description
-class DefExpr(object):
+class DefExpr(UnicodeMixin):
def __eq__(self, other):
if type(self) is not type(other):
return False
try:
- for key, value in self.__dict__.iteritems():
+ for key, value in iteritems(self.__dict__):
if value != getattr(other, key):
return False
except AttributeError:
@@ -161,9 +160,6 @@ class DefExpr(object):
"""Prefix a name node (a node returned by :meth:`get_name`)."""
raise NotImplementedError()
- def __str__(self):
- return unicode(self).encode('utf-8')
-
def __unicode__(self):
raise NotImplementedError()
@@ -196,7 +192,7 @@ class NameDefExpr(PrimaryDefExpr):
return self.name.replace(u' ', u'-')
def __unicode__(self):
- return unicode(self.name)
+ return text_type(self.name)
class PathDefExpr(PrimaryDefExpr):
@@ -221,10 +217,10 @@ class PathDefExpr(PrimaryDefExpr):
return PathDefExpr([prefix] + self.path)
def __unicode__(self):
- return u'::'.join(map(unicode, self.path))
+ return u'::'.join(map(text_type, self.path))
-class ArrayTypeSuffixDefExpr(object):
+class ArrayTypeSuffixDefExpr(UnicodeMixin):
def __init__(self, size_hint=None):
self.size_hint = size_hint
@@ -234,7 +230,7 @@ class ArrayTypeSuffixDefExpr(object):
def __unicode__(self):
return u'[%s]' % (
- self.size_hint is not None and unicode(self.size_hint) or u'',
+ self.size_hint is not None and text_type(self.size_hint) or u'',
)
@@ -253,7 +249,7 @@ class TemplateDefExpr(PrimaryDefExpr):
u'.'.join(x.get_id() for x in self.args))
def __unicode__(self):
- return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
+ return u'%s<%s>' % (self.typename, u', '.join(map(text_type, self.args)))
class ConstantTemplateArgExpr(PrimaryDefExpr):
@@ -265,7 +261,7 @@ class ConstantTemplateArgExpr(PrimaryDefExpr):
return self.arg.replace(u' ', u'-')
def __unicode__(self):
- return unicode(self.arg)
+ return text_type(self.arg)
class WrappingDefExpr(DefExpr):
@@ -284,13 +280,13 @@ class ModifierDefExpr(WrappingDefExpr):
self.modifiers = modifiers
def get_id(self):
- pieces = [_id_shortwords.get(unicode(x), unicode(x))
+ pieces = [_id_shortwords.get(text_type(x), text_type(x))
for x in self.modifiers]
pieces.append(self.typename.get_id())
return u'-'.join(pieces)
def __unicode__(self):
- return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
+ return u' '.join(map(text_type, list(self.modifiers) + [self.typename]))
class PtrDefExpr(WrappingDefExpr):
@@ -373,7 +369,7 @@ class ArgumentDefExpr(DefExpr):
if self.default is not None:
buf.append('=%s' % self.default)
for suffix in self.type_suffixes:
- buf.append(unicode(suffix))
+ buf.append(text_type(suffix))
return u''.join(buf)
@@ -415,12 +411,12 @@ class TypeObjDefExpr(NamedDefExpr):
def __unicode__(self):
buf = self.get_modifiers()
if self.typename is None:
- buf.append(unicode(self.name))
+ buf.append(text_type(self.name))
else:
- buf.extend(map(unicode, (self.typename, self.name)))
+ buf.extend(map(text_type, (self.typename, self.name)))
buf = [u' '.join(buf)]
for suffix in self.type_suffixes:
- buf.append(unicode(suffix))
+ buf.append(text_type(suffix))
return u''.join(buf)
@@ -441,10 +437,10 @@ class MemberObjDefExpr(NamedDefExpr):
def __unicode__(self):
buf = self.get_modifiers()
- buf.extend((unicode(self.typename), unicode(self.name)))
+ buf.extend((text_type(self.typename), text_type(self.name)))
buf = [u' '.join(buf)]
for suffix in self.type_suffixes:
- buf.append(unicode(suffix))
+ buf.append(text_type(suffix))
if self.value is not None:
buf.append(u' = %s' % self.value)
return u''.join(buf)
@@ -485,9 +481,9 @@ class FuncDefExpr(NamedDefExpr):
if self.constexpr:
buf.append(u'constexpr')
if self.rv is not None:
- buf.append(unicode(self.rv))
+ buf.append(text_type(self.rv))
buf.append(u'%s(%s)' % (self.name, u', '.join(
- map(unicode, self.signature))))
+ map(text_type, self.signature))))
if self.const:
buf.append(u'const')
if self.volatile:
@@ -520,7 +516,7 @@ class ClassDefExpr(NamedDefExpr):
def _tostring(self, visibility='public'):
buf = self.get_modifiers(visibility)
- buf.append(unicode(self.name))
+ buf.append(text_type(self.name))
if self.bases:
buf.append(u':')
buf.append(u', '.join(base._tostring('private')
@@ -1001,19 +997,19 @@ class CPPObject(ObjectDescription):
def attach_name(self, node, name):
owner, name = name.split_owner()
- varname = unicode(name)
+ varname = text_type(name)
if owner is not None:
- owner = unicode(owner) + '::'
+ owner = text_type(owner) + '::'
node += addnodes.desc_addname(owner, owner)
node += addnodes.desc_name(varname, varname)
def attach_type_suffixes(self, node, suffixes):
for suffix in suffixes:
- node += nodes.Text(unicode(suffix))
+ node += nodes.Text(text_type(suffix))
def attach_type(self, node, type):
# XXX: link to c?
- text = unicode(type)
+ text = text_type(type)
pnode = addnodes.pending_xref(
'', refdomain='cpp', reftype='type',
reftarget=text, modname=None, classname=None)
@@ -1035,7 +1031,7 @@ class CPPObject(ObjectDescription):
def add_target_and_index(self, sigobj, sig, signode):
theid = sigobj.get_id()
- name = unicode(sigobj.name)
+ name = text_type(sigobj.name)
if theid not in self.state.document.ids:
signode['names'].append(theid)
signode['ids'].append(theid)
@@ -1101,8 +1097,8 @@ class CPPClassObject(CPPObject):
signode += nodes.Text(' : ')
for base in cls.bases:
self.attach_modifiers(signode, base, 'private')
- signode += nodes.emphasis(unicode(base.name),
- unicode(base.name))
+ signode += nodes.emphasis(text_type(base.name),
+ text_type(base.name))
signode += nodes.Text(', ')
signode.pop() # remove the trailing comma
@@ -1152,7 +1148,7 @@ class CPPFunctionObject(CPPObject):
def attach_function(self, node, func):
owner, name = func.name.split_owner()
if owner is not None:
- owner = unicode(owner) + '::'
+ owner = text_type(owner) + '::'
node += addnodes.desc_addname(owner, owner)
# cast operator is special. in this case the return value
@@ -1162,7 +1158,7 @@ class CPPFunctionObject(CPPObject):
node += nodes.Text(u' ')
self.attach_type(node, name.typename)
else:
- funcname = unicode(name)
+ funcname = text_type(name)
node += addnodes.desc_name(funcname, funcname)
paramlist = addnodes.desc_parameterlist()
@@ -1171,10 +1167,10 @@ class CPPFunctionObject(CPPObject):
if arg.type is not None:
self.attach_type(param, arg.type)
param += nodes.Text(u' ')
- param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
+ param += nodes.emphasis(text_type(arg.name), text_type(arg.name))
self.attach_type_suffixes(param, arg.type_suffixes)
if arg.default is not None:
- def_ = u'=' + unicode(arg.default)
+ def_ = u'=' + text_type(arg.default)
param += nodes.emphasis(def_, def_)
paramlist += param
@@ -1280,14 +1276,14 @@ class CPPDomain(Domain):
}
def clear_doc(self, docname):
- for fullname, (fn, _, _) in self.data['objects'].items():
+ for fullname, (fn, _, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
def _create_refnode(expr):
- name = unicode(expr)
+ name = text_type(expr)
if name not in self.data['objects']:
return None
obj = self.data['objects'][name]
@@ -1321,5 +1317,5 @@ class CPPDomain(Domain):
return _create_refnode(expr.prefix(parent))
def get_objects(self):
- for refname, (docname, type, theid) in self.data['objects'].iteritems():
+ for refname, (docname, type, theid) in iteritems(self.data['objects']):
yield (refname, refname, type, docname, refname, 1)
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index 9b7777f4..8cc49b09 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems
+
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.locale import l_, _
@@ -183,7 +185,7 @@ class JavaScriptDomain(Domain):
}
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
@@ -215,6 +217,6 @@ class JavaScriptDomain(Domain):
name.replace('$', '_S_'), contnode, name)
def get_objects(self):
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in list(self.data['objects'].items()):
yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 9e083a12..1780b4a1 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -11,6 +11,7 @@
import re
+from six import iteritems
from docutils import nodes
from docutils.parsers.rst import directives
@@ -514,7 +515,7 @@ class PythonModuleIndex(Index):
ignores = self.domain.env.config['modindex_common_prefix']
ignores = sorted(ignores, key=len, reverse=True)
# list of all modules, sorted by module name
- modules = sorted(self.domain.data['modules'].iteritems(),
+ modules = sorted(iteritems(self.domain.data['modules']),
key=lambda x: x[0].lower())
# sort out collapsable modules
prev_modname = ''
@@ -564,7 +565,7 @@ class PythonModuleIndex(Index):
collapse = len(modules) - num_toplevels < num_toplevels
# sort by first letter
- content = sorted(content.iteritems())
+ content = sorted(iteritems(content))
return content, collapse
@@ -619,10 +620,10 @@ class PythonDomain(Domain):
]
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
- for modname, (fn, _, _, _) in self.data['modules'].items():
+ for modname, (fn, _, _, _) in list(self.data['modules'].items()):
if fn == docname:
del self.data['modules'][modname]
@@ -720,8 +721,8 @@ class PythonDomain(Domain):
contnode, name)
def get_objects(self):
- for modname, info in self.data['modules'].iteritems():
+ for modname, info in iteritems(self.data['modules']):
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in iteritems(self.data['objects']):
if type != 'module': # modules are already handled
yield (refname, refname, type, docname, refname, 1)
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
index c51c85fe..e213211a 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -11,6 +11,8 @@
import re
+from six import iteritems
+
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.locale import l_, _
@@ -117,7 +119,7 @@ class ReSTDomain(Domain):
}
def clear_doc(self, docname):
- for (typ, name), doc in self.data['objects'].items():
+ for (typ, name), doc in list(self.data['objects'].items()):
if doc == docname:
del self.data['objects'][typ, name]
@@ -133,5 +135,5 @@ class ReSTDomain(Domain):
contnode, target + ' ' + objtype)
def get_objects(self):
- for (typ, name), docname in self.data['objects'].iteritems():
+ for (typ, name), docname in iteritems(self.data['objects']):
yield name, name, typ, docname, typ + '-' + name, 1
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 07b39417..f4e22b4b 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -12,6 +12,7 @@
import re
import unicodedata
+from six import iteritems
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@@ -508,22 +509,22 @@ class StandardDomain(Domain):
}
def clear_doc(self, docname):
- for key, (fn, _) in self.data['progoptions'].items():
+ for key, (fn, _) in list(self.data['progoptions'].items()):
if fn == docname:
del self.data['progoptions'][key]
- for key, (fn, _) in self.data['objects'].items():
+ for key, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][key]
- for key, (fn, _, _) in self.data['labels'].items():
+ for key, (fn, _, _) in list(self.data['labels'].items()):
if fn == docname:
del self.data['labels'][key]
- for key, (fn, _) in self.data['anonlabels'].items():
+ for key, (fn, _) in list(self.data['anonlabels'].items()):
if fn == docname:
del self.data['anonlabels'][key]
def process_doc(self, env, docname, document):
labels, anonlabels = self.data['labels'], self.data['anonlabels']
- for name, explicit in document.nametypes.iteritems():
+ for name, explicit in iteritems(document.nametypes):
if not explicit:
continue
labelid = document.nameids[name]
@@ -621,16 +622,16 @@ class StandardDomain(Domain):
labelid, contnode)
def get_objects(self):
- for (prog, option), info in self.data['progoptions'].iteritems():
+ for (prog, option), info in iteritems(self.data['progoptions']):
yield (option, option, 'option', info[0], info[1], 1)
- for (type, name), info in self.data['objects'].iteritems():
+ for (type, name), info in iteritems(self.data['objects']):
yield (name, name, type, info[0], info[1],
self.object_types[type].attrs['searchprio'])
- for name, info in self.data['labels'].iteritems():
+ for name, info in iteritems(self.data['labels']):
yield (name, info[2], 'label', info[0], info[1], -1)
# add anonymous-only labels as well
non_anon_labels = set(self.data['labels'])
- for name, info in self.data['anonlabels'].iteritems():
+ for name, info in iteritems(self.data['anonlabels']):
if name not in non_anon_labels:
yield (name, name, 'label', info[0], info[1], -1)
diff --git a/sphinx/environment.py b/sphinx/environment.py
index a0fb87da..ec65e5d2 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -18,11 +18,12 @@ import codecs
import imghdr
import string
import unicodedata
-import cPickle as pickle
from os import path
from glob import glob
-from itertools import izip, groupby
+from itertools import groupby
+from six import iteritems, itervalues, text_type, class_types
+from six.moves import cPickle as pickle, zip
from docutils import nodes
from docutils.io import FileInput, NullOutput
from docutils.core import Publisher
@@ -39,7 +40,6 @@ from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
from sphinx.util.nodes import clean_astext, make_refnode, WarningStream
from sphinx.util.osutil import SEP, fs_encoding, find_catalog_files
from sphinx.util.matching import compile_matchers
-from sphinx.util.pycompat import class_types
from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _
@@ -136,7 +136,7 @@ class BuildEnvironment:
del self.domains
picklefile = open(filename, 'wb')
# remove potentially pickling-problematic values from config
- for key, val in vars(self.config).items():
+ for key, val in list(vars(self.config).items()):
if key.startswith('_') or \
isinstance(val, types.ModuleType) or \
isinstance(val, types.FunctionType) or \
@@ -278,11 +278,11 @@ class BuildEnvironment:
self.images.purge_doc(docname)
self.dlfiles.purge_doc(docname)
- for subfn, fnset in self.files_to_rebuild.items():
+ for subfn, fnset in list(self.files_to_rebuild.items()):
fnset.discard(docname)
if not fnset:
del self.files_to_rebuild[subfn]
- for key, (fn, _) in self.citations.items():
+ for key, (fn, _) in list(self.citations.items()):
if fn == docname:
del self.citations[key]
for version, changes in self.versionchanges.items():
@@ -421,7 +421,7 @@ class BuildEnvironment:
else:
# check if a config value was changed that affects how
# doctrees are read
- for key, descr in config.values.iteritems():
+ for key, descr in iteritems(config.values):
if descr[1] != 'env':
continue
if self.config[key] != config[key]:
@@ -593,7 +593,7 @@ class BuildEnvironment:
FileInput.__init__(self_, *args, **kwds)
def decode(self_, data):
- if isinstance(data, unicode):
+ if isinstance(data, text_type):
return data
return data.decode(self_.encoding, 'sphinx')
@@ -632,7 +632,7 @@ class BuildEnvironment:
self.note_indexentries_from(docname, doctree)
self.note_citations_from(docname, doctree)
self.build_toc_from(docname, doctree)
- for domain in self.domains.itervalues():
+ for domain in itervalues(self.domains):
domain.process_doc(self, docname, doctree)
# allow extension-specific post-processing
@@ -818,7 +818,7 @@ class BuildEnvironment:
candidates['*'] = rel_imgpath
# map image paths to unique image names (so that they can be put
# into a single directory)
- for imgpath in candidates.itervalues():
+ for imgpath in itervalues(candidates):
self.dependencies.setdefault(docname, set()).add(imgpath)
if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
self.warn_node('image file not readable: %s' % imgpath,
@@ -1508,7 +1508,7 @@ class BuildEnvironment:
# Force the word to be unicode if it's a ASCII bytestring.
# This will solve problems with unicode normalization later.
# For instance the RFC role will add bytestrings at the moment
- word = unicode(word)
+ word = text_type(word)
entry = dic.get(word)
if not entry:
dic[word] = entry = [[], {}]
@@ -1522,7 +1522,7 @@ class BuildEnvironment:
else:
entry[0].append((main, uri))
- for fn, entries in self.indexentries.iteritems():
+ for fn, entries in iteritems(self.indexentries):
# new entry types must be listed in directives/other.py!
for type, value, tid, main in entries:
try:
@@ -1560,8 +1560,7 @@ class BuildEnvironment:
if lckey[0:1] in lcletters:
return chr(127) + lckey
return lckey
- newlist = new.items()
- newlist.sort(key=keyfunc)
+ newlist = sorted(new.items(), key=keyfunc)
if group_entries:
# fixup entries: transform
@@ -1597,7 +1596,7 @@ class BuildEnvironment:
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())
+ v[1] = sorted((si, se) for (si, (se, void)) in iteritems(v[1]))
# now calculate the key
letter = unicodedata.normalize('NFD', k[0])[0].upper()
if letter in letters:
@@ -1649,7 +1648,7 @@ class BuildEnvironment:
# else it will stay None
# same for children
if includes:
- for subindex, args in enumerate(izip(includes,
+ for subindex, args in enumerate(zip(includes,
[None] + includes,
includes[1:] + [None])):
collect([(docname, subindex)] + parents,
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index a79849ae..ab081097 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -17,6 +17,7 @@ import inspect
import traceback
from types import FunctionType, BuiltinFunctionType, MethodType
+from six import PY3, iteritems, itervalues, text_type, class_types
from docutils import nodes
from docutils.utils import assemble_option_dict
from docutils.statemachine import ViewList
@@ -29,7 +30,6 @@ from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util.compat import Directive
from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \
safe_getattr, safe_repr, is_builtin_class_method
-from sphinx.util.pycompat import class_types
from sphinx.util.docstrings import prepare_docstring
@@ -54,9 +54,10 @@ class DefDict(dict):
return dict.__getitem__(self, key)
except KeyError:
return self.default
- def __nonzero__(self):
+ def __bool__(self):
# docutils check "if option_spec"
return True
+ __nonzero__ = __bool__ # for python2 compatibility
identity = lambda x: x
@@ -264,7 +265,7 @@ class Documenter(object):
@staticmethod
def get_attr(obj, name, *defargs):
"""getattr() override for types such as Zope interfaces."""
- for typ, func in AutoDirective._special_attrgetters.iteritems():
+ for typ, func in iteritems(AutoDirective._special_attrgetters):
if isinstance(obj, typ):
return func(obj, name, *defargs)
return safe_getattr(obj, name, *defargs)
@@ -480,7 +481,7 @@ class Documenter(object):
docstring = self.get_attr(self.object, '__doc__', None)
# make sure we have Unicode docstrings, then sanitize and split
# into lines
- if isinstance(docstring, unicode):
+ if isinstance(docstring, text_type):
return [prepare_docstring(docstring, ignore)]
elif isinstance(docstring, str): # this will not trigger on Py3
return [prepare_docstring(force_decode(docstring, encoding),
@@ -504,9 +505,9 @@ class Documenter(object):
# set sourcename and add content from attribute documentation
if self.analyzer:
# prevent encoding errors when the file name is non-ASCII
- if not isinstance(self.analyzer.srcname, unicode):
- filename = unicode(self.analyzer.srcname,
- sys.getfilesystemencoding(), 'replace')
+ if not isinstance(self.analyzer.srcname, text_type):
+ filename = text_type(self.analyzer.srcname,
+ sys.getfilesystemencoding(), 'replace')
else:
filename = self.analyzer.srcname
sourcename = u'%s:docstring of %s' % (filename, self.fullname)
@@ -550,7 +551,7 @@ class Documenter(object):
if self.analyzer:
attr_docs = self.analyzer.find_attr_docs()
namespace = '.'.join(self.objpath)
- for item in attr_docs.iteritems():
+ for item in iteritems(attr_docs):
if item[0][0] == namespace:
analyzed_member_names.add(item[0][1])
if not want_all:
@@ -691,7 +692,7 @@ class Documenter(object):
# document non-skipped members
memberdocumenters = []
for (mname, member, isattr) in self.filter_members(members, want_all):
- classes = [cls for cls in AutoDirective._registry.itervalues()
+ classes = [cls for cls in itervalues(AutoDirective._registry)
if cls.can_document_member(member, mname, isattr, self)]
if not classes:
# don't know how to document this member
@@ -1128,7 +1129,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
docstrings.append(initdocstring)
doc = []
for docstring in docstrings:
- if not isinstance(docstring, unicode):
+ if not isinstance(docstring, text_type):
docstring = force_decode(docstring, encoding)
doc.append(prepare_docstring(docstring))
return doc
@@ -1212,7 +1213,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
return inspect.isroutine(member) and \
not isinstance(parent, ModuleDocumenter)
- if sys.version_info >= (3, 0):
+ if PY3:
def import_object(self):
ret = ClassLevelDocumenter.import_object(self)
obj_from_parent = self.parent.__dict__.get(self.object_name)
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index 5bee387e..8ba76a58 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -59,6 +59,7 @@ import sys
import inspect
import posixpath
+from six import text_type
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from docutils import nodes
@@ -116,7 +117,7 @@ def autosummary_table_visit_html(self, node):
par = col1_entry[0]
for j, subnode in enumerate(list(par)):
if isinstance(subnode, nodes.Text):
- new_text = unicode(subnode.astext())
+ new_text = text_type(subnode.astext())
new_text = new_text.replace(u" ", u"\u00a0")
par[j] = nodes.Text(new_text)
except IndexError:
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 5daf95f5..7b7c0707 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -110,14 +110,11 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
# read
items = find_autosummary_in_files(sources)
- # remove possible duplicates
- items = dict([(item, True) for item in items]).keys()
-
# keep track of new files
new_files = []
# write
- for name, path, template_name in sorted(items, key=str):
+ for name, path, template_name in sorted(set(items), key=str):
if path is None:
# The corresponding autosummary:: directive did not have
# a :toctree: option
diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py
index f1ac6cec..3d2da66d 100644
--- a/sphinx/ext/coverage.py
+++ b/sphinx/ext/coverage.py
@@ -13,9 +13,11 @@
import re
import glob
import inspect
-import cPickle as pickle
from os import path
+from six import iteritems
+from six.moves import cPickle as pickle
+
from sphinx.builders import Builder
@@ -52,7 +54,7 @@ class CoverageBuilder(Builder):
self.warn('invalid regex %r in coverage_c_regexes' % exp)
self.c_ignorexps = {}
- for (name, exps) in self.config.coverage_ignore_c_items.iteritems():
+ for (name, exps) in iteritems(self.config.coverage_ignore_c_items):
self.c_ignorexps[name] = compile_regex_list(
'coverage_ignore_c_items', exps, self.warn)
self.mod_ignorexps = compile_regex_list(
@@ -109,7 +111,7 @@ class CoverageBuilder(Builder):
write_header(op, 'Undocumented C API elements', '=')
op.write('\n')
- for filename, undoc in self.c_undoc.iteritems():
+ for filename, undoc in iteritems(self.c_undoc):
write_header(op, filename)
for typ, name in undoc:
op.write(' * %-50s [%9s]\n' % (name, typ))
@@ -211,8 +213,7 @@ class CoverageBuilder(Builder):
try:
if self.config.coverage_write_headline:
write_header(op, 'Undocumented Python objects', '=')
- keys = self.py_undoc.keys()
- keys.sort()
+ keys = sorted(self.py_undoc.keys())
for name in keys:
undoc = self.py_undoc[name]
if 'error' in undoc:
@@ -229,7 +230,7 @@ class CoverageBuilder(Builder):
if undoc['classes']:
op.write('Classes:\n')
for name, methods in sorted(
- undoc['classes'].iteritems()):
+ iteritems(undoc['classes'])):
if not methods:
op.write(' * %s\n' % name)
else:
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
index ef27dc11..b7e247ec 100644
--- a/sphinx/ext/doctest.py
+++ b/sphinx/ext/doctest.py
@@ -14,11 +14,11 @@ import re
import sys
import time
import codecs
-import StringIO
from os import path
# circumvent relative import
doctest = __import__('doctest')
+from six import itervalues, StringIO, binary_type
from docutils import nodes
from docutils.parsers.rst import directives
@@ -27,7 +27,6 @@ from sphinx.util import force_decode
from sphinx.util.nodes import set_source_info
from sphinx.util.compat import Directive
from sphinx.util.console import bold
-from sphinx.util.pycompat import bytes
blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
@@ -158,7 +157,7 @@ class TestCode(object):
class SphinxDocTestRunner(doctest.DocTestRunner):
def summarize(self, out, verbose=None):
- string_io = StringIO.StringIO()
+ string_io = StringIO()
old_stdout = sys.stdout
sys.stdout = string_io
try:
@@ -233,7 +232,7 @@ Results of doctest builder run on %s
self.info(text, nonl=True)
if self.app.quiet:
self.warn(text)
- if isinstance(text, bytes):
+ if isinstance(text, binary_type):
text = force_decode(text, None)
self.outfile.write(text)
@@ -312,24 +311,24 @@ Doctest summary
groups[groupname] = TestGroup(groupname)
groups[groupname].add_code(code)
for code in add_to_all_groups:
- for group in groups.itervalues():
+ for group in itervalues(groups):
group.add_code(code)
if self.config.doctest_global_setup:
code = TestCode(self.config.doctest_global_setup,
'testsetup', lineno=0)
- for group in groups.itervalues():
+ for group in itervalues(groups):
group.add_code(code, prepend=True)
if self.config.doctest_global_cleanup:
code = TestCode(self.config.doctest_global_cleanup,
'testcleanup', lineno=0)
- for group in groups.itervalues():
+ for group in itervalues(groups):
group.add_code(code)
if not groups:
return
self._out('\nDocument: %s\n----------%s\n' %
(docname, '-'*len(docname)))
- for group in groups.itervalues():
+ for group in itervalues(groups):
self.test_group(group, self.env.doc2path(docname, base=None))
# Separately count results from setup code
res_f, res_t = self.setup_runner.summarize(self._out, verbose=False)
diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py
index 18da573e..2a54761a 100644
--- a/sphinx/ext/extlinks.py
+++ b/sphinx/ext/extlinks.py
@@ -24,6 +24,7 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems
from docutils import nodes, utils
from sphinx.util.nodes import split_explicit_title
@@ -51,7 +52,7 @@ def make_link_role(base_url, prefix):
return role
def setup_link_roles(app):
- for name, (base_url, prefix) in app.config.extlinks.iteritems():
+ for name, (base_url, prefix) in iteritems(app.config.extlinks):
app.add_role(name, make_link_role(base_url, prefix))
def setup(app):
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index abfb6ac6..3fbded34 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -20,6 +20,7 @@ try:
except ImportError:
from sha import sha
+from six import text_type
from docutils import nodes
from docutils.parsers.rst import directives
@@ -145,7 +146,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
ensuredir(path.dirname(outfn))
# graphviz expects UTF-8 by default
- if isinstance(code, unicode):
+ if isinstance(code, text_type):
code = code.encode('utf-8')
dot_args = [self.builder.config.graphviz_dot]
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index e2c44b58..6dcd3ea1 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -27,27 +27,27 @@
import time
import zlib
import codecs
-import urllib2
import posixpath
from os import path
import re
+from six import iteritems
+from six.moves.urllib import request
from docutils import nodes
from docutils.utils import relative_path
from sphinx.locale import _
from sphinx.builders.html import INVENTORY_FILENAME
-from sphinx.util.pycompat import b
-handlers = [urllib2.ProxyHandler(), urllib2.HTTPRedirectHandler(),
- urllib2.HTTPHandler()]
+handlers = [request.ProxyHandler(), request.HTTPRedirectHandler(),
+ request.HTTPHandler()]
try:
- handlers.append(urllib2.HTTPSHandler)
+ handlers.append(request.HTTPSHandler)
except AttributeError:
pass
-urllib2.install_opener(urllib2.build_opener(*handlers))
+request.install_opener(request.build_opener(*handlers))
UTF8StreamReader = codecs.lookup('utf-8')[2]
@@ -55,9 +55,9 @@ UTF8StreamReader = codecs.lookup('utf-8')[2]
def read_inventory_v1(f, uri, join):
f = UTF8StreamReader(f)
invdata = {}
- line = f.next()
+ line = next(f)
projname = line.rstrip()[11:]
- line = f.next()
+ line = next(f)
version = line.rstrip()[11:]
for line in f:
name, type, location = line.rstrip().split(None, 2)
@@ -85,19 +85,19 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
def read_chunks():
decompressor = zlib.decompressobj()
- for chunk in iter(lambda: f.read(bufsize), b('')):
+ for chunk in iter(lambda: f.read(bufsize), b''):
yield decompressor.decompress(chunk)
yield decompressor.flush()
def split_lines(iter):
- buf = b('')
+ buf = b''
for chunk in iter:
buf += chunk
- lineend = buf.find(b('\n'))
+ lineend = buf.find(b'\n')
while lineend != -1:
yield buf[:lineend].decode('utf-8')
buf = buf[lineend+1:]
- lineend = buf.find(b('\n'))
+ lineend = buf.find(b'\n')
assert not buf
for line in split_lines(read_chunks()):
@@ -129,7 +129,7 @@ def fetch_inventory(app, uri, inv):
join = localuri and path.join or posixpath.join
try:
if inv.find('://') != -1:
- f = urllib2.urlopen(inv)
+ f = request.urlopen(inv)
else:
f = open(path.join(app.srcdir, inv), 'rb')
except Exception as err:
@@ -167,7 +167,7 @@ def load_mappings(app):
env.intersphinx_named_inventory = {}
cache = env.intersphinx_cache
update = False
- for key, value in app.config.intersphinx_mapping.iteritems():
+ for key, value in iteritems(app.config.intersphinx_mapping):
if isinstance(value, tuple):
# new format
name, (uri, inv) = key, value
@@ -202,13 +202,13 @@ def load_mappings(app):
# add the unnamed inventories last. This means that the
# unnamed inventories will shadow the named ones but the named
# ones can still be accessed when the name is specified.
- cached_vals = list(cache.itervalues())
+ cached_vals = list(cache.values())
named_vals = sorted(v for v in cached_vals if v[0])
unnamed_vals = [v for v in cached_vals if not v[0]]
for name, _, invdata in named_vals + unnamed_vals:
if name:
env.intersphinx_named_inventory[name] = invdata
- for type, objects in invdata.iteritems():
+ for type, objects in iteritems(invdata):
env.intersphinx_inventory.setdefault(
type, {}).update(objects)
diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py
index 96ca81a5..b67ea79c 100644
--- a/sphinx/ext/napoleon/__init__.py
+++ b/sphinx/ext/napoleon/__init__.py
@@ -10,6 +10,9 @@
"""
import sys
+
+from six import PY2, iteritems
+
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
@@ -214,9 +217,9 @@ class Config(object):
}
def __init__(self, **settings):
- for name, (default, rebuild) in self._config_values.iteritems():
+ for name, (default, rebuild) in iteritems(self._config_values):
setattr(self, name, default)
- for name, value in settings.iteritems():
+ for name, value in iteritems(settings):
setattr(self, name, value)
@@ -249,7 +252,7 @@ def setup(app):
app.connect('autodoc-process-docstring', _process_docstring)
app.connect('autodoc-skip-member', _skip_member)
- for name, (default, rebuild) in Config._config_values.iteritems():
+ for name, (default, rebuild) in iteritems(Config._config_values):
app.add_config_value(name, default, rebuild)
@@ -346,12 +349,12 @@ def _skip_member(app, what, name, obj, skip, options):
if name != '__weakref__' and name != '__init__' and has_doc and is_member:
cls_is_owner = False
if what == 'class' or what == 'exception':
- if sys.version_info[0] < 3:
+ if PY2:
cls = getattr(obj, 'im_class', getattr(obj, '__objclass__',
None))
cls_is_owner = (cls and hasattr(cls, name) and
name in cls.__dict__)
- elif sys.version_info[1] >= 3:
+ elif sys.version_info >= (3, 3):
qualname = getattr(obj, '__qualname__', '')
cls_path, _, _ = qualname.rpartition('.')
if cls_path:
diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
index 2819ffe3..1a8d88c6 100644
--- a/sphinx/ext/napoleon/docstring.py
+++ b/sphinx/ext/napoleon/docstring.py
@@ -14,13 +14,12 @@
import collections
import inspect
import re
-import sys
-from sphinx.ext.napoleon.iterators import modify_iter
+from six import string_types
+from six.moves import range
-if sys.version_info[0] >= 3:
- basestring = str
- xrange = range
+from sphinx.ext.napoleon.iterators import modify_iter
+from sphinx.util.pycompat import UnicodeMixin
_directive_regex = re.compile(r'\.\. \S+::')
@@ -28,7 +27,7 @@ _google_untyped_arg_regex = re.compile(r'\s*(\w+)\s*:\s*(.*)')
_google_typed_arg_regex = re.compile(r'\s*(\w+)\s*\(\s*(.+?)\s*\)\s*:\s*(.*)')
-class GoogleDocstring(object):
+class GoogleDocstring(UnicodeMixin):
"""Parse Google style docstrings.
Convert Google style docstrings to reStructuredText.
@@ -116,7 +115,7 @@ class GoogleDocstring(object):
self._name = name
self._obj = obj
self._opt = options
- if isinstance(docstring, basestring):
+ if isinstance(docstring, string_types):
docstring = docstring.splitlines()
self._lines = docstring
self._line_iter = modify_iter(docstring, modifier=lambda s: s.rstrip())
@@ -151,20 +150,6 @@ class GoogleDocstring(object):
}
self._parse()
- def __str__(self):
- """Return the parsed docstring in reStructuredText format.
-
- Returns
- -------
- str
- UTF-8 encoded version of the docstring.
-
- """
- if sys.version_info[0] >= 3:
- return self.__unicode__()
- else:
- return self.__unicode__().encode('utf8')
-
def __unicode__(self):
"""Return the parsed docstring in reStructuredText format.
@@ -192,7 +177,7 @@ class GoogleDocstring(object):
line = self._line_iter.peek()
while(not self._is_section_break()
and (not line or self._is_indented(line, indent))):
- lines.append(self._line_iter.next())
+ lines.append(next(self._line_iter))
line = self._line_iter.peek()
return lines
@@ -201,19 +186,19 @@ class GoogleDocstring(object):
while (self._line_iter.has_next()
and self._line_iter.peek()
and not self._is_section_header()):
- lines.append(self._line_iter.next())
+ lines.append(next(self._line_iter))
return lines
def _consume_empty(self):
lines = []
line = self._line_iter.peek()
while self._line_iter.has_next() and not line:
- lines.append(self._line_iter.next())
+ lines.append(next(self._line_iter))
line = self._line_iter.peek()
return lines
def _consume_field(self, parse_type=True, prefer_type=False):
- line = self._line_iter.next()
+ line = next(self._line_iter)
match = None
_name, _type, _desc = line.strip(), '', ''
@@ -270,7 +255,7 @@ class GoogleDocstring(object):
return []
def _consume_section_header(self):
- section = self._line_iter.next()
+ section = next(self._line_iter)
stripped_section = section.strip(':')
if stripped_section.lower() in self._sections:
section = stripped_section
@@ -280,7 +265,7 @@ class GoogleDocstring(object):
self._consume_empty()
lines = []
while not self._is_section_break():
- lines.append(self._line_iter.next())
+ lines.append(next(self._line_iter))
return lines + self._consume_empty()
def _dedent(self, lines, full=False):
@@ -597,7 +582,7 @@ class GoogleDocstring(object):
if start == -1:
lines = []
end = -1
- for i in reversed(xrange(len(lines))):
+ for i in reversed(range(len(lines))):
line = lines[i]
if line:
end = i
@@ -710,7 +695,7 @@ class NumpyDocstring(GoogleDocstring):
name, obj, options)
def _consume_field(self, parse_type=True, prefer_type=False):
- line = self._line_iter.next()
+ line = next(self._line_iter)
if parse_type:
_name, _, _type = line.partition(':')
else:
@@ -727,10 +712,10 @@ class NumpyDocstring(GoogleDocstring):
return self._consume_fields(prefer_type=True)
def _consume_section_header(self):
- section = self._line_iter.next()
+ section = next(self._line_iter)
if not _directive_regex.match(section):
# Consume the header underline
- self._line_iter.next()
+ next(self._line_iter)
return section
def _is_section_break(self):
@@ -745,7 +730,7 @@ class NumpyDocstring(GoogleDocstring):
def _is_section_header(self):
section, underline = self._line_iter.peek(2)
section = section.lower()
- if section in self._sections and isinstance(underline, basestring):
+ if section in self._sections and isinstance(underline, string_types):
pattern = r'[=\-`:\'"~^_*+#<>]{' + str(len(section)) + r'}$'
return bool(re.match(pattern, underline))
elif self._directive_sections:
diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py
index 2f1904da..90a0a1ac 100644
--- a/sphinx/ext/napoleon/iterators.py
+++ b/sphinx/ext/napoleon/iterators.py
@@ -12,10 +12,11 @@
"""
import collections
-import sys
+from six import PY3
-if sys.version_info[0] >= 3:
+
+if PY3:
callable = lambda o: hasattr(o, '__call__')
@@ -75,7 +76,7 @@ class peek_iter(object):
n = 1
try:
while len(self._cache) < n:
- self._cache.append(self._iterable.next())
+ self._cache.append(next(self._iterable))
except StopIteration:
while len(self._cache) < n:
self._cache.append(self.sentinel)
@@ -238,7 +239,7 @@ class modify_iter(peek_iter):
n = 1
try:
while len(self._cache) < n:
- self._cache.append(self.modifier(self._iterable.next()))
+ self._cache.append(self.modifier(next(self._iterable)))
except StopIteration:
while len(self._cache) < n:
self._cache.append(self.sentinel)
diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py
index 6bfe644c..e0fed6e0 100644
--- a/sphinx/ext/pngmath.py
+++ b/sphinx/ext/pngmath.py
@@ -21,12 +21,13 @@ try:
except ImportError:
from sha import sha
+from six import text_type
from docutils import nodes
from sphinx.errors import SphinxError
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT
-from sphinx.util.pycompat import b, sys_encoding
+from sphinx.util.pycompat import sys_encoding
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
class MathExtError(SphinxError):
@@ -66,7 +67,7 @@ DOC_BODY_PREVIEW = r'''
\end{document}
'''
-depth_re = re.compile(b(r'\[\d+ depth=(-?\d+)\]'))
+depth_re = re.compile(br'\[\d+ depth=(-?\d+)\]')
def render_math(self, math):
"""Render the LaTeX math expression *math* using latex and dvipng.
@@ -191,7 +192,7 @@ def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
except MathExtError as exc:
- msg = unicode(exc)
+ msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 74a00463..4a62bf6d 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems, text_type
from docutils import nodes
from sphinx import addnodes
@@ -29,7 +30,7 @@ def doctree_read(app, doctree):
except Exception:
env._viewcode_modules[modname] = False
return
- if not isinstance(analyzer.code, unicode):
+ if not isinstance(analyzer.code, text_type):
code = analyzer.code.decode(analyzer.encoding)
else:
code = analyzer.code
@@ -91,7 +92,7 @@ def collect_pages(app):
app.builder.info(' (%d module code pages)' %
len(env._viewcode_modules), nonl=1)
- for modname, entry in env._viewcode_modules.iteritems():
+ for modname, entry in iteritems(env._viewcode_modules):
if not entry:
continue
code, tags, used = entry
@@ -109,7 +110,7 @@ def collect_pages(app):
# the collected tags (HACK: this only works if the tag boundaries are
# properly nested!)
maxindex = len(lines) - 1
- for name, docname in used.iteritems():
+ for name, docname in iteritems(used):
type, start, end = tags[name]
backlink = urito(pagename, docname) + '#' + modname + '.' + name
lines[start] = (
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index b5779ab4..599a76a9 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -9,7 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-import sys
import re
import textwrap
@@ -19,6 +18,8 @@ except ImportError:
# parser is not available on Jython
parser = None
+from six import PY2, text_type
+
from sphinx.util.pycompat import htmlescape
from sphinx.util.texescape import tex_hl_escape_map_new
from sphinx.ext import doctest
@@ -131,7 +132,7 @@ class PygmentsBridge(object):
# lines beginning with "..." are probably placeholders for suite
src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src)
- if sys.version_info < (3, 0) and isinstance(src, unicode):
+ if PY2 and isinstance(src, text_type):
# 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
@@ -150,7 +151,7 @@ class PygmentsBridge(object):
return True
def highlight_block(self, source, lang, warn=None, force=False, **kwargs):
- if not isinstance(source, unicode):
+ if not isinstance(source, text_type):
source = source.decode()
if not pygments:
return self.unhighlighted(source)
@@ -207,7 +208,7 @@ class PygmentsBridge(object):
if self.dest == 'html':
return hlsource
else:
- if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6
+ if not isinstance(hlsource, text_type): # Py2 / Pygments < 1.6
hlsource = hlsource.decode()
return hlsource.translate(tex_hl_escape_map_new)
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
index f4a5a815..b161b427 100644
--- a/sphinx/jinja2glue.py
+++ b/sphinx/jinja2glue.py
@@ -12,6 +12,7 @@
from os import path
from pprint import pformat
+from six import string_types
from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, \
contextfunction
from jinja2.utils import open_if_exists
@@ -22,7 +23,7 @@ from sphinx.util.osutil import mtimes_of_files
def _tobool(val):
- if isinstance(val, basestring):
+ if isinstance(val, string_types):
return val.lower() in ('true', '1', 'yes', 'on')
return bool(val)
@@ -113,7 +114,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
self.pathchain = pathchain
# make the paths into loaders
- self.loaders = map(SphinxFileSystemLoader, loaderchain)
+ self.loaders = [SphinxFileSystemLoader(x) for x in loaderchain]
use_i18n = builder.app.translator is not None
extensions = use_i18n and ['jinja2.ext.i18n'] or []
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index b76aab1f..9332f474 100644
--- a/sphinx/locale/__init__.py
+++ b/sphinx/locale/__init__.py
@@ -9,12 +9,13 @@
:license: BSD, see LICENSE for details.
"""
-import sys
import gettext
-import UserString
+from six import PY3, text_type
+from six.moves import UserString
-class _TranslationProxy(UserString.UserString, object):
+
+class _TranslationProxy(UserString, object):
"""
Class for proxy strings from gettext translations. This is a helper for the
lazy_* functions from this module.
@@ -32,7 +33,7 @@ class _TranslationProxy(UserString.UserString, object):
def __new__(cls, func, *args):
if not args:
# not called with "function" and "arguments", but a plain string
- return unicode(func)
+ return text_type(func)
return object.__new__(cls)
def __getnewargs__(self):
@@ -59,11 +60,12 @@ class _TranslationProxy(UserString.UserString, object):
def __contains__(self, key):
return key in self.data
- def __nonzero__(self):
+ def __bool__(self):
return bool(self.data)
+ __nonzero__ = __bool__ # for python2 compatibility
def __dir__(self):
- return dir(unicode)
+ return dir(text_type)
def __iter__(self):
return iter(self.data)
@@ -75,7 +77,7 @@ class _TranslationProxy(UserString.UserString, object):
return str(self.data)
def __unicode__(self):
- return unicode(self.data)
+ return text_type(self.data)
def __add__(self, other):
return self.data + other
@@ -132,7 +134,7 @@ class _TranslationProxy(UserString.UserString, object):
def __repr__(self):
try:
- return 'i' + repr(unicode(self.data))
+ return 'i' + repr(text_type(self.data))
except:
return '<%s broken>' % self.__class__.__name__
@@ -183,7 +185,7 @@ pairindextypes = {
translators = {}
-if sys.version_info >= (3, 0):
+if PY3:
def _(message):
return translators['sphinx'].gettext(message)
else:
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index b735fb31..461eea05 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -13,12 +13,14 @@ from __future__ import print_function
import sys
from os import path
+from six import iteritems, text_type, BytesIO, StringIO
+
from sphinx import package_dir
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, detect_encoding
-from sphinx.util.pycompat import StringIO, BytesIO, TextIOWrapper
+from sphinx.util.pycompat import TextIOWrapper
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
@@ -30,9 +32,9 @@ pydriver = driver.Driver(pygrammar, convert=nodes.convert)
# an object with attributes corresponding to token and symbol names
class sym: pass
-for k, v in pygrammar.symbol2number.iteritems():
+for k, v in iteritems(pygrammar.symbol2number):
setattr(sym, k, v)
-for k, v in token.tok_name.iteritems():
+for k, v in iteritems(token.tok_name):
setattr(sym, v, k)
# a dict mapping terminal and nonterminal numbers to their names
@@ -98,7 +100,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
continue # skip over semicolon
if parent[idx].type == sym.NEWLINE:
prefix = parent[idx].get_prefix()
- if not isinstance(prefix, unicode):
+ if not isinstance(prefix, text_type):
prefix = prefix.decode(self.encoding)
docstring = prepare_commentdoc(prefix)
if docstring:
@@ -116,7 +118,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
if not pnode or pnode.type not in (token.INDENT, token.DEDENT):
break
prefix = pnode.get_prefix()
- if not isinstance(prefix, unicode):
+ if not isinstance(prefix, text_type):
prefix = prefix.decode(self.encoding)
docstring = prepare_commentdoc(prefix)
self.add_docstring(node, docstring)
@@ -339,7 +341,7 @@ if __name__ == '__main__':
x1 = time.time()
ma.parse()
x2 = time.time()
- #for (ns, name), doc in ma.find_attr_docs().iteritems():
+ #for (ns, name), doc in iteritems(ma.find_attr_docs()):
# print '>>', ns, name
# print '\n'.join(doc)
pprint.pprint(ma.find_tags())
diff --git a/sphinx/pycode/pgen2/literals.py b/sphinx/pycode/pgen2/literals.py
index ce4a0ebc..25e09b62 100644
--- a/sphinx/pycode/pgen2/literals.py
+++ b/sphinx/pycode/pgen2/literals.py
@@ -8,6 +8,9 @@ from __future__ import print_function
import re
+from six import text_type
+
+
simple_escapes = {"a": "\a",
"b": "\b",
"f": "\f",
@@ -67,7 +70,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 and not isinstance(s, unicode):
+ if encoding and not isinstance(s, text_type):
s = s.decode(encoding)
if s.startswith('u') or s.startswith('U'):
regex = uni_escape_re
diff --git a/sphinx/pycode/pgen2/pgen.py b/sphinx/pycode/pgen2/pgen.py
index ab990cef..e199ed8a 100644
--- a/sphinx/pycode/pgen2/pgen.py
+++ b/sphinx/pycode/pgen2/pgen.py
@@ -3,6 +3,8 @@
from __future__ import print_function
+from six import iteritems
+
# Pgen imports
from sphinx.pycode.pgen2 import grammar, token, tokenize
@@ -29,7 +31,7 @@ class ParserGenerator(object):
def make_grammar(self):
c = PgenGrammar()
- names = self.dfas.keys()
+ names = list(self.dfas.keys())
names.sort()
names.remove(self.startsymbol)
names.insert(0, self.startsymbol)
@@ -42,7 +44,7 @@ class ParserGenerator(object):
states = []
for state in dfa:
arcs = []
- for label, next in state.arcs.iteritems():
+ for label, next in iteritems(state.arcs):
arcs.append((self.make_label(c, label), dfa.index(next)))
if state.isfinal:
arcs.append((0, dfa.index(state)))
@@ -108,7 +110,7 @@ class ParserGenerator(object):
return ilabel
def addfirstsets(self):
- names = self.dfas.keys()
+ names = list(self.dfas.keys())
names.sort()
for name in names:
if name not in self.first:
@@ -121,7 +123,7 @@ class ParserGenerator(object):
state = dfa[0]
totalset = {}
overlapcheck = {}
- for label, next in state.arcs.iteritems():
+ for label, next in iteritems(state.arcs):
if label in self.dfas:
if label in self.first:
fset = self.first[label]
@@ -136,7 +138,7 @@ class ParserGenerator(object):
totalset[label] = 1
overlapcheck[label] = {label: 1}
inverse = {}
- for label, itsfirst in overlapcheck.iteritems():
+ for label, itsfirst in iteritems(overlapcheck):
for symbol in itsfirst:
if symbol in inverse:
raise ValueError("rule %s is ambiguous; %s is in the"
@@ -195,7 +197,7 @@ class ParserGenerator(object):
for label, next in nfastate.arcs:
if label is not None:
addclosure(next, arcs.setdefault(label, {}))
- for label, nfaset in arcs.iteritems():
+ for label, nfaset in iteritems(arcs):
for st in states:
if st.nfaset == nfaset:
break
@@ -225,7 +227,7 @@ class ParserGenerator(object):
print("Dump of DFA for", name)
for i, state in enumerate(dfa):
print(" State", i, state.isfinal and "(final)" or "")
- for label, next in state.arcs.iteritems():
+ for label, next in iteritems(state.arcs):
print(" %s -> %d" % (label, dfa.index(next)))
def simplify_dfa(self, dfa):
@@ -322,9 +324,9 @@ class ParserGenerator(object):
return value
def gettoken(self):
- tup = self.generator.next()
+ tup = next(self.generator)
while tup[0] in (tokenize.COMMENT, tokenize.NL):
- tup = self.generator.next()
+ tup = next(self.generator)
self.type, self.value, self.begin, self.end, self.line = tup
#print token.tok_name[self.type], repr(self.value)
@@ -333,7 +335,7 @@ class ParserGenerator(object):
try:
msg = msg % args
except:
- msg = " ".join([msg] + map(str, args))
+ msg = " ".join([msg] + [str(x) for x in args])
raise SyntaxError(msg, (self.filename, self.end[0],
self.end[1], self.line))
@@ -351,7 +353,7 @@ class DFAState(object):
def __init__(self, nfaset, final):
assert isinstance(nfaset, dict)
- assert isinstance(iter(nfaset).next(), NFAState)
+ assert isinstance(next(iter(nfaset)), NFAState)
assert isinstance(final, NFAState)
self.nfaset = nfaset
self.isfinal = final in nfaset
@@ -364,7 +366,7 @@ class DFAState(object):
self.arcs[label] = next
def unifystate(self, old, new):
- for label, next in self.arcs.iteritems():
+ for label, next in iteritems(self.arcs):
if next is old:
self.arcs[label] = new
@@ -377,7 +379,7 @@ class DFAState(object):
# would invoke this method recursively, with cycles...
if len(self.arcs) != len(other.arcs):
return False
- for label, next in self.arcs.iteritems():
+ for label, next in iteritems(self.arcs):
if next is not other.arcs.get(label):
return False
return True
diff --git a/sphinx/pycode/pgen2/token.py b/sphinx/pycode/pgen2/token.py
index 56a40ce7..55bf5e8d 100755
--- a/sphinx/pycode/pgen2/token.py
+++ b/sphinx/pycode/pgen2/token.py
@@ -68,7 +68,7 @@ NT_OFFSET = 256
#--end constants--
tok_name = {}
-for _name, _value in globals().items():
+for _name, _value in list(globals().items()):
if type(_value) is type(0):
tok_name[_value] = _name
diff --git a/sphinx/pycode/pgen2/tokenize.py b/sphinx/pycode/pgen2/tokenize.py
index 4e94fa5c..f516f78b 100644
--- a/sphinx/pycode/pgen2/tokenize.py
+++ b/sphinx/pycode/pgen2/tokenize.py
@@ -97,8 +97,9 @@ ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
PseudoExtras = group(r'\\\r?\n', Comment, Triple)
PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
-tokenprog, pseudoprog, single3prog, double3prog = map(
- re.compile, (Token, PseudoToken, Single3, Double3))
+tokenprog, pseudoprog, single3prog, double3prog = [
+ re.compile(x) for x in (Token, PseudoToken, Single3, Double3)
+]
endprogs = {"'": re.compile(Single), '"': re.compile(Double),
"'''": single3prog, '"""': double3prog,
"r'''": single3prog, 'r"""': double3prog,
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index e480923d..acf26df7 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -26,6 +26,8 @@ try:
except ImportError:
pass
+from six import PY2, PY3, text_type
+from six.moves import input
from docutils.utils import column_width
from sphinx import __version__
@@ -35,16 +37,12 @@ from sphinx.util.console import purple, bold, red, turquoise, \
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
+term_input = input
PROMPT_PREFIX = '> '
-if sys.version_info >= (3, 0):
+if PY3:
# prevents that the file is checked for being written in Python 2.x syntax
QUICKSTART_CONF = u'#!/usr/bin/env python3\n'
else:
@@ -997,7 +995,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
else:
prompt = PROMPT_PREFIX + text + ': '
- if sys.version_info < (3, 0):
+ if PY2:
# for Python 2.x, try to get a Unicode string out of it
if prompt.encode('ascii', 'replace').decode('ascii', 'replace') \
!= prompt:
@@ -1015,7 +1013,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
x = term_input(prompt).strip()
if default and not x:
x = default
- if not isinstance(x, unicode):
+ if not isinstance(x, text_type):
# 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:
@@ -1037,7 +1035,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
d[key] = x
-if sys.version_info >= (3, 0):
+if PY3:
# remove Unicode literal prefixes
def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
return rex.sub('\\1', source)
@@ -1241,10 +1239,10 @@ def generate(d, overwrite=True, silent=False):
else:
d['extensions'] = extensions
d['copyright'] = time.strftime('%Y') + ', ' + d['author']
- d['author_texescaped'] = unicode(d['author']).\
+ d['author_texescaped'] = text_type(d['author']).\
translate(texescape.tex_escape_map)
d['project_doc'] = d['project'] + ' Documentation'
- d['project_doc_texescaped'] = unicode(d['project'] + ' Documentation').\
+ d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\
translate(texescape.tex_escape_map)
# escape backslashes and single quotes in strings that are put into
diff --git a/sphinx/roles.py b/sphinx/roles.py
index f0b8cedc..2778759a 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -11,6 +11,7 @@
import re
+from six import iteritems
from docutils import nodes, utils
from docutils.parsers.rst import roles
@@ -34,7 +35,7 @@ generic_docroles = {
'regexp' : nodes.literal,
}
-for rolename, nodeclass in generic_docroles.iteritems():
+for rolename, nodeclass in iteritems(generic_docroles):
generic = roles.GenericRole(rolename, nodeclass)
role = roles.CustomRole(rolename, generic, {'classes': [rolename]})
roles.register_local_role(rolename, role)
@@ -313,5 +314,5 @@ specific_docroles = {
'index': index_role,
}
-for rolename, func in specific_docroles.iteritems():
+for rolename, func in iteritems(specific_docroles):
roles.register_local_role(rolename, func)
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index b4f5a799..43e3e404 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -11,8 +11,9 @@
from __future__ import with_statement
import re
-import cPickle as pickle
+from six import iteritems, itervalues, text_type, string_types
+from six.moves import cPickle as pickle
from docutils.nodes import raw, comment, title, Text, NodeVisitor, SkipNode
from sphinx.util import jsdump, rpartition
@@ -237,7 +238,7 @@ class IndexBuilder(object):
def load(self, stream, format):
"""Reconstruct from frozen data."""
- if isinstance(format, basestring):
+ if isinstance(format, string_types):
format = self.formats[format]
frozen = format.load(stream)
# if an old index is present, we treat it as not existing.
@@ -249,7 +250,7 @@ class IndexBuilder(object):
def load_terms(mapping):
rv = {}
- for k, v in mapping.iteritems():
+ for k, v in iteritems(mapping):
if isinstance(v, int):
rv[k] = set([index2fn[v]])
else:
@@ -262,7 +263,7 @@ class IndexBuilder(object):
def dump(self, stream, format):
"""Dump the frozen index to a stream."""
- if isinstance(format, basestring):
+ if isinstance(format, string_types):
format = self.formats[format]
format.dump(self.freeze(), stream)
@@ -270,7 +271,7 @@ class IndexBuilder(object):
rv = {}
otypes = self._objtypes
onames = self._objnames
- for domainname, domain in self.env.domains.iteritems():
+ for domainname, domain in iteritems(self.env.domains):
for fullname, dispname, type, docname, anchor, prio in \
domain.get_objects():
# XXX use dispname?
@@ -289,7 +290,7 @@ class IndexBuilder(object):
if otype:
# use unicode() to fire translation proxies
onames[typeindex] = (domainname, type,
- unicode(domain.get_type_name(otype)))
+ text_type(domain.get_type_name(otype)))
else:
onames[typeindex] = (domainname, type, type)
if anchor == fullname:
@@ -304,7 +305,7 @@ class IndexBuilder(object):
def get_terms(self, fn2index):
rvs = {}, {}
for rv, mapping in zip(rvs, (self._mapping, self._title_mapping)):
- for k, v in mapping.iteritems():
+ for k, v in iteritems(mapping):
if len(v) == 1:
fn, = v
if fn in fn2index:
@@ -315,14 +316,14 @@ class IndexBuilder(object):
def freeze(self):
"""Create a usable data structure for serializing."""
- filenames = self._titles.keys()
- titles = self._titles.values()
+ filenames = list(self._titles.keys())
+ titles = list(self._titles.values())
fn2index = dict((f, i) for (i, f) in enumerate(filenames))
terms, title_terms = self.get_terms(fn2index)
objects = self.get_objects(fn2index) # populates _objtypes
objtypes = dict((v, k[0] + ':' + k[1])
- for (k, v) in self._objtypes.iteritems())
+ for (k, v) in iteritems(self._objtypes))
objnames = self._objnames
return dict(filenames=filenames, titles=titles, terms=terms,
objects=objects, objtypes=objtypes, objnames=objnames,
@@ -338,9 +339,9 @@ class IndexBuilder(object):
if filename in self._titles:
new_titles[filename] = self._titles[filename]
self._titles = new_titles
- for wordnames in self._mapping.itervalues():
+ for wordnames in itervalues(self._mapping):
wordnames.intersection_update(filenames)
- for wordnames in self._title_mapping.itervalues():
+ for wordnames in itervalues(self._title_mapping):
wordnames.intersection_update(filenames)
def feed(self, filename, title, doctree):
diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py
index 6084a067..bc308b67 100644
--- a/sphinx/search/ja.py
+++ b/sphinx/search/ja.py
@@ -21,6 +21,8 @@ import os
import re
import sys
+from six import iteritems
+
try:
import MeCab
native_module = True
@@ -91,14 +93,14 @@ class MecabBinder(object):
class TinySegmenter(object):
- patterns_ = dict([(re.compile(pattern), value) for pattern, value in {
+ patterns_ = dict([(re.compile(pattern), value) for pattern, value in iteritems({
u'[一二三四五六七八九十百千万億兆]': u'M',
u'[一-龠々〆ヵヶ]': u'H',
u'[ぁ-ん]': u'I',
u'[ァ-ヴーア-ン゙ー]': u'K',
u'[a-zA-Za-zA-Z]': u'A',
u'[0-90-9]': u'N',
- }.iteritems()])
+ })])
BIAS__ = -332
BC1__ = {u'HH':6,u'II':2461,u'KH':406,u'OH':-1378}
BC2__ = {u'AA':-3267,u'AI':2744,u'AN':-878,u'HH':-4070,u'HM':-1711,u'HN':4012,u'HO':3761,u'IA':1327,u'IH':-1184,u'II':-1332,u'IK':1721,u'IO':5492,u'KI':3831,u'KK':-8741,u'MH':-3132,u'MK':3334,u'OO':-2920}
@@ -145,7 +147,7 @@ class TinySegmenter(object):
# ctype_
def ctype_(self, char):
- for pattern, value in self.patterns_.iteritems():
+ for pattern, value in iteritems(self.patterns_):
if pattern.match(char):
return value
return u'O'
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index deb8ceab..8ed17113 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -15,11 +15,11 @@ from __future__ import print_function
import sys
import os
-import types
-from StringIO import StringIO
from distutils.cmd import Command
from distutils.errors import DistutilsOptionError
+from six import StringIO, string_types
+
from sphinx.application import Sphinx
from sphinx.util.console import darkred, nocolor, color_terminal
from sphinx.util.osutil import abspath
@@ -109,7 +109,7 @@ class BuildDoc(Command):
if val is None:
setattr(self, option, default)
return default
- elif not isinstance(val, types.StringTypes):
+ elif not isinstance(val, string_types):
raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
% (option, what, val))
return val
diff --git a/sphinx/theming.py b/sphinx/theming.py
index abc09c17..41cbcae9 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -13,9 +13,11 @@ import os
import shutil
import zipfile
import tempfile
-import ConfigParser
from os import path
+from six import string_types, iteritems
+from six.moves import configparser
+
try:
import pkg_resources
except ImportError:
@@ -100,12 +102,12 @@ class Theme(object):
fp.write(tinfo.read(name))
fp.close()
- self.themeconf = ConfigParser.RawConfigParser()
+ self.themeconf = configparser.RawConfigParser()
self.themeconf.read(path.join(self.themedir, THEMECONF))
try:
inherit = self.themeconf.get('theme', 'inherit')
- except ConfigParser.NoOptionError:
+ except configparser.NoOptionError:
raise ThemeError('theme %r doesn\'t have "inherit" setting' % name)
if inherit == 'none':
self.base = None
@@ -121,7 +123,7 @@ class Theme(object):
"""
try:
return self.themeconf.get(section, name)
- except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+ except (configparser.NoOptionError, configparser.NoSectionError):
if self.base is not None:
return self.base.get_confstr(section, name, default)
if default is NODEFAULT:
@@ -141,9 +143,9 @@ class Theme(object):
for conf in reversed(chain):
try:
options.update(conf.items('options'))
- except ConfigParser.NoSectionError:
+ except configparser.NoSectionError:
pass
- for option, value in overrides.iteritems():
+ for option, value in iteritems(overrides):
if option not in options:
raise ThemeError('unsupported theme option %r given' % option)
options[option] = value
@@ -188,7 +190,7 @@ def load_theme_plugins():
except:
path = func_or_path
- if isinstance(path, basestring):
+ if isinstance(path, string_types):
theme_paths.append(path)
else:
raise ThemeError('Plugin %r does not response correctly.' %
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 06c6ce24..2c6731a2 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -12,7 +12,6 @@
import os
import re
import sys
-import shutil
import fnmatch
import tempfile
import posixpath
@@ -22,6 +21,8 @@ from os import path
from codecs import open, BOM_UTF8
from collections import deque
+from six import iteritems, text_type, binary_type
+from six.moves import range
import docutils
from docutils.utils import relative_path
@@ -29,7 +30,6 @@ import jinja2
import sphinx
from sphinx.errors import PycodeError
-from sphinx.util.pycompat import bytes
# import other utilities; partly for backwards compatibility, so don't
# prune unused ones indiscriminately
@@ -54,7 +54,7 @@ def docname_join(basedocname, docname):
def path_stabilize(filepath):
"normalize path separater and unicode string"
newpath = filepath.replace(os.path.sep, SEP)
- if isinstance(newpath, unicode):
+ if isinstance(newpath, text_type):
newpath = unicodedata.normalize('NFC', newpath)
return newpath
@@ -122,7 +122,7 @@ class FilenameUniqDict(dict):
return uniquename
def purge_doc(self, docname):
- for filename, (docs, unique) in self.items():
+ for filename, (docs, unique) in list(self.items()):
docs.discard(docname)
if not docs:
del self[filename]
@@ -190,7 +190,7 @@ def save_traceback(app):
docutils.__version__, docutils.__version_details__,
jinja2.__version__)).encode('utf-8'))
if app is not None:
- for extname, extmod in app._extensions.iteritems():
+ for extname, extmod in iteritems(app._extensions):
os.write(fd, ('# %s from %s\n' % (
extname, getattr(extmod, '__file__', 'unknown'))
).encode('utf-8'))
@@ -328,7 +328,7 @@ def parselinenos(spec, total):
else:
start = (begend[0] == '') and 0 or int(begend[0])-1
end = (begend[1] == '') and total or int(begend[1])
- items.extend(xrange(start, end))
+ items.extend(range(start, end))
except Exception:
raise ValueError('invalid line number spec: %r' % spec)
return items
@@ -336,7 +336,7 @@ def parselinenos(spec, total):
def force_decode(string, encoding):
"""Forcibly get a unicode string out of a bytestring."""
- if isinstance(string, bytes):
+ if isinstance(string, binary_type):
try:
if encoding:
string = string.decode(encoding)
@@ -368,7 +368,7 @@ def rpartition(s, t):
def split_into(n, type, value):
"""Split an index entry into a given number of parts at semicolons."""
- parts = map(lambda x: x.strip(), value.split(';', n-1))
+ parts = [x.strip() for x in value.split(';', n-1)]
if sum(1 for part in parts if part) < n:
raise ValueError('invalid %s index entry %r' % (type, value))
return parts
@@ -420,11 +420,13 @@ class PeekableIterator(object):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
"""Return the next item from the iterator."""
if self.remaining:
return self.remaining.popleft()
- return self._iterator.next()
+ return next(self._iterator)
+
+ next = __next__ # Python 2 compatibility
def push(self, item):
"""Push the `item` on the internal stack, it will be returned on the
@@ -434,6 +436,6 @@ class PeekableIterator(object):
def peek(self):
"""Return the next item without changing the state of the iterator."""
- item = self.next()
+ item = next(self)
self.push(item)
return item
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index e7132874..f82f1f45 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -9,17 +9,17 @@
:license: BSD, see LICENSE for details.
"""
-import sys
-
# this imports the standard library inspect module without resorting to
# relatively import this module
inspect = __import__('inspect')
+from six import PY3, binary_type
+from six.moves import builtins
+
from sphinx.util import force_decode
-from sphinx.util.pycompat import bytes, builtins
-if sys.version_info >= (3, 0):
+if PY3:
from functools import partial
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
@@ -129,7 +129,7 @@ def safe_repr(object):
s = repr(object)
except Exception:
raise ValueError
- if isinstance(s, bytes):
+ if isinstance(s, binary_type):
return force_decode(s, None).replace('\n', ' ')
return s.replace('\n', ' ')
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py
index 85845a72..ede4ae7d 100644
--- a/sphinx/util/jsdump.py
+++ b/sphinx/util/jsdump.py
@@ -12,6 +12,8 @@
import re
+from six import iteritems, integer_types, string_types
+
from sphinx.util.pycompat import u
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
@@ -74,7 +76,7 @@ double in super""".split())
def dumps(obj, key=False):
if key:
- if not isinstance(obj, basestring):
+ if not isinstance(obj, string_types):
obj = str(obj)
if _nameonly_re.match(obj) and obj not in reswords:
return obj # return it as a bare word
@@ -84,16 +86,16 @@ def dumps(obj, key=False):
return 'null'
elif obj is True or obj is False:
return obj and 'true' or 'false'
- elif isinstance(obj, (int, long, float)):
+ elif isinstance(obj, integer_types + (float,)):
return str(obj)
elif isinstance(obj, dict):
return '{%s}' % ','.join('%s:%s' % (
dumps(key, True),
dumps(value)
- ) for key, value in obj.iteritems())
+ ) for key, value in iteritems(obj))
elif isinstance(obj, (tuple, list, set)):
return '[%s]' % ','.join(dumps(x) for x in obj)
- elif isinstance(obj, basestring):
+ elif isinstance(obj, string_types):
return encode_string(obj)
raise TypeError(type(obj))
diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py
index 05a6ec6e..ac5c54ae 100644
--- a/sphinx/util/jsonimpl.py
+++ b/sphinx/util/jsonimpl.py
@@ -9,15 +9,17 @@
:license: BSD, see LICENSE for details.
"""
-import UserString
import json
+from six import text_type
+from six.moves import UserString
+
class SphinxJSONEncoder(json.JSONEncoder):
"""JSONEncoder subclass that forces translation proxies."""
def default(self, obj):
- if isinstance(obj, UserString.UserString):
- return unicode(obj)
+ if isinstance(obj, UserString):
+ return text_type(obj)
return json.JSONEncoder.default(self, obj)
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index 496a2a41..9b5f58b7 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -20,6 +20,8 @@ import shutil
import gettext
from os import path
+from six import PY2, text_type
+
# Errnos that we need.
EEXIST = getattr(errno, 'EEXIST', 0)
ENOENT = getattr(errno, 'ENOENT', 0)
@@ -147,13 +149,13 @@ no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
def make_filename(string):
return no_fn_re.sub('', string) or 'sphinx'
-if sys.version_info < (3, 0):
+if PY2:
# strftime for unicode strings
def ustrftime(format, *args):
# if a locale is set, the time strings are encoded in the encoding
# given by LC_TIME; if that is available, use it
enc = locale.getlocale(locale.LC_TIME)[1] or 'utf-8'
- return time.strftime(unicode(format).encode(enc), *args).decode(enc)
+ return time.strftime(text_type(format).encode(enc), *args).decode(enc)
else:
ustrftime = time.strftime
@@ -187,12 +189,6 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-if sys.version_info < (3, 0):
- bytes = str
-else:
- bytes = bytes
-
-
def abspath(pathdir):
pathdir = path.abspath(pathdir)
if isinstance(pathdir, bytes):
diff --git a/sphinx/util/png.py b/sphinx/util/png.py
index 65fc4d8d..397adb24 100644
--- a/sphinx/util/png.py
+++ b/sphinx/util/png.py
@@ -12,14 +12,13 @@
import struct
import binascii
-from sphinx.util.pycompat import b
LEN_IEND = 12
LEN_DEPTH = 22
DEPTH_CHUNK_LEN = struct.pack('!i', 10)
-DEPTH_CHUNK_START = b('tEXtDepth\x00')
-IEND_CHUNK = b('\x00\x00\x00\x00IEND\xAE\x42\x60\x82')
+DEPTH_CHUNK_START = b'tEXtDepth\x00'
+IEND_CHUNK = b'\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
def read_png_depth(filename):
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index 8cc7c5de..5031dd9b 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -12,20 +12,16 @@
import sys
import codecs
+from six import PY3, text_type, exec_
+
# ------------------------------------------------------------------------------
# Python 2/3 compatibility
-if sys.version_info >= (3, 0):
+if PY3:
# Python 3
- class_types = (type,)
- # the ubiquitous "bytes" helper functions
- def b(s):
- return s.encode('utf-8')
- bytes = bytes
# prefix for Unicode strings
u = ''
- # StringIO/BytesIO classes
- from io import StringIO, BytesIO, TextIOWrapper
+ from io import TextIOWrapper
# safely encode a string for printing to the terminal
def terminal_safe(s):
return s.encode('ascii', 'backslashreplace').decode('ascii')
@@ -46,19 +42,19 @@ if sys.version_info >= (3, 0):
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)
- from itertools import zip_longest # Python 3 name
- import builtins
+ return text_type(tree)
+ from html import escape as htmlescape # >= Python 3.2
+
+ class UnicodeMixin:
+ """Mixin class to handle defining the proper __str__/__unicode__
+ methods in Python 2 or 3."""
+
+ def __str__(self):
+ return self.__unicode__()
else:
# Python 2
- from types import ClassType
- class_types = (type, ClassType)
- b = str
- bytes = str
u = 'u'
- from StringIO import StringIO
- BytesIO = StringIO
# no need to refactor on 2.x versions
convert_with_2to3 = None
def TextIOWrapper(stream, encoding):
@@ -68,11 +64,16 @@ else:
return s.encode('ascii', 'backslashreplace')
# some kind of default system encoding; should be used with a lenient
# error handler
- import locale
- sys_encoding = locale.getpreferredencoding()
+ sys_encoding = __import__('locale').getpreferredencoding()
# use Python 3 name
- from itertools import izip_longest as zip_longest
- import __builtin__ as builtins
+ from cgi import escape as htmlescape # 2.6, 2.7
+
+ class UnicodeMixin(object):
+ """Mixin class to handle defining the proper __str__/__unicode__
+ methods in Python 2 or 3."""
+
+ def __str__(self):
+ return self.__unicode__().encode('utf8')
def execfile_(filepath, _globals):
@@ -87,7 +88,7 @@ def execfile_(filepath, _globals):
# py26 accept only LF eol instead of CRLF
if sys.version_info[:2] == (2, 6):
- source = source.replace(b('\r\n'), b('\n'))
+ source = source.replace(b'\r\n', b'\n')
# compile to a code object, handle syntax errors
filepath_enc = filepath.encode(fs_encoding)
@@ -101,10 +102,4 @@ def execfile_(filepath, _globals):
code = compile(source, filepath_enc, 'exec')
else:
raise
- exec code in _globals
-
-
-if sys.version_info >= (3, 2):
- from html import escape as htmlescape # >= Python 3.2
-else: # 2.6, 2.7, 3.1
- from cgi import escape as htmlescape
+ exec_(code, _globals)
diff --git a/sphinx/util/tags.py b/sphinx/util/tags.py
index 2a9b2a02..d5141587 100644
--- a/sphinx/util/tags.py
+++ b/sphinx/util/tags.py
@@ -35,9 +35,9 @@ class BooleanParser(Parser):
node = nodes.Const(None, lineno=token.lineno)
else:
node = nodes.Name(token.value, 'load', lineno=token.lineno)
- self.stream.next()
+ next(self.stream)
elif token.type == 'lparen':
- self.stream.next()
+ next(self.stream)
node = self.parse_expression()
self.stream.expect('rparen')
else:
diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py
index c0619f46..6fcf9ff0 100644
--- a/sphinx/util/texescape.py
+++ b/sphinx/util/texescape.py
@@ -9,93 +9,95 @@
:license: BSD, see LICENSE for details.
"""
+from __future__ import unicode_literals
+
tex_replacements = [
# map TeX special chars
- (u'$', ur'\$'),
- (u'%', ur'\%'),
- (u'&', ur'\&'),
- (u'#', ur'\#'),
- (u'_', ur'\_'),
- (u'{', ur'\{'),
- (u'}', ur'\}'),
- (u'[', ur'{[}'),
- (u']', ur'{]}'),
- (u'`', ur'{}`'),
- (u'\\',ur'\textbackslash{}'),
- (u'~', ur'\textasciitilde{}'),
- (u'<', ur'\textless{}'),
- (u'>', ur'\textgreater{}'),
- (u'^', ur'\textasciicircum{}'),
+ ('$', r'\$'),
+ ('%', r'\%'),
+ ('&', r'\&'),
+ ('#', r'\#'),
+ ('_', r'\_'),
+ ('{', r'\{'),
+ ('}', r'\}'),
+ ('[', r'{[}'),
+ (']', r'{]}'),
+ ('`', r'{}`'),
+ ('\\',r'\textbackslash{}'),
+ ('~', r'\textasciitilde{}'),
+ ('<', r'\textless{}'),
+ ('>', r'\textgreater{}'),
+ ('^', r'\textasciicircum{}'),
# map special Unicode characters to TeX commands
- (u'¶', ur'\P{}'),
- (u'§', ur'\S{}'),
- (u'€', ur'\texteuro{}'),
- (u'∞', ur'\(\infty\)'),
- (u'±', ur'\(\pm\)'),
- (u'→', ur'\(\rightarrow\)'),
- (u'‣', ur'\(\rightarrow\)'),
+ ('¶', r'\P{}'),
+ ('§', r'\S{}'),
+ ('€', r'\texteuro{}'),
+ ('∞', r'\(\infty\)'),
+ ('±', r'\(\pm\)'),
+ ('→', r'\(\rightarrow\)'),
+ ('‣', r'\(\rightarrow\)'),
# used to separate -- in options
- (u'', ur'{}'),
+ ('', r'{}'),
# map some special Unicode characters to similar ASCII ones
- (u'─', ur'-'),
- (u'⎽', ur'\_'),
- (u'╲', ur'\textbackslash{}'),
- (u'|', ur'\textbar{}'),
- (u'│', ur'\textbar{}'),
- (u'ℯ', ur'e'),
- (u'ⅈ', ur'i'),
- (u'₁', ur'1'),
- (u'₂', ur'2'),
+ ('─', r'-'),
+ ('⎽', r'\_'),
+ ('╲', r'\textbackslash{}'),
+ ('|', r'\textbar{}'),
+ ('│', r'\textbar{}'),
+ ('ℯ', r'e'),
+ ('ⅈ', r'i'),
+ ('₁', r'1'),
+ ('₂', r'2'),
# map Greek alphabet
- (u'α', ur'\(\alpha\)'),
- (u'β', ur'\(\beta\)'),
- (u'γ', ur'\(\gamma\)'),
- (u'δ', ur'\(\delta\)'),
- (u'ε', ur'\(\epsilon\)'),
- (u'ζ', ur'\(\zeta\)'),
- (u'η', ur'\(\eta\)'),
- (u'θ', ur'\(\theta\)'),
- (u'ι', ur'\(\iota\)'),
- (u'κ', ur'\(\kappa\)'),
- (u'λ', ur'\(\lambda\)'),
- (u'μ', ur'\(\mu\)'),
- (u'ν', ur'\(\nu\)'),
- (u'ξ', ur'\(\xi\)'),
- (u'ο', ur'o'),
- (u'π', ur'\(\pi\)'),
- (u'ρ', ur'\(\rho\)'),
- (u'σ', ur'\(\sigma\)'),
- (u'τ', ur'\(\tau\)'),
- (u'υ', u'\\(\\upsilon\\)'),
- (u'φ', ur'\(\phi\)'),
- (u'χ', ur'\(\chi\)'),
- (u'ψ', ur'\(\psi\)'),
- (u'ω', ur'\(\omega\)'),
- (u'Α', ur'A'),
- (u'Β', ur'B'),
- (u'Γ', ur'\(\Gamma\)'),
- (u'Δ', ur'\(\Delta\)'),
- (u'Ε', ur'E'),
- (u'Ζ', ur'Z'),
- (u'Η', ur'H'),
- (u'Θ', ur'\(\Theta\)'),
- (u'Ι', ur'I'),
- (u'Κ', ur'K'),
- (u'Λ', ur'\(\Lambda\)'),
- (u'Μ', ur'M'),
- (u'Ν', ur'N'),
- (u'Ξ', ur'\(\Xi\)'),
- (u'Ο', ur'O'),
- (u'Π', ur'\(\Pi\)'),
- (u'Ρ', ur'P'),
- (u'Σ', ur'\(\Sigma\)'),
- (u'Τ', ur'T'),
- (u'Υ', u'\\(\\Upsilon\\)'),
- (u'Φ', ur'\(\Phi\)'),
- (u'Χ', ur'X'),
- (u'Ψ', ur'\(\Psi\)'),
- (u'Ω', ur'\(\Omega\)'),
- (u'Ω', ur'\(\Omega\)'),
+ ('α', r'\(\alpha\)'),
+ ('β', r'\(\beta\)'),
+ ('γ', r'\(\gamma\)'),
+ ('δ', r'\(\delta\)'),
+ ('ε', r'\(\epsilon\)'),
+ ('ζ', r'\(\zeta\)'),
+ ('η', r'\(\eta\)'),
+ ('θ', r'\(\theta\)'),
+ ('ι', r'\(\iota\)'),
+ ('κ', r'\(\kappa\)'),
+ ('λ', r'\(\lambda\)'),
+ ('μ', r'\(\mu\)'),
+ ('ν', r'\(\nu\)'),
+ ('ξ', r'\(\xi\)'),
+ ('ο', r'o'),
+ ('π', r'\(\pi\)'),
+ ('ρ', r'\(\rho\)'),
+ ('σ', r'\(\sigma\)'),
+ ('τ', r'\(\tau\)'),
+ ('υ', '\\(\\upsilon\\)'),
+ ('φ', r'\(\phi\)'),
+ ('χ', r'\(\chi\)'),
+ ('ψ', r'\(\psi\)'),
+ ('ω', r'\(\omega\)'),
+ ('Α', r'A'),
+ ('Β', r'B'),
+ ('Γ', r'\(\Gamma\)'),
+ ('Δ', r'\(\Delta\)'),
+ ('Ε', r'E'),
+ ('Ζ', r'Z'),
+ ('Η', r'H'),
+ ('Θ', r'\(\Theta\)'),
+ ('Ι', r'I'),
+ ('Κ', r'K'),
+ ('Λ', r'\(\Lambda\)'),
+ ('Μ', r'M'),
+ ('Ν', r'N'),
+ ('Ξ', r'\(\Xi\)'),
+ ('Ο', r'O'),
+ ('Π', r'\(\Pi\)'),
+ ('Ρ', r'P'),
+ ('Σ', r'\(\Sigma\)'),
+ ('Τ', r'T'),
+ ('Υ', '\\(\\Upsilon\\)'),
+ ('Φ', r'\(\Phi\)'),
+ ('Χ', r'X'),
+ ('Ψ', r'\(\Psi\)'),
+ ('Ω', r'\(\Omega\)'),
+ ('Ω', r'\(\Omega\)'),
]
tex_escape_map = {}
@@ -105,8 +107,8 @@ tex_hl_escape_map_new = {}
def init():
for a, b in tex_replacements:
tex_escape_map[ord(a)] = b
- tex_replace_map[ord(a)] = u'_'
+ tex_replace_map[ord(a)] = '_'
for a, b in tex_replacements:
- if a in u'[]{}\\': continue
+ if a in '[]{}\\': continue
tex_hl_escape_map_new[ord(a)] = b
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
index a41de0f0..8d34802e 100644
--- a/sphinx/versioning.py
+++ b/sphinx/versioning.py
@@ -13,7 +13,8 @@ from uuid import uuid4
from operator import itemgetter
from itertools import product
-from sphinx.util.pycompat import zip_longest
+from six import iteritems
+from six.moves import range, zip_longest
# anything below that ratio is considered equal/changed
@@ -81,7 +82,7 @@ def merge_doctrees(old, new, condition):
# choose the old node with the best ratio for each new node and set the uid
# as long as the ratio is under a certain value, in which case we consider
# them not changed but different
- ratios = sorted(ratios.iteritems(), key=itemgetter(1))
+ ratios = sorted(iteritems(ratios), key=itemgetter(1))
for (old_node, new_node), ratio in ratios:
if new_node in seen:
continue
@@ -116,7 +117,7 @@ def levenshtein_distance(a, b):
a, b = b, a
if not a:
return len(b)
- previous_row = xrange(len(b) + 1)
+ previous_row = range(len(b) + 1)
for i, column1 in enumerate(a):
current_row = [i + 1]
for j, column2 in enumerate(b):
diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py
index 0e9131d0..4cdedc0d 100644
--- a/sphinx/websupport/__init__.py
+++ b/sphinx/websupport/__init__.py
@@ -10,12 +10,11 @@
"""
import sys
-import cPickle as pickle
import posixpath
from os import path
+from six.moves import cPickle as pickle
from jinja2 import Environment, FileSystemLoader
-
from docutils.core import publish_parts
from sphinx.application import Sphinx
diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py
index 45068d29..f2a67b4d 100644
--- a/sphinx/websupport/search/__init__.py
+++ b/sphinx/websupport/search/__init__.py
@@ -11,6 +11,8 @@
import re
+from six import text_type
+
class BaseSearch(object):
def __init__(self, path):
@@ -109,7 +111,7 @@ class BaseSearch(object):
context_end < len(text) and '...' or ''])
try:
- return unicode(context, errors='ignore')
+ return text_type(context, errors='ignore')
except TypeError:
return context
diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py
index 6d1f9de4..17adf058 100644
--- a/sphinx/websupport/search/whooshsearch.py
+++ b/sphinx/websupport/search/whooshsearch.py
@@ -14,6 +14,8 @@ from whoosh.fields import Schema, ID, TEXT
from whoosh.qparser import QueryParser
from whoosh.analysis import StemmingAnalyzer
+from six import text_type
+
from sphinx.util.osutil import ensuredir
from sphinx.websupport.search import BaseSearch
@@ -43,7 +45,7 @@ class WhooshSearch(BaseSearch):
self.index_writer.commit()
def add_document(self, pagename, title, text):
- self.index_writer.add_document(path=unicode(pagename),
+ self.index_writer.add_document(path=text_type(pagename),
title=title,
text=text)
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index 13dd5d42..2d336692 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -14,6 +14,7 @@ import posixpath
import os
import copy
+from six import string_types
from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
@@ -74,7 +75,7 @@ class HTMLTranslator(BaseTranslator):
self.protect_literal_text = 0
self.permalink_text = builder.config.html_add_permalinks
# support backwards-compatible setting to a bool
- if not isinstance(self.permalink_text, basestring):
+ if not isinstance(self.permalink_text, string_types):
self.permalink_text = self.permalink_text and u'\u00B6' or ''
self.permalink_text = self.encode(self.permalink_text)
self.secnumber_suffix = builder.config.html_secnumber_suffix
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 9d3c0179..9eeedae3 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -16,6 +16,7 @@ import re
import sys
from os import path
+from six import itervalues, text_type
from docutils import nodes, writers
from docutils.writers.latex2e import Babel
@@ -306,7 +307,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return '\\autopageref*{%s}' % self.idescape(id)
def idescape(self, id):
- return unicode(id).translate(tex_replace_map).\
+ return text_type(id).translate(tex_replace_map).\
encode('ascii', 'backslashreplace').decode('ascii').\
replace('\\', '_')
@@ -319,7 +320,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if i > 0:
ret.append('\\indexspace\n')
ret.append('\\bigletter{%s}\n' %
- unicode(letter).translate(tex_escape_map))
+ text_type(letter).translate(tex_escape_map))
for entry in entries:
if not entry[3]:
continue
@@ -335,7 +336,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# latex_domain_indices can be False/True or a list of index names
indices_config = self.builder.config.latex_domain_indices
if indices_config:
- for domain in self.builder.env.domains.itervalues():
+ for domain in itervalues(self.builder.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -710,7 +711,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\n\\hline\n')
self.body.extend(self.tableheaders)
self.body.append('\\endhead\n\n')
- self.body.append(ur'\hline \multicolumn{%s}{|r|}{{\textsf{%s}}} \\ \hline'
+ self.body.append(r'\hline \multicolumn{%s}{|r|}{{\textsf{%s}}} \\ \hline'
% (self.table.colcount,
_('Continued on next page')))
self.body.append('\n\\endfoot\n\n')
@@ -1136,21 +1137,21 @@ class LaTeXTranslator(nodes.NodeVisitor):
p = scre.sub('!', self.encode(string))
self.body.append(r'\index{%s%s}' % (p, m))
elif type == 'pair':
- p1, p2 = map(self.encode, split_into(2, 'pair', string))
+ p1, p2 = [self.encode(x) for x in split_into(2, 'pair', string)]
self.body.append(r'\index{%s!%s%s}\index{%s!%s%s}' %
(p1, p2, m, p2, p1, m))
elif type == 'triple':
- p1, p2, p3 = map(self.encode,
- split_into(3, 'triple', string))
+ p1, p2, p3 = [self.encode(x)
+ for x in split_into(3, 'triple', string)]
self.body.append(
r'\index{%s!%s %s%s}\index{%s!%s, %s%s}'
r'\index{%s!%s %s%s}' %
(p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m))
elif type == 'see':
- p1, p2 = map(self.encode, split_into(2, 'see', string))
+ p1, p2 = [self.encode(x) for x in split_into(2, 'see', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
elif type == 'seealso':
- p1, p2 = map(self.encode, split_into(2, 'seealso', string))
+ p1, p2 = [self.encode(x) for x in split_into(2, 'seealso', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
else:
self.builder.warn(
@@ -1512,7 +1513,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# text handling
def encode(self, text):
- text = unicode(text).translate(tex_escape_map)
+ text = text_type(text).translate(tex_escape_map)
if self.literal_whitespace:
# Insert a blank before the newline, to avoid
# ! LaTeX Error: There's no line here to end.
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index 76f28a4f..d8da901e 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -10,10 +10,11 @@
"""
import re
-import string
import textwrap
from os import path
+from six import itervalues
+from six.moves import range
from docutils import nodes, writers
from sphinx import addnodes, __version__
@@ -457,7 +458,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
indices_config = self.builder.config.texinfo_domain_indices
if indices_config:
- for domain in self.builder.env.domains.itervalues():
+ for domain in itervalues(self.builder.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -974,7 +975,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
self.body.append('\n%s\n' % self.entry_sep)
self.entry_sep = '@tab'
def depart_entry(self, node):
- for i in xrange(node.get('morecols', 0)):
+ for i in range(node.get('morecols', 0)):
self.body.append('\n@tab\n')
## Field Lists
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index 62d3791f..3f2edd14 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -488,7 +488,7 @@ class TextTranslator(nodes.NodeVisitor):
for i, cell in enumerate(line):
par = my_wrap(cell, width=colwidths[i])
if par:
- maxwidth = max(map(column_width, par))
+ maxwidth = max(column_width(x) for x in par)
else:
maxwidth = 0
realwidths[i] = max(realwidths[i], maxwidth)