summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup.py2
-rw-r--r--sphinx/application.py13
-rw-r--r--sphinx/builders/changes.py8
-rw-r--r--sphinx/builders/gettext.py4
-rw-r--r--sphinx/builders/html.py19
-rw-r--r--sphinx/builders/latex.py3
-rw-r--r--sphinx/builders/linkcheck.py13
-rw-r--r--sphinx/builders/manpage.py4
-rw-r--r--sphinx/builders/qthelp.py3
-rw-r--r--sphinx/builders/texinfo.py3
-rw-r--r--sphinx/cmdline.py11
-rw-r--r--sphinx/config.py21
-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.py74
-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.py28
-rw-r--r--sphinx/ext/autodoc.py20
-rw-r--r--sphinx/ext/autosummary/__init__.py3
-rw-r--r--sphinx/ext/coverage.py10
-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.py23
-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.py3
-rw-r--r--sphinx/ext/viewcode.py7
-rw-r--r--sphinx/highlighting.py9
-rw-r--r--sphinx/jinja2glue.py3
-rw-r--r--sphinx/locale/__init__.py17
-rw-r--r--sphinx/pycode/__init__.py14
-rw-r--r--sphinx/pycode/pgen2/literals.py5
-rw-r--r--sphinx/pycode/pgen2/pgen.py24
-rwxr-xr-xsphinx/pycode/pgen2/token.py2
-rw-r--r--sphinx/quickstart.py20
-rw-r--r--sphinx/roles.py5
-rw-r--r--sphinx/search/__init__.py21
-rw-r--r--sphinx/search/ja.py8
-rw-r--r--sphinx/setup_command.py3
-rw-r--r--sphinx/theming.py16
-rw-r--r--sphinx/util/__init__.py22
-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.py8
-rw-r--r--sphinx/util/pycompat.py47
-rw-r--r--sphinx/util/tags.py4
-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.py9
-rw-r--r--sphinx/writers/texinfo.py7
-rwxr-xr-xtests/coverage.py10
-rw-r--r--tests/etree13/ElementTree.py9
-rw-r--r--tests/etree13/HTMLTreeBuilder.py4
-rwxr-xr-xtests/path.py12
-rw-r--r--tests/roots/test-autosummary/contents.rst12
-rwxr-xr-xtests/run.py5
-rw-r--r--tests/test_application.py4
-rw-r--r--tests/test_autodoc.py4
-rw-r--r--tests/test_autosummary.py4
-rw-r--r--tests/test_build_html.py12
-rw-r--r--tests/test_build_latex.py6
-rw-r--r--tests/test_build_texinfo.py6
-rw-r--r--tests/test_config.py4
-rw-r--r--tests/test_cpp_domain.py84
-rw-r--r--tests/test_doctest.py5
-rw-r--r--tests/test_docutilsconf.py3
-rw-r--r--tests/test_env.py4
-rw-r--r--tests/test_intersphinx.py5
-rw-r--r--tests/test_intl.py5
-rw-r--r--tests/test_napoleon_iterators.py16
-rw-r--r--tests/test_quickstart.py40
-rw-r--r--tests/test_searchadapters.py3
-rw-r--r--tests/test_websupport.py3
-rw-r--r--tests/util.py5
85 files changed, 518 insertions, 463 deletions
diff --git a/setup.py b/setup.py
index a92c93b45..92c489fbb 100644
--- a/setup.py
+++ b/setup.py
@@ -45,7 +45,7 @@ if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 2):
print('ERROR: Sphinx requires at least Python 2.6 or 3.2 to run.')
sys.exit(1)
-requires = ['Pygments>=1.2', 'docutils>=0.10', 'snowballstemmer>=1.1']
+requires = ['six', 'Pygments>=1.2', 'docutils>=0.10', 'snowballstemmer>=1.1']
if (3, 0) <= sys.version_info < (3, 3):
requires.append('Jinja2>=2.3,<2.7')
diff --git a/sphinx/application.py b/sphinx/application.py
index 89d1d7869..6d1c334b3 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 3a52c713d..abc18388a 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 e25e780a9..2300b4a07 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -18,6 +18,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
@@ -186,7 +188,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
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 035c734ce..15e848029 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
@@ -58,7 +59,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 +164,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))
@@ -264,7 +265,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 +296,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 +346,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 +697,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 +714,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 +799,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 f54533057..c9690ebb4 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
@@ -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 e46c8379f..484bd95e3 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
@@ -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 4b360cde0..dfbf89862 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 1863fb49a..c0fff2a6a 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 cc38eb175..a3152e7cb 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
@@ -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 07551e67e..ba1dc6c24 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):
@@ -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 527ea453d..7b35f8ab5 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 b, execfile_
nonascii_re = re.compile(b(r'[\x80-\xff]'))
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
-if sys.version_info >= (3, 0):
+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 250a013e9..3ac222025 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 d28c00fb5..01c8c012a 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 200fd5158..51b886fdf 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 d9d5ef245..0ac1b7aba 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 df927e646..11fe5ad1b 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):
@@ -368,7 +364,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)
@@ -410,12 +406,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)
@@ -436,10 +432,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)
@@ -480,9 +476,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:
@@ -515,7 +511,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')
@@ -993,19 +989,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)
@@ -1027,7 +1023,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)
@@ -1093,8 +1089,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
@@ -1144,7 +1140,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
@@ -1154,7 +1150,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()
@@ -1163,10 +1159,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
@@ -1279,7 +1275,7 @@ class CPPDomain(Domain):
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]
@@ -1313,5 +1309,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 9b7777f41..8cc49b098 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 9e083a12e..1780b4a14 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 c51c85feb..e213211ab 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 07b394177..f4e22b4b8 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 a0fb87dad..c251ebf1f 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:
@@ -1597,7 +1597,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 +1649,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 a79849aef..11b38d994 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
@@ -264,7 +264,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 +480,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 +504,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 +550,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 +691,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 +1128,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 +1212,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 5bee387e5..8ba76a58d 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/coverage.py b/sphinx/ext/coverage.py
index f1ac6cec5..3cf0ff55c 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))
@@ -229,7 +231,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 ef27dc119..b7e247ec9 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 18da573ef..2a54761af 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 abfb6ac6d..3fbded342 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 e2c44b58c..772b1e7f3 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -27,11 +27,12 @@
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
@@ -40,14 +41,14 @@ 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 +56,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)
@@ -129,7 +130,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 +168,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 +203,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 96ca81a56..b67ea79c0 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 2819ffe34..1a8d88c6a 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 2f1904dab..90a0a1ac2 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 6bfe644c6..9bc1e546a 100644
--- a/sphinx/ext/pngmath.py
+++ b/sphinx/ext/pngmath.py
@@ -21,6 +21,7 @@ try:
except ImportError:
from sha import sha
+from six import text_type
from docutils import nodes
from sphinx.errors import SphinxError
@@ -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 74a004635..4a62bf6d6 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 b5779ab42..599a76a90 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 f4a5a8159..c939cba02 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)
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index b76aab1f7..75deac05c 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):
@@ -63,7 +64,7 @@ class _TranslationProxy(UserString.UserString, object):
return bool(self.data)
def __dir__(self):
- return dir(unicode)
+ return dir(text_type)
def __iter__(self):
return iter(self.data)
@@ -75,7 +76,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 +133,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 +184,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 b735fb31b..461eea056 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 ce4a0ebc3..25e09b62d 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 ab990cefe..3c37b1399 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)
@@ -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 56a40ce75..55bf5e8d1 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/quickstart.py b/sphinx/quickstart.py
index e480923d5..acf26df7b 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 f0b8cedcf..2778759a6 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 b4f5a799e..fb44cff84 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:
@@ -322,7 +323,7 @@ class IndexBuilder(object):
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 6084a0675..bc308b67a 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-z4-Z]': u'A',
u'[0-90-ļ¼™]': 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 deb8ceabc..c2a661ee6 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -16,10 +16,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
+
from sphinx.application import Sphinx
from sphinx.util.console import darkred, nocolor, color_terminal
from sphinx.util.osutil import abspath
diff --git a/sphinx/theming.py b/sphinx/theming.py
index abc09c17f..41cbcae96 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 06c6ce244..cc3c9fe10 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)
@@ -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 e71328744..f82f1f451 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 85845a722..ede4ae7da 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 05a6ec6e2..ac5c54aec 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 496a2a41f..50cf8ee5c 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,7 +189,7 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-if sys.version_info < (3, 0):
+if PY2:
bytes = str
else:
bytes = bytes
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index 8cc7c5de4..af2037d08 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -12,20 +12,19 @@
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 +45,20 @@ 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 +68,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):
@@ -101,10 +106,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 2a9b2a028..d5141587b 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/versioning.py b/sphinx/versioning.py
index a41de0f09..8d34802ef 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 0e9131d0e..4cdedc0dd 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 45068d29b..f2a67b4d4 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 6d1f9de4a..17adf0584 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 13dd5d424..2d3366924 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 9d3c01795..53aff908d 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):
@@ -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 76f28a4ff..d8da901e4 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/tests/coverage.py b/tests/coverage.py
index 95063b676..fa65a7158 100755
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -69,15 +69,11 @@ import sys
import atexit
import threading
import token
-import types
import zipimport
from socket import gethostname
-# Python version compatibility
-try:
- strclass = basestring # new to 2.3
-except:
- strclass = str
+from six import string_types
+
# 2. IMPLEMENTATION
#
@@ -845,7 +841,7 @@ class coverage:
# On windows, the shell doesn't expand wildcards. Do it here.
globbed = []
for morf in morfs:
- if isinstance(morf, strclass):
+ if isinstance(morf, string_types):
globbed.extend(glob.glob(morf))
else:
globbed.append(morf)
diff --git a/tests/etree13/ElementTree.py b/tests/etree13/ElementTree.py
index 892b08a01..e9e9d8b5a 100644
--- a/tests/etree13/ElementTree.py
+++ b/tests/etree13/ElementTree.py
@@ -81,6 +81,9 @@
from __future__ import generators
from __future__ import absolute_import
+from six import string_types
+
+
__all__ = [
# public symbols
"Comment",
@@ -828,7 +831,7 @@ def _namespaces(elem, encoding, default_namespace=None):
tag = elem.tag
if isinstance(tag, QName) and tag.text not in qnames:
add_qname(tag.text)
- elif isinstance(tag, basestring):
+ elif isinstance(tag, string_types):
if tag not in qnames:
add_qname(tag)
elif tag is not None and tag is not Comment and tag is not PI:
@@ -1184,7 +1187,7 @@ class _IterParseIterator(object):
append((event, None))
parser.EndNamespaceDeclHandler = handler
- def next(self):
+ def __next__(self):
while 1:
try:
item = self._events[self._index]
@@ -1205,6 +1208,8 @@ class _IterParseIterator(object):
self._index = self._index + 1
return item
+ next = __next__ # Python 2 compatibility
+
def __iter__(self):
return self
diff --git a/tests/etree13/HTMLTreeBuilder.py b/tests/etree13/HTMLTreeBuilder.py
index 3e3a7d925..cf332c759 100644
--- a/tests/etree13/HTMLTreeBuilder.py
+++ b/tests/etree13/HTMLTreeBuilder.py
@@ -54,6 +54,8 @@ import htmlentitydefs
import re, string, sys
import mimetools, StringIO
+from six import text_type
+
from . import ElementTree
AUTOCLOSE = "p", "li", "tr", "th", "td", "head", "body"
@@ -199,7 +201,7 @@ class HTMLTreeBuilder(HTMLParser):
def handle_data(self, data):
if isinstance(data, type('')) and is_not_ascii(data):
# convert to unicode, but only if necessary
- data = unicode(data, self.encoding, "ignore")
+ data = text_type(data, self.encoding, "ignore")
self.__builder.data(data)
##
diff --git a/tests/path.py b/tests/path.py
index f40e7b043..2a4affe77 100755
--- a/tests/path.py
+++ b/tests/path.py
@@ -12,20 +12,22 @@ import sys
import shutil
from codecs import open
+from six import PY2, text_type
+
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
-class path(unicode):
+class path(text_type):
"""
Represents a path which behaves like a string.
"""
- if sys.version_info < (3, 0):
+ if PY2:
def __new__(cls, s, encoding=FILESYSTEMENCODING, errors='strict'):
if isinstance(s, str):
s = s.decode(encoding, errors)
- return unicode.__new__(cls, s)
- return unicode.__new__(cls, s)
+ return text_type.__new__(cls, s)
+ return text_type.__new__(cls, s)
@property
def parent(self):
@@ -193,4 +195,4 @@ class path(unicode):
__div__ = __truediv__ = joinpath
def __repr__(self):
- return '%s(%s)' % (self.__class__.__name__, unicode.__repr__(self))
+ return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self))
diff --git a/tests/roots/test-autosummary/contents.rst b/tests/roots/test-autosummary/contents.rst
index 3f16af998..32390a32e 100644
--- a/tests/roots/test-autosummary/contents.rst
+++ b/tests/roots/test-autosummary/contents.rst
@@ -1,6 +1,6 @@
-
-.. autosummary::
- :nosignatures:
- :toctree:
-
- dummy_module
+
+.. autosummary::
+ :nosignatures:
+ :toctree:
+
+ dummy_module
diff --git a/tests/run.py b/tests/run.py
index 7d51100d9..e8cf787ff 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -15,6 +15,9 @@ import sys
from os import path, chdir, listdir, environ
import shutil
+from six import PY3
+
+
testroot = path.dirname(__file__) or '.'
if 'BUILD_TEST_PATH' in environ:
# for tox testing
@@ -26,7 +29,7 @@ else:
shutil.rmtree(newroot, ignore_errors=True)
-if sys.version_info >= (3, 0):
+if PY3:
print('Copying and converting sources to build/lib/tests...')
from distutils.util import copydir_run_2to3
copydir_run_2to3(testroot, newroot)
diff --git a/tests/test_application.py b/tests/test_application.py
index 3d464eb59..49c27452a 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -9,9 +9,9 @@
:license: BSD, see LICENSE for details.
"""
-from StringIO import StringIO
-
+from six import StringIO
from docutils import nodes
+
from sphinx.application import ExtensionError
from sphinx.domains import Domain
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 30de8790f..b85aee78e 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -10,13 +10,11 @@
:license: BSD, see LICENSE for details.
"""
-import sys
-from StringIO import StringIO
-
# "raises" imported for usage by autodoc
from util import TestApp, Struct, raises
from nose.tools import with_setup
+from six import StringIO
from docutils.statemachine import ViewList
from sphinx.ext.autodoc import AutoDirective, add_documenter, \
diff --git a/tests/test_autosummary.py b/tests/test_autosummary.py
index fc506cd95..7504f11cb 100644
--- a/tests/test_autosummary.py
+++ b/tests/test_autosummary.py
@@ -10,6 +10,8 @@
"""
import sys
+from six import iteritems
+
from sphinx.ext.autosummary import mangle_signature
from util import with_app, test_roots
@@ -97,6 +99,6 @@ def test_get_items_summary():
'noSentence': "this doesn't start with a",
'emptyLine': "This is the real summary",
}
- for key, expected in expected_values.iteritems():
+ for key, expected in iteritems(expected_values):
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
' expected %r' % (key, autosummary_items[key], expected)
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index f4b8c21c2..afe78526a 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -11,9 +11,9 @@
import os
import re
-import sys
-import htmlentitydefs
-from StringIO import StringIO
+
+from six import PY3, iteritems, StringIO
+from six.moves import html_entities
try:
import pygments
@@ -54,7 +54,7 @@ None:\\d+: WARNING: citation not found: missing
%(root)s/markup.txt:: WARNING: invalid pair index entry u'keyword; '
"""
-if sys.version_info >= (3, 0):
+if PY3:
ENV_WARNINGS = remove_unicode_literals(ENV_WARNINGS)
HTML_WARNINGS = remove_unicode_literals(HTML_WARNINGS)
@@ -344,9 +344,9 @@ def test_html(app):
'--- Expected (regex):\n' + html_warnings_exp + \
'--- Got:\n' + html_warnings
- for fname, paths in HTML_XPATH.iteritems():
+ for fname, paths in iteritems(HTML_XPATH):
parser = NslessParser()
- parser.entity.update(htmlentitydefs.entitydefs)
+ parser.entity.update(html_entities.entitydefs)
fp = open(os.path.join(app.outdir, fname), 'rb')
try:
etree = ET.parse(fp, parser)
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 0b2d89645..41ae03df3 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -12,10 +12,10 @@ from __future__ import print_function
import os
import re
-import sys
-from StringIO import StringIO
from subprocess import Popen, PIPE
+from six import PY3, StringIO
+
from sphinx.writers.latex import LaTeXTranslator
from util import test_root, SkipTest, remove_unicode_literals, with_app
@@ -35,7 +35,7 @@ WARNING: invalid pair index entry u''
WARNING: invalid pair index entry u'keyword; '
"""
-if sys.version_info >= (3, 0):
+if PY3:
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index 2dcce7ed1..fbe8a1731 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -12,10 +12,10 @@ from __future__ import print_function
import os
import re
-import sys
-from StringIO import StringIO
from subprocess import Popen, PIPE
+from six import PY3, StringIO
+
from sphinx.writers.texinfo import TexinfoTranslator
from util import test_root, SkipTest, remove_unicode_literals, with_app
@@ -34,7 +34,7 @@ None:None: WARNING: no matching candidate for image URI u'foo.\\*'
None:None: WARNING: no matching candidate for image URI u'svgimg.\\*'
"""
-if sys.version_info >= (3, 0):
+if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
diff --git a/tests/test_config.py b/tests/test_config.py
index db9a2a010..eaecb066e 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -9,7 +9,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import sys
+from six import PY3
from util import TestApp, with_app, with_tempdir, raises, raises_msg
@@ -101,7 +101,7 @@ def test_errors_warnings(dir):
# test the warning for bytestrings with non-ascii content
# bytestrings with non-ascii content are a syntax error in python3 so we
# skip the test there
- if sys.version_info >= (3, 0):
+ if PY3:
return
(dir / 'conf.py').write_text(
u'# -*- coding: latin-1\nproject = "fooƤ"\n', encoding='latin-1')
diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py
index 8e1cb22bb..1fec2ba29 100644
--- a/tests/test_cpp_domain.py
+++ b/tests/test_cpp_domain.py
@@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
+from six import text_type
+
from util import raises
from sphinx.domains.cpp import DefinitionParser, DefinitionError
@@ -20,100 +22,100 @@ def parse(name, string):
def test_type_definitions():
rv = parse('member_object', ' const std::string & name = 42')
- assert unicode(rv) == 'const std::string& name = 42'
+ assert text_type(rv) == 'const std::string& name = 42'
rv = parse('member_object', ' const std::string & name leftover')
- assert unicode(rv) == 'const std::string& name'
+ assert text_type(rv) == 'const std::string& name'
rv = parse('member_object', ' const std::string & name [n] leftover')
- assert unicode(rv) == 'const std::string& name[n]'
+ assert text_type(rv) == 'const std::string& name[n]'
rv = parse('member_object', 'const std::vector< unsigned int, long> &name')
- assert unicode(rv) == 'const std::vector<unsigned int, long>& name'
+ assert text_type(rv) == 'const std::vector<unsigned int, long>& name'
x = 'std::vector<std::pair<std::string, int>>& module::test(register ' \
'foo, bar, std::string baz="foobar, blah, bleh") const = 0'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'module::myclass::operator std::vector<std::string>()'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'explicit module::myclass::foo::foo()'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int printf(const char* fmt, ...)'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int foo(const unsigned int j)'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int foo(const unsigned int const j)'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int foo(const int* const ptr)'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'std::vector<std::pair<std::string, long long>> module::blah'
- assert unicode(parse('type_object', x)) == x
+ assert text_type(parse('type_object', x)) == x
- assert unicode(parse('type_object', 'long long int foo')) == 'long long foo'
+ assert text_type(parse('type_object', 'long long int foo')) == 'long long foo'
x = 'void operator()(const boost::array<VertexID, 2>& v) const'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'void operator()(const boost::array<VertexID, 2, "foo, bar">& v) const'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::MyClass(MyClass::MyClass&&)'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'constexpr int get_value()'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'static constexpr int get_value()'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int get_value() const noexcept'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int get_value() const noexcept = delete'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::MyClass(MyClass::MyClass&&) = default'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_virtual_function() const override'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_member_function() volatile'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_member_function() const volatile'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_member_function() &&'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_member_function() &'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'MyClass::a_member_function() const &'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int main(int argc, char* argv[][])'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'std::vector<std::pair<std::string, int>>& module::test(register ' \
'foo, bar[n], std::string baz="foobar, blah, bleh") const = 0'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'module::myclass foo[n]'
- assert unicode(parse('member_object', x)) == x
+ assert text_type(parse('member_object', x)) == x
x = 'int foo(Foo f=Foo(double(), std::make_pair(int(2), double(3.4))))'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int foo(A a=x(a))'
- assert unicode(parse('function', x)) == x
+ assert text_type(parse('function', x)) == x
x = 'int foo(B b=x(a)'
raises(DefinitionError, parse, 'function', x)
@@ -127,31 +129,31 @@ def test_type_definitions():
def test_bases():
x = 'A'
- assert unicode(parse('class', x)) == x
+ assert text_type(parse('class', x)) == x
x = 'A : B'
- assert unicode(parse('class', x)) == x
+ assert text_type(parse('class', x)) == x
x = 'A : private B'
- assert unicode(parse('class', x)) == 'A : B'
+ assert text_type(parse('class', x)) == 'A : B'
x = 'A : public B'
- assert unicode(parse('class', x)) == x
+ assert text_type(parse('class', x)) == x
x = 'A : B, C'
- assert unicode(parse('class', x)) == x
+ assert text_type(parse('class', x)) == x
x = 'A : B, protected C, D'
- assert unicode(parse('class', x)) == x
+ assert text_type(parse('class', x)) == x
def test_operators():
x = parse('function', 'void operator new [ ] ()')
- assert unicode(x) == 'void operator new[]()'
+ assert text_type(x) == 'void operator new[]()'
x = parse('function', 'void operator delete ()')
- assert unicode(x) == 'void operator delete()'
+ assert text_type(x) == 'void operator delete()'
for op in '*-+=/%!':
x = parse('function', 'void operator %s ()' % op)
- assert unicode(x) == 'void operator%s()' % op
+ assert text_type(x) == 'void operator%s()' % op
diff --git a/tests/test_doctest.py b/tests/test_doctest.py
index ba720041b..9fb8a2ead 100644
--- a/tests/test_doctest.py
+++ b/tests/test_doctest.py
@@ -11,12 +11,13 @@
from __future__ import print_function
import sys
-import StringIO
+
+from six import StringIO
from util import with_app
-status = StringIO.StringIO()
+status = StringIO()
cleanup_called = 0
@with_app(buildername='doctest', status=status)
diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py
index fcfef13b3..3389a16ee 100644
--- a/tests/test_docutilsconf.py
+++ b/tests/test_docutilsconf.py
@@ -11,9 +11,10 @@
import os
import re
-from StringIO import StringIO
from functools import wraps
+from six import StringIO
+
from util import test_roots, TestApp
diff --git a/tests/test_env.py b/tests/test_env.py
index eaaa212f8..11e73edfe 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -8,7 +8,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import sys
+from six import PY3
from util import TestApp, remove_unicode_literals, path
@@ -57,7 +57,7 @@ def test_images():
htmlbuilder.imgpath = 'dummy'
htmlbuilder.post_process_images(tree)
image_uri_message = "no matching candidate for image URI u'foo.*'"
- if sys.version_info >= (3, 0):
+ if PY3:
image_uri_message = remove_unicode_literals(image_uri_message)
assert image_uri_message in app._warning.content[-1]
assert set(htmlbuilder.images.keys()) == \
diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py
index d342590d7..dd71c6fbd 100644
--- a/tests/test_intersphinx.py
+++ b/tests/test_intersphinx.py
@@ -11,11 +11,8 @@
import zlib
import posixpath
-try:
- from io import BytesIO
-except ImportError:
- from cStringIO import StringIO as BytesIO
+from six import BytesIO
from docutils import nodes
from sphinx import addnodes
diff --git a/tests/test_intl.py b/tests/test_intl.py
index 56c88bd67..b4ce96449 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -13,10 +13,11 @@ from __future__ import print_function
import os
import re
-from StringIO import StringIO
from subprocess import Popen, PIPE
from xml.etree import ElementTree
+from six import StringIO, string_types
+
from util import test_roots, path, with_app, SkipTest
@@ -76,7 +77,7 @@ def elem_gettexts(elem):
# this function copied from Python-2.7 'ElementTree.itertext'.
# for compatibility to Python-2.6
tag = self.tag
- if not isinstance(tag, basestring) and tag is not None:
+ if not isinstance(tag, string_types) and tag is not None:
return
if self.text:
yield self.text
diff --git a/tests/test_napoleon_iterators.py b/tests/test_napoleon_iterators.py
index db0be32c8..320047e5a 100644
--- a/tests/test_napoleon_iterators.py
+++ b/tests/test_napoleon_iterators.py
@@ -29,7 +29,7 @@ class BaseIteratorsTest(TestCase):
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(expected, it.peek)
self.assertTrueTwice(it.has_next)
- self.assertEqual(expected, it.next())
+ self.assertEqual(expected, next(it))
if is_last:
self.assertFalseTwice(it.has_next)
self.assertRaisesTwice(StopIteration, it.next)
@@ -217,7 +217,7 @@ class PeekIterTest(BaseIteratorsTest):
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(['1', '2', '3', it.sentinel], it.peek, 4)
self.assertTrueTwice(it.has_next)
- self.assertEqual('1', it.next())
+ self.assertEqual('1', next(it))
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(['2', '3'], it.peek, 2)
self.assertTrueTwice(it.has_next)
@@ -237,7 +237,7 @@ class PeekIterTest(BaseIteratorsTest):
it = peek_iter(a)
self.assertTrueTwice(it.has_next)
self.assertEqualTwice('1', it.peek)
- self.assertEqual('1', it.next())
+ self.assertEqual('1', next(it))
self.assertFalseTwice(it.has_next)
self.assertEqualTwice(it.sentinel, it.peek)
self.assertFalseTwice(it.has_next)
@@ -246,10 +246,10 @@ class PeekIterTest(BaseIteratorsTest):
it = peek_iter(a)
self.assertTrueTwice(it.has_next)
self.assertEqualTwice('1', it.peek)
- self.assertEqual('1', it.next())
+ self.assertEqual('1', next(it))
self.assertTrueTwice(it.has_next)
self.assertEqualTwice('2', it.peek)
- self.assertEqual('2', it.next())
+ self.assertEqual('2', next(it))
self.assertFalseTwice(it.has_next)
self.assertEqualTwice(it.sentinel, it.peek)
self.assertFalseTwice(it.has_next)
@@ -265,7 +265,7 @@ class PeekIterTest(BaseIteratorsTest):
it = peek_iter(a)
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(['1'], it.peek, 1)
- self.assertEqual('1', it.next())
+ self.assertEqual('1', next(it))
self.assertFalseTwice(it.has_next)
self.assertEqualTwice([it.sentinel], it.peek, 1)
self.assertFalseTwice(it.has_next)
@@ -274,10 +274,10 @@ class PeekIterTest(BaseIteratorsTest):
it = peek_iter(a)
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(['1'], it.peek, 1)
- self.assertEqual('1', it.next())
+ self.assertEqual('1', next(it))
self.assertTrueTwice(it.has_next)
self.assertEqualTwice(['2'], it.peek, 1)
- self.assertEqual('2', it.next())
+ self.assertEqual('2', next(it))
self.assertFalseTwice(it.has_next)
self.assertEqualTwice([it.sentinel], it.peek, 1)
self.assertFalseTwice(it.has_next)
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index ef29a2b06..901d8ccd9 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -11,10 +11,11 @@
import sys
import time
-from StringIO import StringIO
-import tempfile
-from util import raises, with_tempdir, with_app, SkipTest
+from six import PY2, text_type, StringIO
+from six.moves import input
+
+from util import raises, with_tempdir, SkipTest
from sphinx import application
from sphinx import quickstart as qs
@@ -28,18 +29,18 @@ warnfile = StringIO()
def setup_module():
nocolor()
-def mock_raw_input(answers, needanswer=False):
+def mock_input(answers, needanswer=False):
called = set()
- def raw_input(prompt):
+ def input_(prompt):
if prompt in called:
raise AssertionError('answer for %r missing and no default '
'present' % prompt)
called.add(prompt)
- if sys.version_info < (3, 0):
+ if PY2:
prompt = str(prompt) # Python2.x raw_input emulation
# `raw_input` encode `prompt` by default encoding to print.
else:
- prompt = unicode(prompt) # Python3.x input emulation
+ prompt = text_type(prompt) # Python3.x input emulation
# `input` decode prompt by default encoding before print.
for question in answers:
if prompt.startswith(qs.PROMPT_PREFIX + question):
@@ -47,15 +48,12 @@ def mock_raw_input(answers, needanswer=False):
if needanswer:
raise AssertionError('answer for %r missing' % prompt)
return ''
- return raw_input
+ return input_
-try:
- real_raw_input = raw_input
-except NameError:
- real_raw_input = input
+real_input = input
def teardown_module():
- qs.term_input = real_raw_input
+ qs.term_input = real_input
qs.TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
coloron()
@@ -68,7 +66,7 @@ def test_quickstart_inputstrip():
'Q3': 'N',
'Q4': 'N ',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
qs.do_prompt(d, 'k1', 'Q1')
assert d['k1'] == 'Y'
qs.do_prompt(d, 'k2', 'Q2')
@@ -88,7 +86,7 @@ def test_do_prompt():
'Q5': 'no',
'Q6': 'foo',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
try:
qs.do_prompt(d, 'k1', 'Q1')
except AssertionError:
@@ -113,7 +111,7 @@ def test_do_prompt_with_nonascii():
answers = {
'Q1': u'\u30c9\u30a4\u30c4',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
try:
qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c')
except UnicodeEncodeError:
@@ -131,7 +129,7 @@ def test_quickstart_defaults(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
@@ -186,7 +184,7 @@ def test_quickstart_all_answers(tempdir):
'Create Windows command file': 'no',
'Do you want to use the epub builder': 'yes',
}
- qs.term_input = mock_raw_input(answers, needanswer=True)
+ qs.term_input = mock_input(answers, needanswer=True)
qs.TERM_ENCODING = 'utf-8'
d = {}
qs.ask_user(d)
@@ -232,7 +230,7 @@ def test_generated_files_eol(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
@@ -253,7 +251,7 @@ def test_quickstart_and_build(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
@@ -279,7 +277,7 @@ def test_default_filename(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
index 81d7c1784..9a41601d7 100644
--- a/tests/test_searchadapters.py
+++ b/tests/test_searchadapters.py
@@ -10,7 +10,8 @@
"""
import os
-from StringIO import StringIO
+
+from six import StringIO
from sphinx.websupport import WebSupport
diff --git a/tests/test_websupport.py b/tests/test_websupport.py
index bcb756755..d355422c9 100644
--- a/tests/test_websupport.py
+++ b/tests/test_websupport.py
@@ -10,9 +10,10 @@
"""
import os
-from StringIO import StringIO
from functools import wraps
+from six import StringIO
+
from sphinx.websupport import WebSupport
from sphinx.websupport.errors import DocumentNotFoundError, \
CommentNotAllowedError, UserNotAuthorizedError
diff --git a/tests/util.py b/tests/util.py
index 8c4ff3dff..72cac038b 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -8,12 +8,13 @@
"""
import sys
-import StringIO
import tempfile
import shutil
import re
from functools import wraps
+from six import StringIO
+
from sphinx import application
from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
@@ -162,7 +163,7 @@ class TestApp(application.Sphinx):
if confoverrides is None:
confoverrides = {}
if status is None:
- status = StringIO.StringIO()
+ status = StringIO()
if warning is None:
warning = ListOutput('stderr')
if freshenv is None: