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