diff --git a/setup.py b/setup.py index a92c93b45..92c489fbb 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 2): print('ERROR: Sphinx requires at least Python 2.6 or 3.2 to run.') sys.exit(1) -requires = ['Pygments>=1.2', 'docutils>=0.10', 'snowballstemmer>=1.1'] +requires = ['six', 'Pygments>=1.2', 'docutils>=0.10', 'snowballstemmer>=1.1'] if (3, 0) <= sys.version_info < (3, 3): requires.append('Jinja2>=2.3,<2.7') diff --git a/sphinx/application.py b/sphinx/application.py index 89d1d7869..4b1177156 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -18,8 +18,8 @@ import types import posixpath import traceback from os import path -from cStringIO import StringIO +import six from docutils import nodes from docutils.parsers.rst import convert_directive_function, \ directives, roles @@ -84,14 +84,14 @@ class Sphinx(object): self.parallel = parallel if status is None: - self._status = StringIO() + self._status = six.cStringIO() self.quiet = True else: self._status = status self.quiet = False if warning is None: - self._warning = StringIO() + self._warning = six.cStringIO() else: self._warning = warning self._warncount = 0 diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index 07551e67e..377f2385e 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -16,6 +16,7 @@ import getopt import traceback from os import path +import six from docutils.utils import SystemMessage from sphinx import __version__ @@ -24,7 +25,7 @@ from sphinx.application import Sphinx from sphinx.util import Tee, format_exception_cut_frames, save_traceback from sphinx.util.console import red, nocolor, color_terminal from sphinx.util.osutil import abspath, fs_encoding -from sphinx.util.pycompat import terminal_safe, bytes +from sphinx.util.pycompat import terminal_safe def usage(argv, msg=None): @@ -183,7 +184,7 @@ def main(argv): print('Error: -D option argument must be in the form name=value.', file=sys.stderr) return 1 - if likely_encoding and isinstance(val, bytes): + if likely_encoding and isinstance(val, six.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, six.binary_type): try: val = val.decode(likely_encoding) except UnicodeError: diff --git a/sphinx/config.py b/sphinx/config.py index 527ea453d..6cbbd6410 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -11,18 +11,19 @@ import os import re -import sys from os import path +import six + from sphinx.errors import ConfigError from sphinx.locale import l_ from sphinx.util.osutil import make_filename -from sphinx.util.pycompat import bytes, b, execfile_ +from sphinx.util.pycompat import b, execfile_ nonascii_re = re.compile(b(r'[\x80-\xff]')) CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s" -if sys.version_info >= (3, 0): +if six.PY3: CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?" class Config(object): @@ -243,7 +244,7 @@ class Config(object): # check all string values for non-ASCII characters in bytestrings, # since that can result in UnicodeErrors all over the place for name, value in self._raw_config.iteritems(): - if isinstance(value, bytes) and nonascii_re.search(value): + if isinstance(value, six.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') diff --git a/sphinx/environment.py b/sphinx/environment.py index a0fb87dad..195ae724b 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -23,6 +23,7 @@ from os import path from glob import glob from itertools import izip, groupby +import six 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 _ @@ -140,7 +140,7 @@ class BuildEnvironment: if key.startswith('_') or \ isinstance(val, types.ModuleType) or \ isinstance(val, types.FunctionType) or \ - isinstance(val, class_types): + isinstance(val, six.class_types): del self.config[key] try: pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL) diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index a79849aef..1fc2a3db3 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 +import six 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 @@ -1028,7 +1028,7 @@ class ClassDocumenter(ModuleLevelDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): - return isinstance(member, class_types) + return isinstance(member, six.class_types) def import_object(self): ret = ModuleLevelDocumenter.import_object(self) @@ -1162,7 +1162,7 @@ class ExceptionDocumenter(ClassDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): - return isinstance(member, class_types) and \ + return isinstance(member, six.class_types) and \ issubclass(member, BaseException) @@ -1212,7 +1212,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): return inspect.isroutine(member) and \ not isinstance(parent, ModuleDocumenter) - if sys.version_info >= (3, 0): + if six.PY3: def import_object(self): ret = ClassLevelDocumenter.import_object(self) obj_from_parent = self.parent.__dict__.get(self.object_name) @@ -1282,7 +1282,7 @@ class AttributeDocumenter(ClassLevelDocumenter): "instancemethod") return isdatadesc or (not isinstance(parent, ModuleDocumenter) and not inspect.isroutine(member) - and not isinstance(member, class_types)) + and not isinstance(member, six.class_types)) def document_members(self, all_members=False): pass diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index ef27dc119..6484677ca 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') +import six 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*', 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 = six.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, six.binary_type): text = force_decode(text, None) self.outfile.write(text) diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py index 96ca81a56..c6fd3c349 100644 --- a/sphinx/ext/napoleon/__init__.py +++ b/sphinx/ext/napoleon/__init__.py @@ -10,6 +10,9 @@ """ import sys + +import six + from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring @@ -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 six.PY2: cls = getattr(obj, 'im_class', getattr(obj, '__objclass__', None)) cls_is_owner = (cls and hasattr(cls, name) and name in cls.__dict__) - elif sys.version_info[1] >= 3: + elif sys.version_info >= (3, 3): qualname = getattr(obj, '__qualname__', '') cls_path, _, _ = qualname.rpartition('.') if cls_path: diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index 2819ffe34..dea55c629 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -14,11 +14,13 @@ import collections import inspect import re -import sys + +import six + from sphinx.ext.napoleon.iterators import modify_iter -if sys.version_info[0] >= 3: +if six.PY3: basestring = str xrange = range @@ -160,7 +162,7 @@ class GoogleDocstring(object): UTF-8 encoded version of the docstring. """ - if sys.version_info[0] >= 3: + if six.PY3: return self.__unicode__() else: return self.__unicode__().encode('utf8') diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py index 2f1904dab..7db350b77 100644 --- a/sphinx/ext/napoleon/iterators.py +++ b/sphinx/ext/napoleon/iterators.py @@ -12,10 +12,11 @@ """ import collections -import sys + +import six -if sys.version_info[0] >= 3: +if six.PY3: callable = lambda o: hasattr(o, '__call__') diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index b5779ab42..6e5ada6f5 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 +import six + 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 six.PY2 and isinstance(src, unicode): # Non-ASCII chars will only occur in string literals # and comments. If we wanted to give them to the parser # correctly, we'd have to find out the correct source diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index b76aab1f7..fc2ffedb6 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -9,10 +9,11 @@ :license: BSD, see LICENSE for details. """ -import sys import gettext import UserString +import six + class _TranslationProxy(UserString.UserString, object): """ @@ -183,7 +184,7 @@ pairindextypes = { translators = {} -if sys.version_info >= (3, 0): +if six.PY3: def _(message): return translators['sphinx'].gettext(message) else: diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index b735fb31b..53223d250 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 +import six + 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 @@ -174,8 +176,8 @@ class ModuleAnalyzer(object): @classmethod def for_string(cls, string, modname, srcname=''): if isinstance(string, bytes): - return cls(BytesIO(string), modname, srcname) - return cls(StringIO(string), modname, srcname, decoded=True) + return cls(six.BytesIO(string), modname, srcname) + return cls(six.StringIO(string), modname, srcname, decoded=True) @classmethod def for_file(cls, filename, modname): diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index e480923d5..180066e00 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -16,6 +16,8 @@ from io import open TERM_ENCODING = getattr(sys.stdin, 'encoding', None) +import six + #try to import readline, unix specific enhancement try: import readline @@ -44,7 +46,7 @@ except NameError: PROMPT_PREFIX = '> ' -if sys.version_info >= (3, 0): +if six.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 +999,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 six.PY2: # for Python 2.x, try to get a Unicode string out of it if prompt.encode('ascii', 'replace').decode('ascii', 'replace') \ != prompt: @@ -1037,7 +1039,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty): d[key] = x -if sys.version_info >= (3, 0): +if six.PY3: # remove Unicode literal prefixes def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")): return rex.sub('\\1', source) diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py index deb8ceabc..029a44c24 100644 --- a/sphinx/setup_command.py +++ b/sphinx/setup_command.py @@ -16,10 +16,11 @@ from __future__ import print_function import sys import os import types -from StringIO import StringIO from distutils.cmd import Command from distutils.errors import DistutilsOptionError +import six + from sphinx.application import Sphinx from sphinx.util.console import darkred, nocolor, color_terminal from sphinx.util.osutil import abspath @@ -141,7 +142,7 @@ class BuildDoc(Command): # Windows' poor cmd box doesn't understand ANSI sequences nocolor() if not self.verbose: - status_stream = StringIO() + status_stream = six.StringIO() else: status_stream = sys.stdout confoverrides = {} diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 06c6ce244..3c9366a17 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,7 @@ from os import path from codecs import open, BOM_UTF8 from collections import deque +import six import docutils from docutils.utils import relative_path @@ -29,7 +29,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 @@ -336,7 +335,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, six.binary_type): try: if encoding: string = string.decode(encoding) diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index e71328744..7cf0be38a 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -9,17 +9,16 @@ :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') +import six + from sphinx.util import force_decode -from sphinx.util.pycompat import bytes, builtins -if sys.version_info >= (3, 0): +if six.PY3: from functools import partial def getargspec(func): """Like inspect.getargspec but supports functools.partial as well.""" @@ -129,7 +128,7 @@ def safe_repr(object): s = repr(object) except Exception: raise ValueError - if isinstance(s, bytes): + if isinstance(s, six.binary_type): return force_decode(s, None).replace('\n', ' ') return s.replace('\n', ' ') @@ -146,6 +145,6 @@ def is_builtin_class_method(obj, attr_name): classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__] cls = classes[0] if classes else object - if not hasattr(builtins, safe_getattr(cls, '__name__', '')): + if not hasattr(six.moves.builtins, safe_getattr(cls, '__name__', '')): return False - return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls + return getattr(six.moves.builtins, safe_getattr(cls, '__name__', '')) is cls diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index 496a2a41f..00cc1ae31 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -20,6 +20,8 @@ import shutil import gettext from os import path +import six + # Errnos that we need. EEXIST = getattr(errno, 'EEXIST', 0) ENOENT = getattr(errno, 'ENOENT', 0) @@ -147,7 +149,7 @@ 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 six.PY2: # strftime for unicode strings def ustrftime(format, *args): # if a locale is set, the time strings are encoded in the encoding @@ -187,7 +189,7 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction): fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() -if sys.version_info < (3, 0): +if six.PY2: bytes = str else: bytes = bytes diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 8cc7c5de4..8d1b3d061 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -12,20 +12,19 @@ import sys import codecs +import six + # ------------------------------------------------------------------------------ # Python 2/3 compatibility -if sys.version_info >= (3, 0): +if six.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') @@ -47,18 +46,12 @@ if sys.version_info >= (3, 0): # 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 + from html import escape as htmlescape # >= Python 3.2 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 +61,9 @@ 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 def execfile_(filepath, _globals): @@ -101,10 +92,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 + six.exec_(code, _globals) diff --git a/sphinx/versioning.py b/sphinx/versioning.py index a41de0f09..8cc618e8d 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -13,7 +13,7 @@ from uuid import uuid4 from operator import itemgetter from itertools import product -from sphinx.util.pycompat import zip_longest +import six # anything below that ratio is considered equal/changed @@ -52,7 +52,7 @@ def merge_doctrees(old, new, condition): ratios = {} seen = set() # compare the nodes each doctree in order - for old_node, new_node in zip_longest(old_iter, new_iter): + for old_node, new_node in six.moves.zip_longest(old_iter, new_iter): if old_node is None: new_nodes.append(new_node) continue diff --git a/tests/path.py b/tests/path.py index f40e7b043..860e65e18 100755 --- a/tests/path.py +++ b/tests/path.py @@ -12,6 +12,8 @@ import sys import shutil from codecs import open +import six + FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding() @@ -20,7 +22,7 @@ class path(unicode): """ Represents a path which behaves like a string. """ - if sys.version_info < (3, 0): + if six.PY2: def __new__(cls, s, encoding=FILESYSTEMENCODING, errors='strict'): if isinstance(s, str): s = s.decode(encoding, errors) diff --git a/tests/roots/test-autosummary/contents.rst b/tests/roots/test-autosummary/contents.rst index 3f16af998..32390a32e 100644 --- a/tests/roots/test-autosummary/contents.rst +++ b/tests/roots/test-autosummary/contents.rst @@ -1,6 +1,6 @@ - -.. autosummary:: - :nosignatures: - :toctree: - - dummy_module + +.. autosummary:: + :nosignatures: + :toctree: + + dummy_module diff --git a/tests/run.py b/tests/run.py index 7d51100d9..8d2a828a0 100755 --- a/tests/run.py +++ b/tests/run.py @@ -15,6 +15,9 @@ import sys from os import path, chdir, listdir, environ import shutil +import six + + testroot = path.dirname(__file__) or '.' if 'BUILD_TEST_PATH' in environ: # for tox testing @@ -26,7 +29,7 @@ else: shutil.rmtree(newroot, ignore_errors=True) -if sys.version_info >= (3, 0): +if six.PY3: print('Copying and converting sources to build/lib/tests...') from distutils.util import copydir_run_2to3 copydir_run_2to3(testroot, newroot) diff --git a/tests/test_application.py b/tests/test_application.py index 3d464eb59..d8c52b246 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 - +import six from docutils import nodes + from sphinx.application import ExtensionError from sphinx.domains import Domain @@ -49,7 +49,7 @@ def test_emit_with_nonascii_name_node(app): def test_output(): - status, warnings = StringIO(), StringIO() + status, warnings = six.StringIO(), six.StringIO() app = TestApp(status=status, warning=warnings) try: status.truncate(0) # __init__ writes to status @@ -70,7 +70,7 @@ def test_output(): def test_extensions(): - status, warnings = StringIO(), StringIO() + status, warnings = six.StringIO(), six.StringIO() app = TestApp(status=status, warning=warnings) try: app.setup_extension('shutil') @@ -85,7 +85,7 @@ def test_domain_override(): name = 'foo' class C(Domain): name = 'foo' - status, warnings = StringIO(), StringIO() + status, warnings = six.StringIO(), six.StringIO() app = TestApp(status=status, warning=warnings) try: # No domain know named foo. diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 30de8790f..7b6c017e3 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 +import six from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ @@ -811,7 +809,7 @@ class Class(Base): u"""should be documented as well - süß""" # initialized to any class imported from another module - mdocattr = StringIO() + mdocattr = six.StringIO() """should be documented as well - süß""" roger = _funky_classmethod("roger", 2, 3, 4) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index f4b8c21c2..8fb5313ee 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 + +import six try: import pygments @@ -29,7 +29,7 @@ def teardown_module(): (test_root / '_build').rmtree(True) -html_warnfile = StringIO() +html_warnfile = six.StringIO() ENV_WARNINGS = """\ %(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \ @@ -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 six.PY3: ENV_WARNINGS = remove_unicode_literals(ENV_WARNINGS) HTML_WARNINGS = remove_unicode_literals(HTML_WARNINGS) diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 0b2d89645..0a2a6421f 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 +import six + from sphinx.writers.latex import LaTeXTranslator from util import test_root, SkipTest, remove_unicode_literals, with_app @@ -26,7 +26,7 @@ def teardown_module(): (test_root / '_build').rmtree(True) -latex_warnfile = StringIO() +latex_warnfile = six.StringIO() LATEX_WARNINGS = ENV_WARNINGS + """\ None:None: WARNING: citation not found: missing @@ -35,7 +35,7 @@ WARNING: invalid pair index entry u'' WARNING: invalid pair index entry u'keyword; ' """ -if sys.version_info >= (3, 0): +if six.PY3: LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS) diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index 2dcce7ed1..3cb30a2d5 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 +import six + from sphinx.writers.texinfo import TexinfoTranslator from util import test_root, SkipTest, remove_unicode_literals, with_app @@ -26,7 +26,7 @@ def teardown_module(): (test_root / '_build').rmtree(True) -texinfo_warnfile = StringIO() +texinfo_warnfile = six.StringIO() TEXINFO_WARNINGS = ENV_WARNINGS + """\ None:None: WARNING: citation not found: missing @@ -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 six.PY3: TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS) diff --git a/tests/test_config.py b/tests/test_config.py index db9a2a010..f69a2185a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -9,7 +9,7 @@ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ -import sys +import six from util import TestApp, with_app, with_tempdir, raises, raises_msg @@ -101,7 +101,7 @@ def test_errors_warnings(dir): # test the warning for bytestrings with non-ascii content # bytestrings with non-ascii content are a syntax error in python3 so we # skip the test there - if sys.version_info >= (3, 0): + if six.PY3: return (dir / 'conf.py').write_text( u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1') diff --git a/tests/test_doctest.py b/tests/test_doctest.py index ba720041b..d90a5be82 100644 --- a/tests/test_doctest.py +++ b/tests/test_doctest.py @@ -11,12 +11,13 @@ from __future__ import print_function import sys -import StringIO + +import six from util import with_app -status = StringIO.StringIO() +status = six.StringIO() cleanup_called = 0 @with_app(buildername='doctest', status=status) diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py index fcfef13b3..edd72be8a 100644 --- a/tests/test_docutilsconf.py +++ b/tests/test_docutilsconf.py @@ -11,13 +11,14 @@ import os import re -from StringIO import StringIO from functools import wraps +import six + from util import test_roots, TestApp -html_warnfile = StringIO() +html_warnfile = six.StringIO() root = test_roots / 'test-docutilsconf' diff --git a/tests/test_env.py b/tests/test_env.py index eaaa212f8..10dd9c8a1 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 +import six 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 six.PY3: image_uri_message = remove_unicode_literals(image_uri_message) assert image_uri_message in app._warning.content[-1] assert set(htmlbuilder.images.keys()) == \ diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py index d342590d7..9ed9fe688 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 +import six from docutils import nodes from sphinx import addnodes @@ -48,7 +45,7 @@ a term std:term -1 glossary.html#term-a-term - def test_read_inventory_v1(): - f = BytesIO(inventory_v1) + f = six.BytesIO(inventory_v1) f.readline() invdata = read_inventory_v1(f, '/util', posixpath.join) assert invdata['py:module']['module'] == \ @@ -58,12 +55,12 @@ def test_read_inventory_v1(): def test_read_inventory_v2(): - f = BytesIO(inventory_v2) + f = six.BytesIO(inventory_v2) f.readline() invdata1 = read_inventory_v2(f, '/util', posixpath.join) # try again with a small buffer size to test the chunking algorithm - f = BytesIO(inventory_v2) + f = six.BytesIO(inventory_v2) f.readline() invdata2 = read_inventory_v2(f, '/util', posixpath.join, bufsize=5) diff --git a/tests/test_intl.py b/tests/test_intl.py index 56c88bd67..64f584fbb 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -13,14 +13,15 @@ from __future__ import print_function import os import re -from StringIO import StringIO from subprocess import Popen, PIPE from xml.etree import ElementTree +import six + from util import test_roots, path, with_app, SkipTest -warnfile = StringIO() +warnfile = six.StringIO() root = test_roots / 'test-intl' doctreedir = root / '_build' / 'doctree' diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index ef29a2b06..f729f570f 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -11,8 +11,8 @@ import sys import time -from StringIO import StringIO -import tempfile + +import six from util import raises, with_tempdir, with_app, SkipTest @@ -22,7 +22,7 @@ from sphinx.util.console import nocolor, coloron from sphinx.util.pycompat import execfile_ -warnfile = StringIO() +warnfile = six.StringIO() def setup_module(): @@ -35,7 +35,7 @@ def mock_raw_input(answers, needanswer=False): raise AssertionError('answer for %r missing and no default ' 'present' % prompt) called.add(prompt) - if sys.version_info < (3, 0): + if six.PY2: prompt = str(prompt) # Python2.x raw_input emulation # `raw_input` encode `prompt` by default encoding to print. else: @@ -264,7 +264,7 @@ def test_quickstart_and_build(tempdir): (tempdir / '_build' / 'html'), #outdir (tempdir / '_build' / '.doctree'), #doctreedir 'html', #buildername - status=StringIO(), + status=six.StringIO(), warning=warnfile) app.builder.build_all() warnings = warnfile.getvalue() diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py index 81d7c1784..1aebcd9f0 100644 --- a/tests/test_searchadapters.py +++ b/tests/test_searchadapters.py @@ -10,7 +10,8 @@ """ import os -from StringIO import StringIO + +import six from sphinx.websupport import WebSupport @@ -31,8 +32,8 @@ def search_adapter_helper(adapter): clear_builddir() settings = {'builddir': os.path.join(test_root, 'websupport'), - 'status': StringIO(), - 'warning': StringIO()} + 'status': six.StringIO(), + 'warning': six.StringIO()} settings.update({'srcdir': test_root, 'search': adapter}) support = WebSupport(**settings) diff --git a/tests/test_websupport.py b/tests/test_websupport.py index bcb756755..7c7a4f0f3 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 +import six + from sphinx.websupport import WebSupport from sphinx.websupport.errors import DocumentNotFoundError, \ CommentNotAllowedError, UserNotAuthorizedError @@ -30,8 +31,8 @@ from util import test_root, raises, skip_if default_settings = {'builddir': os.path.join(test_root, 'websupport'), - 'status': StringIO(), - 'warning': StringIO()} + 'status': six.StringIO(), + 'warning': six.StringIO()} def teardown_module(): (test_root / 'generated').rmtree(True) diff --git a/tests/util.py b/tests/util.py index 8c4ff3dff..5eb879f58 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 +import six + 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 = six.StringIO() if warning is None: warning = ListOutput('stderr') if freshenv is None: